mirror of
https://github.com/nasa/openmct.git
synced 2025-02-01 00:45:41 +00:00
Merge branch 'topic-conditionals' of https://github.com/nasa/openmct into conditionset-multi-value-operations
This commit is contained in:
commit
a681d67e05
@ -48,18 +48,32 @@ export default class ConditionClass extends EventEmitter {
|
||||
* @param conditionConfiguration: {id: uuid,trigger: enum, criteria: Array of {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} }
|
||||
* @param openmct
|
||||
*/
|
||||
constructor(conditionConfiguration, openmct) {
|
||||
constructor(conditionConfiguration, openmct, conditionManager) {
|
||||
super();
|
||||
|
||||
this.openmct = openmct;
|
||||
this.conditionManager = conditionManager;
|
||||
this.id = conditionConfiguration.id;
|
||||
this.criteria = [];
|
||||
this.criteriaResults = {};
|
||||
this.result = undefined;
|
||||
this.latestTimestamp = {};
|
||||
|
||||
if (conditionConfiguration.configuration.criteria) {
|
||||
this.createCriteria(conditionConfiguration.configuration.criteria);
|
||||
}
|
||||
this.trigger = conditionConfiguration.configuration.trigger;
|
||||
this.conditionManager.on('broadcastTelemetry', this.handleBroadcastTelemetry, this);
|
||||
}
|
||||
|
||||
handleBroadcastTelemetry(datum) {
|
||||
if (!datum || !datum.id) {
|
||||
console.log('no data received');
|
||||
return;
|
||||
}
|
||||
this.criteria.forEach(criterion => {
|
||||
criterion.emit(`subscription:${datum.id}`, datum);
|
||||
});
|
||||
}
|
||||
|
||||
update(conditionConfiguration) {
|
||||
@ -172,7 +186,6 @@ export default class ConditionClass extends EventEmitter {
|
||||
let found = this.findCriterion(criterion.id);
|
||||
if (found) {
|
||||
this.criteria[found.index] = criterion.data;
|
||||
this.subscribe();
|
||||
// TODO nothing is listening to this
|
||||
this.emitEvent('conditionUpdated', {
|
||||
trigger: this.trigger,
|
||||
@ -181,21 +194,40 @@ export default class ConditionClass extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
handleCriterionResult(eventData) {
|
||||
updateCriteriaResults(eventData) {
|
||||
const id = eventData.id;
|
||||
|
||||
if (this.findCriterion(id)) {
|
||||
this.criteriaResults[id] = eventData.data.result;
|
||||
}
|
||||
}
|
||||
|
||||
handleCriterionResult(eventData) {
|
||||
this.updateCriteriaResults(eventData);
|
||||
this.handleConditionUpdated(eventData.data);
|
||||
}
|
||||
|
||||
subscribe() {
|
||||
// TODO it looks like on any single criterion update subscriptions fire for all criteria
|
||||
this.criteria.forEach((criterion) => {
|
||||
criterion.subscribe();
|
||||
})
|
||||
requestLADConditionResult() {
|
||||
const criteriaResults = this.criteria
|
||||
.map(criterion => criterion.requestLAD());
|
||||
|
||||
return Promise.all(criteriaResults)
|
||||
.then(results => {
|
||||
results.forEach(result => {
|
||||
this.updateCriteriaResults(result);
|
||||
this.latestTimestamp = this.getLatestTimestamp(this.latestTimestamp, result.data)
|
||||
});
|
||||
this.evaluate();
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
data: Object.assign({}, this.latestTimestamp, { result: this.result })
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getTelemetrySubscriptions() {
|
||||
return this.criteria.map(criterion => criterion.telemetryObjectIdAsString);
|
||||
}
|
||||
|
||||
handleConditionUpdated(datum) {
|
||||
@ -223,6 +255,19 @@ export default class ConditionClass extends EventEmitter {
|
||||
this.result = computeCondition(this.criteriaResults, this.trigger === TRIGGER.ALL);
|
||||
}
|
||||
|
||||
getLatestTimestamp(current, compare) {
|
||||
const timestamp = Object.assign({}, current);
|
||||
|
||||
this.openmct.time.getAllTimeSystems().forEach(timeSystem => {
|
||||
if (!timestamp[timeSystem.key]
|
||||
|| compare[timeSystem.key] > timestamp[timeSystem.key]
|
||||
) {
|
||||
timestamp[timeSystem.key] = compare[timeSystem.key];
|
||||
}
|
||||
});
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
emitEvent(eventName, data) {
|
||||
this.emit(eventName, {
|
||||
id: this.id,
|
||||
@ -231,6 +276,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.conditionManager.off('broadcastTelemetry', this.handleBroadcastTelemetry, this);
|
||||
if (typeof this.stopObservingForChanges === 'function') {
|
||||
this.stopObservingForChanges();
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.conditionSetDomainObject = conditionSetDomainObject;
|
||||
this.timeAPI = this.openmct.time;
|
||||
this.latestTimestamp = {};
|
||||
this.composition = this.openmct.composition.get(conditionSetDomainObject);
|
||||
this.composition.on('add', this.subscribeToTelemetry, this);
|
||||
this.composition.on('remove', this.unsubscribeFromTelemetry, this);
|
||||
this.compositionLoad = this.composition.load();
|
||||
this.subscriptions = {};
|
||||
this.initialize();
|
||||
|
||||
this.stopObservingForChanges = this.openmct.objects.observe(this.conditionSetDomainObject, '*', (newDomainObject) => {
|
||||
@ -38,6 +43,30 @@ export default class ConditionManager extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
subscribeToTelemetry(endpoint) {
|
||||
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
if (this.subscriptions[id]) {
|
||||
console.log('subscription already exists');
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscriptions[id] = this.openmct.telemetry.subscribe(
|
||||
endpoint,
|
||||
this.broadcastTelemetry.bind(this, id)
|
||||
);
|
||||
}
|
||||
|
||||
unsubscribeFromTelemetry(endpointIdentifier) {
|
||||
const id = this.openmct.objects.makeKeyString(endpointIdentifier);
|
||||
if (!this.subscriptions[id]) {
|
||||
console.log('no subscription to remove');
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.conditionResults = {};
|
||||
this.conditionClassCollection = [];
|
||||
@ -56,18 +85,13 @@ export default class ConditionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
initCondition(conditionConfiguration, index) {
|
||||
let condition = new Condition(conditionConfiguration, this.openmct);
|
||||
let condition = new Condition(conditionConfiguration, this.openmct, this);
|
||||
condition.on('conditionResultUpdated', this.handleConditionResult.bind(this));
|
||||
if (index !== undefined) {
|
||||
this.conditionClassCollection.splice(index + 1, 0, condition);
|
||||
} else {
|
||||
this.conditionClassCollection.unshift(condition);
|
||||
}
|
||||
//There are no criteria for a default condition and hence no subscriptions.
|
||||
//Hence the conditionResult must be manually triggered for it.
|
||||
if (conditionConfiguration.isDefault) {
|
||||
this.handleConditionResult();
|
||||
}
|
||||
}
|
||||
|
||||
createCondition(conditionConfiguration) {
|
||||
@ -150,18 +174,10 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.persistConditions();
|
||||
}
|
||||
|
||||
handleConditionResult(resultObj) {
|
||||
getCurrentCondition() {
|
||||
const conditionCollection = this.conditionSetDomainObject.configuration.conditionCollection;
|
||||
let currentCondition = conditionCollection[conditionCollection.length-1];
|
||||
|
||||
if (resultObj) {
|
||||
const id = resultObj.id;
|
||||
if (this.findConditionById(id)) {
|
||||
this.conditionResults[id] = resultObj.data.result;
|
||||
}
|
||||
this.updateTimestamp(resultObj.data);
|
||||
}
|
||||
|
||||
for (let i = 0; i < conditionCollection.length - 1; i++) {
|
||||
if (this.conditionResults[conditionCollection[i].id]) {
|
||||
//first condition to be true wins
|
||||
@ -169,7 +185,27 @@ export default class ConditionManager extends EventEmitter {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return currentCondition;
|
||||
}
|
||||
|
||||
updateConditionResults(resultObj) {
|
||||
if (!resultObj) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = resultObj.id;
|
||||
|
||||
if (this.findConditionById(id)) {
|
||||
this.conditionResults[id] = resultObj.data.result;
|
||||
}
|
||||
|
||||
this.updateTimestamp(resultObj.data);
|
||||
}
|
||||
|
||||
handleConditionResult(resultObj) {
|
||||
// update conditions results and then calculate the current condition
|
||||
this.updateConditionResults(resultObj);
|
||||
const currentCondition = this.getCurrentCondition();
|
||||
this.emit('conditionSetResultUpdated',
|
||||
Object.assign(
|
||||
{
|
||||
@ -192,14 +228,50 @@ export default class ConditionManager extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
requestLADConditionSetOutput() {
|
||||
if (!this.conditionClassCollection.length || this.conditionClassCollection.length === 1) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return this.compositionLoad.then(() => {
|
||||
const ladConditionResults = this.conditionClassCollection
|
||||
.map(condition => condition.requestLADConditionResult());
|
||||
|
||||
return Promise.all(ladConditionResults)
|
||||
.then((results) => {
|
||||
results.forEach(resultObj => { this.updateConditionResults(resultObj); });
|
||||
const currentCondition = this.getCurrentCondition();
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
output: currentCondition.configuration.output,
|
||||
id: this.conditionSetDomainObject.identifier,
|
||||
conditionId: currentCondition.id
|
||||
},
|
||||
this.latestTimestamp
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
broadcastTelemetry(id, datum) {
|
||||
this.emit(`broadcastTelemetry`, Object.assign({}, datum, {id: id}));
|
||||
}
|
||||
|
||||
persistConditions() {
|
||||
this.openmct.objects.mutate(this.conditionSetDomainObject, 'configuration.conditionCollection', this.conditionSetDomainObject.configuration.conditionCollection);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.composition.off('add', this.subscribeToTelemetry, this);
|
||||
this.composition.off('remove', this.unsubscribeFromTelemetry, this);
|
||||
Object.values(this.subscriptions).forEach(unsubscribe => unsubscribe());
|
||||
this.subscriptions = undefined;
|
||||
|
||||
if(this.stopObservingForChanges) {
|
||||
this.stopObservingForChanges();
|
||||
}
|
||||
|
||||
this.conditionClassCollection.forEach((condition) => {
|
||||
condition.off('conditionResultUpdated', this.handleConditionResult);
|
||||
condition.destroy();
|
||||
|
@ -47,6 +47,8 @@ describe('ConditionManager', () => {
|
||||
]
|
||||
}
|
||||
};
|
||||
let mockComposition;
|
||||
let loader;
|
||||
|
||||
function mockAngularComponents() {
|
||||
let mockInjector = jasmine.createSpyObj('$injector', ['get']);
|
||||
@ -71,9 +73,33 @@ describe('ConditionManager', () => {
|
||||
openmct.$injector = mockInjector;
|
||||
}
|
||||
|
||||
beforeAll(function () {
|
||||
beforeEach(function () {
|
||||
|
||||
mockAngularComponents();
|
||||
mockListener = jasmine.createSpy('mockListener');
|
||||
loader = {};
|
||||
loader.promise = new Promise(function (resolve, reject) {
|
||||
loader.resolve = resolve;
|
||||
loader.reject = reject;
|
||||
});
|
||||
|
||||
mockComposition = jasmine.createSpyObj('compositionCollection', [
|
||||
'load',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
mockComposition.load.and.callFake(() => {
|
||||
setTimeout(() => {
|
||||
loader.resolve();
|
||||
});
|
||||
return loader.promise;
|
||||
});
|
||||
mockComposition.on('add', mockListener);
|
||||
mockComposition.on('remove', mockListener);
|
||||
openmct.composition = jasmine.createSpyObj('compositionAPI', [
|
||||
'get'
|
||||
]);
|
||||
openmct.composition.get.and.returnValue(mockComposition);
|
||||
|
||||
openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString', 'observe', 'mutate']);
|
||||
openmct.objects.get.and.returnValues(new Promise(function (resolve, reject) {
|
||||
@ -84,10 +110,11 @@ describe('ConditionManager', () => {
|
||||
openmct.objects.makeKeyString.and.returnValue(conditionSetDomainObject.identifier.key);
|
||||
openmct.objects.observe.and.returnValue(function () {});
|
||||
openmct.objects.mutate.and.returnValue(function () {});
|
||||
|
||||
conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||
mockListener = jasmine.createSpy('mockListener');
|
||||
|
||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||
conditionMgr.on('broadcastTelemetry', mockListener);
|
||||
});
|
||||
|
||||
it('creates a conditionCollection with a default condition', function () {
|
||||
|
@ -25,27 +25,60 @@ import ConditionManager from './ConditionManager'
|
||||
export default class ConditionSetTelemetryProvider {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
this.conditionManagerPool = {};
|
||||
}
|
||||
|
||||
isTelemetryObject(domainObject) {
|
||||
return domainObject.type === 'conditionSet';
|
||||
}
|
||||
|
||||
supportsRequest(domainObject, options) {
|
||||
return false;
|
||||
supportsRequest(domainObject) {
|
||||
return domainObject.type === 'conditionSet';
|
||||
}
|
||||
|
||||
supportsSubscribe(domainObject) {
|
||||
return domainObject.type === 'conditionSet';
|
||||
}
|
||||
|
||||
request(domainObject) {
|
||||
let conditionManager = this.getConditionManager(domainObject);
|
||||
|
||||
return conditionManager.requestLADConditionSetOutput()
|
||||
.then(latestOutput => {
|
||||
return latestOutput ? [latestOutput] : [];
|
||||
});
|
||||
}
|
||||
|
||||
subscribe(domainObject, callback) {
|
||||
let conditionManager = new ConditionManager(domainObject, this.openmct);
|
||||
let conditionManager = this.getConditionManager(domainObject);
|
||||
|
||||
conditionManager.on('conditionSetResultUpdated', callback);
|
||||
|
||||
return function unsubscribe() {
|
||||
conditionManager.off('conditionSetResultUpdated');
|
||||
conditionManager.destroy();
|
||||
return this.destroyConditionManager.bind(this, this.openmct.objects.makeKeyString(domainObject.identifier));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns conditionManager instance for corresponding domain object
|
||||
* creates the instance if it is not yet created
|
||||
* @private
|
||||
*/
|
||||
getConditionManager(domainObject) {
|
||||
const id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (!this.conditionManagerPool[id]) {
|
||||
this.conditionManagerPool[id] = new ConditionManager(domainObject, this.openmct);
|
||||
}
|
||||
|
||||
return this.conditionManagerPool[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* cleans up and destroys conditionManager instance for corresponding domain object id
|
||||
* can be called manually for views that only request but do not subscribe to data
|
||||
*/
|
||||
destroyConditionManager(id) {
|
||||
this.conditionManagerPool[id].off('conditionSetResultUpdated');
|
||||
this.conditionManagerPool[id].destroy();
|
||||
delete this.conditionManagerPool[id];
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,19 @@ let openmct = {},
|
||||
mockListener,
|
||||
testConditionDefinition,
|
||||
testTelemetryObject,
|
||||
conditionObj;
|
||||
conditionObj,
|
||||
conditionManager,
|
||||
mockBroadcastTelemetry;
|
||||
|
||||
describe("The condition", function () {
|
||||
|
||||
beforeEach (() => {
|
||||
conditionManager = jasmine.createSpyObj('conditionManager',
|
||||
['on']
|
||||
);
|
||||
mockBroadcastTelemetry = jasmine.createSpy('listener');
|
||||
conditionManager.on('broadcastTelemetry', mockBroadcastTelemetry);
|
||||
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
testTelemetryObject = {
|
||||
identifier:{ namespace: "", key: "test-object"},
|
||||
@ -66,11 +74,14 @@ describe("The condition", function () {
|
||||
testConditionDefinition = {
|
||||
id: '123-456',
|
||||
configuration: {
|
||||
name: 'mock condition',
|
||||
output: 'mock output',
|
||||
trigger: TRIGGER.ANY,
|
||||
criteria: [
|
||||
{
|
||||
id: '1234-5678-9999-0000',
|
||||
operation: 'equalTo',
|
||||
input: false,
|
||||
input: ['0'],
|
||||
metadata: 'value',
|
||||
telemetry: testTelemetryObject.identifier
|
||||
}
|
||||
@ -80,14 +91,14 @@ describe("The condition", function () {
|
||||
|
||||
conditionObj = new Condition(
|
||||
testConditionDefinition,
|
||||
openmct
|
||||
openmct,
|
||||
conditionManager
|
||||
);
|
||||
|
||||
conditionObj.on('conditionUpdated', mockListener);
|
||||
|
||||
});
|
||||
|
||||
it("generates criteria with an id", function () {
|
||||
it("generates criteria with the correct properties", function () {
|
||||
const testCriterion = testConditionDefinition.configuration.criteria[0];
|
||||
let criterion = conditionObj.generateCriterion(testCriterion);
|
||||
expect(criterion.id).toBeDefined();
|
||||
@ -98,6 +109,7 @@ describe("The condition", function () {
|
||||
});
|
||||
|
||||
it("initializes with an id", function () {
|
||||
console.log(conditionObj);
|
||||
expect(conditionObj.id).toBeDefined();
|
||||
});
|
||||
|
||||
|
@ -23,18 +23,24 @@
|
||||
import EventEmitter from 'EventEmitter';
|
||||
|
||||
export default class StyleRuleManager extends EventEmitter {
|
||||
constructor(conditionalStyleConfiguration, openmct) {
|
||||
constructor(styleConfiguration, openmct, callback) {
|
||||
super();
|
||||
this.openmct = openmct;
|
||||
if (conditionalStyleConfiguration && conditionalStyleConfiguration.conditionSetIdentifier) {
|
||||
this.initialize(conditionalStyleConfiguration);
|
||||
this.subscribeToConditionSet();
|
||||
this.callback = callback;
|
||||
if (styleConfiguration) {
|
||||
this.initialize(styleConfiguration);
|
||||
if (styleConfiguration.conditionSetIdentifier) {
|
||||
this.subscribeToConditionSet();
|
||||
} else {
|
||||
this.applyStaticStyle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initialize(conditionalStyleConfiguration) {
|
||||
this.conditionSetIdentifier = conditionalStyleConfiguration.conditionSetIdentifier;
|
||||
this.updateConditionStylesMap(conditionalStyleConfiguration.styles || []);
|
||||
initialize(styleConfiguration) {
|
||||
this.conditionSetIdentifier = styleConfiguration.conditionSetIdentifier;
|
||||
this.staticStyle = styleConfiguration.staticStyle;
|
||||
this.updateConditionStylesMap(styleConfiguration.styles || []);
|
||||
}
|
||||
|
||||
subscribeToConditionSet() {
|
||||
@ -46,13 +52,14 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
updateConditionalStyleConfig(conditionalStyleConfiguration) {
|
||||
if (!conditionalStyleConfiguration || !conditionalStyleConfiguration.conditionSetIdentifier) {
|
||||
updateObjectStyleConfig(styleConfiguration) {
|
||||
if (!styleConfiguration || !styleConfiguration.conditionSetIdentifier) {
|
||||
this.initialize(styleConfiguration || {});
|
||||
this.destroy();
|
||||
} else {
|
||||
let isNewConditionSet = !this.conditionSetIdentifier ||
|
||||
this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, conditionalStyleConfiguration.conditionSetIdentifier);
|
||||
this.initialize(conditionalStyleConfiguration);
|
||||
this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
|
||||
this.initialize(styleConfiguration);
|
||||
//Only resubscribe if the conditionSet has changed.
|
||||
if (isNewConditionSet) {
|
||||
this.subscribeToConditionSet();
|
||||
@ -63,7 +70,11 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
updateConditionStylesMap(conditionStyles) {
|
||||
let conditionStyleMap = {};
|
||||
conditionStyles.forEach((conditionStyle) => {
|
||||
conditionStyleMap[conditionStyle.conditionId] = conditionStyle.style;
|
||||
if (conditionStyle.conditionId) {
|
||||
conditionStyleMap[conditionStyle.conditionId] = conditionStyle.style;
|
||||
} else {
|
||||
conditionStyleMap.static = conditionStyle.style;
|
||||
}
|
||||
});
|
||||
this.conditionalStyleMap = conditionStyleMap;
|
||||
}
|
||||
@ -74,26 +85,33 @@ export default class StyleRuleManager extends EventEmitter {
|
||||
if (foundStyle !== this.currentStyle) {
|
||||
this.currentStyle = foundStyle;
|
||||
}
|
||||
this.updateDomainObjectStyle();
|
||||
} else {
|
||||
if (this.currentStyle !== this.defaultStyle) {
|
||||
this.currentStyle = this.defaultStyle;
|
||||
}
|
||||
this.applyStaticStyle();
|
||||
}
|
||||
|
||||
this.updateDomainObjectStyle();
|
||||
}
|
||||
|
||||
updateDomainObjectStyle() {
|
||||
this.emit('conditionalStyleUpdated', this.currentStyle)
|
||||
if (this.callback) {
|
||||
this.callback(Object.assign({}, this.currentStyle));
|
||||
}
|
||||
}
|
||||
|
||||
applyStaticStyle() {
|
||||
if (this.staticStyle) {
|
||||
this.currentStyle = this.staticStyle.style;
|
||||
} else {
|
||||
if (this.currentStyle) {
|
||||
Object.keys(this.currentStyle).forEach(key => {
|
||||
this.currentStyle[key] = 'transparent';
|
||||
});
|
||||
}
|
||||
}
|
||||
this.updateDomainObjectStyle();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.currentStyle) {
|
||||
Object.keys(this.currentStyle).forEach(key => {
|
||||
this.currentStyle[key] = 'inherit';
|
||||
});
|
||||
}
|
||||
this.updateDomainObjectStyle();
|
||||
this.applyStaticStyle();
|
||||
if (this.stopProvidingTelemetry) {
|
||||
this.stopProvidingTelemetry();
|
||||
}
|
||||
|
@ -42,28 +42,15 @@
|
||||
|
||||
<span class="c-condition__name">{{ condition.configuration.name }}</span>
|
||||
<!-- TODO: description should be derived from criteria -->
|
||||
<span v-if="condition.isDefault"
|
||||
class="c-condition__summary"
|
||||
>
|
||||
When all else fails
|
||||
</span>
|
||||
<span v-else
|
||||
class="c-condition__summary"
|
||||
>
|
||||
<span class="c-condition__summary">
|
||||
<template v-if="!canEvaluateCriteria">
|
||||
Define criteria
|
||||
</template>
|
||||
<template v-else>
|
||||
When
|
||||
<span v-for="(criterion, index) in condition.configuration.criteria"
|
||||
:key="index"
|
||||
>
|
||||
{{ getRule(criterion, index) }}
|
||||
<template v-if="!isLastCriterion">
|
||||
{{ getConjunction }}
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
<span v-else>
|
||||
<condition-description :show-label="false"
|
||||
:condition="condition"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="c-condition__buttons">
|
||||
@ -179,40 +166,23 @@
|
||||
Output: {{ condition.configuration.output }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="condition.isDefault"
|
||||
class="c-condition__summary"
|
||||
>
|
||||
When all else fails
|
||||
</div>
|
||||
<div v-else
|
||||
class="c-condition__summary"
|
||||
>
|
||||
<template v-if="!canEvaluateCriteria">
|
||||
Define criteria
|
||||
</template>
|
||||
<template v-else>
|
||||
When
|
||||
<span v-for="(criterion, index) in condition.configuration.criteria"
|
||||
:key="index"
|
||||
>
|
||||
{{ getRule(criterion, index) }}
|
||||
<template v-if="!isLastCriterion">
|
||||
{{ getConjunction }}
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
<div class="c-condition__summary">
|
||||
<condition-description :show-label="false"
|
||||
:condition="condition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Criterion from './Criterion.vue';
|
||||
import { OPERATIONS } from '../utils/operations';
|
||||
import ConditionDescription from "./ConditionDescription.vue";
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
components: {
|
||||
Criterion
|
||||
Criterion,
|
||||
ConditionDescription
|
||||
},
|
||||
props: {
|
||||
condition: {
|
||||
@ -246,19 +216,17 @@ export default {
|
||||
computed: {
|
||||
canEvaluateCriteria: function () {
|
||||
let criteria = this.condition.configuration.criteria;
|
||||
let lastCriterion = criteria[criteria.length - 1];
|
||||
if (lastCriterion.telemetry &&
|
||||
lastCriterion.operation &&
|
||||
(lastCriterion.input.length ||
|
||||
lastCriterion.operation === 'isDefined' ||
|
||||
lastCriterion.operation === 'isUndefined')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
if (criteria.length) {
|
||||
let lastCriterion = criteria[criteria.length - 1];
|
||||
if (lastCriterion.telemetry &&
|
||||
lastCriterion.operation &&
|
||||
(lastCriterion.input.length ||
|
||||
lastCriterion.operation === 'isDefined' ||
|
||||
lastCriterion.operation === 'isUndefined')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
getConjunction: function () {
|
||||
return this.condition.configuration.trigger === 'all' ? 'and' : 'or';
|
||||
return false;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
@ -268,20 +236,6 @@ export default {
|
||||
this.setOutputSelection();
|
||||
},
|
||||
methods: {
|
||||
getRule(criterion, index) {
|
||||
return `${criterion.telemetry.name} ${criterion.telemetry.fieldName} ${this.findDescription(criterion.operation, criterion.input)}`;
|
||||
},
|
||||
isLastCriterion(index) {
|
||||
return index === this.condition.configuration.criteria.length - 1;
|
||||
},
|
||||
findDescription(operation, values) {
|
||||
for (let i=0, ii= OPERATIONS.length; i < ii; i++) {
|
||||
if (operation === OPERATIONS[i].name) {
|
||||
return OPERATIONS[i].getDescription(values);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
setOutputSelection() {
|
||||
let conditionOutput = this.condition.configuration.output;
|
||||
if (conditionOutput) {
|
||||
|
@ -107,6 +107,7 @@ export default {
|
||||
this.composition.off('add', this.addTelemetryObject);
|
||||
this.composition.off('remove', this.removeTelemetryObject);
|
||||
if(this.conditionManager) {
|
||||
this.conditionManager.off('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
|
||||
this.conditionManager.destroy();
|
||||
}
|
||||
if (this.stopObservingForChanges) {
|
||||
@ -121,11 +122,12 @@ export default {
|
||||
this.conditionCollection = this.domainObject.configuration.conditionCollection;
|
||||
this.observeForChanges();
|
||||
this.conditionManager = new ConditionManager(this.domainObject, this.openmct);
|
||||
this.conditionManager.on('conditionSetResultUpdated', (data) => {
|
||||
this.$emit('conditionSetResultUpdated', data);
|
||||
})
|
||||
this.conditionManager.on('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
|
||||
},
|
||||
methods: {
|
||||
handleConditionSetResultUpdated(data) {
|
||||
this.$emit('conditionSetResultUpdated', data)
|
||||
},
|
||||
observeForChanges() {
|
||||
this.stopObservingForChanges = this.openmct.objects.observe(this.domainObject, 'configuration.conditionCollection', (newConditionCollection) => {
|
||||
this.conditionCollection = newConditionCollection;
|
||||
|
123
src/plugins/condition/components/ConditionDescription.vue
Normal file
123
src/plugins/condition/components/ConditionDescription.vue
Normal file
@ -0,0 +1,123 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div class="c-style__condition-desc">
|
||||
<span v-if="showLabel && condition"
|
||||
class="c-style__condition-desc__name c-condition__name"
|
||||
>
|
||||
{{ condition.configuration.name }}
|
||||
</span>
|
||||
<span v-for="(criterionDescription, index) in criterionDescriptions"
|
||||
:key="criterionDescription"
|
||||
class="c-style__condition-desc__text"
|
||||
>
|
||||
<template v-if="!index">When</template>
|
||||
{{ criterionDescription }}
|
||||
<template v-if="index < (criterionDescriptions.length-1)">{{ triggerDescription }}</template>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TRIGGER } from "@/plugins/condition/utils/constants";
|
||||
import { OPERATIONS } from "@/plugins/condition/utils/operations";
|
||||
|
||||
export default {
|
||||
name: 'ConditionDescription',
|
||||
inject: [
|
||||
'openmct'
|
||||
],
|
||||
props: {
|
||||
showLabel: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
condition: {
|
||||
type: Object,
|
||||
default() {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
criterionDescriptions: [],
|
||||
triggerDescription: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
condition: {
|
||||
handler(val) {
|
||||
this.getConditionDescription();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getConditionDescription();
|
||||
},
|
||||
methods: {
|
||||
getConditionDescription() {
|
||||
if (this.condition) {
|
||||
this.triggerDescription = this.condition.configuration.trigger === TRIGGER.ANY ? ' or ' : ' and ';
|
||||
this.criterionDescriptions = [];
|
||||
this.condition.configuration.criteria.forEach((criterion, index) => {
|
||||
this.getCriterionDescription(criterion, index);
|
||||
});
|
||||
if (this.condition.isDefault) {
|
||||
this.criterionDescriptions.splice(0, 0, 'all else fails');
|
||||
}
|
||||
} else {
|
||||
this.criterionDescriptions = [];
|
||||
}
|
||||
},
|
||||
getCriterionDescription(criterion, index) {
|
||||
this.openmct.objects.get(criterion.telemetry).then((telemetryObject) => {
|
||||
if (telemetryObject.type === 'unknown') {
|
||||
let description = `Unknown ${criterion.metadata} ${this.getOperatorText(criterion.operation, criterion.input)}`;
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
} else {
|
||||
let metadataValue = criterion.metadata;
|
||||
if (criterion.metadata) {
|
||||
this.telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
const metadataObj = this.telemetryMetadata.valueMetadatas.find((metadata) => metadata.key === criterion.metadata);
|
||||
if (metadataObj && metadataObj.name) {
|
||||
metadataValue = metadataObj.name;
|
||||
}
|
||||
}
|
||||
let description = `${telemetryObject.name} ${metadataValue} ${this.getOperatorText(criterion.operation, criterion.input)}`;
|
||||
if (this.criterionDescriptions[index]) {
|
||||
this.criterionDescriptions[index] = description;
|
||||
} else {
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getOperatorText(operationName, values) {
|
||||
const found = OPERATIONS.find((operation) => operation.name === operationName);
|
||||
return found ? found.getDescription(values) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
80
src/plugins/condition/components/ConditionError.vue
Normal file
80
src/plugins/condition/components/ConditionError.vue
Normal file
@ -0,0 +1,80 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div v-if="conditionErrors.length"
|
||||
class="c-condition__errors"
|
||||
>
|
||||
<div v-for="(error, index) in conditionErrors"
|
||||
:key="index"
|
||||
class="u-alert u-alert--block u-alert--with-icon"
|
||||
>{{ error.message.errorText }} {{ error.additionalInfo }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { ERROR } from "@/plugins/condition/utils/constants";
|
||||
|
||||
export default {
|
||||
name: 'ConditionError',
|
||||
inject: [
|
||||
'openmct'
|
||||
],
|
||||
props: {
|
||||
condition: {
|
||||
type: Object,
|
||||
default() {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
conditionErrors: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getConditionErrors();
|
||||
},
|
||||
methods: {
|
||||
getConditionErrors() {
|
||||
if (this.condition) {
|
||||
this.condition.configuration.criteria.forEach((criterion, index) => {
|
||||
this.getCriterionErrors(criterion, index);
|
||||
});
|
||||
}
|
||||
},
|
||||
getCriterionErrors(criterion, index) {
|
||||
this.openmct.objects.get(criterion.telemetry).then((telemetryObject) => {
|
||||
if (telemetryObject.type === 'unknown') {
|
||||
this.conditionErrors.push({
|
||||
message: ERROR.TELEMETRY_NOT_FOUND,
|
||||
additionalInfo: criterion.telemetry ? `Key: ${this.openmct.objects.makeKeyString(criterion.telemetry)}` : ''
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -163,7 +163,6 @@ export default {
|
||||
if (ev) {this.clearInputs()}
|
||||
if (this.criterion.telemetry) {
|
||||
this.openmct.objects.get(this.criterion.telemetry).then((telemetryObject) => {
|
||||
this.criterion.telemetry.name = telemetryObject.name;
|
||||
this.telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
this.telemetryMetadataOptions = this.telemetryMetadata.values();
|
||||
this.updateOperations();
|
||||
@ -175,7 +174,6 @@ export default {
|
||||
},
|
||||
updateOperations(ev) {
|
||||
if (ev) {
|
||||
this.criterion.telemetry.fieldName = ev.target.options[ev.target.selectedIndex].text;
|
||||
this.clearInputs()
|
||||
}
|
||||
this.getOperationFormat();
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
.c-condition {
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
|
||||
> * + * {
|
||||
margin-top: $interiorMarginSm;
|
||||
@ -24,10 +25,13 @@
|
||||
|
||||
/***************************** HEADER */
|
||||
&__header {
|
||||
$h: 22px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: start;
|
||||
align-content: stretch;
|
||||
overflow: hidden;
|
||||
min-height: $h;
|
||||
line-height: $h;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
@ -36,6 +40,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__drag-grippy {
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
&__name {
|
||||
font-weight: bold;
|
||||
align-self: baseline; // Fixes bold line-height offset problem
|
||||
|
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<li class="c-tree__item-h">
|
||||
<div
|
||||
class="c-tree__item"
|
||||
:class="{ 'is-alias': isAlias, 'is-navigated-object': navigated }"
|
||||
@click="handleItemSelected(node.object, node)"
|
||||
>
|
||||
<view-control
|
||||
v-model="expanded"
|
||||
class="c-tree__item__view-control"
|
||||
:enabled="hasChildren"
|
||||
:propagate="false"
|
||||
/>
|
||||
<div class="c-tree__item__label c-object-label">
|
||||
<div
|
||||
class="c-tree__item__type-icon c-object-label__type-icon"
|
||||
:class="typeClass"
|
||||
></div>
|
||||
<div class="c-tree__item__name c-object-label__name">{{ node.object.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
v-if="expanded"
|
||||
class="c-tree"
|
||||
>
|
||||
<li
|
||||
v-if="isLoading && !loaded"
|
||||
class="c-tree__item-h"
|
||||
>
|
||||
<div class="c-tree__item loading">
|
||||
<span class="c-tree__item__label">Loading...</span>
|
||||
</div>
|
||||
</li>
|
||||
<condition-set-dialog-tree-item
|
||||
v-for="child in children"
|
||||
:key="child.id"
|
||||
:node="child"
|
||||
:selected-item="selectedItem"
|
||||
:handle-item-selected="handleItemSelected"
|
||||
/>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import viewControl from '@/ui/components/viewControl.vue';
|
||||
|
||||
export default {
|
||||
name: 'ConditionSetDialogTreeItem',
|
||||
inject: ['openmct'],
|
||||
components: {
|
||||
viewControl
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
selectedItem: {
|
||||
type: Object,
|
||||
default() {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
handleItemSelected: {
|
||||
type: Function,
|
||||
default() {
|
||||
return (item) => {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasChildren: false,
|
||||
isLoading: false,
|
||||
loaded: false,
|
||||
children: [],
|
||||
expanded: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
navigated() {
|
||||
const itemId = this.selectedItem && this.selectedItem.itemId;
|
||||
const isSelectedObject = itemId && this.openmct.objects.areIdsEqual(this.node.object.identifier, itemId);
|
||||
if (isSelectedObject && this.node.objectPath && this.node.objectPath.length > 1) {
|
||||
const isParent = this.openmct.objects.areIdsEqual(this.node.objectPath[1].identifier, this.selectedItem.parentId);
|
||||
return isSelectedObject && isParent;
|
||||
}
|
||||
return isSelectedObject;
|
||||
},
|
||||
isAlias() {
|
||||
let parent = this.node.objectPath[1];
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
|
||||
return parentKeyString !== this.node.object.location;
|
||||
},
|
||||
typeClass() {
|
||||
let type = this.openmct.types.get(this.node.object.type);
|
||||
if (!type) {
|
||||
return 'icon-object-unknown';
|
||||
}
|
||||
return type.definition.cssClass;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
expanded() {
|
||||
if (!this.hasChildren) {
|
||||
return;
|
||||
}
|
||||
if (!this.loaded && !this.isLoading) {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addChild);
|
||||
this.composition.on('remove', this.removeChild);
|
||||
this.composition.load().then(this.finishLoading);
|
||||
this.isLoading = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.domainObject = this.node.object;
|
||||
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
||||
this.domainObject = newObject;
|
||||
});
|
||||
|
||||
this.$once('hook:destroyed', removeListener);
|
||||
if (this.openmct.composition.get(this.node.object)) {
|
||||
this.hasChildren = true;
|
||||
}
|
||||
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.expanded = false;
|
||||
},
|
||||
destroyed() {
|
||||
if (this.composition) {
|
||||
this.composition.off('add', this.addChild);
|
||||
this.composition.off('remove', this.removeChild);
|
||||
delete this.composition;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addChild(child) {
|
||||
this.children.push({
|
||||
id: this.openmct.objects.makeKeyString(child.identifier),
|
||||
object: child,
|
||||
objectPath: [child].concat(this.node.objectPath),
|
||||
navigateToParent: this.navigateToPath
|
||||
});
|
||||
},
|
||||
removeChild(identifier) {
|
||||
let removeId = this.openmct.objects.makeKeyString(identifier);
|
||||
this.children = this.children
|
||||
.filter(c => c.id !== removeId);
|
||||
},
|
||||
finishLoading() {
|
||||
this.isLoading = false;
|
||||
this.loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<div class="u-contents">
|
||||
<div class="c-overlay__top-bar">
|
||||
<div class="c-overlay__dialog-title">Select Condition Set</div>
|
||||
</div>
|
||||
<div class="c-overlay__contents-main c-selector c-tree-and-search">
|
||||
<div class="c-tree-and-search__search">
|
||||
<search ref="shell-search"
|
||||
class="c-search"
|
||||
:value="searchValue"
|
||||
@input="searchTree"
|
||||
@clear="searchTree"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- loading -->
|
||||
<div v-if="isLoading"
|
||||
class="c-tree-and-search__loading loading"
|
||||
></div>
|
||||
<!-- end loading -->
|
||||
|
||||
<div v-if="(allTreeItems.length === 0) || (searchValue && filteredTreeItems.length === 0)"
|
||||
class="c-tree-and-search__no-results"
|
||||
>
|
||||
No results found
|
||||
</div>
|
||||
|
||||
<!-- main tree -->
|
||||
<ul v-if="!isLoading"
|
||||
v-show="!searchValue"
|
||||
class="c-tree-and-search__tree c-tree"
|
||||
>
|
||||
<condition-set-dialog-tree-item
|
||||
v-for="treeItem in allTreeItems"
|
||||
:key="treeItem.id"
|
||||
:node="treeItem"
|
||||
:selected-item="selectedItem"
|
||||
:handle-item-selected="handleItemSelection"
|
||||
/>
|
||||
</ul>
|
||||
<!-- end main tree -->
|
||||
|
||||
<!-- search tree -->
|
||||
<ul v-if="searchValue"
|
||||
class="c-tree-and-search__tree c-tree"
|
||||
>
|
||||
<condition-set-dialog-tree-item
|
||||
v-for="treeItem in filteredTreeItems"
|
||||
:key="treeItem.id"
|
||||
:node="treeItem"
|
||||
:selected-item="selectedItem"
|
||||
:handle-item-selected="handleItemSelection"
|
||||
/>
|
||||
</ul>
|
||||
<!-- end search tree -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from '@/ui/components/search.vue';
|
||||
import ConditionSetDialogTreeItem from './ConditionSetDialogTreeItem.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
name: 'ConditionSetSelectorDialog',
|
||||
components: {
|
||||
search,
|
||||
ConditionSetDialogTreeItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
searchValue: '',
|
||||
allTreeItems: [],
|
||||
filteredTreeItems: [],
|
||||
isLoading: false,
|
||||
selectedItem: undefined
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchService = this.openmct.$injector.get('searchService');
|
||||
this.getAllChildren();
|
||||
},
|
||||
methods: {
|
||||
getAllChildren() {
|
||||
this.isLoading = true;
|
||||
this.openmct.objects.get('ROOT')
|
||||
.then(root => {
|
||||
return this.openmct.composition.get(root).load()
|
||||
})
|
||||
.then(children => {
|
||||
this.isLoading = false;
|
||||
this.allTreeItems = children.map(c => {
|
||||
return {
|
||||
id: this.openmct.objects.makeKeyString(c.identifier),
|
||||
object: c,
|
||||
objectPath: [c],
|
||||
navigateToParent: '/browse'
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
getFilteredChildren() {
|
||||
this.searchService.query(this.searchValue).then(children => {
|
||||
this.filteredTreeItems = children.hits.map(child => {
|
||||
|
||||
let context = child.object.getCapability('context'),
|
||||
object = child.object.useCapability('adapter'),
|
||||
objectPath = [],
|
||||
navigateToParent;
|
||||
|
||||
if (context) {
|
||||
objectPath = context.getPath().slice(1)
|
||||
.map(oldObject => oldObject.useCapability('adapter'))
|
||||
.reverse();
|
||||
navigateToParent = '/browse/' + objectPath.slice(1)
|
||||
.map((parent) => this.openmct.objects.makeKeyString(parent.identifier))
|
||||
.join('/');
|
||||
}
|
||||
|
||||
return {
|
||||
id: this.openmct.objects.makeKeyString(object.identifier),
|
||||
object,
|
||||
objectPath,
|
||||
navigateToParent
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
searchTree(value) {
|
||||
this.searchValue = value;
|
||||
|
||||
if (this.searchValue !== '') {
|
||||
this.getFilteredChildren();
|
||||
}
|
||||
},
|
||||
handleItemSelection(item, node) {
|
||||
if (item && item.type === 'conditionSet') {
|
||||
const parentId = (node.objectPath && node.objectPath.length > 1) ? node.objectPath[1].identifier : undefined;
|
||||
this.selectedItem = {
|
||||
itemId: item.identifier,
|
||||
parentId
|
||||
};
|
||||
this.$emit('conditionSetSelected', item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="conditionStyle"
|
||||
class="holder c-c-button-wrapper align-left"
|
||||
>
|
||||
<div>{{ conditionStyle.conditionName }}</div>
|
||||
<span :style="conditionStyle.style">ABC</span>
|
||||
<toolbar-color-picker v-if="conditionStyle.style.border"
|
||||
:options="borderColorOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<toolbar-color-picker v-if="conditionStyle.style.backgroundColor"
|
||||
:options="backgroundColorOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ToolbarColorPicker from "@/ui/toolbar/components/toolbar-color-picker.vue";
|
||||
export default {
|
||||
components: {
|
||||
ToolbarColorPicker
|
||||
},
|
||||
inject: [
|
||||
'openmct'
|
||||
],
|
||||
props: {
|
||||
conditionStyle: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
condition: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
borderColorOption() {
|
||||
return {
|
||||
icon: 'icon-line-horz',
|
||||
title: 'Set border color',
|
||||
value: this.conditionStyle.style.border.replace('1px solid ', ''),
|
||||
property: 'border'
|
||||
}
|
||||
},
|
||||
backgroundColorOption() {
|
||||
return {
|
||||
icon: 'icon-paint-bucket',
|
||||
title: 'Set background color',
|
||||
value: this.conditionStyle.style.backgroundColor,
|
||||
property: 'backgroundColor'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateStyleValue(value, item) {
|
||||
if (item.property === 'border') {
|
||||
value = '1px solid ' + value;
|
||||
}
|
||||
this.conditionStyle.style[item.property] = value;
|
||||
this.$emit('persist', this.conditionStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,43 +1,117 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!conditionalStyles.length"
|
||||
class="holder c-c-button-wrapper align-left"
|
||||
>
|
||||
<button
|
||||
class="c-c-button c-c-button--minor add-criteria-button"
|
||||
@click="addConditionSet"
|
||||
>
|
||||
<span class="c-c-button__label">Use conditional styling</span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="holder c-c-button-wrapper align-left">
|
||||
<button
|
||||
class="c-c-button c-c-button--minor add-criteria-button"
|
||||
@click="removeConditionSet"
|
||||
<div class="c-inspector__styles c-inspect-styles">
|
||||
<template v-if="!conditionSetDomainObject">
|
||||
<div class="c-inspect-styles__header">
|
||||
Object Style
|
||||
</div>
|
||||
<div class="c-inspect-styles__content">
|
||||
<div v-if="staticStyle"
|
||||
class="c-inspect-styles__style"
|
||||
>
|
||||
<span class="c-c-button__label">Remove conditional styling</span>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateStaticStyle"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
id="addConditionSet"
|
||||
class="c-button c-button--major c-toggle-styling-button labeled"
|
||||
@click="addConditionSet"
|
||||
>
|
||||
<span class="c-cs-button__label">Use Conditional Styling...</span>
|
||||
</button>
|
||||
</div>
|
||||
<ul>
|
||||
<li v-for="conditionStyle in conditionalStyles"
|
||||
:key="conditionStyle.conditionId"
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="c-inspect-styles__header">
|
||||
Conditional Object Styles
|
||||
</div>
|
||||
<div class="c-inspect-styles__content c-inspect-styles__condition-set">
|
||||
<a v-if="conditionSetDomainObject"
|
||||
class="c-object-label icon-conditional"
|
||||
:href="navigateToPath"
|
||||
@click="navigateOrPreview"
|
||||
>
|
||||
<conditional-style :condition-style="conditionStyle"
|
||||
@persist="updateConditionalStyle"
|
||||
<span class="c-object-label__name">{{ conditionSetDomainObject.name }}</span>
|
||||
</a>
|
||||
<template v-if="isEditing">
|
||||
<button
|
||||
id="changeConditionSet"
|
||||
class="c-button labeled"
|
||||
@click="addConditionSet"
|
||||
>
|
||||
<span class="c-button__label">Change...</span>
|
||||
</button>
|
||||
|
||||
<button class="c-click-icon icon-x"
|
||||
title="Remove conditional styles"
|
||||
@click="removeConditionSet"
|
||||
></button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="conditionsLoaded"
|
||||
class="c-inspect-styles__conditions"
|
||||
>
|
||||
<div v-for="(conditionStyle, index) in conditionalStyles"
|
||||
:key="index"
|
||||
class="c-inspect-styles__condition"
|
||||
>
|
||||
<condition-error :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<condition-description :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ConditionalStyle from "./ConditionalStyle.vue";
|
||||
import StyleEditor from "./StyleEditor.vue";
|
||||
import ConditionSetSelectorDialog from "./ConditionSetSelectorDialog.vue";
|
||||
import ConditionDescription from "@/plugins/condition/components/ConditionDescription.vue";
|
||||
import ConditionError from "@/plugins/condition/components/ConditionError.vue";
|
||||
import Vue from 'vue';
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
|
||||
export default {
|
||||
name: 'ConditionalStylesView',
|
||||
components: {
|
||||
ConditionalStyle
|
||||
ConditionDescription,
|
||||
ConditionError,
|
||||
StyleEditor
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
@ -53,112 +127,204 @@ export default {
|
||||
default() {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
canHide: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
conditionalStyles: []
|
||||
conditionalStyles: [],
|
||||
staticStyle: undefined,
|
||||
conditionSetDomainObject: undefined,
|
||||
isEditing: this.openmct.editor.isEditing(),
|
||||
conditions: undefined,
|
||||
conditionsLoaded: false,
|
||||
navigateToPath: ''
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.openmct.editor.off('isEditing', this.setEditState);
|
||||
},
|
||||
mounted() {
|
||||
if (this.domainObject.configuration && this.domainObject.configuration.conditionalStyle) {
|
||||
if (this.itemId) {
|
||||
let conditionalStyle = this.domainObject.configuration.conditionalStyle[this.itemId];
|
||||
if (conditionalStyle) {
|
||||
this.conditionalStyles = conditionalStyle.styles || [];
|
||||
}
|
||||
} else {
|
||||
this.conditionalStyles = this.domainObject.configuration.conditionalStyle.styles || [];
|
||||
this.previewAction = new PreviewAction(this.openmct);
|
||||
if (this.domainObject.configuration && this.domainObject.configuration.objectStyles) {
|
||||
let objectStyles = this.itemId ? this.domainObject.configuration.objectStyles[this.itemId] : this.domainObject.configuration.objectStyles;
|
||||
this.initializeStaticStyle(objectStyles);
|
||||
if (objectStyles && objectStyles.conditionSetIdentifier) {
|
||||
this.openmct.objects.get(objectStyles.conditionSetIdentifier).then(this.initialize);
|
||||
this.conditionalStyles = objectStyles.styles;
|
||||
}
|
||||
} else {
|
||||
this.initializeStaticStyle();
|
||||
}
|
||||
this.openmct.editor.on('isEditing', this.setEditState);
|
||||
},
|
||||
methods: {
|
||||
addConditionSet() {
|
||||
//TODO: this.conditionSetIdentifier will be set by the UI before calling this
|
||||
this.conditionSetIdentifier = {
|
||||
namespace: '',
|
||||
key: "81088c8a-4b80-41fe-9d07-fda8b22d6f5f"
|
||||
};
|
||||
initialize(conditionSetDomainObject) {
|
||||
//If there are new conditions in the conditionSet we need to set those styles to default
|
||||
this.conditionSetDomainObject = conditionSetDomainObject;
|
||||
this.enableConditionSetNav();
|
||||
this.initializeConditionalStyles();
|
||||
},
|
||||
setEditState(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
},
|
||||
addConditionSet() {
|
||||
let conditionSetDomainObject;
|
||||
const handleItemSelection = (item) => {
|
||||
if (item) {
|
||||
conditionSetDomainObject = item;
|
||||
}
|
||||
};
|
||||
const dismissDialog = (overlay, initialize) => {
|
||||
overlay.dismiss();
|
||||
if (initialize && conditionSetDomainObject) {
|
||||
this.conditionSetDomainObject = conditionSetDomainObject;
|
||||
this.conditionalStyles = [];
|
||||
this.initializeConditionalStyles();
|
||||
}
|
||||
};
|
||||
let vm = new Vue({
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
components: {ConditionSetSelectorDialog},
|
||||
data() {
|
||||
return {
|
||||
handleItemSelection
|
||||
}
|
||||
},
|
||||
template: '<condition-set-selector-dialog @conditionSetSelected="handleItemSelection"></condition-set-selector-dialog>'
|
||||
}).$mount();
|
||||
|
||||
let overlay = this.openmct.overlays.overlay({
|
||||
element: vm.$el,
|
||||
size: 'small',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OK',
|
||||
emphasis: 'true',
|
||||
callback: () => dismissDialog(overlay, true)
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: () => dismissDialog(overlay, false)
|
||||
}
|
||||
],
|
||||
onDestroy: () => vm.$destroy()
|
||||
});
|
||||
},
|
||||
enableConditionSetNav() {
|
||||
this.openmct.objects.getOriginalPath(this.conditionSetDomainObject.identifier).then(
|
||||
(objectPath) => {
|
||||
this.objectPath = objectPath;
|
||||
this.navigateToPath = '#/browse/' + this.objectPath
|
||||
.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
|
||||
.reverse()
|
||||
.join('/');
|
||||
}
|
||||
);
|
||||
},
|
||||
navigateOrPreview(event) {
|
||||
// If editing, display condition set in Preview overlay; otherwise nav to it while browsing
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
event.preventDefault();
|
||||
this.previewAction.invoke(this.objectPath);
|
||||
}
|
||||
},
|
||||
removeConditionSet() {
|
||||
//TODO: Handle the case where domainObject has items with styles but we're trying to remove the styles on the domainObject itself
|
||||
this.conditionSetIdentifier = '';
|
||||
this.conditionSetDomainObject = undefined;
|
||||
this.conditionalStyles = [];
|
||||
let domainObjectConditionalStyle = (this.domainObject.configuration && this.domainObject.configuration.conditionalStyle) || {};
|
||||
if (domainObjectConditionalStyle) {
|
||||
if (this.itemId) {
|
||||
domainObjectConditionalStyle[this.itemId] = undefined;
|
||||
delete domainObjectConditionalStyle[this.itemId];
|
||||
} else {
|
||||
domainObjectConditionalStyle.conditionSetIdentifier = undefined;
|
||||
delete domainObjectConditionalStyle.conditionSetIdentifier;
|
||||
domainObjectConditionalStyle.styles = undefined;
|
||||
delete domainObjectConditionalStyle.styles;
|
||||
}
|
||||
if (_.isEmpty(domainObjectConditionalStyle)) {
|
||||
domainObjectConditionalStyle = undefined;
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
if (this.itemId) {
|
||||
domainObjectStyles[this.itemId].conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles[this.itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[this.itemId].styles = undefined;
|
||||
delete domainObjectStyles[this.itemId].styles;
|
||||
if (_.isEmpty(domainObjectStyles[this.itemId])) {
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
} else {
|
||||
domainObjectStyles.conditionSetIdentifier = undefined;
|
||||
delete domainObjectStyles.conditionSetIdentifier;
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
}
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
this.persist(domainObjectConditionalStyle);
|
||||
|
||||
this.persist(domainObjectStyles);
|
||||
},
|
||||
initializeConditionalStyles() {
|
||||
this.openmct.objects.get(this.conditionSetIdentifier).then((conditionSetDomainObject) => {
|
||||
conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
this.conditionalStyles.push({
|
||||
conditionId: conditionConfiguration.id,
|
||||
conditionName: conditionConfiguration.name,
|
||||
style: Object.assign({}, this.initialStyles)
|
||||
});
|
||||
});
|
||||
let domainObjectConditionalStyle = (this.domainObject.configuration && this.domainObject.configuration.conditionalStyle) || {};
|
||||
let conditionalStyle = {
|
||||
conditionSetIdentifier: this.conditionSetIdentifier,
|
||||
styles: this.conditionalStyles
|
||||
};
|
||||
if (this.itemId) {
|
||||
this.persist({
|
||||
...domainObjectConditionalStyle,
|
||||
[this.itemId]: conditionalStyle
|
||||
});
|
||||
if (!this.conditions) {
|
||||
this.conditions = {};
|
||||
}
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
this.conditions[conditionConfiguration.id] = conditionConfiguration;
|
||||
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
|
||||
if (foundStyle) {
|
||||
foundStyle.style = Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles, foundStyle.style);
|
||||
} else {
|
||||
this.persist({
|
||||
...domainObjectConditionalStyle,
|
||||
...conditionalStyle
|
||||
this.conditionalStyles.splice(index, 0, {
|
||||
conditionId: conditionConfiguration.id,
|
||||
style: Object.assign((this.canHide ? { isStyleInvisible: '' } : {}), this.initialStyles)
|
||||
});
|
||||
}
|
||||
});
|
||||
this.conditionsLoaded = true;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
initializeStaticStyle(objectStyles) {
|
||||
let staticStyle = objectStyles && objectStyles.staticStyle;
|
||||
this.staticStyle = staticStyle || {
|
||||
style: Object.assign({}, this.initialStyles)
|
||||
};
|
||||
},
|
||||
findStyleByConditionId(id) {
|
||||
return this.conditionalStyles.find(conditionalStyle => conditionalStyle.conditionId === id);
|
||||
},
|
||||
updateStaticStyle(staticStyle) {
|
||||
this.staticStyle = staticStyle;
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
},
|
||||
updateConditionalStyle(conditionStyle) {
|
||||
let found = this.findStyleByConditionId(conditionStyle.conditionId);
|
||||
if (found) {
|
||||
found.style = conditionStyle.style;
|
||||
let domainObjectConditionalStyle = this.domainObject.configuration.conditionalStyle || {};
|
||||
|
||||
if (this.itemId) {
|
||||
let itemConditionalStyle = domainObjectConditionalStyle[this.itemId];
|
||||
if (itemConditionalStyle) {
|
||||
this.persist({
|
||||
...domainObjectConditionalStyle,
|
||||
[this.itemId]: {
|
||||
...itemConditionalStyle,
|
||||
styles: this.conditionalStyles
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
domainObjectConditionalStyle.styles = this.conditionalStyles;
|
||||
this.persist(domainObjectConditionalStyle);
|
||||
}
|
||||
this.persist(this.getDomainObjectConditionalStyle());
|
||||
}
|
||||
},
|
||||
persist(conditionalStyle) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration.conditionalStyle', conditionalStyle);
|
||||
getDomainObjectConditionalStyle() {
|
||||
let objectStyle = {
|
||||
styles: this.conditionalStyles,
|
||||
staticStyle: this.staticStyle
|
||||
};
|
||||
if (this.conditionSetDomainObject) {
|
||||
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
|
||||
}
|
||||
|
||||
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
|
||||
|
||||
if (this.itemId) {
|
||||
domainObjectStyles[this.itemId] = objectStyle;
|
||||
} else {
|
||||
//we're deconstructing here to ensure that if an item within a domainObject already had a style we don't lose it
|
||||
domainObjectStyles = {
|
||||
...domainObjectStyles,
|
||||
...objectStyle
|
||||
}
|
||||
}
|
||||
|
||||
return domainObjectStyles;
|
||||
},
|
||||
getCondition(id) {
|
||||
return this.conditions ? this.conditions[id] : {};
|
||||
},
|
||||
persist(style) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration.objectStyles', style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
179
src/plugins/condition/components/inspector/StyleEditor.vue
Normal file
179
src/plugins/condition/components/inspector/StyleEditor.vue
Normal file
@ -0,0 +1,179 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div class="c-style">
|
||||
<span class="c-style-thumb"
|
||||
:class="{ 'is-style-invisible': styleItem.style.isStyleInvisible }"
|
||||
:style="[styleItem.style.imageUrl ? { backgroundImage:'url(' + styleItem.style.imageUrl + ')'} : styleItem.style ]"
|
||||
>
|
||||
<span class="c-style-thumb__text"
|
||||
:class="{ 'hide-nice': !styleItem.style.color }"
|
||||
>
|
||||
ABC
|
||||
</span>
|
||||
</span>
|
||||
<span class="c-toolbar">
|
||||
<toolbar-color-picker v-if="styleItem.style.border"
|
||||
class="c-style__toolbar-button--border-color u-menu-to--center"
|
||||
:options="borderColorOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<toolbar-color-picker v-if="styleItem.style.backgroundColor"
|
||||
class="c-style__toolbar-button--background-color u-menu-to--center"
|
||||
:options="backgroundColorOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<toolbar-color-picker v-if="styleItem.style.color"
|
||||
class="c-style__toolbar-button--color u-menu-to--center"
|
||||
:options="colorOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<toolbar-button v-if="styleItem.style.imageUrl !== undefined"
|
||||
class="c-style__toolbar-button--image-url"
|
||||
:options="imageUrlOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<toolbar-toggle-button v-if="styleItem.style.isStyleInvisible !== undefined"
|
||||
class="c-style__toolbar-button--toggle-visible"
|
||||
:options="isStyleInvisibleOption"
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ToolbarColorPicker from "@/ui/toolbar/components/toolbar-color-picker.vue";
|
||||
import ToolbarButton from "@/ui/toolbar/components/toolbar-button.vue";
|
||||
import ToolbarToggleButton from "@/ui/toolbar/components/toolbar-toggle-button.vue";
|
||||
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
||||
|
||||
export default {
|
||||
name: 'StyleEditor',
|
||||
components: {
|
||||
ToolbarButton,
|
||||
ToolbarColorPicker,
|
||||
ToolbarToggleButton
|
||||
},
|
||||
inject: [
|
||||
'openmct'
|
||||
],
|
||||
props: {
|
||||
isEditing: {
|
||||
type: Boolean
|
||||
},
|
||||
styleItem: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
borderColorOption() {
|
||||
return {
|
||||
icon: 'icon-line-horz',
|
||||
title: STYLE_CONSTANTS.borderColorTitle,
|
||||
value: this.styleItem.style.border.replace('1px solid ', ''),
|
||||
property: 'border',
|
||||
isEditing: this.isEditing
|
||||
}
|
||||
},
|
||||
backgroundColorOption() {
|
||||
return {
|
||||
icon: 'icon-paint-bucket',
|
||||
title: STYLE_CONSTANTS.backgroundColorTitle,
|
||||
value: this.styleItem.style.backgroundColor,
|
||||
property: 'backgroundColor',
|
||||
isEditing: this.isEditing
|
||||
}
|
||||
},
|
||||
colorOption() {
|
||||
return {
|
||||
icon: 'icon-font',
|
||||
title: STYLE_CONSTANTS.textColorTitle,
|
||||
value: this.styleItem.style.color,
|
||||
property: 'color',
|
||||
isEditing: this.isEditing
|
||||
}
|
||||
},
|
||||
imageUrlOption() {
|
||||
return {
|
||||
icon: 'icon-image',
|
||||
title: STYLE_CONSTANTS.imagePropertiesTitle,
|
||||
dialog: {
|
||||
name: "Image Properties",
|
||||
sections: [
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
key: "url",
|
||||
control: "textfield",
|
||||
name: "Image URL",
|
||||
"cssClass": "l-input-lg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
property: 'imageUrl',
|
||||
formKeys: ['url'],
|
||||
value: {url: this.styleItem.style.imageUrl},
|
||||
isEditing: this.isEditing
|
||||
}
|
||||
},
|
||||
isStyleInvisibleOption() {
|
||||
return {
|
||||
value: this.styleItem.style.isStyleInvisible,
|
||||
property: 'isStyleInvisible',
|
||||
isEditing: this.isEditing,
|
||||
options: [
|
||||
{
|
||||
value: '',
|
||||
icon: 'icon-eye-disabled',
|
||||
title: STYLE_CONSTANTS.visibilityHidden
|
||||
},
|
||||
{
|
||||
value: STYLE_CONSTANTS.isStyleInvisible,
|
||||
icon: 'icon-eye-open',
|
||||
title: STYLE_CONSTANTS.visibilityVisible
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateStyleValue(value, item) {
|
||||
if (item.property === 'border') {
|
||||
value = '1px solid ' + value;
|
||||
}
|
||||
if (value && (value.url !== undefined)) {
|
||||
this.styleItem.style[item.property] = value.url;
|
||||
} else {
|
||||
this.styleItem.style[item.property] = value;
|
||||
}
|
||||
this.$emit('persist', this.styleItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,100 @@
|
||||
/********************************************* INSPECTOR STYLES TAB */
|
||||
.c-inspect-styles {
|
||||
> * + * {
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
|
||||
&__content,
|
||||
&__conditions,
|
||||
&__condition {
|
||||
> * + * {
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__condition-set {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.c-object-label {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.c-button {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__style,
|
||||
&__condition {
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
|
||||
&__condition {
|
||||
@include discreteItem();
|
||||
}
|
||||
|
||||
.c-style {
|
||||
padding: 2px; // Allow a bit of room for thumb box-shadow
|
||||
|
||||
&__condition-desc {
|
||||
@include ellipsize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-inspect-styles__style {
|
||||
.is-editing & {
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
}
|
||||
}
|
||||
|
||||
.l-shell:not(.is-editing) .c-inspect-styles {
|
||||
.c-toolbar {
|
||||
// Disabled-look toolbar when not editing
|
||||
pointer-events: none;
|
||||
cursor: inherit;
|
||||
|
||||
// Hide control buttons, like image URL
|
||||
[class*='--image-url'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Make buttons look disabled by knocking back icon, not swatch element
|
||||
.c-icon-button {
|
||||
&:before {
|
||||
opacity: $controlDisabledOpacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-toggle-styling-button {
|
||||
display: none;
|
||||
|
||||
.is-editing & {
|
||||
display: block;
|
||||
align-self: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.is-style-invisible {
|
||||
display: none !important;
|
||||
|
||||
.is-editing & {
|
||||
display: block !important;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
&.c-style-thumb {
|
||||
display: block !important;
|
||||
@include bgCheckerboard($size: 10px, $imp: true);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
@ -44,33 +44,37 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
this.operation = telemetryDomainObjectDefinition.operation;
|
||||
this.input = telemetryDomainObjectDefinition.input;
|
||||
this.metadata = telemetryDomainObjectDefinition.metadata;
|
||||
this.subscription = null;
|
||||
this.telemetryObjectIdAsString = null;
|
||||
this.telemetryObjectIdAsString = undefined;
|
||||
this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj));
|
||||
}
|
||||
|
||||
initialize(obj) {
|
||||
this.telemetryObject = obj;
|
||||
this.telemetryMetaData = this.openmct.telemetry.getMetadata(obj).valueMetadatas;
|
||||
this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetryObject.identifier);
|
||||
this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry);
|
||||
this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription);
|
||||
this.emitEvent('criterionUpdated', this);
|
||||
}
|
||||
|
||||
handleSubscription(data) {
|
||||
if (data) {
|
||||
data = this.createNormalizedDatum(data);
|
||||
}
|
||||
formatData(data) {
|
||||
const normalizedDatum = this.createNormalizedDatum(data);
|
||||
const datum = {
|
||||
result: this.computeResult(data)
|
||||
};
|
||||
if (data) {
|
||||
// TODO check back to see if we should format times here
|
||||
this.timeAPI.getAllTimeSystems().forEach(timeSystem => {
|
||||
datum[timeSystem.key] = data[timeSystem.key]
|
||||
});
|
||||
result: this.computeResult(normalizedDatum)
|
||||
}
|
||||
|
||||
this.emitEvent('criterionResultUpdated', datum);
|
||||
if (normalizedDatum) {
|
||||
// TODO check back to see if we should format times here
|
||||
this.timeAPI.getAllTimeSystems().forEach(timeSystem => {
|
||||
datum[timeSystem.key] = normalizedDatum[timeSystem.key]
|
||||
});
|
||||
}
|
||||
return datum;
|
||||
}
|
||||
|
||||
handleSubscription(data) {
|
||||
if(this.isValid()) {
|
||||
this.emitEvent('criterionResultUpdated', this.formatData(data));
|
||||
}
|
||||
}
|
||||
|
||||
createNormalizedDatum(telemetryDatum) {
|
||||
@ -116,34 +120,33 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
return this.telemetryObject && this.metadata && this.operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to the telemetry object and returns an unsubscribe function
|
||||
* If the telemetry is not valid, returns nothing
|
||||
*/
|
||||
subscribe() {
|
||||
if (this.isValid()) {
|
||||
this.unsubscribe();
|
||||
this.subscription = this.telemetryAPI.subscribe(this.telemetryObject, (datum) => {
|
||||
this.handleSubscription(datum);
|
||||
});
|
||||
} else {
|
||||
this.handleSubscription();
|
||||
}
|
||||
}
|
||||
requestLAD(options) {
|
||||
options = Object.assign({},
|
||||
options,
|
||||
{
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Calls an unsubscribe function returned by subscribe() and deletes any initialized data
|
||||
*/
|
||||
unsubscribe() {
|
||||
//unsubscribe from telemetry source
|
||||
if (typeof this.subscription === 'function') {
|
||||
this.subscription();
|
||||
if (!this.isValid()) {
|
||||
return this.formatData({});
|
||||
}
|
||||
delete this.subscription;
|
||||
|
||||
return this.telemetryAPI.request(
|
||||
this.telemetryObject,
|
||||
options
|
||||
).then(results => {
|
||||
const latestDatum = results.length ? results[results.length - 1] : {};
|
||||
return {
|
||||
id: this.id,
|
||||
data: this.formatData(latestDatum)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.unsubscribe();
|
||||
this.off(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription);
|
||||
this.emitEvent('criterionRemoved');
|
||||
delete this.telemetryObjectIdAsString;
|
||||
delete this.telemetryObject;
|
||||
|
@ -78,7 +78,9 @@ describe("The telemetry criterion", function () {
|
||||
|
||||
testCriterionDefinition = {
|
||||
id: 'test-criterion-id',
|
||||
telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier)
|
||||
telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier),
|
||||
operation: 'lessThan',
|
||||
metadata: 'sin'
|
||||
};
|
||||
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
@ -102,12 +104,7 @@ describe("The telemetry criterion", function () {
|
||||
expect(mockListener2).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("subscribes to telemetry providers", function () {
|
||||
telemetryCriterion.subscribe();
|
||||
expect(telemetryCriterion.subscription).toBeDefined();
|
||||
});
|
||||
|
||||
it("emits update event on new data from telemetry providers", function () {
|
||||
it("updates and emits event on new data from telemetry providers", function () {
|
||||
telemetryCriterion.initialize(testTelemetryObject);
|
||||
spyOn(telemetryCriterion, 'emitEvent').and.callThrough();
|
||||
telemetryCriterion.handleSubscription({
|
||||
@ -115,16 +112,5 @@ describe("The telemetry criterion", function () {
|
||||
utc: 'Hi'
|
||||
});
|
||||
expect(telemetryCriterion.emitEvent).toHaveBeenCalled();
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("un-subscribes from telemetry providers", function () {
|
||||
telemetryCriterion.subscribe();
|
||||
expect(telemetryCriterion.subscription).toBeDefined();
|
||||
telemetryCriterion.destroy();
|
||||
expect(telemetryCriterion.subscription).toBeUndefined();
|
||||
expect(telemetryCriterion.telemetryObjectIdAsString).toBeUndefined();
|
||||
expect(telemetryCriterion.telemetryObject).toBeUndefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -2,3 +2,22 @@ export const TRIGGER = {
|
||||
ANY: 'any',
|
||||
ALL: 'all'
|
||||
};
|
||||
|
||||
export const STYLE_CONSTANTS = {
|
||||
isStyleInvisible: 'is-style-invisible',
|
||||
borderColorTitle: 'Set border color',
|
||||
textColorTitle: 'Set text color',
|
||||
backgroundColorTitle: 'Set background color',
|
||||
imagePropertiesTitle: 'Edit image properties',
|
||||
visibilityHidden: 'Hidden',
|
||||
visibilityVisible: 'Visible'
|
||||
};
|
||||
|
||||
export const ERROR = {
|
||||
'TELEMETRY_NOT_FOUND': {
|
||||
errorText: 'Telemetry not found for criterion'
|
||||
},
|
||||
'CONDITION_NOT_FOUND': {
|
||||
errorText: 'Condition not found'
|
||||
}
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + values[0];
|
||||
return ' is ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -20,7 +20,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + values[0];
|
||||
return ' is not ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -32,7 +32,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' > ' + values[0];
|
||||
return ' > ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -44,7 +44,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' < ' + values[0];
|
||||
return ' < ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -56,7 +56,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' >= ' + values[0];
|
||||
return ' >= ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -68,7 +68,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' <= ' + values[0];
|
||||
return ' <= ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -80,7 +80,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 2,
|
||||
getDescription: function (values) {
|
||||
return ' is between ' + values[0] + ' and ' + values[1];
|
||||
return ' is between ' + values.join(', ') + ' and ' + values[1];
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -92,7 +92,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['number'],
|
||||
inputCount: 2,
|
||||
getDescription: function (values) {
|
||||
return ' is not between ' + values[0] + ' and ' + values[1];
|
||||
return ' is not between ' + values.join(', ') + ' and ' + values[1];
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -104,7 +104,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' contains ' + values[0];
|
||||
return ' contains ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -116,7 +116,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' does not contain ' + values[0];
|
||||
return ' does not contain ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -128,7 +128,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' starts with ' + values[0];
|
||||
return ' starts with ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -140,7 +140,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' ends with ' + values[0];
|
||||
return ' ends with ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -152,7 +152,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['string'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is exactly ' + values[0];
|
||||
return ' is exactly ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -188,7 +188,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is ' + values[0];
|
||||
return ' is ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -200,7 +200,7 @@ export const OPERATIONS = [
|
||||
appliesTo: ['enum'],
|
||||
inputCount: 1,
|
||||
getDescription: function (values) {
|
||||
return ' is not ' + values[0];
|
||||
return ' is not ' + values.join(', ');
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -2,15 +2,19 @@ export const getStyleProp = (key, defaultValue) => {
|
||||
let styleProp = undefined;
|
||||
switch(key) {
|
||||
case 'fill': styleProp = {
|
||||
backgroundColor: defaultValue || 'none'
|
||||
backgroundColor: defaultValue || 'transparent'
|
||||
};
|
||||
break;
|
||||
case 'stroke': styleProp = {
|
||||
border: '1px solid ' + defaultValue || 'none'
|
||||
border: '1px solid ' + (defaultValue || 'transparent')
|
||||
};
|
||||
break;
|
||||
case 'color': styleProp = {
|
||||
color: defaultValue || 'inherit'
|
||||
color: defaultValue || 'transparent'
|
||||
};
|
||||
break;
|
||||
case 'url': styleProp = {
|
||||
imageUrl: defaultValue || 'transparent'
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
@ -23,20 +23,20 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="isEditing"
|
||||
class="c-properties"
|
||||
class="c-inspect-properties"
|
||||
>
|
||||
<div class="c-properties__header">
|
||||
<div class="c-inspect-properties__header">
|
||||
Alphanumeric Format
|
||||
</div>
|
||||
<ul class="c-properties__section">
|
||||
<li class="c-properties__row">
|
||||
<ul class="c-inspect-properties__section">
|
||||
<li class="c-inspect-properties__row">
|
||||
<div
|
||||
class="c-properties__label"
|
||||
class="c-inspect-properties__label"
|
||||
title="Printf formatting for the selected telemetry"
|
||||
>
|
||||
<label for="telemetryPrintfFormat">Format</label>
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
<input
|
||||
id="telemetryPrintfFormat"
|
||||
type="text"
|
||||
|
@ -29,6 +29,7 @@
|
||||
>
|
||||
<div
|
||||
class="c-box-view"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
</layout-frame>
|
||||
@ -36,7 +37,7 @@
|
||||
|
||||
<script>
|
||||
import LayoutFrame from './LayoutFrame.vue'
|
||||
import conditionalStylesMixin from '../mixins/conditionalStyles-mixin';
|
||||
import conditionalStylesMixin from '../mixins/objectlStyles-mixin';
|
||||
|
||||
export default {
|
||||
makeDefinition() {
|
||||
@ -73,14 +74,13 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
if (this.itemStyle) {
|
||||
return this.itemStyle;
|
||||
} else {
|
||||
return {
|
||||
backgroundColor: this.item.fill,
|
||||
border: '1px solid ' + this.item.stroke
|
||||
};
|
||||
}
|
||||
return Object.assign({
|
||||
backgroundColor: this.item.fill,
|
||||
border: '1px solid ' + this.item.stroke
|
||||
}, this.itemStyle);
|
||||
},
|
||||
styleClass() {
|
||||
return this.itemStyle && this.itemStyle.isStyleInvisible;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -29,6 +29,7 @@
|
||||
>
|
||||
<div
|
||||
class="c-image-view"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
</layout-frame>
|
||||
@ -36,7 +37,7 @@
|
||||
|
||||
<script>
|
||||
import LayoutFrame from './LayoutFrame.vue'
|
||||
import conditionalStylesMixin from "../mixins/conditionalStyles-mixin";
|
||||
import conditionalStylesMixin from "../mixins/objectlStyles-mixin";
|
||||
|
||||
export default {
|
||||
makeDefinition(openmct, gridSize, element) {
|
||||
@ -74,9 +75,12 @@ export default {
|
||||
computed: {
|
||||
style() {
|
||||
return {
|
||||
backgroundImage: 'url(' + this.item.url + ')',
|
||||
border: this.itemStyle ? this.itemStyle.border : '1px solid ' + this.item.stroke
|
||||
}
|
||||
backgroundImage: this.itemStyle ? ('url(' + this.itemStyle.imageUrl + ')') : 'url(' + this.item.url + ')',
|
||||
border: (this.itemStyle && this.itemStyle.border) ? this.itemStyle.border : ('1px solid ' + this.item.stroke)
|
||||
};
|
||||
},
|
||||
styleClass() {
|
||||
return this.itemStyle && this.itemStyle.isStyleInvisible;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -23,6 +23,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="l-layout__frame c-frame no-frame"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
>
|
||||
<svg
|
||||
@ -60,7 +61,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
import conditionalStylesMixin from "../mixins/conditionalStyles-mixin";
|
||||
import conditionalStylesMixin from "../mixins/objectlStyles-mixin";
|
||||
|
||||
const START_HANDLE_QUADRANTS = {
|
||||
1: 'c-frame-edit__handle--sw',
|
||||
@ -145,6 +146,9 @@ export default {
|
||||
height: `${height}px`
|
||||
};
|
||||
},
|
||||
styleClass() {
|
||||
return this.itemStyle && this.itemStyle.isStyleInvisible;
|
||||
},
|
||||
startHandleClass() {
|
||||
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
|
||||
},
|
||||
|
@ -36,7 +36,8 @@
|
||||
<div
|
||||
v-if="showLabel"
|
||||
class="c-telemetry-view__label"
|
||||
:style="conditionalStyle"
|
||||
:class="[styleClass]"
|
||||
:style="objectStyle"
|
||||
>
|
||||
<div class="c-telemetry-view__label-text">
|
||||
{{ domainObject.name }}
|
||||
@ -47,8 +48,8 @@
|
||||
v-if="showValue"
|
||||
:title="fieldName"
|
||||
class="c-telemetry-view__value"
|
||||
:class="[telemetryClass]"
|
||||
:style="!telemetryClass && conditionalStyle"
|
||||
:class="[telemetryClass, !telemetryClass && styleClass]"
|
||||
:style="!telemetryClass && objectStyle"
|
||||
>
|
||||
<div class="c-telemetry-view__value-text">
|
||||
{{ telemetryValue }}
|
||||
@ -113,7 +114,7 @@ export default {
|
||||
formats: undefined,
|
||||
domainObject: undefined,
|
||||
currentObjectPath: undefined,
|
||||
conditionalStyle: ''
|
||||
objectStyle: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -133,6 +134,9 @@ export default {
|
||||
fontSize: this.item.size
|
||||
}
|
||||
},
|
||||
styleClass() {
|
||||
return this.objectStyle && this.objectStyle.isStyleInvisible;
|
||||
},
|
||||
fieldName() {
|
||||
return this.valueMetadata && this.valueMetadata.name;
|
||||
},
|
||||
@ -192,7 +196,6 @@ export default {
|
||||
|
||||
if (this.styleRuleManager) {
|
||||
this.styleRuleManager.destroy();
|
||||
this.styleRuleManager.off('conditionalStyleUpdated', this.updateStyle.bind(this));
|
||||
delete this.styleRuleManager;
|
||||
}
|
||||
|
||||
@ -238,7 +241,7 @@ export default {
|
||||
},
|
||||
setObject(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.initConditionalStyles();
|
||||
this.initObjectStyles();
|
||||
this.keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
|
||||
@ -264,20 +267,27 @@ export default {
|
||||
showContextMenu(event) {
|
||||
this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
|
||||
},
|
||||
initConditionalStyles() {
|
||||
this.styleRuleManager = new StyleRuleManager(this.domainObject.configuration.conditionalStyle, this.openmct);
|
||||
this.styleRuleManager.on('conditionalStyleUpdated', this.updateStyle.bind(this));
|
||||
initObjectStyles() {
|
||||
this.styleRuleManager = new StyleRuleManager(this.domainObject.configuration.objectStyles, this.openmct, this.updateStyle.bind(this));
|
||||
|
||||
if (this.unlistenStyles) {
|
||||
this.unlistenStyles();
|
||||
}
|
||||
this.unlistenStyles = this.openmct.objects.observe(this.domainObject, 'configuration.conditionalStyle', (newConditionalStyle) => {
|
||||
//Updating conditional styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
this.styleRuleManager.updateConditionalStyleConfig(newConditionalStyle);
|
||||
this.unlistenStyles = this.openmct.objects.observe(this.domainObject, 'configuration.objectStyles', (newObjectStyle) => {
|
||||
//Updating object styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
this.styleRuleManager.updateObjectStyleConfig(newObjectStyle);
|
||||
});
|
||||
},
|
||||
updateStyle(styleObj) {
|
||||
this.conditionalStyle = styleObj;
|
||||
let keys = Object.keys(styleObj);
|
||||
keys.forEach(key => {
|
||||
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('transparent') > -1)) {
|
||||
if (styleObj[key]) {
|
||||
styleObj[key] = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
this.objectStyle = styleObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
>
|
||||
<div
|
||||
class="c-text-view"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
>
|
||||
{{ item.text }}
|
||||
@ -38,7 +39,7 @@
|
||||
|
||||
<script>
|
||||
import LayoutFrame from './LayoutFrame.vue'
|
||||
import conditionalStylesMixin from "../mixins/conditionalStyles-mixin";
|
||||
import conditionalStylesMixin from "../mixins/objectlStyles-mixin";
|
||||
|
||||
export default {
|
||||
makeDefinition(openmct, gridSize, element) {
|
||||
@ -78,16 +79,15 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
if (this.itemStyle) {
|
||||
return this.itemStyle;
|
||||
} else {
|
||||
return {
|
||||
backgroundColor: this.item.fill,
|
||||
borderColor: this.item.stroke,
|
||||
color: this.item.color,
|
||||
fontSize: this.item.size
|
||||
};
|
||||
}
|
||||
return Object.assign({
|
||||
backgroundColor: this.item.fill,
|
||||
border: '1px solid ' + this.item.stroke,
|
||||
color: this.item.color,
|
||||
fontSize: this.item.size
|
||||
}, this.itemStyle);
|
||||
},
|
||||
styleClass() {
|
||||
return this.itemStyle && this.itemStyle.isStyleInvisible;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -1,54 +0,0 @@
|
||||
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
itemStyle: this.itemStyle
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.domainObject = this.$parent.domainObject;
|
||||
this.itemId = this.item.id;
|
||||
this.conditionalStyle = this.getConditionalStyleForItem(this.domainObject.configuration.conditionalStyle);
|
||||
this.initConditionalStyles();
|
||||
},
|
||||
destroyed() {
|
||||
if (this.stopListeningConditionalStyles) {
|
||||
this.stopListeningConditionalStyles();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getConditionalStyleForItem(conditionalStyle) {
|
||||
if (conditionalStyle) {
|
||||
return conditionalStyle[this.itemId];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
initConditionalStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager(this.conditionalStyle, this.openmct);
|
||||
this.styleRuleManager.on('conditionalStyleUpdated', this.updateStyle.bind(this));
|
||||
} else {
|
||||
this.styleRuleManager.updateConditionalStyleConfig(this.conditionalStyle);
|
||||
}
|
||||
|
||||
if (this.stopListeningConditionalStyles) {
|
||||
this.stopListeningConditionalStyles();
|
||||
}
|
||||
|
||||
this.stopListeningConditionalStyles = this.openmct.objects.observe(this.domainObject, 'configuration.conditionalStyle', (newConditionalStyle) => {
|
||||
//Updating conditional styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
let newItemConditionalStyle = this.getConditionalStyleForItem(newConditionalStyle);
|
||||
if (this.conditionalStyle !== newItemConditionalStyle) {
|
||||
this.conditionalStyle = newItemConditionalStyle;
|
||||
this.styleRuleManager.updateConditionalStyleConfig(this.conditionalStyle);
|
||||
}
|
||||
});
|
||||
},
|
||||
updateStyle(style) {
|
||||
this.itemStyle = style;
|
||||
}
|
||||
}
|
||||
};
|
59
src/plugins/displayLayout/mixins/objectlStyles-mixin.js
Normal file
59
src/plugins/displayLayout/mixins/objectlStyles-mixin.js
Normal file
@ -0,0 +1,59 @@
|
||||
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
itemStyle: this.itemStyle
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.domainObject = this.$parent.domainObject;
|
||||
this.itemId = this.item.id;
|
||||
this.objectStyle = this.getObjectStyleForItem(this.domainObject.configuration.objectStyles);
|
||||
this.initObjectStyles();
|
||||
},
|
||||
destroyed() {
|
||||
if (this.stopListeningObjectStyles) {
|
||||
this.stopListeningObjectStyles();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getObjectStyleForItem(objectStyle) {
|
||||
if (objectStyle) {
|
||||
return objectStyle[this.itemId] ? Object.assign({}, objectStyle[this.itemId]) : undefined;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this));
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
|
||||
}
|
||||
|
||||
if (this.stopListeningObjectStyles) {
|
||||
this.stopListeningObjectStyles();
|
||||
}
|
||||
|
||||
this.stopListeningObjectStyles = this.openmct.objects.observe(this.domainObject, 'configuration.objectStyles', (newObjectStyle) => {
|
||||
//Updating object styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
let newItemObjectStyle = this.getObjectStyleForItem(newObjectStyle);
|
||||
if (this.objectStyle !== newItemObjectStyle) {
|
||||
this.objectStyle = newItemObjectStyle;
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
|
||||
}
|
||||
});
|
||||
},
|
||||
updateStyle(style) {
|
||||
this.itemStyle = style;
|
||||
let keys = Object.keys(this.itemStyle);
|
||||
keys.forEach((key) => {
|
||||
if ((typeof this.itemStyle[key] === 'string') && (this.itemStyle[key].indexOf('transparent') > -1)) {
|
||||
delete this.itemStyle[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="c-properties__section c-filter-settings">
|
||||
<div class="c-inspect-properties__section c-filter-settings">
|
||||
<li
|
||||
v-for="(filter, index) in filterField.filters"
|
||||
:key="index"
|
||||
class="c-properties__row c-filter-settings__setting"
|
||||
class="c-inspect-properties__row c-filter-settings__setting"
|
||||
>
|
||||
<div
|
||||
class="c-properties__label label"
|
||||
class="c-inspect-properties__label label"
|
||||
:disabled="useGlobal"
|
||||
>
|
||||
{{ filterField.name }} =
|
||||
</div>
|
||||
<div class="c-properties__value value">
|
||||
<div class="c-inspect-properties__value value">
|
||||
<!-- EDITING -->
|
||||
<!-- String input, editing -->
|
||||
<template v-if="!filter.possibleValues && isEditing">
|
||||
|
@ -26,17 +26,17 @@
|
||||
</div>
|
||||
|
||||
<div v-if="expanded">
|
||||
<ul class="c-properties">
|
||||
<ul class="c-inspect-properties">
|
||||
<div
|
||||
v-if="!isEditing && persistedFilters.useGlobal"
|
||||
class="c-properties__label span-all"
|
||||
class="c-inspect-properties__label span-all"
|
||||
>
|
||||
Uses global filter
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="isEditing"
|
||||
class="c-properties__label span-all"
|
||||
class="c-inspect-properties__label span-all"
|
||||
>
|
||||
<toggle-switch
|
||||
:id="keyString"
|
||||
|
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
<ul
|
||||
v-if="expanded"
|
||||
class="c-properties"
|
||||
class="c-inspect-properties"
|
||||
>
|
||||
<filter-field
|
||||
v-for="metadatum in globalMetadata"
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
.c-filter-tree {
|
||||
// Filters UI uses a tree-based structure
|
||||
.c-properties {
|
||||
.c-inspect-properties {
|
||||
// Add extra margin to account for filter-indicator
|
||||
margin-left: 38px;
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="c-properties">
|
||||
<div class="c-inspect-properties">
|
||||
<template v-if="isEditing">
|
||||
<div class="c-properties__header">
|
||||
<div class="c-inspect-properties__header">
|
||||
Table Column Size
|
||||
</div>
|
||||
<ul class="c-properties__section">
|
||||
<li class="c-properties__row">
|
||||
<ul class="c-inspect-properties__section">
|
||||
<li class="c-inspect-properties__row">
|
||||
<div
|
||||
class="c-properties__label"
|
||||
class="c-inspect-properties__label"
|
||||
title="Auto-size table"
|
||||
>
|
||||
<label for="AutoSizeControl">Auto-size</label>
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
<input
|
||||
id="AutoSizeControl"
|
||||
type="checkbox"
|
||||
@ -22,22 +22,22 @@
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="c-properties__header">
|
||||
<div class="c-inspect-properties__header">
|
||||
Table Column Visibility
|
||||
</div>
|
||||
<ul class="c-properties__section">
|
||||
<ul class="c-inspect-properties__section">
|
||||
<li
|
||||
v-for="(title, key) in headers"
|
||||
:key="key"
|
||||
class="c-properties__row"
|
||||
class="c-inspect-properties__row"
|
||||
>
|
||||
<div
|
||||
class="c-properties__label"
|
||||
class="c-inspect-properties__label"
|
||||
title="Show or hide column"
|
||||
>
|
||||
<label :for="key + 'ColumnControl'">{{ title }}</label>
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
<input
|
||||
:id="key + 'ColumnControl'"
|
||||
type="checkbox"
|
||||
|
@ -100,10 +100,12 @@ $colorStatusErrorFilter: invert(10%) sepia(96%) saturate(4360%) hue-rotate(351de
|
||||
$colorStatusBtnBg: #666; // Where is this used?
|
||||
$colorStatusPartialBg: #3f5e8b;
|
||||
$colorStatusCompleteBg: #457638;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorAlert: #ff8a0d;
|
||||
$colorAlertFg: #fff;
|
||||
$colorWarningHi: #ff0000;
|
||||
$colorWarningHiFg: #ffdad0;
|
||||
$colorError: #ff3c00;
|
||||
$colorErrorFg: #fff;
|
||||
$colorWarningHi: #990000;
|
||||
$colorWarningHiFg: #FF9594;
|
||||
$colorWarningLo: #ff9900;
|
||||
$colorWarningLoFg: #523400;
|
||||
$colorDiagnostic: #a4b442;
|
||||
@ -215,6 +217,7 @@ $colorSelectBg: $colorBtnBg; // This must be a solid color, not a gradient, due
|
||||
$colorSelectFg: $colorBtnFg;
|
||||
$colorSelectArw: lighten($colorBtnBg, 20%);
|
||||
$shdwSelect: rgba(black, 0.5) 0 0.5px 3px;
|
||||
$controlDisabledOpacity: 0.2;
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: pullForward($colorBodyBg, 15%);
|
||||
@ -320,7 +323,7 @@ $shdwItemText: none;
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderBg: rgba($colorBodyFg, 0.2);
|
||||
$colorTabHeaderFg: $colorBodyFg;
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
|
@ -104,10 +104,12 @@ $colorStatusErrorFilter: invert(10%) sepia(96%) saturate(4360%) hue-rotate(351de
|
||||
$colorStatusBtnBg: #666; // Where is this used?
|
||||
$colorStatusPartialBg: #3f5e8b;
|
||||
$colorStatusCompleteBg: #457638;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorAlert: #ff8a0d;
|
||||
$colorAlertFg: #fff;
|
||||
$colorWarningHi: #ff0000;
|
||||
$colorWarningHiFg: #ffdad0;
|
||||
$colorError: #ff3c00;
|
||||
$colorErrorFg: #fff;
|
||||
$colorWarningHi: #990000;
|
||||
$colorWarningHiFg: #FF9594;
|
||||
$colorWarningLo: #ff9900;
|
||||
$colorWarningLoFg: #523400;
|
||||
$colorDiagnostic: #a4b442;
|
||||
@ -219,6 +221,7 @@ $colorSelectBg: $colorBtnBg; // This must be a solid color, not a gradient, due
|
||||
$colorSelectFg: $colorBtnFg;
|
||||
$colorSelectArw: lighten($colorBtnBg, 20%);
|
||||
$shdwSelect: rgba(black, 0.5) 0 0.5px 3px;
|
||||
$controlDisabledOpacity: 0.2;
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: pullForward($colorBodyBg, 15%);
|
||||
@ -324,7 +327,7 @@ $shdwItemText: none;
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderBg: rgba($colorBodyFg, 0.2);
|
||||
$colorTabHeaderFg: $colorBodyFg;
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
|
@ -100,8 +100,10 @@ $colorStatusErrorFilter: invert(8%) sepia(96%) saturate(4511%) hue-rotate(352deg
|
||||
$colorStatusBtnBg: #666; // Where is this used?
|
||||
$colorStatusPartialBg: #c9d6ff;
|
||||
$colorStatusCompleteBg: #a4e4b4;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorAlert: #ff8a0d;
|
||||
$colorAlertFg: #fff;
|
||||
$colorError: #ff3c00;
|
||||
$colorErrorFg: #fff;
|
||||
$colorWarningHi: #990000;
|
||||
$colorWarningHiFg: #FF9594;
|
||||
$colorWarningLo: #ff9900;
|
||||
@ -215,6 +217,7 @@ $colorSelectBg: $colorBtnBg; // This must be a solid color, not a gradient, due
|
||||
$colorSelectFg: $colorBtnFg;
|
||||
$colorSelectArw: lighten($colorBtnBg, 20%);
|
||||
$shdwSelect: none;
|
||||
$controlDisabledOpacity: 0.3;
|
||||
|
||||
// Menus
|
||||
$colorMenuBg: pushBack($colorBodyBg, 10%);
|
||||
@ -320,8 +323,8 @@ $shdwItemText: none;
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
$colorTabHeaderFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: rgba($colorBodyFg, 0.2);
|
||||
$colorTabHeaderFg: $colorBodyFg;
|
||||
$colorTabHeaderBorder: $colorBodyBg;
|
||||
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
|
||||
$colorTabGroupHeaderFg: pullForward($colorTabGroupHeaderBg, 40%);
|
||||
|
@ -94,9 +94,6 @@ $tableResizeColHitareaD: 6px;
|
||||
$mobileMenuIconD: 24px; // Used
|
||||
$mobileTreeItemH: 35px; // Used
|
||||
|
||||
/************************** VISUAL */
|
||||
$controlDisabledOpacity: 0.5;
|
||||
|
||||
/************************** UI ELEMENTS */
|
||||
/*************** Progress Bar */
|
||||
$colorProgressBarHolder: rgba(black, 0.1);
|
||||
@ -148,6 +145,7 @@ $glyph-icon-filter-outline: '\e927';
|
||||
$glyph-icon-suitcase: '\e928';
|
||||
$glyph-icon-cursor-lock: '\e929';
|
||||
$glyph-icon-flag: '\e92a';
|
||||
$glyph-icon-eye-disabled: '\e92b';
|
||||
$glyph-icon-arrows-right-left: '\ea00';
|
||||
$glyph-icon-arrows-up-down: '\ea01';
|
||||
$glyph-icon-bullet: '\ea02';
|
||||
|
@ -229,6 +229,7 @@ section {
|
||||
|
||||
&.is-expanded {
|
||||
flex: 1 1 100%;
|
||||
max-height: max-content;
|
||||
}
|
||||
|
||||
.c-section__header {
|
||||
@ -785,7 +786,25 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************** SLIDERS */
|
||||
/******************************************************** STYLE EDITING */
|
||||
.c-style {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
|
||||
> * + * { margin-left: $interiorMargin; }
|
||||
}
|
||||
|
||||
.c-style-thumb {
|
||||
background-size: cover;
|
||||
border: 1px solid transparent;
|
||||
border-radius: $basicCr;
|
||||
box-shadow: rgba($colorBodyFg, 0.4) 0 0 3px;
|
||||
flex: 0 0 auto;
|
||||
padding: $interiorMargin $interiorMarginLg;
|
||||
}
|
||||
|
||||
/******************************************************** SLIDERS */
|
||||
.c-slider {
|
||||
@include cControl();
|
||||
> * + * { margin-left: $interiorMargin; }
|
||||
|
@ -35,6 +35,22 @@ div {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.u-menu-to {
|
||||
&--left {
|
||||
.c-menu {
|
||||
left: auto !important;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--center {
|
||||
.c-menu {
|
||||
left: 50% !important;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.u-space {
|
||||
// Provides a separator space between elements
|
||||
&--right {
|
||||
|
@ -82,6 +82,7 @@
|
||||
.icon-suitcase { @include glyphBefore($glyph-icon-suitcase); }
|
||||
.icon-cursor-lock { @include glyphBefore($glyph-icon-cursor-lock); }
|
||||
.icon-flag { @include glyphBefore($glyph-icon-flag); }
|
||||
.icon-eye-disabled { @include glyphBefore($glyph-icon-eye-disabled); }
|
||||
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
|
||||
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
|
||||
.icon-bullet { @include glyphBefore($glyph-icon-bullet); }
|
||||
|
@ -67,15 +67,12 @@
|
||||
}
|
||||
|
||||
&__object-name--w {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
@include headerFont(1.4em);
|
||||
min-width: 0;
|
||||
|
||||
&:before {
|
||||
// Icon
|
||||
opacity: 0.5;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,24 @@
|
||||
background-size: $bgSize;
|
||||
}
|
||||
|
||||
@mixin bgCheckerboard($c: $colorBodyFg, $opacity: 0.3, $size: 32px, $imp: false) {
|
||||
$color: rgba($c, $opacity);
|
||||
$bgPos: floor($size / 2);
|
||||
|
||||
$impStr: null;
|
||||
@if $imp {
|
||||
$impStr: !important;
|
||||
}
|
||||
|
||||
background-image:
|
||||
linear-gradient(45deg, $color 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, $color 75%),
|
||||
linear-gradient(45deg, transparent 75%, $color 75%),
|
||||
linear-gradient(45deg, $color 25%, transparent 25%) $impStr;
|
||||
background-size: $size $size;
|
||||
background-position:0 0, 0 0, -1*$bgPos -1*$bgPos, $bgPos $bgPos;
|
||||
}
|
||||
|
||||
@mixin disabled() {
|
||||
opacity: $controlDisabledOpacity;
|
||||
pointer-events: none !important;
|
||||
@ -403,9 +421,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@mixin cClickIcon() {
|
||||
@include cControl();
|
||||
color: $colorBodyFg;
|
||||
cursor: pointer;
|
||||
padding: 4px; // Bigger hit area
|
||||
opacity: 0.6;
|
||||
|
@ -40,7 +40,7 @@
|
||||
display: inline-block;
|
||||
font-family: symbolsfont;
|
||||
font-size: 0.8em;
|
||||
margin-right: $interiorMargin;
|
||||
margin-right: $interiorMarginSm;
|
||||
@if $glyph != null {
|
||||
content: $glyph $impStr;
|
||||
}
|
||||
@ -71,6 +71,30 @@
|
||||
&.is-limit--lwr:before { content: $glyph-icon-arrow-down !important; }
|
||||
}
|
||||
|
||||
@mixin uIndicator($bg, $fg, $glyph) {
|
||||
background: $bg;
|
||||
color: $fg;
|
||||
|
||||
&[class*='--with-icon'] {
|
||||
&:before {
|
||||
color: $fg;
|
||||
display: inline-block;
|
||||
font-family: symbolsfont;
|
||||
margin-right: $interiorMarginSm;
|
||||
@if $glyph != null {
|
||||
content: $glyph;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[class*='--block'] {
|
||||
border-radius: $controlCr;
|
||||
display: inline-block;
|
||||
padding: 2px $interiorMargin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*************************************************** STYLES */
|
||||
*:not(tr) {
|
||||
&.is-limit--yellow {
|
||||
@ -173,3 +197,5 @@ tr {
|
||||
}
|
||||
}
|
||||
|
||||
.u-alert { @include uIndicator($colorAlert, $colorAlertFg, $glyph-icon-alert-triangle); }
|
||||
.u-error { @include uIndicator($colorError, $colorErrorFg, $glyph-icon-alert-triangle); }
|
||||
|
@ -2,7 +2,7 @@
|
||||
"metadata": {
|
||||
"name": "Open MCT Symbols 16px",
|
||||
"lastOpened": 0,
|
||||
"created": 1581619121103
|
||||
"created": 1585006719465
|
||||
},
|
||||
"iconSets": [
|
||||
{
|
||||
@ -351,13 +351,21 @@
|
||||
"code": 59690,
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 177,
|
||||
"id": 152,
|
||||
"name": "icon-eye-disabled",
|
||||
"prevSize": 24,
|
||||
"code": 59691,
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 27,
|
||||
"id": 105,
|
||||
"name": "icon-arrows-right-left",
|
||||
"prevSize": 24,
|
||||
"code": 59904,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 26,
|
||||
@ -365,7 +373,7 @@
|
||||
"name": "icon-arrows-up-down",
|
||||
"prevSize": 24,
|
||||
"code": 59905,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 68,
|
||||
@ -373,7 +381,7 @@
|
||||
"name": "icon-bullet",
|
||||
"prevSize": 24,
|
||||
"code": 59906,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 150,
|
||||
@ -381,7 +389,7 @@
|
||||
"prevSize": 24,
|
||||
"code": 59907,
|
||||
"name": "icon-calendar",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 45,
|
||||
@ -389,7 +397,7 @@
|
||||
"name": "icon-chain-links",
|
||||
"prevSize": 24,
|
||||
"code": 59908,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 73,
|
||||
@ -397,7 +405,7 @@
|
||||
"name": "icon-download",
|
||||
"prevSize": 24,
|
||||
"code": 59909,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 39,
|
||||
@ -405,7 +413,7 @@
|
||||
"name": "icon-duplicate",
|
||||
"prevSize": 24,
|
||||
"code": 59910,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 50,
|
||||
@ -413,7 +421,7 @@
|
||||
"name": "icon-folder-new",
|
||||
"prevSize": 24,
|
||||
"code": 59911,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 138,
|
||||
@ -421,7 +429,7 @@
|
||||
"name": "icon-fullscreen-collapse",
|
||||
"prevSize": 24,
|
||||
"code": 59912,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 139,
|
||||
@ -429,7 +437,7 @@
|
||||
"name": "icon-fullscreen-expand",
|
||||
"prevSize": 24,
|
||||
"code": 59913,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 122,
|
||||
@ -437,7 +445,7 @@
|
||||
"name": "icon-layers",
|
||||
"prevSize": 24,
|
||||
"code": 59914,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 151,
|
||||
@ -445,7 +453,7 @@
|
||||
"name": "icon-line-horz",
|
||||
"prevSize": 24,
|
||||
"code": 59915,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 100,
|
||||
@ -453,7 +461,7 @@
|
||||
"name": "icon-magnify",
|
||||
"prevSize": 24,
|
||||
"code": 59916,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 99,
|
||||
@ -461,7 +469,7 @@
|
||||
"name": "icon-magnify-in",
|
||||
"prevSize": 24,
|
||||
"code": 59917,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 101,
|
||||
@ -469,7 +477,7 @@
|
||||
"name": "icon-magnify-out-v2",
|
||||
"prevSize": 24,
|
||||
"code": 59918,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 103,
|
||||
@ -477,7 +485,7 @@
|
||||
"name": "icon-menu",
|
||||
"prevSize": 24,
|
||||
"code": 59919,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 124,
|
||||
@ -485,7 +493,7 @@
|
||||
"name": "icon-move",
|
||||
"prevSize": 24,
|
||||
"code": 59920,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 7,
|
||||
@ -493,7 +501,7 @@
|
||||
"name": "icon-new-window",
|
||||
"prevSize": 24,
|
||||
"code": 59921,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 63,
|
||||
@ -501,7 +509,7 @@
|
||||
"name": "icon-paint-bucket-v2",
|
||||
"prevSize": 24,
|
||||
"code": 59922,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 15,
|
||||
@ -509,7 +517,7 @@
|
||||
"name": "icon-pencil",
|
||||
"prevSize": 24,
|
||||
"code": 59923,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 54,
|
||||
@ -517,7 +525,7 @@
|
||||
"name": "icon-pencil-edit-in-place",
|
||||
"prevSize": 24,
|
||||
"code": 59924,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 40,
|
||||
@ -525,7 +533,7 @@
|
||||
"name": "icon-play",
|
||||
"prevSize": 24,
|
||||
"code": 59925,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 125,
|
||||
@ -533,7 +541,7 @@
|
||||
"name": "icon-pause",
|
||||
"prevSize": 24,
|
||||
"code": 59926,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 119,
|
||||
@ -541,7 +549,7 @@
|
||||
"name": "icon-plot-resource",
|
||||
"prevSize": 24,
|
||||
"code": 59927,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 48,
|
||||
@ -549,7 +557,7 @@
|
||||
"name": "icon-pointer-left",
|
||||
"prevSize": 24,
|
||||
"code": 59928,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 47,
|
||||
@ -557,7 +565,7 @@
|
||||
"name": "icon-pointer-right",
|
||||
"prevSize": 24,
|
||||
"code": 59929,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 85,
|
||||
@ -565,7 +573,7 @@
|
||||
"name": "icon-refresh",
|
||||
"prevSize": 24,
|
||||
"code": 59930,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 55,
|
||||
@ -573,7 +581,7 @@
|
||||
"name": "icon-save",
|
||||
"prevSize": 24,
|
||||
"code": 59931,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 56,
|
||||
@ -581,7 +589,7 @@
|
||||
"name": "icon-save-as",
|
||||
"prevSize": 24,
|
||||
"code": 59932,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 58,
|
||||
@ -589,7 +597,7 @@
|
||||
"name": "icon-sine",
|
||||
"prevSize": 24,
|
||||
"code": 59933,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 113,
|
||||
@ -597,7 +605,7 @@
|
||||
"name": "icon-font",
|
||||
"prevSize": 24,
|
||||
"code": 59934,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 41,
|
||||
@ -605,7 +613,7 @@
|
||||
"name": "icon-thumbs-strip",
|
||||
"prevSize": 24,
|
||||
"code": 59935,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 146,
|
||||
@ -613,7 +621,7 @@
|
||||
"name": "icon-two-parts-both",
|
||||
"prevSize": 24,
|
||||
"code": 59936,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 145,
|
||||
@ -621,7 +629,7 @@
|
||||
"name": "icon-two-parts-one-only",
|
||||
"prevSize": 24,
|
||||
"code": 59937,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 82,
|
||||
@ -629,7 +637,7 @@
|
||||
"name": "icon-resync",
|
||||
"prevSize": 24,
|
||||
"code": 59938,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 86,
|
||||
@ -637,7 +645,7 @@
|
||||
"name": "icon-reset",
|
||||
"prevSize": 24,
|
||||
"code": 59939,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 61,
|
||||
@ -645,7 +653,7 @@
|
||||
"name": "icon-x-in-circle",
|
||||
"prevSize": 24,
|
||||
"code": 59940,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 84,
|
||||
@ -653,7 +661,7 @@
|
||||
"name": "icon-brightness",
|
||||
"prevSize": 24,
|
||||
"code": 59941,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 83,
|
||||
@ -661,7 +669,7 @@
|
||||
"name": "icon-contrast",
|
||||
"prevSize": 24,
|
||||
"code": 59942,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 87,
|
||||
@ -669,7 +677,7 @@
|
||||
"name": "icon-expand",
|
||||
"prevSize": 24,
|
||||
"code": 59943,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 89,
|
||||
@ -677,7 +685,7 @@
|
||||
"name": "icon-list-view",
|
||||
"prevSize": 24,
|
||||
"code": 59944,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 133,
|
||||
@ -685,7 +693,7 @@
|
||||
"name": "icon-grid-snap-to",
|
||||
"prevSize": 24,
|
||||
"code": 59945,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 132,
|
||||
@ -693,7 +701,7 @@
|
||||
"name": "icon-grid-snap-no",
|
||||
"prevSize": 24,
|
||||
"code": 59946,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 94,
|
||||
@ -701,7 +709,7 @@
|
||||
"name": "icon-frame-show",
|
||||
"prevSize": 24,
|
||||
"code": 59947,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 95,
|
||||
@ -709,7 +717,7 @@
|
||||
"name": "icon-frame-hide",
|
||||
"prevSize": 24,
|
||||
"code": 59948,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 97,
|
||||
@ -717,7 +725,7 @@
|
||||
"name": "icon-import",
|
||||
"prevSize": 24,
|
||||
"code": 59949,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 96,
|
||||
@ -725,7 +733,7 @@
|
||||
"name": "icon-export",
|
||||
"prevSize": 24,
|
||||
"code": 59950,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 114,
|
||||
@ -733,7 +741,7 @@
|
||||
"name": "icon-font-size",
|
||||
"prevSize": 24,
|
||||
"code": 59951,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 163,
|
||||
@ -741,7 +749,7 @@
|
||||
"name": "icon-clear-data",
|
||||
"prevSize": 24,
|
||||
"code": 59952,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 173,
|
||||
@ -749,7 +757,7 @@
|
||||
"name": "icon-history",
|
||||
"prevSize": 24,
|
||||
"code": 59953,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 144,
|
||||
@ -757,7 +765,7 @@
|
||||
"name": "icon-activity",
|
||||
"prevSize": 24,
|
||||
"code": 60160,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 104,
|
||||
@ -765,7 +773,7 @@
|
||||
"name": "icon-activity-mode",
|
||||
"prevSize": 24,
|
||||
"code": 60161,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 137,
|
||||
@ -773,7 +781,7 @@
|
||||
"name": "icon-autoflow-tabular",
|
||||
"prevSize": 24,
|
||||
"code": 60162,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 115,
|
||||
@ -781,7 +789,7 @@
|
||||
"name": "icon-clock",
|
||||
"prevSize": 24,
|
||||
"code": 60163,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 2,
|
||||
@ -789,7 +797,7 @@
|
||||
"name": "icon-database",
|
||||
"prevSize": 24,
|
||||
"code": 60164,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 3,
|
||||
@ -797,7 +805,7 @@
|
||||
"name": "icon-database-query",
|
||||
"prevSize": 24,
|
||||
"code": 60165,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 67,
|
||||
@ -805,7 +813,7 @@
|
||||
"name": "icon-dataset",
|
||||
"prevSize": 24,
|
||||
"code": 60166,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 59,
|
||||
@ -813,7 +821,7 @@
|
||||
"name": "icon-datatable",
|
||||
"prevSize": 24,
|
||||
"code": 60167,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 136,
|
||||
@ -821,7 +829,7 @@
|
||||
"name": "icon-dictionary",
|
||||
"prevSize": 24,
|
||||
"code": 60168,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 51,
|
||||
@ -829,7 +837,7 @@
|
||||
"name": "icon-folder",
|
||||
"prevSize": 24,
|
||||
"code": 60169,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 147,
|
||||
@ -837,7 +845,7 @@
|
||||
"name": "icon-image",
|
||||
"prevSize": 24,
|
||||
"code": 60170,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 4,
|
||||
@ -845,7 +853,7 @@
|
||||
"name": "icon-layout",
|
||||
"prevSize": 24,
|
||||
"code": 60171,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 24,
|
||||
@ -853,7 +861,7 @@
|
||||
"name": "icon-object",
|
||||
"prevSize": 24,
|
||||
"code": 60172,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 52,
|
||||
@ -861,7 +869,7 @@
|
||||
"name": "icon-object-unknown",
|
||||
"prevSize": 24,
|
||||
"code": 60173,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 105,
|
||||
@ -869,7 +877,7 @@
|
||||
"name": "icon-packet",
|
||||
"prevSize": 24,
|
||||
"code": 60174,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 126,
|
||||
@ -877,7 +885,7 @@
|
||||
"name": "icon-page",
|
||||
"prevSize": 24,
|
||||
"code": 60175,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 130,
|
||||
@ -885,7 +893,7 @@
|
||||
"name": "icon-plot-overlay",
|
||||
"prevSize": 24,
|
||||
"code": 60176,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 80,
|
||||
@ -893,7 +901,7 @@
|
||||
"name": "icon-plot-stacked",
|
||||
"prevSize": 24,
|
||||
"code": 60177,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 134,
|
||||
@ -901,7 +909,7 @@
|
||||
"name": "icon-session",
|
||||
"prevSize": 24,
|
||||
"code": 60178,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 109,
|
||||
@ -909,7 +917,7 @@
|
||||
"name": "icon-tabular",
|
||||
"prevSize": 24,
|
||||
"code": 60179,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 107,
|
||||
@ -917,7 +925,7 @@
|
||||
"name": "icon-tabular-lad",
|
||||
"prevSize": 24,
|
||||
"code": 60180,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 106,
|
||||
@ -925,7 +933,7 @@
|
||||
"name": "icon-tabular-lad-set",
|
||||
"prevSize": 24,
|
||||
"code": 60181,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 70,
|
||||
@ -933,7 +941,7 @@
|
||||
"name": "icon-tabular-realtime",
|
||||
"prevSize": 24,
|
||||
"code": 60182,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 60,
|
||||
@ -941,7 +949,7 @@
|
||||
"name": "icon-tabular-scrolling",
|
||||
"prevSize": 24,
|
||||
"code": 60183,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 131,
|
||||
@ -949,7 +957,7 @@
|
||||
"name": "icon-telemetry",
|
||||
"prevSize": 24,
|
||||
"code": 60184,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 108,
|
||||
@ -957,7 +965,7 @@
|
||||
"name": "icon-timeline",
|
||||
"prevSize": 24,
|
||||
"code": 60185,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 81,
|
||||
@ -965,7 +973,7 @@
|
||||
"name": "icon-timer",
|
||||
"prevSize": 24,
|
||||
"code": 60186,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 69,
|
||||
@ -973,7 +981,7 @@
|
||||
"name": "icon-topic",
|
||||
"prevSize": 24,
|
||||
"code": 60187,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 79,
|
||||
@ -981,7 +989,7 @@
|
||||
"name": "icon-box-with-dashed-lines-v2",
|
||||
"prevSize": 24,
|
||||
"code": 60188,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 90,
|
||||
@ -989,7 +997,7 @@
|
||||
"name": "icon-summary-widget",
|
||||
"prevSize": 24,
|
||||
"code": 60189,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 92,
|
||||
@ -997,7 +1005,7 @@
|
||||
"name": "icon-notebook",
|
||||
"prevSize": 24,
|
||||
"code": 60190,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 168,
|
||||
@ -1005,7 +1013,7 @@
|
||||
"name": "icon-tabs-view",
|
||||
"prevSize": 24,
|
||||
"code": 60191,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 117,
|
||||
@ -1013,7 +1021,7 @@
|
||||
"name": "icon-flexible-layout",
|
||||
"prevSize": 24,
|
||||
"code": 60192,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 166,
|
||||
@ -1021,7 +1029,7 @@
|
||||
"name": "icon-generator-sine",
|
||||
"prevSize": 24,
|
||||
"code": 60193,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 167,
|
||||
@ -1029,7 +1037,7 @@
|
||||
"name": "icon-generator-event",
|
||||
"prevSize": 24,
|
||||
"code": 60194,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 165,
|
||||
@ -1037,7 +1045,7 @@
|
||||
"name": "icon-gauge-v2",
|
||||
"prevSize": 24,
|
||||
"code": 60195,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 170,
|
||||
@ -1045,7 +1053,7 @@
|
||||
"name": "icon-spectra",
|
||||
"prevSize": 24,
|
||||
"code": 60196,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 171,
|
||||
@ -1053,7 +1061,7 @@
|
||||
"name": "icon-telemetry-spectra",
|
||||
"prevSize": 24,
|
||||
"code": 60197,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 172,
|
||||
@ -1061,7 +1069,7 @@
|
||||
"name": "icon-pushbutton",
|
||||
"prevSize": 24,
|
||||
"code": 60198,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 174,
|
||||
@ -1069,7 +1077,7 @@
|
||||
"name": "icon-conditional",
|
||||
"prevSize": 24,
|
||||
"code": 60199,
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
}
|
||||
],
|
||||
"id": 0,
|
||||
@ -1644,6 +1652,25 @@
|
||||
"isMulticolor": false,
|
||||
"isMulticolor2": false
|
||||
},
|
||||
{
|
||||
"id": 152,
|
||||
"paths": [
|
||||
"M209.46 608.68q-7.46-9.86-14.26-20.28c-14.737-21.984-27.741-47.184-37.759-73.847l-0.841-2.553c11.078-29.259 24.068-54.443 39.51-77.869l-0.91 1.469c23.221-34.963 50.705-64.8 82.207-89.793l0.793-0.607c57.663-45.719 130.179-75.053 209.311-79.947l1.069-0.053 114.48-140.88c-27.366-5.017-58.869-7.898-91.041-7.92l-0.019-0c-245.8 0-452.2 168-510.8 395.6 21.856 82.93 60.906 154.847 113.325 214.773l-0.525-0.613z",
|
||||
"M814.76 415.080q7.52 10 14.44 20.52c14.737 21.984 27.741 47.184 37.759 73.847l0.841 2.553c-10.859 29.216-23.863 54.416-39.447 77.748l0.847-1.348c-23.221 34.963-50.705 64.8-82.207 89.793l-0.793 0.607c-57.762 45.834-130.437 75.216-209.743 80.049l-1.057 0.051-114.46 140.86c27.346 4.988 58.817 7.84 90.955 7.84 0.037 0 0.074-0 0.111-0l-0.005 0c245.8 0 452.2-168 510.8-395.6-21.856-82.93-60.906-154.847-113.325-214.773l0.525 0.613z",
|
||||
"M832 0l-832 1024h192l832-1024h-192z"
|
||||
],
|
||||
"attrs": [
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"isMulticolor2": false,
|
||||
"grid": 16,
|
||||
"tags": [
|
||||
"icon-eye-disabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 105,
|
||||
"paths": [
|
||||
|
1
src/styles/fonts/Open-MCT-Symbols-16px.svg
Executable file → Normal file
1
src/styles/fonts/Open-MCT-Symbols-16px.svg
Executable file → Normal file
@ -50,6 +50,7 @@
|
||||
<glyph unicode="" glyph-name="icon-suitcase" d="M768 704c-0.080 70.66-57.34 127.92-127.993 128h-256.007c-70.66-0.080-127.92-57.34-128-127.993v-128.007h-64v-768h640v768h-64zM384 703.88l0.12 0.12 255.88-0.12v-127.88h-256zM0 512v-640c0.102-35.305 28.695-63.898 63.99-64h64.010v768h-64c-35.305-0.102-63.898-28.695-64-63.99v-0.010zM960 576h-64v-768h64c35.305 0.102 63.898 28.695 64 63.99v640.010c-0.102 35.305-28.695 63.898-63.99 64h-0.010z" />
|
||||
<glyph unicode="" glyph-name="icon-cursor-locked" horiz-adv-x="768" d="M704 512h-64v64c0 141.385-114.615 256-256 256s-256-114.615-256-256v0-64h-64c-35.301-0.113-63.887-28.699-64-63.989v-576.011c0.113-35.301 28.699-63.887 63.989-64h640.011c35.301 0.113 63.887 28.699 64 63.989v576.011c-0.113 35.301-28.699 63.887-63.989 64h-0.011zM256 576c0 70.692 57.308 128 128 128s128-57.308 128-128v0-64h-256zM533.4-64l-128 128-43-85-170.4 383.6 383.6-170.2-85-43 128-128z" />
|
||||
<glyph unicode="" glyph-name="icon-flag" d="M192 192h832l-192 320 192 320h-896c-70.606-0.215-127.785-57.394-128-127.979v-896.021h192z" />
|
||||
<glyph unicode="" glyph-name="icon-eye-disabled" d="M209.46 223.32q-7.46 9.86-14.26 20.28c-14.737 21.984-27.741 47.184-37.759 73.847l-0.841 2.553c11.078 29.259 24.068 54.443 39.51 77.869l-0.91-1.469c23.221 34.963 50.705 64.8 82.207 89.793l0.793 0.607c57.663 45.719 130.179 75.053 209.311 79.947l1.069 0.053 114.48 140.88c-27.366 5.017-58.869 7.898-91.041 7.92h-0.019c-245.8 0-452.2-168-510.8-395.6 21.856-82.93 60.906-154.847 113.325-214.773l-0.525 0.613zM814.76 416.92q7.52-10 14.44-20.52c14.737-21.984 27.741-47.184 37.759-73.847l0.841-2.553c-10.859-29.216-23.863-54.416-39.447-77.748l0.847 1.348c-23.221-34.963-50.705-64.8-82.207-89.793l-0.793-0.607c-57.762-45.834-130.437-75.216-209.743-80.049l-1.057-0.051-114.46-140.86c27.346-4.988 58.817-7.84 90.955-7.84 0.037 0 0.074 0 0.111 0h-0.005c245.8 0 452.2 168 510.8 395.6-21.856 82.93-60.906 154.847-113.325 214.773l0.525-0.613zM832 832l-832-1024h192l832 1024h-192z" />
|
||||
<glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 320l-448-512v1024zM448 832l-448-512 448-512z" />
|
||||
<glyph unicode="" glyph-name="icon-arrows-up-down" d="M512 832l512-448h-1024zM0 256l512-448 512 448z" />
|
||||
<glyph unicode="" glyph-name="icon-bullet" d="M832 80c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
|
||||
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
BIN
src/styles/fonts/Open-MCT-Symbols-16px.ttf
Executable file → Normal file
BIN
src/styles/fonts/Open-MCT-Symbols-16px.ttf
Executable file → Normal file
Binary file not shown.
BIN
src/styles/fonts/Open-MCT-Symbols-16px.woff
Executable file → Normal file
BIN
src/styles/fonts/Open-MCT-Symbols-16px.woff
Executable file → Normal file
Binary file not shown.
@ -2,6 +2,7 @@
|
||||
@import "../api/overlays/components/overlay-component.scss";
|
||||
@import "../plugins/condition/components/condition.scss";
|
||||
@import "../plugins/condition/components/condition-set.scss";
|
||||
@import "../plugins/condition/components/inspector/conditional-styles.scss";
|
||||
@import "../plugins/displayLayout/components/box-view.scss";
|
||||
@import "../plugins/displayLayout/components/display-layout.scss";
|
||||
@import "../plugins/displayLayout/components/edit-marquee.scss";
|
||||
|
@ -5,6 +5,7 @@
|
||||
<script>
|
||||
import _ from "lodash"
|
||||
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
||||
|
||||
export default {
|
||||
inject: ["openmct"],
|
||||
@ -37,13 +38,12 @@ export default {
|
||||
this.unlisten();
|
||||
}
|
||||
|
||||
if (this.stopListeningConditionalStyles) {
|
||||
this.stopListeningConditionalStyles();
|
||||
if (this.stopListeningStyles) {
|
||||
this.stopListeningStyles();
|
||||
}
|
||||
|
||||
if (this.styleRuleManager) {
|
||||
this.styleRuleManager.destroy();
|
||||
this.styleRuleManager.off('conditionalStyleUpdated', this.updateStyle.bind(this));
|
||||
delete this.styleRuleManager;
|
||||
}
|
||||
},
|
||||
@ -60,7 +60,7 @@ export default {
|
||||
this.$el.addEventListener('drop', this.addObjectToParent);
|
||||
if (this.currentObject) {
|
||||
//This is to apply styles to subobjects in a layout
|
||||
this.initConditionalStyles();
|
||||
this.initObjectStyles();
|
||||
}
|
||||
|
||||
},
|
||||
@ -102,8 +102,19 @@ export default {
|
||||
}
|
||||
let keys = Object.keys(styleObj);
|
||||
keys.forEach(key => {
|
||||
this.$el.style[key] = styleObj[key];
|
||||
})
|
||||
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('transparent') > -1)) {
|
||||
if (this.$el.style[key]) {
|
||||
this.$el.style[key] = '';
|
||||
}
|
||||
} else {
|
||||
if (!styleObj.isStyleInvisible && this.$el.classList.contains(STYLE_CONSTANTS.isStyleInvisible)) {
|
||||
this.$el.classList.remove(STYLE_CONSTANTS.isStyleInvisible);
|
||||
} else if (styleObj.isStyleInvisible && !this.$el.classList.contains(styleObj.isStyleInvisible)) {
|
||||
this.$el.classList.add(styleObj.isStyleInvisible);
|
||||
}
|
||||
this.$el.style[key] = styleObj[key];
|
||||
}
|
||||
});
|
||||
},
|
||||
updateView(immediatelySelect) {
|
||||
this.clear();
|
||||
@ -181,25 +192,24 @@ export default {
|
||||
|
||||
this.viewKey = viewKey;
|
||||
|
||||
this.initConditionalStyles();
|
||||
this.initObjectStyles();
|
||||
|
||||
this.updateView(immediatelySelect);
|
||||
},
|
||||
initConditionalStyles() {
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager((this.currentObject.configuration && this.currentObject.configuration.conditionalStyle), this.openmct);
|
||||
this.styleRuleManager.on('conditionalStyleUpdated', this.updateStyle.bind(this));
|
||||
this.styleRuleManager = new StyleRuleManager((this.currentObject.configuration && this.currentObject.configuration.objectStyles), this.openmct, this.updateStyle.bind(this));
|
||||
} else {
|
||||
this.styleRuleManager.updateConditionalStyleConfig(this.currentObject.configuration && this.currentObject.configuration.conditionalStyle);
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.currentObject.configuration && this.currentObject.configuration.objectStyles);
|
||||
}
|
||||
|
||||
if (this.stopListeningConditionalStyles) {
|
||||
this.stopListeningConditionalStyles();
|
||||
if (this.stopListeningStyles) {
|
||||
this.stopListeningStyles();
|
||||
}
|
||||
|
||||
this.stopListeningConditionalStyles = this.openmct.objects.observe(this.currentObject, 'configuration.conditionalStyle', (newConditionalStyle) => {
|
||||
//Updating conditional styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
this.styleRuleManager.updateConditionalStyleConfig(newConditionalStyle);
|
||||
this.stopListeningStyles = this.openmct.objects.observe(this.currentObject, 'configuration.objectStyles', (newObjectStyle) => {
|
||||
//Updating styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
this.styleRuleManager.updateObjectStyleConfig(newObjectStyle);
|
||||
});
|
||||
},
|
||||
loadComposition() {
|
||||
|
@ -1,28 +1,42 @@
|
||||
.c-object-label {
|
||||
// <a> tag and draggable element that holds type icon and name.
|
||||
// Used mostly in trees and lists
|
||||
border-radius: $controlCr;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
flex: 0 1 auto;
|
||||
overflow: hidden;
|
||||
padding: $interiorMarginSm 1px;
|
||||
white-space: nowrap;
|
||||
|
||||
&__name {
|
||||
@include ellipsize();
|
||||
display: inline;
|
||||
color: $colorItemTreeFg;
|
||||
}
|
||||
|
||||
&__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;
|
||||
opacity: 0.6;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.c-tree .c-object-label {
|
||||
border-radius: $controlCr;
|
||||
padding: $interiorMarginSm 1px;
|
||||
|
||||
&__name {
|
||||
display: inline;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__type-icon {
|
||||
// Type icon. Must be an HTML entity to allow inclusion of alias indicator.
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
font-size: 1.3em;
|
||||
margin-right: $interiorMarginSm;
|
||||
color: $colorItemTreeIcon;
|
||||
font-size: 1.25em;
|
||||
margin-right: $interiorMarginSm;
|
||||
opacity: 1;
|
||||
width: $treeTypeIconW;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
'c-disclosure-triangle--expanded' : value,
|
||||
'is-enabled' : enabled
|
||||
}"
|
||||
@click="$emit('input', !value)"
|
||||
@click="handleClick"
|
||||
></span>
|
||||
</template>
|
||||
|
||||
@ -21,6 +21,18 @@ export default {
|
||||
// Used as such in the tree - when a node doesn't have children, set disabled to true.
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
propagate: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
this.$emit('input', !this.value);
|
||||
if (!this.propagate) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,40 @@
|
||||
<template>
|
||||
<div class="c-inspector">
|
||||
<div class="c-inspector__tabs">
|
||||
<div v-if="showStyles"
|
||||
class="c-inspector__tabs__holder"
|
||||
<object-name />
|
||||
<div v-if="showStyles"
|
||||
class="c-inspector__tabs c-tabs"
|
||||
>
|
||||
<div v-for="tabbedView in tabbedViews"
|
||||
:key="tabbedView.key"
|
||||
class="c-inspector__tab c-tab"
|
||||
:class="{'is-current': isCurrent(tabbedView)}"
|
||||
@click="updateCurrentTab(tabbedView)"
|
||||
>
|
||||
<div v-for="tabbedView in tabbedViews"
|
||||
:key="tabbedView.key"
|
||||
class="c-inspector__tabs__header"
|
||||
@click="updateCurrentTab(tabbedView)"
|
||||
>
|
||||
<span class="c-inspector__tabs__label c-tab"
|
||||
:class="{'is-current': isCurrent(tabbedView)}"
|
||||
>{{ tabbedView.name }}</span>
|
||||
</div>
|
||||
{{ tabbedView.name }}
|
||||
</div>
|
||||
<div class="c-inspector__tabs__contents">
|
||||
<multipane v-if="currentTabbedView.key === '__properties'"
|
||||
class="c-inspector"
|
||||
type="vertical"
|
||||
>
|
||||
<pane class="c-inspector__properties">
|
||||
<properties />
|
||||
<location />
|
||||
<inspector-views />
|
||||
</pane>
|
||||
<pane
|
||||
v-if="isEditing && hasComposition"
|
||||
class="c-inspector__elements"
|
||||
handle="before"
|
||||
label="Elements"
|
||||
>
|
||||
<elements />
|
||||
</pane>
|
||||
</multipane>
|
||||
<pane v-else
|
||||
class="c-inspector__styles"
|
||||
>
|
||||
<styles-inspector-view />
|
||||
|
||||
</div>
|
||||
<div class="c-inspector__content">
|
||||
<multipane v-if="currentTabbedView.key === '__properties'"
|
||||
type="vertical"
|
||||
>
|
||||
<pane class="c-inspector__properties">
|
||||
<properties />
|
||||
<location />
|
||||
<inspector-views />
|
||||
</pane>
|
||||
</div>
|
||||
<pane
|
||||
v-if="isEditing && hasComposition"
|
||||
class="c-inspector__elements"
|
||||
handle="before"
|
||||
label="Elements"
|
||||
>
|
||||
<elements />
|
||||
</pane>
|
||||
</multipane>
|
||||
<template v-else>
|
||||
<styles-inspector-view />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -49,6 +45,7 @@ import pane from '../layout/pane.vue';
|
||||
import Elements from './Elements.vue';
|
||||
import Location from './Location.vue';
|
||||
import Properties from './Properties.vue';
|
||||
import ObjectName from './ObjectName.vue';
|
||||
import InspectorViews from './InspectorViews.vue';
|
||||
import _ from "lodash";
|
||||
import StylesInspectorView from "./StylesInspectorView.vue";
|
||||
@ -62,6 +59,7 @@ export default {
|
||||
pane,
|
||||
Elements,
|
||||
Properties,
|
||||
ObjectName,
|
||||
Location,
|
||||
InspectorViews
|
||||
},
|
||||
@ -112,7 +110,10 @@ export default {
|
||||
let type = this.openmct.types.get(object.type);
|
||||
this.showStyles = (this.excludeObjectTypes.indexOf(object.type) < 0) && type.definition.creatable;
|
||||
}
|
||||
this.updateCurrentTab(this.tabbedViews[0]);
|
||||
if (!this.currentTabbedView.key || (!this.showStyles && this.currentTabbedView.key === this.tabbedViews[1].key))
|
||||
{
|
||||
this.updateCurrentTab(this.tabbedViews[0]);
|
||||
}
|
||||
}
|
||||
},
|
||||
updateCurrentTab(view) {
|
||||
|
@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<div class="c-properties c-properties--location">
|
||||
<div class="c-inspect-properties c-inspect-properties--location">
|
||||
<div
|
||||
class="c-properties__header"
|
||||
class="c-inspect-properties__header"
|
||||
title="The location of this linked object."
|
||||
>
|
||||
Original Location
|
||||
</div>
|
||||
<ul
|
||||
v-if="!multiSelect"
|
||||
class="c-properties__section"
|
||||
class="c-inspect-properties__section"
|
||||
>
|
||||
<li
|
||||
v-if="originalPath.length"
|
||||
class="c-properties__row"
|
||||
class="c-inspect-properties__row"
|
||||
>
|
||||
<ul class="c-properties__value c-location">
|
||||
<ul class="c-inspect-properties__value c-location">
|
||||
<li
|
||||
v-for="pathObject in orderedOriginalPath"
|
||||
:key="pathObject.key"
|
||||
@ -30,7 +30,7 @@
|
||||
</ul>
|
||||
<div
|
||||
v-if="multiSelect"
|
||||
class="c-properties__row--span-all"
|
||||
class="c-inspect-properties__row--span-all"
|
||||
>
|
||||
No location to display for multiple items
|
||||
</div>
|
||||
|
76
src/ui/inspector/ObjectName.vue
Normal file
76
src/ui/inspector/ObjectName.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="c-inspector__header">
|
||||
<div v-if="!multiSelect && !singleSelectNonObject"
|
||||
class="c-inspector__selected-w c-object-label"
|
||||
:class="typeCssClass"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
{{ itemsSelected }} items selected
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
domainObject: {},
|
||||
multiSelect: false,
|
||||
itemsSelected: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
item() {
|
||||
return this.domainObject || {};
|
||||
},
|
||||
type() {
|
||||
return this.openmct.types.get(this.item.type);
|
||||
},
|
||||
typeCssClass() {
|
||||
if (this.type.definition.cssClass === undefined) {
|
||||
return 'icon-object';
|
||||
}
|
||||
return this.type.definition.cssClass;
|
||||
},
|
||||
singleSelectNonObject() {
|
||||
return !this.item.identifier && !this.multiSelect;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.selection.on('change', this.updateSelection);
|
||||
this.updateSelection(this.openmct.selection.get());
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.openmct.selection.off('change', this.updateSelection);
|
||||
},
|
||||
methods: {
|
||||
updateSelection(selection) {
|
||||
if (selection.length === 0 || selection[0].length === 0) {
|
||||
this.domainObject = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection.length > 1) {
|
||||
this.multiSelect = true;
|
||||
this.domainObject = {};
|
||||
this.itemsSelected = selection.length;
|
||||
return;
|
||||
} else {
|
||||
this.multiSelect = false;
|
||||
this.domainObject = selection[0][0].context.item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,72 +1,72 @@
|
||||
<template>
|
||||
<div class="c-properties c-properties--properties">
|
||||
<div class="c-properties__header">
|
||||
Properties
|
||||
<div class="c-inspector__properties c-inspect-properties">
|
||||
<div class="c-inspect-properties__header">
|
||||
Details
|
||||
</div>
|
||||
<ul
|
||||
v-if="!multiSelect && !singleSelectNonObject"
|
||||
class="c-properties__section"
|
||||
class="c-inspect-properties__section"
|
||||
>
|
||||
<li class="c-properties__row">
|
||||
<div class="c-properties__label">
|
||||
<li class="c-inspect-properties__row">
|
||||
<div class="c-inspect-properties__label">
|
||||
Title
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="c-properties__row">
|
||||
<div class="c-properties__label">
|
||||
<li class="c-inspect-properties__row">
|
||||
<div class="c-inspect-properties__label">
|
||||
Type
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ typeName }}
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
v-if="item.created"
|
||||
class="c-properties__row"
|
||||
class="c-inspect-properties__row"
|
||||
>
|
||||
<div class="c-properties__label">
|
||||
<div class="c-inspect-properties__label">
|
||||
Created
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ formatTime(item.created) }}
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
v-if="item.modified"
|
||||
class="c-properties__row"
|
||||
class="c-inspect-properties__row"
|
||||
>
|
||||
<div class="c-properties__label">
|
||||
<div class="c-inspect-properties__label">
|
||||
Modified
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ formatTime(item.modified) }}
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
v-for="prop in typeProperties"
|
||||
:key="prop.name"
|
||||
class="c-properties__row"
|
||||
class="c-inspect-properties__row"
|
||||
>
|
||||
<div class="c-properties__label">
|
||||
<div class="c-inspect-properties__label">
|
||||
{{ prop.name }}
|
||||
</div>
|
||||
<div class="c-properties__value">
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ prop.value }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
v-if="multiSelect"
|
||||
class="c-properties__row--span-all"
|
||||
class="c-inspect-properties__row--span-all"
|
||||
>
|
||||
No properties to display for multiple items
|
||||
</div>
|
||||
<div
|
||||
v-if="singleSelectNonObject"
|
||||
class="c-properties__row--span-all"
|
||||
class="c-inspect-properties__row--span-all"
|
||||
>
|
||||
No properties to display for this item
|
||||
</div>
|
||||
|
@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div class="u-contents"></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import ConditionalStylesView from '../../plugins/condition/components/inspector/ConditionalStylesView.vue';
|
||||
import Vue from 'vue';
|
||||
@ -34,17 +31,18 @@ export default {
|
||||
},
|
||||
updateSelection(selection) {
|
||||
if (selection.length > 0 && selection[0].length > 0) {
|
||||
let isChildItem = false;
|
||||
let domainObject = selection[0][0].context.item;
|
||||
let layoutItem = {};
|
||||
let styleProps = this.getStyleProperties({
|
||||
fill: 'inherit',
|
||||
stroke: 'inherit',
|
||||
color: 'inherit'
|
||||
fill: 'transparent',
|
||||
stroke: 'transparent',
|
||||
color: 'transparent'
|
||||
});
|
||||
if (selection[0].length > 1) {
|
||||
isChildItem = true;
|
||||
//If there are more than 1 items in the selection[0] list, the first one could either be a sub domain object OR a layout drawing control.
|
||||
//The second item in the selection[0] list is the container object (usually a layout)
|
||||
domainObject = selection[0][0].context.item;
|
||||
if (!domainObject) {
|
||||
styleProps = {};
|
||||
layoutItem = selection[0][0].context.layoutItem;
|
||||
@ -58,7 +56,6 @@ export default {
|
||||
this.component = undefined;
|
||||
this.$el.innerHTML = '';
|
||||
}
|
||||
|
||||
let viewContainer = document.createElement('div');
|
||||
this.$el.append(viewContainer);
|
||||
this.component = new Vue({
|
||||
@ -73,10 +70,11 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
layoutItem,
|
||||
styleProps
|
||||
styleProps,
|
||||
isChildItem
|
||||
}
|
||||
},
|
||||
template: '<conditional-styles-view :item-id="layoutItem.id" :initial-styles="styleProps"></conditional-styles-view>'
|
||||
template: '<conditional-styles-view :can-hide="isChildItem" :item-id="layoutItem.id" :initial-styles="styleProps"></conditional-styles-view>'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,46 @@
|
||||
.c-inspector {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
|
||||
> [class*="__"] {
|
||||
min-height: 50px;
|
||||
> * {
|
||||
// Thi is on purpose: want extra margin on top object-name element
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
|
||||
+ [class*="__"] {
|
||||
margin-top: $interiorMargin;
|
||||
&__selected-w,
|
||||
&__multiple-selected-w {
|
||||
@include headerFont(1.1em);
|
||||
padding: $interiorMarginSm 0;
|
||||
}
|
||||
|
||||
&__multiple-selected-w {
|
||||
$p: $interiorMarginLg;
|
||||
background: rgba($colorWarningLo, 0.3);
|
||||
border-radius: $basicCr;
|
||||
display: inline-block;
|
||||
font-style: italic;
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
}
|
||||
|
||||
&__selected {
|
||||
@include ellipsize();
|
||||
flex: 1 1 auto;
|
||||
|
||||
&--non-domain-object {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
> .l-pane__contents {
|
||||
overflow: auto;
|
||||
&__tabs {
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.8em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
> * {
|
||||
// Fend off scrollbar
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
&__content {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&__elements {
|
||||
@ -58,67 +83,41 @@
|
||||
margin-left: $treeItemIndent;
|
||||
}
|
||||
|
||||
&__tabs {
|
||||
$h: 20px;
|
||||
@include abs();
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
|
||||
> * + * {
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
|
||||
&__holder {
|
||||
display: flex;
|
||||
min-height: $h;
|
||||
|
||||
&__header {
|
||||
|
||||
&:before {
|
||||
margin-right: $interiorMarginSm;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__contents {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&--hidden {
|
||||
height: 1000px;
|
||||
width: 1000px;
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
}
|
||||
.l-multipane {
|
||||
.l-pane {
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-properties {
|
||||
display: grid;
|
||||
grid-row-gap: 0;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
align-items: start;
|
||||
min-width: 150px;
|
||||
|
||||
.c-inspect-properties,
|
||||
.c-inspect-styles {
|
||||
[class*="header"] {
|
||||
@include propertiesHeader();
|
||||
flex: 0 0 auto;
|
||||
font-size: .85em;
|
||||
text-transform: uppercase;
|
||||
|
||||
&:not(:first-child) {
|
||||
// Allow multiple headers within a component
|
||||
margin-top: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************************* INSPECTOR PROPERTIES TAB */
|
||||
.c-inspect-properties {
|
||||
display: grid;
|
||||
grid-row-gap: $interiorMarginSm;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
align-items: start;
|
||||
min-width: 150px;
|
||||
|
||||
[class*="span-all"],
|
||||
[class*="header"] {
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
|
||||
+ .c-properties {
|
||||
+ .c-inspect-properties {
|
||||
margin-top: $interiorMarginLg;
|
||||
}
|
||||
|
||||
@ -136,11 +135,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
font-size: .85em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&__label,
|
||||
&__value {
|
||||
padding: 3px $interiorMarginLg 3px 0;
|
||||
@ -164,6 +158,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************* LEGACY SUPPORT */
|
||||
.c-inspector {
|
||||
// FilterField.vue
|
||||
|
@ -7,11 +7,11 @@
|
||||
@click="goToParent"
|
||||
></button>
|
||||
<div
|
||||
class="l-browse-bar__object-name--w"
|
||||
class="l-browse-bar__object-name--w c-object-label"
|
||||
:class="type.cssClass"
|
||||
>
|
||||
<span
|
||||
class="l-browse-bar__object-name c-input-inline"
|
||||
class="l-browse-bar__object-name c-object-label__name c-input-inline"
|
||||
contenteditable
|
||||
@blur="updateName"
|
||||
@keydown.enter.prevent
|
||||
|
@ -35,9 +35,15 @@
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&__pane-tree,
|
||||
&__pane-main {
|
||||
.l-pane__contents {
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
|
||||
+ * {
|
||||
margin-top: $interiorMarginLg;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
.c-tree-and-search {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
padding-right: $interiorMarginSm;
|
||||
overflow: auto;
|
||||
|
||||
@ -136,3 +137,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-selector {
|
||||
.c-tree-and-search__tree.c-tree {
|
||||
border: 1px solid $colorInteriorBorder;
|
||||
border-radius: $controlCr;
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,9 @@
|
||||
|
||||
&--vertical {
|
||||
height: 100%;
|
||||
> .l-pane .l-pane__contents {
|
||||
padding-right: $interiorMarginSm; // Fend off scrollbar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,9 +93,6 @@
|
||||
// Don't pad all nested __contents
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> [class*="__"] + [class*="__"] {
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************ DESKTOP STYLES */
|
||||
@ -263,6 +263,8 @@
|
||||
}
|
||||
|
||||
&[class*="--vertical"] {
|
||||
// l-pane--vertical
|
||||
|
||||
> .l-pane__handle {
|
||||
cursor: row-resize;
|
||||
left: 0;
|
||||
|
@ -36,7 +36,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onClick(event) {
|
||||
if (this.options.dialog) {
|
||||
if ((this.options.isEditing === undefined || this.options.isEditing) && this.options.dialog) {
|
||||
this.openmct.$injector.get('dialogService')
|
||||
.getUserInput(this.options.dialog, this.options.value)
|
||||
.then(value => {
|
||||
|
@ -4,7 +4,7 @@
|
||||
class="c-icon-button c-icon-button--swatched"
|
||||
:class="[options.icon, {'c-icon-button--mixed': nonSpecific}]"
|
||||
:title="options.title"
|
||||
@click="toggle"
|
||||
@click="handleClick"
|
||||
>
|
||||
<div
|
||||
class="c-swatch"
|
||||
@ -146,6 +146,11 @@ export default {
|
||||
if (color.value !== this.options.value) {
|
||||
this.$emit('change', color.value, this.options);
|
||||
}
|
||||
},
|
||||
handleClick(event) {
|
||||
if ((this.options.isEditing === undefined) || this.options.isEditing) {
|
||||
this.toggle(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
cycle() {
|
||||
this.$emit('change', this.nextValue.value, this.options);
|
||||
if (this.options.isEditing === undefined || this.options.isEditing) {
|
||||
this.$emit('change', this.nextValue.value, this.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user