diff --git a/copyright-notice.html b/copyright-notice.html index 2e323d1e392..ffcbb9a4e18 100644 --- a/copyright-notice.html +++ b/copyright-notice.html @@ -1,5 +1,5 @@ \ No newline at end of file +--> diff --git a/copyright-notice.js b/copyright-notice.js index 82fd0deeb42..dc566ef7eb9 100644 --- a/copyright-notice.js +++ b/copyright-notice.js @@ -1,5 +1,5 @@ /***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government + * Open MCT, Copyright (c) 2014-2020, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * @@ -18,4 +18,4 @@ * 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. - *****************************************************************************/ \ No newline at end of file + *****************************************************************************/ diff --git a/example/generator/GeneratorMetadataProvider.js b/example/generator/GeneratorMetadataProvider.js index ae62f748620..f9618abc156 100644 --- a/example/generator/GeneratorMetadataProvider.js +++ b/example/generator/GeneratorMetadataProvider.js @@ -9,7 +9,8 @@ define([ values: [ { key: "name", - name: "Name" + name: "Name", + format: "string" }, { key: "utc", diff --git a/package.json b/package.json index 50a8d53cd93..bd876eb67eb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "request": "^2.69.0", "split": "^1.0.0", "style-loader": "^1.0.1", + "uuid": "^3.3.3", "v8-compile-cache": "^1.1.0", "vue": "2.5.6", "vue-loader": "^15.2.6", diff --git a/src/MCT.js b/src/MCT.js index c07dd398403..f7eb9db14d5 100644 --- a/src/MCT.js +++ b/src/MCT.js @@ -1,5 +1,5 @@ /***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government + * Open MCT, Copyright (c) 2014-2020, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * @@ -264,6 +264,8 @@ define([ this.install(this.plugins.GoToOriginalAction()); this.install(this.plugins.ImportExport()); this.install(this.plugins.WebPage()); + this.install(this.plugins.Condition()); + this.install(this.plugins.ConditionWidget()); } MCT.prototype = Object.create(EventEmitter.prototype); diff --git a/src/plugins/LADTable/components/LADTable.vue b/src/plugins/LADTable/components/LADTable.vue index 4405a7d49c4..f304603a7b2 100644 --- a/src/plugins/LADTable/components/LADTable.vue +++ b/src/plugins/LADTable/components/LADTable.vue @@ -21,22 +21,24 @@ *****************************************************************************/ diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue new file mode 100644 index 00000000000..e96621f3d3d --- /dev/null +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -0,0 +1,245 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/ConditionDescription.vue b/src/plugins/condition/components/ConditionDescription.vue new file mode 100644 index 00000000000..f80db911f14 --- /dev/null +++ b/src/plugins/condition/components/ConditionDescription.vue @@ -0,0 +1,145 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/ConditionError.vue b/src/plugins/condition/components/ConditionError.vue new file mode 100644 index 00000000000..98f0e523d13 --- /dev/null +++ b/src/plugins/condition/components/ConditionError.vue @@ -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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/ConditionSet.vue b/src/plugins/condition/components/ConditionSet.vue new file mode 100644 index 00000000000..d3ea6f49499 --- /dev/null +++ b/src/plugins/condition/components/ConditionSet.vue @@ -0,0 +1,97 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + + + + + diff --git a/src/plugins/condition/components/Criterion.vue b/src/plugins/condition/components/Criterion.vue new file mode 100644 index 00000000000..287b83127f2 --- /dev/null +++ b/src/plugins/condition/components/Criterion.vue @@ -0,0 +1,293 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/TestData.vue b/src/plugins/condition/components/TestData.vue new file mode 100644 index 00000000000..24ac3ceb93f --- /dev/null +++ b/src/plugins/condition/components/TestData.vue @@ -0,0 +1,237 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/condition-set.scss b/src/plugins/condition/components/condition-set.scss new file mode 100644 index 00000000000..691091c36a1 --- /dev/null +++ b/src/plugins/condition/components/condition-set.scss @@ -0,0 +1,116 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +.c-cs { + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + + &__content { + display: flex; + flex-direction: column; + flex: 0 1 auto; + overflow: hidden; + + > * { + flex: 0 0 auto; + overflow: hidden; + + * { + margin-top: $interiorMarginSm; + } + } + + .c-button { + align-self: start; + } + } + + .is-editing & { + // Add some space to kick away from blue editing border indication + padding: $interiorMargin; + } + + section { + display: flex; + flex-direction: column; + overflow: hidden; + } + + &__conditions-h { + display: flex; + flex-direction: column; + flex: 1 1 auto; + overflow: auto; + padding-right: $interiorMarginSm; + + > * + * { + margin-top: $interiorMarginSm; + } + } + + &__conditions { + > * + * { + margin-top: $interiorMarginSm; + } + } + + .hint { + padding: $interiorMarginSm; + } + + /************************** SPECIFIC ITEMS */ + &__current-output-value { + font-size: 1.25em; + padding: $interiorMargin; + } +} + +/***************************** TEST DATA */ +.c-cs-tests { + flex: 0 1 auto; + overflow: auto; + padding-right: $interiorMarginSm; + + > * + * { + margin-top: $interiorMarginSm; + } +} + +.c-cs-test { + > * { + flex: 0 0 auto; + + * { + margin-left: $interiorMargin; + } + } + + &__controls { + display: flex; + flex: 1 1 auto; + + > * + * { + margin-left: $interiorMargin; + } + } +} + diff --git a/src/plugins/condition/components/condition.scss b/src/plugins/condition/components/condition.scss new file mode 100644 index 00000000000..1f20e671466 --- /dev/null +++ b/src/plugins/condition/components/condition.scss @@ -0,0 +1,133 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +.c-condition, +.c-test-datum { + @include discreteItem(); + display: flex; + padding: $interiorMargin; + + &--edit { + line-height: 160%; // For layout when inputs wrap, like in criteria + } +} + +.c-condition { + flex-direction: column; + min-width: 400px; + + > * + * { + margin-top: $interiorMarginSm; + } + &--browse { + .c-condition__summary { + border-top: 1px solid $colorInteriorBorder; + padding-top: $interiorMargin; + } + } + + /***************************** HEADER */ + &__header { + $h: 22px; + display: flex; + align-items: start; + align-content: stretch; + overflow: hidden; + min-height: $h; + line-height: $h; + + > * { + flex: 0 0 auto; + + * { + margin-left: $interiorMarginSm; + } + } + } + + &__drag-grippy { + transform: translateY(50%); + } + + &__name { + font-weight: bold; + align-self: baseline; // Fixes bold line-height offset problem + } + + &__output, + &__summary { + flex: 1 1 auto; + } +} + +/***************************** CONDITION DEFINITION, EDITING */ +.c-cdef { + display: grid; + grid-row-gap: $interiorMarginSm; + grid-column-gap: $interiorMargin; + grid-auto-columns: min-content 1fr max-content; + align-items: start; + min-width: 150px; + margin-left: 29px; + overflow: hidden; + + &__criteria, + &__match-and-criteria { + display: contents; + } + + &__label { + grid-column: 1; + text-align: right; + white-space: nowrap; + } + + &__separator { + grid-column: 1 / span 3; + } + + &__controls { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + grid-column: 2; + + > * > * { + margin-right: $interiorMarginSm; + } + } + + &__buttons { + grid-column: 3; + } +} + +.c-c__drag-ghost { + width: 100%; + min-height: $interiorMarginSm; + + &.dragging { + min-height: 5em; + background-color: lightblue; + border-radius: 2px; + } + +} diff --git a/src/plugins/condition/components/inspector/ConditionSetDialogTreeItem.vue b/src/plugins/condition/components/inspector/ConditionSetDialogTreeItem.vue new file mode 100644 index 00000000000..7c3b189c9d5 --- /dev/null +++ b/src/plugins/condition/components/inspector/ConditionSetDialogTreeItem.vue @@ -0,0 +1,185 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/inspector/ConditionSetSelectorDialog.vue b/src/plugins/condition/components/inspector/ConditionSetSelectorDialog.vue new file mode 100644 index 00000000000..38e241f96d1 --- /dev/null +++ b/src/plugins/condition/components/inspector/ConditionSetSelectorDialog.vue @@ -0,0 +1,172 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/inspector/ConditionalStylesView.vue b/src/plugins/condition/components/inspector/ConditionalStylesView.vue new file mode 100644 index 00000000000..1b5d87349ef --- /dev/null +++ b/src/plugins/condition/components/inspector/ConditionalStylesView.vue @@ -0,0 +1,335 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/inspector/StyleEditor.vue b/src/plugins/condition/components/inspector/StyleEditor.vue new file mode 100644 index 00000000000..b830c1fc3d3 --- /dev/null +++ b/src/plugins/condition/components/inspector/StyleEditor.vue @@ -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. +*****************************************************************************/ + + + + diff --git a/src/plugins/condition/components/inspector/conditional-styles.scss b/src/plugins/condition/components/inspector/conditional-styles.scss new file mode 100644 index 00000000000..4033d27b016 --- /dev/null +++ b/src/plugins/condition/components/inspector/conditional-styles.scss @@ -0,0 +1,124 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +/********************************************* 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; + background-color: transparent !important; + border-color: transparent !important; + @include bgCheckerboard($size: 10px, $imp: true); + opacity: 1; + } +} diff --git a/src/plugins/condition/criterion/AllTelemetryCriterion.js b/src/plugins/condition/criterion/AllTelemetryCriterion.js new file mode 100644 index 00000000000..8355975d503 --- /dev/null +++ b/src/plugins/condition/criterion/AllTelemetryCriterion.js @@ -0,0 +1,172 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import EventEmitter from 'EventEmitter'; +import {OPERATIONS} from '../utils/operations'; +import {computeCondition} from "@/plugins/condition/utils/evaluator"; + +export default class TelemetryCriterion extends EventEmitter { + + /** + * Subscribes/Unsubscribes to telemetry and emits the result + * of operations performed on the telemetry data returned and a given input value. + * @constructor + * @param telemetryDomainObjectDefinition {id: uuid, operation: enum, input: Array, metadata: string, key: {domainObject.identifier} } + * @param openmct + */ + constructor(telemetryDomainObjectDefinition, openmct) { + super(); + + this.openmct = openmct; + this.objectAPI = this.openmct.objects; + this.telemetryAPI = this.openmct.telemetry; + this.timeAPI = this.openmct.time; + this.id = telemetryDomainObjectDefinition.id; + this.telemetry = telemetryDomainObjectDefinition.telemetry; + this.operation = telemetryDomainObjectDefinition.operation; + this.telemetryObjects = Object.assign({}, telemetryDomainObjectDefinition.telemetryObjects); + this.input = telemetryDomainObjectDefinition.input; + this.metadata = telemetryDomainObjectDefinition.metadata; + this.telemetryDataCache = {}; + } + + updateTelemetry(telemetryObjects) { + this.telemetryObjects = Object.assign({}, telemetryObjects); + } + + formatData(data, telemetryObjects) { + if (data) { + this.telemetryDataCache[data.id] = this.computeResult(data); + } + + let keys = Object.keys(telemetryObjects); + keys.forEach((key) => { + let telemetryObject = telemetryObjects[key]; + const id = this.openmct.objects.makeKeyString(telemetryObject.identifier); + if (this.telemetryDataCache[id] === undefined) { + this.telemetryDataCache[id] = false; + } + }); + + const datum = { + result: computeCondition(this.telemetryDataCache, this.telemetry === 'all') + }; + + if (data) { + // TODO check back to see if we should format times here + this.timeAPI.getAllTimeSystems().forEach(timeSystem => { + datum[timeSystem.key] = data[timeSystem.key] + }); + } + return datum; + } + + handleSubscription(data, telemetryObjects) { + if(this.isValid()) { + this.emitEvent('criterionResultUpdated', this.formatData(data, telemetryObjects)); + } else { + this.emitEvent('criterionResultUpdated', this.formatData({}, telemetryObjects)); + } + } + + findOperation(operation) { + for (let i=0; i < OPERATIONS.length; i++) { + if (operation === OPERATIONS[i].name) { + return OPERATIONS[i].operation; + } + } + return null; + } + + computeResult(data) { + let result = false; + if (data) { + let comparator = this.findOperation(this.operation); + let params = []; + params.push(data[this.metadata]); + if (this.input instanceof Array && this.input.length) { + this.input.forEach(input => params.push(input)); + } + if (typeof comparator === 'function') { + result = comparator(params); + } + } + return result; + } + + emitEvent(eventName, data) { + this.emit(eventName, { + id: this.id, + data: data + }); + } + + isValid() { + return (this.telemetry === 'any' || this.telemetry === 'all') && this.metadata && this.operation; + } + + requestLAD(options) { + options = Object.assign({}, + options, + { + strategy: 'latest', + size: 1 + } + ); + + if (!this.isValid()) { + return this.formatData({}, options.telemetryObjects); + } + + const telemetryRequests = options.telemetryObjects + .map(telemetryObject => this.telemetryAPI.request( + telemetryObject, + options + )); + + return Promise.all(telemetryRequests) + .then(telemetryRequestsResults => { + telemetryRequestsResults.forEach((results, index) => { + const latestDatum = results.length ? results[results.length - 1] : {}; + if (index === telemetryRequestsResults.length-1) { + //when the last result is computed, we return the result + return { + id: this.id, + data: this.formatData(latestDatum, options.telemetryObjects) + }; + } else { + if (latestDatum) { + this.telemetryDataCache[latestDatum.id] = this.computeResult(latestDatum); + } + } + }); + }); + } + + destroy() { + this.emitEvent('criterionRemoved'); + delete this.telemetryObjects; + delete this.telemetryDataCache; + delete this.telemetryObjectIdAsString; + delete this.telemetryObject; + } +} diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js new file mode 100644 index 00000000000..998e27431cd --- /dev/null +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -0,0 +1,149 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import EventEmitter from 'EventEmitter'; +import {OPERATIONS} from '../utils/operations'; + +export default class TelemetryCriterion extends EventEmitter { + + /** + * Subscribes/Unsubscribes to telemetry and emits the result + * of operations performed on the telemetry data returned and a given input value. + * @constructor + * @param telemetryDomainObjectDefinition {id: uuid, operation: enum, input: Array, metadata: string, key: {domainObject.identifier} } + * @param openmct + */ + constructor(telemetryDomainObjectDefinition, openmct) { + super(); + + this.openmct = openmct; + this.objectAPI = this.openmct.objects; + this.telemetryAPI = this.openmct.telemetry; + this.timeAPI = this.openmct.time; + this.id = telemetryDomainObjectDefinition.id; + this.telemetry = telemetryDomainObjectDefinition.telemetry; + this.operation = telemetryDomainObjectDefinition.operation; + this.input = telemetryDomainObjectDefinition.input; + this.metadata = telemetryDomainObjectDefinition.metadata; + this.telemetryObject = telemetryDomainObjectDefinition.telemetryObject; + this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(telemetryDomainObjectDefinition.telemetry); + this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); + this.emitEvent('criterionUpdated', this); + } + + updateTelemetry(telemetryObjects) { + this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString]; + } + + formatData(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] + }); + } + return datum; + } + + handleSubscription(data) { + if(this.isValid()) { + this.emitEvent('criterionResultUpdated', this.formatData(data)); + } else { + this.emitEvent('criterionResultUpdated', this.formatData({})); + } + } + + findOperation(operation) { + for (let i=0, ii=OPERATIONS.length; i < ii; i++) { + if (operation === OPERATIONS[i].name) { + return OPERATIONS[i].operation; + } + } + return null; + } + + computeResult(data) { + let result = false; + if (data) { + let comparator = this.findOperation(this.operation); + let params = []; + params.push(data[this.metadata]); + if (this.input instanceof Array && this.input.length) { + this.input.forEach(input => params.push(input)); + } + if (typeof comparator === 'function') { + result = comparator(params); + } + } + return result; + } + + emitEvent(eventName, data) { + this.emit(eventName, { + id: this.id, + data: data + }); + } + + isValid() { + return this.telemetryObject && this.metadata && this.operation; + } + + requestLAD(options) { + options = Object.assign({}, + options, + { + strategy: 'latest', + size: 1 + } + ); + + if (!this.isValid()) { + return { + id: this.id, + data: this.formatData({}) + }; + } + + 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.off(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); + this.emitEvent('criterionRemoved'); + delete this.telemetryObjectIdAsString; + delete this.telemetryObject; + } +} diff --git a/src/plugins/condition/criterion/TelemetryCriterionSpec.js b/src/plugins/condition/criterion/TelemetryCriterionSpec.js new file mode 100644 index 00000000000..67c08c1165b --- /dev/null +++ b/src/plugins/condition/criterion/TelemetryCriterionSpec.js @@ -0,0 +1,111 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import TelemetryCriterion from "./TelemetryCriterion"; + +let openmct = {}, + mockListener, + testCriterionDefinition, + testTelemetryObject, + telemetryCriterion; + +describe("The telemetry criterion", function () { + + beforeEach (() => { + testTelemetryObject = { + identifier:{ namespace: "", key: "test-object"}, + type: "test-object", + name: "Test Object", + telemetry: { + valueMetadatas: [{ + key: "value", + name: "Value", + hints: { + range: 2 + } + }, + { + key: "utc", + name: "Time", + format: "utc", + hints: { + domain: 1 + } + }, { + key: "testSource", + source: "value", + name: "Test", + format: "enum" + }] + } + }; + openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString']); + openmct.objects.makeKeyString.and.returnValue(testTelemetryObject.identifier.key); + openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject', "subscribe", "getMetadata", "getValueFormatter"]); + openmct.telemetry.isTelemetryObject.and.returnValue(true); + openmct.telemetry.subscribe.and.returnValue(function () {}); + openmct.telemetry.getValueFormatter.and.returnValue({ + parse: function (value) { + return value; + } + }); + openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry); + + openmct.time = jasmine.createSpyObj('timeAPI', + ['timeSystem', 'bounds', 'getAllTimeSystems'] + ); + openmct.time.timeSystem.and.returnValue({key: 'system'}); + openmct.time.bounds.and.returnValue({start: 0, end: 1}); + openmct.time.getAllTimeSystems.and.returnValue([{key: 'system'}]); + + testCriterionDefinition = { + id: 'test-criterion-id', + telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier), + operation: 'lessThan', + metadata: 'sin', + telemetryObject: testTelemetryObject + }; + + mockListener = jasmine.createSpy('listener'); + + telemetryCriterion = new TelemetryCriterion( + testCriterionDefinition, + openmct + ); + + telemetryCriterion.on('criterionResultUpdated', mockListener); + + }); + + it("initializes with a telemetry objectId as string", function () { + expect(telemetryCriterion.telemetryObjectIdAsString).toEqual(testTelemetryObject.identifier.key); + }); + + it("updates and emits event on new data from telemetry providers", function () { + spyOn(telemetryCriterion, 'emitEvent').and.callThrough(); + telemetryCriterion.handleSubscription({ + value: 'Hello', + utc: 'Hi' + }); + expect(telemetryCriterion.emitEvent).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/condition/plugin.js b/src/plugins/condition/plugin.js new file mode 100644 index 00000000000..7239435ca66 --- /dev/null +++ b/src/plugins/condition/plugin.js @@ -0,0 +1,68 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +import ConditionSetViewProvider from './ConditionSetViewProvider.js'; +import ConditionSetCompositionPolicy from "./ConditionSetCompositionPolicy"; +import ConditionSetMetadataProvider from './ConditionSetMetadataProvider'; +import ConditionSetTelemetryProvider from './ConditionSetTelemetryProvider'; +import ConditionSetViewPolicy from './ConditionSetViewPolicy'; +import uuid from "uuid"; + +export default function ConditionPlugin() { + + return function install(openmct) { + + openmct.types.addType('conditionSet', { + name: 'Condition Set', + key: 'conditionSet', + description: 'Monitor and evaluate telemetry values in real-time with a wide variety of criteria. Use to control the styling of many objects in Open MCT.', + creatable: true, + cssClass: 'icon-conditional', + initialize: function (domainObject) { + domainObject.configuration = { + conditionTestData: [], + conditionCollection: [{ + isDefault: true, + id: uuid(), + configuration: { + name: 'Default', + output: 'Default', + trigger: 'all', + criteria: [] + }, + summary: 'Default condition' + }] + }; + domainObject.composition = []; + domainObject.telemetry = {}; + } + }); + openmct.legacyExtension('policies', { + category: 'view', + implementation: ConditionSetViewPolicy + }); + openmct.composition.addPolicy(new ConditionSetCompositionPolicy(openmct).allow); + openmct.telemetry.addProvider(new ConditionSetMetadataProvider(openmct)); + openmct.telemetry.addProvider(new ConditionSetTelemetryProvider(openmct)); + openmct.objectViews.addProvider(new ConditionSetViewProvider(openmct)); + + } +} diff --git a/src/plugins/condition/pluginSpec.js b/src/plugins/condition/pluginSpec.js new file mode 100644 index 00000000000..664082b95e7 --- /dev/null +++ b/src/plugins/condition/pluginSpec.js @@ -0,0 +1,97 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import { createOpenMct } from "testTools"; +import ConditionPlugin from "./plugin"; + +let openmct = createOpenMct(); +openmct.install(new ConditionPlugin()); + +let conditionSetDefinition; +let mockConditionSetDomainObject; +let element; +let child; + +describe('the plugin', function () { + + beforeAll((done) => { + + conditionSetDefinition = openmct.types.get('conditionSet').definition; + const appHolder = document.createElement('div'); + appHolder.style.width = '640px'; + appHolder.style.height = '480px'; + + element = document.createElement('div'); + child = document.createElement('div'); + element.appendChild(child); + + mockConditionSetDomainObject = { + identifier: { + key: 'testConditionSetKey', + namespace: '' + }, + type: 'conditionSet' + }; + + conditionSetDefinition.initialize(mockConditionSetDomainObject); + + openmct.on('start', done); + openmct.start(appHolder); + }); + + let mockConditionSetObject = { + name: 'Condition Set', + key: 'conditionSet', + creatable: true + }; + + it('defines a conditionSet object type with the correct key', () => { + expect(conditionSetDefinition.key).toEqual(mockConditionSetObject.key); + }); + + describe('the conditionSet object', () => { + + it('is creatable', () => { + expect(conditionSetDefinition.creatable).toEqual(mockConditionSetObject.creatable); + }); + + it('initializes with an empty composition list', () => { + expect(mockConditionSetDomainObject.composition instanceof Array).toBeTrue(); + expect(mockConditionSetDomainObject.composition.length).toEqual(0); + }); + + it('provides a view', () => { + const testViewObject = { + id:"test-object", + type: "conditionSet", + configuration: { + conditionCollection: [] + } + }; + + const applicableViews = openmct.objectViews.get(testViewObject); + let conditionSetView = applicableViews.find((viewProvider) => viewProvider.key === 'conditionSet.view'); + expect(conditionSetView).toBeDefined(); + }); + + }); +}); diff --git a/src/plugins/condition/utils/constants.js b/src/plugins/condition/utils/constants.js new file mode 100644 index 00000000000..9ccd08436e5 --- /dev/null +++ b/src/plugins/condition/utils/constants.js @@ -0,0 +1,54 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +export const TRIGGER = { + ANY: 'any', + ALL: 'all', + NOT: 'not', + XOR: 'xor' +}; + +export const TRIGGER_LABEL = { + 'any': 'when any criteria are met', + 'all': 'when all criteria are met', + 'not': 'when no criteria are met', + 'xor': 'when only one criteria is met' +}; + +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' + } +}; diff --git a/src/plugins/condition/utils/evaluator.js b/src/plugins/condition/utils/evaluator.js new file mode 100644 index 00000000000..7e2b70f7e23 --- /dev/null +++ b/src/plugins/condition/utils/evaluator.js @@ -0,0 +1,54 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +export const computeCondition = (resultMap, allMustBeTrue) => { + let result = false; + for (let key in resultMap) { + if (resultMap.hasOwnProperty(key)) { + result = resultMap[key]; + if (allMustBeTrue && !result) { + //If we want all conditions to be true, then even one negative result should break. + break; + } else if (!allMustBeTrue && result) { + //If we want at least one condition to be true, then even one positive result should break. + break; + } + } + } + return result; +}; + +//Returns true only if limit number of results are satisfied +export const computeConditionByLimit = (resultMap, limit) => { + let trueCount = 0; + for (let key in resultMap) { + if (resultMap.hasOwnProperty(key)) { + if (resultMap[key]) { + trueCount++; + } + if (trueCount > limit) { + break; + } + } + } + return trueCount === limit; +}; diff --git a/src/plugins/condition/utils/evaluatorSpec.js b/src/plugins/condition/utils/evaluatorSpec.js new file mode 100644 index 00000000000..132f77f181c --- /dev/null +++ b/src/plugins/condition/utils/evaluatorSpec.js @@ -0,0 +1,66 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import { computeConditionByLimit } from "./evaluator"; + +describe('evaluate results based on trigger', function () { + + it('should evaluate to true if trigger is NOT', () => { + const results = { + result: false, + result1: false, + result2: false + }; + const result = computeConditionByLimit(results, 0); + expect(result).toBeTrue(); + }); + + it('should evaluate to false if trigger is NOT', () => { + const results = { + result: true, + result1: false, + result2: false + }; + const result = computeConditionByLimit(results, 0); + expect(result).toBeFalse(); + }); + + it('should evaluate to true if trigger is XOR', () => { + const results = { + result: false, + result1: true, + result2: false + }; + const result = computeConditionByLimit(results, 1); + expect(result).toBeTrue(); + }); + + it('should evaluate to false if trigger is XOR', () => { + const results = { + result: false, + result1: true, + result2: true + }; + const result = computeConditionByLimit(results, 1); + expect(result).toBeFalse(); + }); +}); diff --git a/src/plugins/condition/utils/operations.js b/src/plugins/condition/utils/operations.js new file mode 100644 index 00000000000..3026f887bd2 --- /dev/null +++ b/src/plugins/condition/utils/operations.js @@ -0,0 +1,276 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import _ from 'lodash'; + +export const OPERATIONS = [ + { + name: 'equalTo', + operation: function (input) { + return Number(input[0]) === Number(input[1]); + }, + text: 'is equal to', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' is ' + values.join(', '); + } + }, + { + name: 'notEqualTo', + operation: function (input) { + return Number(input[0]) !== Number(input[1]); + }, + text: 'is not equal to', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' is not ' + values.join(', '); + } + }, + { + name: 'greaterThan', + operation: function (input) { + return Number(input[0]) > Number(input[1]); + }, + text: 'is greater than', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' > ' + values.join(', '); + } + }, + { + name: 'lessThan', + operation: function (input) { + return Number(input[0]) < Number(input[1]); + }, + text: 'is less than', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' < ' + values.join(', '); + } + }, + { + name: 'greaterThanOrEq', + operation: function (input) { + return Number(input[0]) >= Number(input[1]); + }, + text: 'is greater than or equal to', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' >= ' + values.join(', '); + } + }, + { + name: 'lessThanOrEq', + operation: function (input) { + return Number(input[0]) <= Number(input[1]); + }, + text: 'is less than or equal to', + appliesTo: ['number'], + inputCount: 1, + getDescription: function (values) { + return ' <= ' + values.join(', '); + } + }, + { + name: 'between', + operation: function (input) { + let numberInputs = []; + input.forEach(inputValue => numberInputs.push(Number(inputValue))); + let larger = Math.max(...numberInputs.slice(1,3)); + let smaller = Math.min(...numberInputs.slice(1,3)); + return (numberInputs[0] > smaller) && (numberInputs[0] < larger); + }, + text: 'is between', + appliesTo: ['number'], + inputCount: 2, + getDescription: function (values) { + return ' is between ' + values[0] + ' and ' + values[1]; + } + }, + { + name: 'notBetween', + operation: function (input) { + let numberInputs = []; + input.forEach(inputValue => numberInputs.push(Number(inputValue))); + let larger = Math.max(...numberInputs.slice(1,3)); + let smaller = Math.min(...numberInputs.slice(1,3)); + return (numberInputs[0] < smaller) || (numberInputs[0] > larger); + }, + text: 'is not between', + appliesTo: ['number'], + inputCount: 2, + getDescription: function (values) { + return ' is not between ' + values[0] + ' and ' + values[1]; + } + }, + { + name: 'textContains', + operation: function (input) { + return input[0] && input[1] && input[0].includes(input[1]); + }, + text: 'text contains', + appliesTo: ['string'], + inputCount: 1, + getDescription: function (values) { + return ' contains ' + values.join(', '); + } + }, + { + name: 'textDoesNotContain', + operation: function (input) { + return input[0] && input[1] && !input[0].includes(input[1]); + }, + text: 'text does not contain', + appliesTo: ['string'], + inputCount: 1, + getDescription: function (values) { + return ' does not contain ' + values.join(', '); + } + }, + { + name: 'textStartsWith', + operation: function (input) { + return input[0].startsWith(input[1]); + }, + text: 'text starts with', + appliesTo: ['string'], + inputCount: 1, + getDescription: function (values) { + return ' starts with ' + values.join(', '); + } + }, + { + name: 'textEndsWith', + operation: function (input) { + return input[0].endsWith(input[1]); + }, + text: 'text ends with', + appliesTo: ['string'], + inputCount: 1, + getDescription: function (values) { + return ' ends with ' + values.join(', '); + } + }, + { + name: 'textIsExactly', + operation: function (input) { + return input[0] === input[1]; + }, + text: 'text is exactly', + appliesTo: ['string'], + inputCount: 1, + getDescription: function (values) { + return ' is exactly ' + values.join(', '); + } + }, + { + name: 'isUndefined', + operation: function (input) { + return typeof input[0] === 'undefined'; + }, + text: 'is undefined', + appliesTo: ['string', 'number', 'enum'], + inputCount: 0, + getDescription: function () { + return ' is undefined'; + } + }, + { + name: 'isDefined', + operation: function (input) { + return typeof input[0] !== 'undefined'; + }, + text: 'is defined', + appliesTo: ['string', 'number', 'enum'], + inputCount: 0, + getDescription: function () { + return ' is defined'; + } + }, + { + name: 'enumValueIs', + operation: function (input) { + return input[0] === input[1]; + }, + text: 'is', + appliesTo: ['enum'], + inputCount: 1, + getDescription: function (values) { + return ' is ' + values.join(', '); + } + }, + { + name: 'enumValueIsNot', + operation: function (input) { + return input[0] !== input[1]; + }, + text: 'is not', + appliesTo: ['enum'], + inputCount: 1, + getDescription: function (values) { + return ' is not ' + values.join(', '); + } + }, + { + name: 'valueIs', + operation: function (input) { + if (input[1]) { + const values = input[1].split(','); + return values.find((value) => input[0].toString() === _.trim(value.toString())); + } + return false; + }, + text: 'is one of', + appliesTo: ["string", "number"], + inputCount: 1, + getDescription: function (values) { + return ' is one of ' + values[0]; + } + }, + { + name: 'valueIsNot', + operation: function (input) { + if (input[1]) { + const values = input[1].split(','); + const found = values.find((value) => input[0].toString() === _.trim(value.toString())); + return !found; + } + return false; + }, + text: 'is not one of', + appliesTo: ["string", "number"], + inputCount: 1, + getDescription: function (values) { + return ' is not one of ' + values[0]; + } + } +]; + +export const INPUT_TYPES = { + 'string': 'text', + 'number': 'number' +}; diff --git a/src/plugins/condition/utils/operationsSpec.js b/src/plugins/condition/utils/operationsSpec.js new file mode 100644 index 00000000000..23866551083 --- /dev/null +++ b/src/plugins/condition/utils/operationsSpec.js @@ -0,0 +1,90 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import { OPERATIONS } from "./operations"; +let isOneOfOperation = OPERATIONS.find((operation) => operation.name === 'valueIs'); +let isNotOneOfOperation = OPERATIONS.find((operation) => operation.name === 'valueIsNot'); +let isBetween = OPERATIONS.find((operation) => operation.name === 'between'); +let isNotBetween = OPERATIONS.find((operation) => operation.name === 'notBetween'); + +describe('Is one of and is not one of operations', function () { + + it('should evaluate isOneOf to true for number inputs', () => { + const inputs = [45, "5,6,45,8"]; + expect(!!isOneOfOperation.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isOneOf to true for string inputs', () => { + const inputs = ["45", " 45, 645, 4,8 "]; + expect(!!isOneOfOperation.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isNotOneOf to true for number inputs', () => { + const inputs = [45, "5,6,4,8"]; + expect(!!isNotOneOfOperation.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isNotOneOf to true for string inputs', () => { + const inputs = ["45", " 5,645, 4,8 "]; + expect(!!isNotOneOfOperation.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isOneOf to false for number inputs', () => { + const inputs = [4, "5, 6, 7, 8"]; + expect(!!isOneOfOperation.operation(inputs)).toBeFalse(); + }); + + it('should evaluate isOneOf to false for string inputs', () => { + const inputs = ["4", "5,645 ,7,8"]; + expect(!!isOneOfOperation.operation(inputs)).toBeFalse(); + }); + + it('should evaluate isNotOneOf to false for number inputs', () => { + const inputs = [4, "5,4, 7,8"]; + expect(!!isNotOneOfOperation.operation(inputs)).toBeFalse(); + }); + + it('should evaluate isNotOneOf to false for string inputs', () => { + const inputs = ["4", "5,46,4,8"]; + expect(!!isNotOneOfOperation.operation(inputs)).toBeFalse(); + }); + + it('should evaluate isBetween to true', () => { + const inputs = ["4", "3", "89"]; + expect(!!isBetween.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isNotBetween to true', () => { + const inputs = ["45", "100", "89"]; + expect(!!isNotBetween.operation(inputs)).toBeTrue(); + }); + + it('should evaluate isBetween to false', () => { + const inputs = ["4", "100", "89"]; + expect(!!isBetween.operation(inputs)).toBeFalse(); + }); + + it('should evaluate isNotBetween to false', () => { + const inputs = ["45", "30", "50"]; + expect(!!isNotBetween.operation(inputs)).toBeFalse(); + }); +}); diff --git a/src/plugins/condition/utils/styleUtils.js b/src/plugins/condition/utils/styleUtils.js new file mode 100644 index 00000000000..10dcb986f16 --- /dev/null +++ b/src/plugins/condition/utils/styleUtils.js @@ -0,0 +1,45 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +export const getStyleProp = (key, defaultValue) => { + let styleProp = undefined; + switch(key) { + case 'fill': styleProp = { + backgroundColor: defaultValue || 'transparent' + }; + break; + case 'stroke': styleProp = { + border: '1px solid ' + (defaultValue || 'transparent') + }; + break; + case 'color': styleProp = { + color: defaultValue || 'transparent' + }; + break; + case 'url': styleProp = { + imageUrl: defaultValue || 'transparent' + }; + break; + } + + return styleProp; +}; diff --git a/src/plugins/conditionWidget/ConditionWidgetViewProvider.js b/src/plugins/conditionWidget/ConditionWidgetViewProvider.js new file mode 100644 index 00000000000..d34af872d20 --- /dev/null +++ b/src/plugins/conditionWidget/ConditionWidgetViewProvider.js @@ -0,0 +1,64 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import ConditionWidgetComponent from './components/ConditionWidget.vue'; +import Vue from 'vue'; + +export default function ConditionWidget(openmct) { + return { + key: 'conditionWidget', + name: 'Condition Widget', + cssClass: 'icon-condition-widget', + canView: function (domainObject) { + return domainObject.type === 'conditionWidget'; + }, + canEdit: function (domainObject) { + return domainObject.type === 'conditionWidget'; + }, + view: function (domainObject) { + let component; + + return { + show: function (element) { + component = new Vue({ + el: element, + components: { + ConditionWidgetComponent: ConditionWidgetComponent + }, + provide: { + openmct, + domainObject + }, + template: '' + }); + }, + destroy: function (element) { + component.$destroy(); + component = undefined; + } + }; + }, + priority: function () { + return 1; + } + }; +} diff --git a/src/plugins/conditionWidget/components/ConditionWidget.vue b/src/plugins/conditionWidget/components/ConditionWidget.vue new file mode 100644 index 00000000000..c6011eba255 --- /dev/null +++ b/src/plugins/conditionWidget/components/ConditionWidget.vue @@ -0,0 +1,55 @@ +/***************************************************************************** +* 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. +*****************************************************************************/ + + + + diff --git a/src/plugins/conditionWidget/components/condition-widget.scss b/src/plugins/conditionWidget/components/condition-widget.scss new file mode 100644 index 00000000000..f25231aa880 --- /dev/null +++ b/src/plugins/conditionWidget/components/condition-widget.scss @@ -0,0 +1,58 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +.c-condition-widget { + $shdwSize: 3px; + @include userSelectNone(); + background-color: rgba($colorBodyFg, 0.1); // Give a little presence if the user hasn't defined a fill color + border-radius: $basicCr; + border: 1px solid transparent; + display: inline-block; + padding: $interiorMarginLg $interiorMarginLg * 2; + cursor: inherit !important; + &[href] { + cursor: pointer !important; + } +} + +// Make Condition Widget expand when in a hidden frame Layout context +// For both static and Flexible Layouts +.c-so-view--no-frame > .c-so-view__object-view > .c-condition-widget { + @include abs(); + display: flex; + align-items: center; + justify-content: center; + padding: 0; +} + +// Add some margin when a Condition Widget is in a Flexible Layout +.c-fl .c-so-view--no-frame .c-condition-widget { + @include abs(1px); +} + +// When the widget is in the main view, center it in the space +.l-shell__main-container > .c-condition-widget { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/src/plugins/conditionWidget/plugin.js b/src/plugins/conditionWidget/plugin.js new file mode 100644 index 00000000000..982700d2f4f --- /dev/null +++ b/src/plugins/conditionWidget/plugin.js @@ -0,0 +1,58 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import ConditionWidgetViewProvider from './ConditionWidgetViewProvider.js'; + +export default function plugin() { + return function install(openmct) { + openmct.objectViews.addProvider(new ConditionWidgetViewProvider(openmct)); + + openmct.types.addType('conditionWidget', { + name: "Condition Widget", + description: "A button that can be used on its own, or dynamically styled with a Condition Set.", + creatable: true, + cssClass: 'icon-condition-widget', + initialize(domainObject) { + domainObject.label = 'Condition Widget'; + }, + form: [ + { + "key": "label", + "name": "Label", + "control": "textfield", + property: [ + "label" + ], + "required": true, + "cssClass": "l-input" + }, + { + "key": "url", + "name": "URL", + "control": "textfield", + "required": false, + "cssClass": "l-input-lg" + } + ] + }); + }; +} diff --git a/src/plugins/displayLayout/DisplayLayoutToolbar.js b/src/plugins/displayLayout/DisplayLayoutToolbar.js index 707c49327c1..f5cfa00fd10 100644 --- a/src/plugins/displayLayout/DisplayLayoutToolbar.js +++ b/src/plugins/displayLayout/DisplayLayoutToolbar.js @@ -347,78 +347,6 @@ define(['lodash'], function (_) { }; } - function getFillMenu(selectedParent, selection) { - return { - control: "color-picker", - domainObject: selectedParent, - applicableSelectedItems: selection.filter(selectionPath => { - let type = selectionPath[0].context.layoutItem.type; - return type === 'text-view' || - type === 'telemetry-view' || - type === 'box-view'; - }), - property: function (selectionPath) { - return getPath(selectionPath) + ".fill"; - }, - icon: "icon-paint-bucket", - title: "Set fill color" - }; - } - - function getStrokeMenu(selectedParent, selection) { - return { - control: "color-picker", - domainObject: selectedParent, - applicableSelectedItems: selection.filter(selectionPath => { - let type = selectionPath[0].context.layoutItem.type; - return type === 'text-view' || - type === 'telemetry-view' || - type === 'box-view' || - type === 'image-view' || - type === 'line-view'; - }), - property: function (selectionPath) { - return getPath(selectionPath) + ".stroke"; - }, - icon: "icon-line-horz", - title: "Set border color" - }; - } - - function getTextColorMenu(selectedParent, selection) { - return { - control: "color-picker", - domainObject: selectedParent, - applicableSelectedItems: selection.filter(selectionPath => { - let type = selectionPath[0].context.layoutItem.type; - return type === 'text-view' || type === 'telemetry-view'; - }), - property: function (selectionPath) { - return getPath(selectionPath) + ".color"; - }, - icon: "icon-font", - mandatory: true, - title: "Set text color", - preventNone: true - }; - } - - function getURLButton(selectedParent, selection) { - return { - control: "button", - domainObject: selectedParent, - applicableSelectedItems: selection.filter(selectionPath => { - return selectionPath[0].context.layoutItem.type === 'image-view'; - }), - property: function (selectionPath) { - return getPath(selectionPath); - }, - icon: "icon-image", - title: "Edit image properties", - dialog: DIALOG_FORM.image - }; - } - function getTextButton(selectedParent, selection) { return { control: "button", @@ -429,7 +357,7 @@ define(['lodash'], function (_) { property: function (selectionPath) { return getPath(selectionPath); }, - icon: "icon-gear", + icon: "icon-font", title: "Edit text properties", dialog: DIALOG_FORM.text }; @@ -505,14 +433,14 @@ define(['lodash'], function (_) { let toolbar = { 'add-menu': [], + 'text': [], + 'url': [], 'toggle-frame': [], 'display-mode': [], 'telemetry-value': [], 'style': [], 'text-style': [], 'position': [], - 'text': [], - 'url': [], 'remove': [] }; @@ -550,15 +478,8 @@ define(['lodash'], function (_) { if (toolbar['telemetry-value'].length === 0) { toolbar['telemetry-value'] = [getTelemetryValueMenu(selectionPath, selectedObjects)]; } - if (toolbar.style.length < 2) { - toolbar.style = [ - getFillMenu(selectedParent, selectedObjects), - getStrokeMenu(selectedParent, selectedObjects) - ]; - } if (toolbar['text-style'].length === 0) { toolbar['text-style'] = [ - getTextColorMenu(selectedParent, selectedObjects), getTextSizeMenu(selectedParent, selectedObjects) ]; } @@ -575,15 +496,8 @@ define(['lodash'], function (_) { toolbar.remove = [getRemoveButton(selectedParent, selectionPath, selectedObjects)]; } } else if (layoutItem.type === 'text-view') { - if (toolbar.style.length < 2) { - toolbar.style = [ - getFillMenu(selectedParent, selectedObjects), - getStrokeMenu(selectedParent, selectedObjects) - ]; - } if (toolbar['text-style'].length === 0) { toolbar['text-style'] = [ - getTextColorMenu(selectedParent, selectedObjects), getTextSizeMenu(selectedParent, selectedObjects) ]; } @@ -603,12 +517,6 @@ define(['lodash'], function (_) { toolbar.remove = [getRemoveButton(selectedParent, selectionPath, selectedObjects)]; } } else if (layoutItem.type === 'box-view') { - if (toolbar.style.length < 2) { - toolbar.style = [ - getFillMenu(selectedParent, selectedObjects), - getStrokeMenu(selectedParent, selectedObjects) - ]; - } if (toolbar.position.length === 0) { toolbar.position = [ getStackOrder(selectedParent, selectionPath), @@ -622,11 +530,6 @@ define(['lodash'], function (_) { toolbar.remove = [getRemoveButton(selectedParent, selectionPath, selectedObjects)]; } } else if (layoutItem.type === 'image-view') { - if (toolbar.style.length === 0) { - toolbar.style = [ - getStrokeMenu(selectedParent, selectedObjects) - ]; - } if (toolbar.position.length === 0) { toolbar.position = [ getStackOrder(selectedParent, selectionPath), @@ -636,18 +539,10 @@ define(['lodash'], function (_) { getWidthInput(selectedParent, selectedObjects) ]; } - if (toolbar.url.length === 0) { - toolbar.url = [getURLButton(selectedParent, selectedObjects)]; - } if (toolbar.remove.length === 0) { toolbar.remove = [getRemoveButton(selectedParent, selectionPath, selectedObjects)]; } } else if (layoutItem.type === 'line-view') { - if (toolbar.style.length === 0) { - toolbar.style = [ - getStrokeMenu(selectedParent, selectedObjects) - ]; - } if (toolbar.position.length === 0) { toolbar.position = [ getStackOrder(selectedParent, selectionPath), diff --git a/src/plugins/displayLayout/components/AlphanumericFormatView.vue b/src/plugins/displayLayout/components/AlphanumericFormatView.vue index 2207d09d2cf..45dec6579f5 100644 --- a/src/plugins/displayLayout/components/AlphanumericFormatView.vue +++ b/src/plugins/displayLayout/components/AlphanumericFormatView.vue @@ -23,20 +23,20 @@