mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 07:16:39 +00:00
Feature/eslint plugin vue (#2548)
* Use eslint-plugin-vue to lint vue files
This commit is contained in:
parent
14ce5e159b
commit
14a0f84c1b
44
.eslintrc.js
44
.eslintrc.js
@ -5,9 +5,16 @@ module.exports = {
|
|||||||
"jasmine": true,
|
"jasmine": true,
|
||||||
"amd": true
|
"amd": true
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"globals": {
|
||||||
"parser": "babel-eslint",
|
"_": "readonly"
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:vue/recommended"
|
||||||
|
],
|
||||||
|
"parser": "vue-eslint-parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint",
|
||||||
"allowImportExportEverywhere": true,
|
"allowImportExportEverywhere": true,
|
||||||
"ecmaVersion": 2015,
|
"ecmaVersion": 2015,
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
@ -58,7 +65,38 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dot-notation": "error",
|
"dot-notation": "error",
|
||||||
"indent": ["error", 4]
|
"indent": ["error", 4],
|
||||||
|
"vue/html-indent": [
|
||||||
|
"error",
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
"attribute": 1,
|
||||||
|
"baseIndent": 0,
|
||||||
|
"closeBracket": 0,
|
||||||
|
"alignAttributesVertically": true,
|
||||||
|
"ignores": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vue/html-self-closing": ["error",
|
||||||
|
{
|
||||||
|
"html": {
|
||||||
|
"void": "never",
|
||||||
|
"normal": "never",
|
||||||
|
"component": "always"
|
||||||
|
},
|
||||||
|
"svg": "always",
|
||||||
|
"math": "always"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vue/max-attributes-per-line": ["error", {
|
||||||
|
"singleline": 1,
|
||||||
|
"multiline": {
|
||||||
|
"max": 1,
|
||||||
|
"allowFirstLine": true
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"vue/multiline-html-element-content-newline": "off",
|
||||||
|
"vue/singleline-html-element-content-newline": "off"
|
||||||
},
|
},
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
"d3-time": "1.0.x",
|
"d3-time": "1.0.x",
|
||||||
"d3-time-format": "2.1.x",
|
"d3-time-format": "2.1.x",
|
||||||
"eslint": "5.2.0",
|
"eslint": "5.2.0",
|
||||||
|
"eslint-plugin-vue": "^6.0.0",
|
||||||
"eventemitter3": "^1.2.0",
|
"eventemitter3": "^1.2.0",
|
||||||
"exports-loader": "^0.7.0",
|
"exports-loader": "^0.7.0",
|
||||||
"express": "^4.13.1",
|
"express": "^4.13.1",
|
||||||
@ -74,8 +75,8 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
"lint": "eslint platform example src openmct.js",
|
"lint": "eslint platform example src/**/*.{js,vue} openmct.js",
|
||||||
"lint:fix": "eslint platform example src openmct.js --fix",
|
"lint:fix": "eslint platform example src/**/*.{js,vue} openmct.js --fix",
|
||||||
"build:prod": "NODE_ENV=production webpack",
|
"build:prod": "NODE_ENV=production webpack",
|
||||||
"build:dev": "webpack",
|
"build:dev": "webpack",
|
||||||
"build:watch": "webpack --watch",
|
"build:watch": "webpack --watch",
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-menu">
|
<div class="c-menu">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="action in actions"
|
<li
|
||||||
:key="action.name"
|
v-for="action in actions"
|
||||||
:class="action.cssClass"
|
:key="action.name"
|
||||||
:title="action.description"
|
:class="action.cssClass"
|
||||||
@click="action.invoke(objectPath)">
|
:title="action.description"
|
||||||
{{ action.name }}
|
@click="action.invoke(objectPath)"
|
||||||
</li>
|
>
|
||||||
<li v-if="actions.length === 0">No actions defined.</li>
|
{{ action.name }}
|
||||||
</ul>
|
</li>
|
||||||
</div>
|
<li v-if="actions.length === 0">
|
||||||
|
No actions defined.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['actions', 'objectPath']
|
inject: ['actions', 'objectPath']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,28 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-message">
|
<div class="c-message">
|
||||||
<!--Uses flex-row -->
|
<!--Uses flex-row -->
|
||||||
<div class="c-message__icon"
|
<div
|
||||||
:class="['u-icon-bg-color-' + iconClass]"></div>
|
class="c-message__icon"
|
||||||
<div class="c-message__text">
|
:class="['u-icon-bg-color-' + iconClass]"
|
||||||
<!-- Uses flex-column -->
|
></div>
|
||||||
<div class="c-message__title"
|
<div class="c-message__text">
|
||||||
v-if="title">
|
<!-- Uses flex-column -->
|
||||||
{{title}}
|
<div
|
||||||
</div>
|
v-if="title"
|
||||||
|
class="c-message__title"
|
||||||
<div class="c-message__hint"
|
>
|
||||||
v-if="hint">
|
{{ title }}
|
||||||
{{hint}}
|
|
||||||
<span v-if="timestamp">[{{timestamp}}]</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="c-message__action-text"
|
|
||||||
v-if="message">
|
|
||||||
{{message}}
|
|
||||||
</div>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="hint"
|
||||||
|
class="c-message__hint"
|
||||||
|
>
|
||||||
|
{{ hint }}
|
||||||
|
<span v-if="timestamp">[{{ timestamp }}]</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message"
|
||||||
|
class="c-message__action-text"
|
||||||
|
>
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -1,28 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-overlay">
|
<div class="c-overlay">
|
||||||
<div class="c-overlay__blocker"
|
<div
|
||||||
@click="destroy">
|
class="c-overlay__blocker"
|
||||||
</div>
|
@click="destroy"
|
||||||
<div class="c-overlay__outer">
|
></div>
|
||||||
<button class="c-click-icon c-overlay__close-button icon-x-in-circle"
|
<div class="c-overlay__outer">
|
||||||
v-if="dismissable"
|
<button
|
||||||
@click="destroy">
|
v-if="dismissable"
|
||||||
|
class="c-click-icon c-overlay__close-button icon-x-in-circle"
|
||||||
|
@click="destroy"
|
||||||
|
></button>
|
||||||
|
<div
|
||||||
|
ref="element"
|
||||||
|
class="c-overlay__contents"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
v-if="buttons"
|
||||||
|
class="c-overlay__button-bar"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
v-for="(button, index) in buttons"
|
||||||
|
:key="index"
|
||||||
|
class="c-button"
|
||||||
|
:class="{'c-button--major': button.emphasis}"
|
||||||
|
@click="buttonClickHandler(button.callback)"
|
||||||
|
>
|
||||||
|
{{ button.label }}
|
||||||
</button>
|
</button>
|
||||||
<div class="c-overlay__contents" ref="element" tabindex="0"></div>
|
<div
|
||||||
<div class="c-overlay__button-bar" v-if="buttons">
|
ref="element"
|
||||||
<button class="c-button"
|
class="c-overlay__contents"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
ref="buttons"
|
></div>
|
||||||
v-for="(button, index) in buttons"
|
<div
|
||||||
:key="index"
|
v-if="buttons"
|
||||||
@focus="focusIndex=index"
|
class="c-overlay__button-bar"
|
||||||
:class="{'c-button--major': focusIndex===index}"
|
>
|
||||||
@click="buttonClickHandler(button.callback)">
|
<button
|
||||||
{{button.label}}
|
v-for="(button, index) in buttons"
|
||||||
|
ref="buttons"
|
||||||
|
:key="index"
|
||||||
|
class="c-button"
|
||||||
|
tabindex="0"
|
||||||
|
:class="{'c-button--major': focusIndex===index}"
|
||||||
|
@focus="focusIndex=index"
|
||||||
|
@click="buttonClickHandler(button.callback)"
|
||||||
|
>
|
||||||
|
{{ button.label }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -174,50 +203,50 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
focusIndex: -1
|
focusIndex: -1
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
inject: ['dismiss', 'element', 'buttons', 'dismissable'],
|
inject: ['dismiss', 'element', 'buttons', 'dismissable'],
|
||||||
mounted() {
|
mounted() {
|
||||||
const element = this.$refs.element;
|
const element = this.$refs.element;
|
||||||
element.appendChild(this.element);
|
element.appendChild(this.element);
|
||||||
const elementForFocus = this.getElementForFocus() || element;
|
const elementForFocus = this.getElementForFocus() || element;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
elementForFocus.focus();
|
elementForFocus.focus();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
if (this.dismissable) {
|
if (this.dismissable) {
|
||||||
this.dismiss();
|
this.dismiss();
|
||||||
}
|
|
||||||
},
|
|
||||||
buttonClickHandler: function (method) {
|
|
||||||
method();
|
|
||||||
this.$emit('destroy');
|
|
||||||
},
|
|
||||||
getElementForFocus: function () {
|
|
||||||
const defaultElement = this.$refs.element;;
|
|
||||||
if (!this.$refs.buttons) {
|
|
||||||
return defaultElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
const focusButton = this.$refs.buttons.filter((button, index) => {
|
|
||||||
if (this.buttons[index].emphasis) {
|
|
||||||
this.focusIndex = index;
|
|
||||||
}
|
|
||||||
return this.buttons[index].emphasis;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!focusButton.length) {
|
|
||||||
return defaultElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
return focusButton[0];
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
buttonClickHandler: function (method) {
|
||||||
|
method();
|
||||||
|
this.$emit('destroy');
|
||||||
|
},
|
||||||
|
getElementForFocus: function () {
|
||||||
|
const defaultElement = this.$refs.element;
|
||||||
|
if (!this.$refs.buttons) {
|
||||||
|
return defaultElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const focusButton = this.$refs.buttons.filter((button, index) => {
|
||||||
|
if (this.buttons[index].emphasis) {
|
||||||
|
this.focusIndex = index;
|
||||||
|
}
|
||||||
|
return this.buttons[index].emphasis;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!focusButton.length) {
|
||||||
|
return defaultElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return focusButton[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<dialog-component>
|
<dialog-component>
|
||||||
<progress-component :model="model"></progress-component>
|
<progress-component :model="model" />
|
||||||
</dialog-component>
|
</dialog-component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -14,9 +14,14 @@ import DialogComponent from './DialogComponent.vue';
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
DialogComponent: DialogComponent,
|
DialogComponent: DialogComponent,
|
||||||
ProgressComponent: ProgressComponent,
|
ProgressComponent: ProgressComponent
|
||||||
},
|
},
|
||||||
inject:['iconClass', 'title', 'hint', 'timestamp', 'message'],
|
inject:['iconClass', 'title', 'hint', 'timestamp', 'message'],
|
||||||
props:['model']
|
props: {
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -44,6 +44,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
LadTableSet: LadTableSet.default
|
LadTableSet: LadTableSet.default
|
||||||
},
|
},
|
||||||
@ -52,7 +53,6 @@ define([
|
|||||||
domainObject,
|
domainObject,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<lad-table-set></lad-table-set>'
|
template: '<lad-table-set></lad-table-set>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -44,6 +44,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
LadTableComponent: LadTableComponent.default
|
LadTableComponent: LadTableComponent.default
|
||||||
},
|
},
|
||||||
@ -52,7 +53,6 @@ define([
|
|||||||
domainObject,
|
domainObject,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<lad-table-component></lad-table-component>'
|
template: '<lad-table-component></lad-table-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<tr @contextmenu.prevent="showContextMenu">
|
<tr @contextmenu.prevent="showContextMenu">
|
||||||
<td>{{name}}</td>
|
<td>{{ name }}</td>
|
||||||
<td>{{timestamp}}</td>
|
<td>{{ timestamp }}</td>
|
||||||
<td :class="valueClass">
|
<td :class="valueClass">
|
||||||
{{value}}
|
{{ value }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -44,7 +44,12 @@ const CONTEXT_MENU_ACTIONS = [
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'objectPath'],
|
inject: ['openmct', 'objectPath'],
|
||||||
props: ['domainObject'],
|
props: {
|
||||||
|
domainObject: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
let currentObjectPath = this.objectPath.slice();
|
let currentObjectPath = this.objectPath.slice();
|
||||||
currentObjectPath.unshift(this.domainObject);
|
currentObjectPath.unshift(this.domainObject);
|
||||||
@ -57,48 +62,16 @@ export default {
|
|||||||
currentObjectPath
|
currentObjectPath
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
updateValues(datum) {
|
|
||||||
this.timestamp = this.formats[this.timestampKey].format(datum);
|
|
||||||
this.value = this.formats[this.valueKey].format(datum);
|
|
||||||
|
|
||||||
var limit = this.limitEvaluator.evaluate(datum, this.valueMetadata);
|
|
||||||
|
|
||||||
if (limit) {
|
|
||||||
this.valueClass = limit.cssClass;
|
|
||||||
} else {
|
|
||||||
this.valueClass = '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateName(name){
|
|
||||||
this.name = name;
|
|
||||||
},
|
|
||||||
updateTimeSystem(timeSystem) {
|
|
||||||
this.value = '---';
|
|
||||||
this.timestamp = '---';
|
|
||||||
this.valueClass = '';
|
|
||||||
this.timestampKey = timeSystem.key;
|
|
||||||
|
|
||||||
this.openmct
|
|
||||||
.telemetry
|
|
||||||
.request(this.domainObject, {strategy: 'latest'})
|
|
||||||
.then((array) => this.updateValues(array[array.length - 1]));
|
|
||||||
|
|
||||||
},
|
|
||||||
showContextMenu(event) {
|
|
||||||
this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||||
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
|
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
|
||||||
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||||
|
|
||||||
this.limitEvaluator = openmct
|
this.limitEvaluator = this.openmct
|
||||||
.telemetry
|
.telemetry
|
||||||
.limitEvaluator(this.domainObject);
|
.limitEvaluator(this.domainObject);
|
||||||
|
|
||||||
this.stopWatchingMutation = openmct
|
this.stopWatchingMutation = this.openmct
|
||||||
.objects
|
.objects
|
||||||
.observe(
|
.observe(
|
||||||
this.domainObject,
|
this.domainObject,
|
||||||
@ -129,6 +102,38 @@ export default {
|
|||||||
this.stopWatchingMutation();
|
this.stopWatchingMutation();
|
||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
this.openmct.off('timeSystem', this.updateTimeSystem);
|
this.openmct.off('timeSystem', this.updateTimeSystem);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValues(datum) {
|
||||||
|
this.timestamp = this.formats[this.timestampKey].format(datum);
|
||||||
|
this.value = this.formats[this.valueKey].format(datum);
|
||||||
|
|
||||||
|
var limit = this.limitEvaluator.evaluate(datum, this.valueMetadata);
|
||||||
|
|
||||||
|
if (limit) {
|
||||||
|
this.valueClass = limit.cssClass;
|
||||||
|
} else {
|
||||||
|
this.valueClass = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateName(name) {
|
||||||
|
this.name = name;
|
||||||
|
},
|
||||||
|
updateTimeSystem(timeSystem) {
|
||||||
|
this.value = '---';
|
||||||
|
this.timestamp = '---';
|
||||||
|
this.valueClass = '';
|
||||||
|
this.timestampKey = timeSystem.key;
|
||||||
|
|
||||||
|
this.openmct
|
||||||
|
.telemetry
|
||||||
|
.request(this.domainObject, {strategy: 'latest'})
|
||||||
|
.then((array) => this.updateValues(array[array.length - 1]));
|
||||||
|
|
||||||
|
},
|
||||||
|
showContextMenu(event) {
|
||||||
|
this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -33,14 +33,13 @@
|
|||||||
<lad-row
|
<lad-row
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
:domainObject="item.domainObject">
|
:domain-object="item.domainObject"
|
||||||
</lad-row>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import lodash from 'lodash';
|
|
||||||
import LadRow from './LADRow.vue';
|
import LadRow from './LADRow.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -53,6 +52,18 @@ export default {
|
|||||||
items: []
|
items: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
|
this.composition.on('add', this.addItem);
|
||||||
|
this.composition.on('remove', this.removeItem);
|
||||||
|
this.composition.on('reorder', this.reorder);
|
||||||
|
this.composition.load();
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.composition.off('add', this.addItem);
|
||||||
|
this.composition.off('remove', this.removeItem);
|
||||||
|
this.composition.off('reorder', this.reorder);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addItem(domainObject) {
|
addItem(domainObject) {
|
||||||
let item = {};
|
let item = {};
|
||||||
@ -72,18 +83,6 @@ export default {
|
|||||||
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
|
||||||
this.composition.on('add', this.addItem);
|
|
||||||
this.composition.on('remove', this.removeItem);
|
|
||||||
this.composition.on('reorder', this.reorder);
|
|
||||||
this.composition.load();
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.composition.off('add', this.addItem);
|
|
||||||
this.composition.off('remove', this.removeItem);
|
|
||||||
this.composition.off('reorder', this.reorder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,29 +21,34 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<table class="c-table c-lad-table">
|
<table class="c-table c-lad-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Timestamp</th>
|
<th>Timestamp</th>
|
||||||
<th>Value</th>
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<template
|
||||||
|
v-for="primary in primaryTelemetryObjects"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
:key="primary.key"
|
||||||
|
class="c-table__group-header"
|
||||||
|
>
|
||||||
|
<td colspan="10">
|
||||||
|
{{ primary.domainObject.name }}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
<lad-row
|
||||||
<tbody>
|
v-for="secondary in secondaryTelemetryObjects[primary.key]"
|
||||||
<template
|
:key="secondary.key"
|
||||||
v-for="primary in primaryTelemetryObjects">
|
:domain-object="secondary.domainObject"
|
||||||
<tr class="c-table__group-header"
|
/>
|
||||||
:key="primary.key">
|
</template>
|
||||||
<td colspan="10">{{primary.domainObject.name}}</td>
|
</tbody>
|
||||||
</tr>
|
</table>
|
||||||
<lad-row
|
|
||||||
v-for="secondary in secondaryTelemetryObjects[primary.key]"
|
|
||||||
:key="secondary.key"
|
|
||||||
:domainObject="secondary.domainObject">
|
|
||||||
</lad-row>
|
|
||||||
</template>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -51,10 +56,9 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import lodash from 'lodash';
|
import LadRow from './LADRow.vue';
|
||||||
import LadRow from './LADRow.vue';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'domainObject'],
|
inject: ['openmct', 'domainObject'],
|
||||||
components: {
|
components: {
|
||||||
LadRow
|
LadRow
|
||||||
@ -66,6 +70,22 @@
|
|||||||
compositions: []
|
compositions: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
|
this.composition.on('add', this.addPrimary);
|
||||||
|
this.composition.on('remove', this.removePrimary);
|
||||||
|
this.composition.on('reorder', this.reorderPrimary);
|
||||||
|
this.composition.load();
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.composition.off('add', this.addPrimary);
|
||||||
|
this.composition.off('remove', this.removePrimary);
|
||||||
|
this.composition.off('reorder', this.reorderPrimary);
|
||||||
|
this.compositions.forEach(c => {
|
||||||
|
c.composition.off('add', c.addCallback);
|
||||||
|
c.composition.off('remove', c.removeCallback);
|
||||||
|
});
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addPrimary(domainObject) {
|
addPrimary(domainObject) {
|
||||||
let primary = {};
|
let primary = {};
|
||||||
@ -75,7 +95,7 @@
|
|||||||
this.$set(this.secondaryTelemetryObjects, primary.key, []);
|
this.$set(this.secondaryTelemetryObjects, primary.key, []);
|
||||||
this.primaryTelemetryObjects.push(primary);
|
this.primaryTelemetryObjects.push(primary);
|
||||||
|
|
||||||
let composition = openmct.composition.get(primary.domainObject),
|
let composition = this.openmct.composition.get(primary.domainObject),
|
||||||
addCallback = this.addSecondary(primary),
|
addCallback = this.addSecondary(primary),
|
||||||
removeCallback = this.removeSecondary(primary);
|
removeCallback = this.removeSecondary(primary);
|
||||||
|
|
||||||
@ -121,23 +141,6 @@
|
|||||||
this.$set(this.secondaryTelemetryObjects, primary.key, array);
|
this.$set(this.secondaryTelemetryObjects, primary.key, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
|
||||||
this.composition.on('add', this.addPrimary);
|
|
||||||
this.composition.on('remove', this.removePrimary);
|
|
||||||
this.composition.on('reorder', this.reorderPrimary);
|
|
||||||
this.composition.load();
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.composition.off('add', this.addPrimary);
|
|
||||||
this.composition.off('remove', this.removePrimary);
|
|
||||||
this.composition.off('reorder', this.reorderPrimary);
|
|
||||||
this.compositions.forEach(c => {
|
|
||||||
c.composition.off('add', c.addCallback);
|
|
||||||
c.composition.off('remove', c.removeCallback);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-indicator c-indicator--clickable icon-clear-data s-status-caution">
|
<div class="c-indicator c-indicator--clickable icon-clear-data s-status-caution">
|
||||||
<span class="label c-indicator__label">
|
<span class="label c-indicator__label">
|
||||||
<button @click="globalClearEmit">Clear Data</button>
|
<button @click="globalClearEmit">Clear Data</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -55,11 +55,11 @@ define([
|
|||||||
openmct,
|
openmct,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
AlphanumericFormatView: AlphanumericFormatView.default
|
AlphanumericFormatView: AlphanumericFormatView.default
|
||||||
},
|
},
|
||||||
template: '<alphanumeric-format-view></alphanumeric-format-view>',
|
template: '<alphanumeric-format-view></alphanumeric-format-view>'
|
||||||
el: element
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
|
@ -21,70 +21,78 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-properties" v-if="isEditing">
|
<div
|
||||||
<div class="c-properties__header">Alphanumeric Format</div>
|
v-if="isEditing"
|
||||||
<ul class="c-properties__section">
|
class="c-properties"
|
||||||
<li class="c-properties__row">
|
>
|
||||||
<div class="c-properties__label" title="Printf formatting for the selected telemetry">
|
<div class="c-properties__header">
|
||||||
<label for="telemetryPrintfFormat">Format</label>
|
Alphanumeric Format
|
||||||
</div>
|
|
||||||
<div class="c-properties__value">
|
|
||||||
<input id="telemetryPrintfFormat"
|
|
||||||
type="text"
|
|
||||||
@change="formatTelemetry"
|
|
||||||
:value="telemetryFormat"
|
|
||||||
:placeholder="nonMixedFormat ? '' : 'Mixed'"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ul class="c-properties__section">
|
||||||
|
<li class="c-properties__row">
|
||||||
|
<div
|
||||||
|
class="c-properties__label"
|
||||||
|
title="Printf formatting for the selected telemetry"
|
||||||
|
>
|
||||||
|
<label for="telemetryPrintfFormat">Format</label>
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
<input
|
||||||
|
id="telemetryPrintfFormat"
|
||||||
|
type="text"
|
||||||
|
:value="telemetryFormat"
|
||||||
|
:placeholder="nonMixedFormat ? '' : 'Mixed'"
|
||||||
|
@change="formatTelemetry"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
data() {
|
data() {
|
||||||
let selectionPath = this.openmct.selection.get()[0];
|
return {
|
||||||
return {
|
isEditing: this.openmct.editor.isEditing(),
|
||||||
isEditing: this.openmct.editor.isEditing(),
|
telemetryFormat: undefined,
|
||||||
telemetryFormat: undefined,
|
nonMixedFormat: false
|
||||||
nonMixedFormat: false
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.openmct.editor.on('isEditing', this.toggleEdit);
|
||||||
|
this.openmct.selection.on('change', this.handleSelection);
|
||||||
|
this.handleSelection(this.openmct.selection.get());
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.editor.off('isEditing', this.toggleEdit);
|
||||||
|
this.openmct.selection.off('change', this.handleSelection);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleEdit(isEditing) {
|
||||||
|
this.isEditing = isEditing;
|
||||||
|
},
|
||||||
|
formatTelemetry(event) {
|
||||||
|
let newFormat = event.currentTarget.value;
|
||||||
|
this.openmct.selection.get().forEach(selectionPath => {
|
||||||
|
selectionPath[0].context.updateTelemetryFormat(newFormat);
|
||||||
|
});
|
||||||
|
this.telemetryFormat = newFormat;
|
||||||
|
},
|
||||||
|
handleSelection(selection) {
|
||||||
|
if (selection.length === 0 || selection[0].length < 2) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleEdit(isEditing) {
|
|
||||||
this.isEditing = isEditing;
|
|
||||||
},
|
|
||||||
formatTelemetry(event) {
|
|
||||||
let newFormat = event.currentTarget.value;
|
|
||||||
this.openmct.selection.get().forEach(selectionPath => {
|
|
||||||
selectionPath[0].context.updateTelemetryFormat(newFormat);
|
|
||||||
});
|
|
||||||
this.telemetryFormat = newFormat;
|
|
||||||
},
|
|
||||||
handleSelection(selection) {
|
|
||||||
if (selection.length === 0 || selection[0].length < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let format = selection[0][0].context.layoutItem.format;
|
let format = selection[0][0].context.layoutItem.format;
|
||||||
this.nonMixedFormat = selection.every(selectionPath => {
|
this.nonMixedFormat = selection.every(selectionPath => {
|
||||||
return selectionPath[0].context.layoutItem.format === format;
|
return selectionPath[0].context.layoutItem.format === format;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.telemetryFormat = this.nonMixedFormat ? format : '';
|
this.telemetryFormat = this.nonMixedFormat ? format : '';
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.openmct.editor.on('isEditing', this.toggleEdit);
|
|
||||||
this.openmct.selection.on('change', this.handleSelection);
|
|
||||||
this.handleSelection(this.openmct.selection.get());
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.openmct.editor.off('isEditing', this.toggleEdit);
|
|
||||||
this.openmct.selection.off('change', this.handleSelection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
@ -21,15 +21,18 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<layout-frame :item="item"
|
<layout-frame
|
||||||
:grid-size="gridSize"
|
:item="item"
|
||||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
:grid-size="gridSize"
|
||||||
@endMove="() => $emit('endMove')">
|
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||||
<div class="c-box-view"
|
@endMove="() => $emit('endMove')"
|
||||||
:style="style">
|
>
|
||||||
</div>
|
<div
|
||||||
</layout-frame>
|
class="c-box-view"
|
||||||
</template>
|
:style="style"
|
||||||
|
></div>
|
||||||
|
</layout-frame>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~styles/sass-base';
|
@import '~styles/sass-base';
|
||||||
@ -44,60 +47,70 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition() {
|
makeDefinition() {
|
||||||
|
return {
|
||||||
|
fill: '#717171',
|
||||||
|
stroke: 'transparent',
|
||||||
|
x: 1,
|
||||||
|
y: 1,
|
||||||
|
width: 10,
|
||||||
|
height: 5
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct'],
|
||||||
|
components: {
|
||||||
|
LayoutFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
gridSize: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
validator: (arr) => arr && arr.length === 2
|
||||||
|
&& arr.every(el => typeof el === 'number')
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
initSelect: Boolean
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
return {
|
return {
|
||||||
fill: '#717171',
|
backgroundColor: this.item.fill,
|
||||||
stroke: 'transparent',
|
border: '1px solid ' + this.item.stroke
|
||||||
x: 1,
|
|
||||||
y: 1,
|
|
||||||
width: 10,
|
|
||||||
height: 5
|
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
inject: ['openmct'],
|
},
|
||||||
components: {
|
watch: {
|
||||||
LayoutFrame
|
index(newIndex) {
|
||||||
},
|
if (!this.context) {
|
||||||
props: {
|
return;
|
||||||
item: Object,
|
|
||||||
gridSize: Array,
|
|
||||||
index: Number,
|
|
||||||
initSelect: Boolean
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
return {
|
|
||||||
backgroundColor: this.item.fill,
|
|
||||||
border: '1px solid ' + this.item.stroke
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
this.context.index = newIndex;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.context = {
|
this.context = {
|
||||||
layoutItem: this.item,
|
layoutItem: this.item,
|
||||||
index: this.index
|
index: this.index
|
||||||
};
|
};
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.context, this.initSelect);
|
this.$el, this.context, this.initSelect);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
if (this.removeSelectable) {
|
if (this.removeSelectable) {
|
||||||
this.removeSelectable();
|
this.removeSelectable();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
|
@ -21,42 +21,49 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="l-layout"
|
<div
|
||||||
@dragover="handleDragOver"
|
class="l-layout"
|
||||||
@click.capture="bypassSelection"
|
:class="{
|
||||||
@drop="handleDrop"
|
'is-multi-selected': selectedLayoutItems.length > 1
|
||||||
:class="{
|
}"
|
||||||
'is-multi-selected': selectedLayoutItems.length > 1
|
@dragover="handleDragOver"
|
||||||
}">
|
@click.capture="bypassSelection"
|
||||||
<!-- Background grid -->
|
@drop="handleDrop"
|
||||||
<div class="l-layout__grid-holder c-grid">
|
>
|
||||||
<div class="c-grid__x l-grid l-grid-x"
|
<!-- Background grid -->
|
||||||
v-if="gridSize[0] >= 3"
|
<div class="l-layout__grid-holder c-grid">
|
||||||
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]">
|
<div
|
||||||
</div>
|
v-if="gridSize[0] >= 3"
|
||||||
<div class="c-grid__y l-grid l-grid-y"
|
class="c-grid__x l-grid l-grid-x"
|
||||||
v-if="gridSize[1] >= 3"
|
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]"
|
||||||
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"></div>
|
></div>
|
||||||
</div>
|
<div
|
||||||
<component v-for="(item, index) in layoutItems"
|
v-if="gridSize[1] >= 3"
|
||||||
:is="item.type"
|
class="c-grid__y l-grid l-grid-y"
|
||||||
:item="item"
|
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"
|
||||||
:key="item.id"
|
></div>
|
||||||
:gridSize="gridSize"
|
|
||||||
:initSelect="initSelectIndex === index"
|
|
||||||
:index="index"
|
|
||||||
:multiSelect="selectedLayoutItems.length > 1"
|
|
||||||
@move="move"
|
|
||||||
@endMove="endMove"
|
|
||||||
@endLineResize='endLineResize'
|
|
||||||
@formatChanged='updateTelemetryFormat'>
|
|
||||||
</component>
|
|
||||||
<edit-marquee v-if='showMarquee'
|
|
||||||
:gridSize="gridSize"
|
|
||||||
:selectedLayoutItems="selectedLayoutItems"
|
|
||||||
@endResize="endResize">
|
|
||||||
</edit-marquee>
|
|
||||||
</div>
|
</div>
|
||||||
|
<component
|
||||||
|
:is="item.type"
|
||||||
|
v-for="(item, index) in layoutItems"
|
||||||
|
:key="item.id"
|
||||||
|
:item="item"
|
||||||
|
:grid-size="gridSize"
|
||||||
|
:init-select="initSelectIndex === index"
|
||||||
|
:index="index"
|
||||||
|
:multi-select="selectedLayoutItems.length > 1"
|
||||||
|
@move="move"
|
||||||
|
@endMove="endMove"
|
||||||
|
@endLineResize="endLineResize"
|
||||||
|
@formatChanged="updateTelemetryFormat"
|
||||||
|
/>
|
||||||
|
<edit-marquee
|
||||||
|
v-if="showMarquee"
|
||||||
|
:grid-size="gridSize"
|
||||||
|
:selected-layout-items="selectedLayoutItems"
|
||||||
|
@endResize="endResize"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -135,452 +142,455 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import uuid from 'uuid';
|
import uuid from 'uuid';
|
||||||
|
|
||||||
import SubobjectView from './SubobjectView.vue'
|
import SubobjectView from './SubobjectView.vue'
|
||||||
import TelemetryView from './TelemetryView.vue'
|
import TelemetryView from './TelemetryView.vue'
|
||||||
import BoxView from './BoxView.vue'
|
import BoxView from './BoxView.vue'
|
||||||
import TextView from './TextView.vue'
|
import TextView from './TextView.vue'
|
||||||
import LineView from './LineView.vue'
|
import LineView from './LineView.vue'
|
||||||
import ImageView from './ImageView.vue'
|
import ImageView from './ImageView.vue'
|
||||||
import EditMarquee from './EditMarquee.vue'
|
import EditMarquee from './EditMarquee.vue'
|
||||||
|
|
||||||
const ITEM_TYPE_VIEW_MAP = {
|
const ITEM_TYPE_VIEW_MAP = {
|
||||||
'subobject-view': SubobjectView,
|
'subobject-view': SubobjectView,
|
||||||
'telemetry-view': TelemetryView,
|
'telemetry-view': TelemetryView,
|
||||||
'box-view': BoxView,
|
'box-view': BoxView,
|
||||||
'line-view': LineView,
|
'line-view': LineView,
|
||||||
'text-view': TextView,
|
'text-view': TextView,
|
||||||
'image-view': ImageView
|
'image-view': ImageView
|
||||||
};
|
};
|
||||||
const ORDERS = {
|
const ORDERS = {
|
||||||
top: Number.POSITIVE_INFINITY,
|
top: Number.POSITIVE_INFINITY,
|
||||||
up: 1,
|
up: 1,
|
||||||
down: -1,
|
down: -1,
|
||||||
bottom: Number.NEGATIVE_INFINITY
|
bottom: Number.NEGATIVE_INFINITY
|
||||||
};
|
};
|
||||||
const DRAG_OBJECT_TRANSFER_PREFIX = 'openmct/domain-object/';
|
const DRAG_OBJECT_TRANSFER_PREFIX = 'openmct/domain-object/';
|
||||||
|
|
||||||
let components = ITEM_TYPE_VIEW_MAP;
|
let components = ITEM_TYPE_VIEW_MAP;
|
||||||
components['edit-marquee'] = EditMarquee;
|
components['edit-marquee'] = EditMarquee;
|
||||||
|
|
||||||
function getItemDefinition(itemType, ...options) {
|
function getItemDefinition(itemType, ...options) {
|
||||||
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
|
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
|
||||||
|
|
||||||
if (!itemView) {
|
if (!itemView) {
|
||||||
throw `Invalid itemType: ${itemType}`;
|
throw `Invalid itemType: ${itemType}`;
|
||||||
}
|
|
||||||
|
|
||||||
return itemView.makeDefinition(...options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
return itemView.makeDefinition(...options);
|
||||||
data() {
|
}
|
||||||
let domainObject = JSON.parse(JSON.stringify(this.domainObject));
|
|
||||||
return {
|
export default {
|
||||||
internalDomainObject: domainObject,
|
components: components,
|
||||||
initSelectIndex: undefined,
|
props: {
|
||||||
selection: []
|
domainObject: {
|
||||||
};
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
let domainObject = JSON.parse(JSON.stringify(this.domainObject));
|
||||||
|
return {
|
||||||
|
internalDomainObject: domainObject,
|
||||||
|
initSelectIndex: undefined,
|
||||||
|
selection: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
gridSize() {
|
||||||
|
return this.internalDomainObject.configuration.layoutGrid;
|
||||||
},
|
},
|
||||||
computed: {
|
layoutItems() {
|
||||||
gridSize() {
|
return this.internalDomainObject.configuration.items;
|
||||||
return this.internalDomainObject.configuration.layoutGrid;
|
},
|
||||||
},
|
selectedLayoutItems() {
|
||||||
layoutItems() {
|
return this.layoutItems.filter(item => {
|
||||||
return this.internalDomainObject.configuration.items;
|
return this.itemIsInCurrentSelection(item);
|
||||||
},
|
});
|
||||||
selectedLayoutItems() {
|
},
|
||||||
return this.layoutItems.filter(item => {
|
showMarquee() {
|
||||||
return this.itemIsInCurrentSelection(item);
|
let selectionPath = this.selection[0];
|
||||||
});
|
let singleSelectedLine = this.selection.length === 1 &&
|
||||||
},
|
|
||||||
showMarquee() {
|
|
||||||
let selectionPath = this.selection[0];
|
|
||||||
let singleSelectedLine = this.selection.length === 1 &&
|
|
||||||
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.type === 'line-view';
|
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.type === 'line-view';
|
||||||
return selectionPath && selectionPath.length > 1 && !singleSelectedLine;
|
return selectionPath && selectionPath.length > 1 && !singleSelectedLine;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inject: ['openmct', 'options', 'objectPath'],
|
||||||
|
mounted() {
|
||||||
|
this.unlisten = this.openmct.objects.observe(this.internalDomainObject, '*', function (obj) {
|
||||||
|
this.internalDomainObject = JSON.parse(JSON.stringify(obj));
|
||||||
|
}.bind(this));
|
||||||
|
this.openmct.selection.on('change', this.setSelection);
|
||||||
|
this.initializeItems();
|
||||||
|
this.composition = this.openmct.composition.get(this.internalDomainObject);
|
||||||
|
this.composition.on('add', this.addChild);
|
||||||
|
this.composition.on('remove', this.removeChild);
|
||||||
|
this.composition.load();
|
||||||
|
},
|
||||||
|
destroyed: function () {
|
||||||
|
this.openmct.selection.off('change', this.setSelection);
|
||||||
|
this.composition.off('add', this.addChild);
|
||||||
|
this.composition.off('remove', this.removeChild);
|
||||||
|
this.unlisten();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addElement(itemType, element) {
|
||||||
|
this.addItem(itemType + '-view', element);
|
||||||
|
},
|
||||||
|
setSelection(selection) {
|
||||||
|
this.selection = selection;
|
||||||
|
},
|
||||||
|
itemIsInCurrentSelection(item) {
|
||||||
|
return this.selection.some(selectionPath =>
|
||||||
|
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.id === item.id);
|
||||||
|
},
|
||||||
|
bypassSelection($event) {
|
||||||
|
if (this.dragInProgress) {
|
||||||
|
if ($event) {
|
||||||
|
$event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
this.dragInProgress = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inject: ['openmct', 'options', 'objectPath'],
|
endLineResize(item, updates) {
|
||||||
props: ['domainObject'],
|
this.dragInProgress = true;
|
||||||
components: components,
|
let index = this.layoutItems.indexOf(item);
|
||||||
methods: {
|
Object.assign(item, updates);
|
||||||
addElement(itemType, element) {
|
this.mutate(`configuration.items[${index}]`, item);
|
||||||
this.addItem(itemType + '-view', element);
|
},
|
||||||
},
|
endResize(scaleWidth, scaleHeight, marqueeStart, marqueeOffset) {
|
||||||
setSelection(selection) {
|
this.dragInProgress = true;
|
||||||
this.selection = selection;
|
this.layoutItems.forEach(item => {
|
||||||
},
|
if (this.itemIsInCurrentSelection(item)) {
|
||||||
itemIsInCurrentSelection(item) {
|
let itemXInMarqueeSpace = item.x - marqueeStart.x;
|
||||||
return this.selection.some(selectionPath =>
|
let itemXInMarqueeSpaceAfterScale = Math.round(itemXInMarqueeSpace * scaleWidth);
|
||||||
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.id === item.id);
|
item.x = itemXInMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
|
||||||
},
|
|
||||||
bypassSelection($event) {
|
|
||||||
if (this.dragInProgress) {
|
|
||||||
if ($event) {
|
|
||||||
$event.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
this.dragInProgress = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
endLineResize(item, updates) {
|
|
||||||
this.dragInProgress = true;
|
|
||||||
let index = this.layoutItems.indexOf(item);
|
|
||||||
Object.assign(item, updates);
|
|
||||||
this.mutate(`configuration.items[${index}]`, item);
|
|
||||||
},
|
|
||||||
endResize(scaleWidth, scaleHeight, marqueeStart, marqueeOffset) {
|
|
||||||
this.dragInProgress = true;
|
|
||||||
this.layoutItems.forEach(item => {
|
|
||||||
if (this.itemIsInCurrentSelection(item)) {
|
|
||||||
let itemXInMarqueeSpace = item.x - marqueeStart.x;
|
|
||||||
let itemXInMarqueeSpaceAfterScale = Math.round(itemXInMarqueeSpace * scaleWidth);
|
|
||||||
item.x = itemXInMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
|
|
||||||
|
|
||||||
let itemYInMarqueeSpace = item.y - marqueeStart.y;
|
let itemYInMarqueeSpace = item.y - marqueeStart.y;
|
||||||
let itemYInMarqueeSpaceAfterScale = Math.round(itemYInMarqueeSpace * scaleHeight);
|
let itemYInMarqueeSpaceAfterScale = Math.round(itemYInMarqueeSpace * scaleHeight);
|
||||||
item.y = itemYInMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
|
item.y = itemYInMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
|
||||||
|
|
||||||
if (item.x2) {
|
if (item.x2) {
|
||||||
let itemX2InMarqueeSpace = item.x2 - marqueeStart.x;
|
let itemX2InMarqueeSpace = item.x2 - marqueeStart.x;
|
||||||
let itemX2InMarqueeSpaceAfterScale = Math.round(itemX2InMarqueeSpace * scaleWidth);
|
let itemX2InMarqueeSpaceAfterScale = Math.round(itemX2InMarqueeSpace * scaleWidth);
|
||||||
item.x2 = itemX2InMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
|
item.x2 = itemX2InMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
|
||||||
} else {
|
|
||||||
item.width = Math.round(item.width * scaleWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.y2) {
|
|
||||||
let itemY2InMarqueeSpace = item.y2 - marqueeStart.y;
|
|
||||||
let itemY2InMarqueeSpaceAfterScale = Math.round(itemY2InMarqueeSpace * scaleHeight);
|
|
||||||
item.y2 = itemY2InMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
|
|
||||||
} else {
|
|
||||||
item.height = Math.round(item.height * scaleHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.mutate("configuration.items", this.layoutItems);
|
|
||||||
},
|
|
||||||
move(gridDelta) {
|
|
||||||
this.dragInProgress = true;
|
|
||||||
|
|
||||||
if (!this.initialPositions) {
|
|
||||||
this.initialPositions = {};
|
|
||||||
_.cloneDeep(this.selectedLayoutItems).forEach(selectedItem => {
|
|
||||||
if (selectedItem.type === 'line-view') {
|
|
||||||
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y, selectedItem.x2, selectedItem.y2];
|
|
||||||
this.startingMinX2 = this.startingMinX2 !== undefined ? Math.min(this.startingMinX2, selectedItem.x2) : selectedItem.x2;
|
|
||||||
this.startingMinY2 = this.startingMinY2 !== undefined ? Math.min(this.startingMinY2, selectedItem.y2) : selectedItem.y2;
|
|
||||||
} else {
|
|
||||||
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.startingMinX = this.startingMinX !== undefined ? Math.min(this.startingMinX, selectedItem.x) : selectedItem.x;
|
|
||||||
this.startingMinY = this.startingMinY !== undefined ? Math.min(this.startingMinY, selectedItem.y) : selectedItem.y;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let layoutItems = this.layoutItems.map(item => {
|
|
||||||
if (this.initialPositions[item.id]) {
|
|
||||||
this.updateItemPosition(item, gridDelta);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateItemPosition(item, gridDelta) {
|
|
||||||
let startingPosition = this.initialPositions[item.id];
|
|
||||||
let [startingX, startingY, startingX2, startingY2] = startingPosition;
|
|
||||||
|
|
||||||
if (this.startingMinX + gridDelta[0] >= 0) {
|
|
||||||
if (item.x2 !== undefined) {
|
|
||||||
if (this.startingMinX2 + gridDelta[0] >= 0) {
|
|
||||||
item.x = startingX + gridDelta[0];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
item.width = Math.round(item.width * scaleWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.y2) {
|
||||||
|
let itemY2InMarqueeSpace = item.y2 - marqueeStart.y;
|
||||||
|
let itemY2InMarqueeSpaceAfterScale = Math.round(itemY2InMarqueeSpace * scaleHeight);
|
||||||
|
item.y2 = itemY2InMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
|
||||||
|
} else {
|
||||||
|
item.height = Math.round(item.height * scaleHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.mutate("configuration.items", this.layoutItems);
|
||||||
|
},
|
||||||
|
move(gridDelta) {
|
||||||
|
this.dragInProgress = true;
|
||||||
|
|
||||||
|
if (!this.initialPositions) {
|
||||||
|
this.initialPositions = {};
|
||||||
|
_.cloneDeep(this.selectedLayoutItems).forEach(selectedItem => {
|
||||||
|
if (selectedItem.type === 'line-view') {
|
||||||
|
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y, selectedItem.x2, selectedItem.y2];
|
||||||
|
this.startingMinX2 = this.startingMinX2 !== undefined ? Math.min(this.startingMinX2, selectedItem.x2) : selectedItem.x2;
|
||||||
|
this.startingMinY2 = this.startingMinY2 !== undefined ? Math.min(this.startingMinY2, selectedItem.y2) : selectedItem.y2;
|
||||||
|
} else {
|
||||||
|
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startingMinX = this.startingMinX !== undefined ? Math.min(this.startingMinX, selectedItem.x) : selectedItem.x;
|
||||||
|
this.startingMinY = this.startingMinY !== undefined ? Math.min(this.startingMinY, selectedItem.y) : selectedItem.y;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layoutItems.forEach(item => {
|
||||||
|
if (this.initialPositions[item.id]) {
|
||||||
|
this.updateItemPosition(item, gridDelta);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateItemPosition(item, gridDelta) {
|
||||||
|
let startingPosition = this.initialPositions[item.id];
|
||||||
|
let [startingX, startingY, startingX2, startingY2] = startingPosition;
|
||||||
|
|
||||||
|
if (this.startingMinX + gridDelta[0] >= 0) {
|
||||||
|
if (item.x2 !== undefined) {
|
||||||
|
if (this.startingMinX2 + gridDelta[0] >= 0) {
|
||||||
item.x = startingX + gridDelta[0];
|
item.x = startingX + gridDelta[0];
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
item.x = startingX + gridDelta[0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.startingMinY + gridDelta[1] >= 0) {
|
if (this.startingMinY + gridDelta[1] >= 0) {
|
||||||
if (item.y2 !== undefined) {
|
if (item.y2 !== undefined) {
|
||||||
if (this.startingMinY2 + gridDelta[1] >= 0) {
|
if (this.startingMinY2 + gridDelta[1] >= 0) {
|
||||||
item.y = startingY + gridDelta[1];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item.y = startingY + gridDelta[1];
|
item.y = startingY + gridDelta[1];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (item.x2 !== undefined && this.startingMinX2 + gridDelta[0] >= 0 && this.startingMinX + gridDelta[0] >= 0) {
|
|
||||||
item.x2 = startingX2 + gridDelta[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.y2 !== undefined && this.startingMinY2 + gridDelta[1] >= 0 && this.startingMinY + gridDelta[1] >= 0) {
|
|
||||||
item.y2 = startingY2 + gridDelta[1];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
endMove() {
|
|
||||||
this.mutate('configuration.items', this.layoutItems);
|
|
||||||
this.initialPositions = undefined;
|
|
||||||
this.startingMinX = undefined;
|
|
||||||
this.startingMinY = undefined;
|
|
||||||
this.startingMinX2 = undefined;
|
|
||||||
this.startingMinY2 = undefined;
|
|
||||||
},
|
|
||||||
mutate(path, value) {
|
|
||||||
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
|
||||||
},
|
|
||||||
handleDrop($event) {
|
|
||||||
if (!$event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$event.preventDefault();
|
|
||||||
|
|
||||||
let domainObject = JSON.parse($event.dataTransfer.getData('openmct/domain-object-path'))[0];
|
|
||||||
let elementRect = this.$el.getBoundingClientRect();
|
|
||||||
let droppedObjectPosition = [
|
|
||||||
Math.floor(($event.pageX - elementRect.left) / this.gridSize[0]),
|
|
||||||
Math.floor(($event.pageY - elementRect.top) / this.gridSize[1])
|
|
||||||
];
|
|
||||||
|
|
||||||
if (this.isTelemetry(domainObject)) {
|
|
||||||
this.addItem('telemetry-view', domainObject, droppedObjectPosition);
|
|
||||||
} else {
|
} else {
|
||||||
let identifier = this.openmct.objects.makeKeyString(domainObject.identifier);
|
item.y = startingY + gridDelta[1];
|
||||||
|
|
||||||
if (!this.objectViewMap[identifier]) {
|
|
||||||
this.addItem('subobject-view', domainObject, droppedObjectPosition);
|
|
||||||
} else {
|
|
||||||
let prompt = this.openmct.overlays.dialog({
|
|
||||||
iconClass: 'alert',
|
|
||||||
message: "This item is already in layout and will not be added again.",
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
label: 'OK',
|
|
||||||
callback: function () {
|
|
||||||
prompt.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
containsObject(identifier) {
|
|
||||||
return _.get(this.internalDomainObject, 'composition')
|
if (item.x2 !== undefined && this.startingMinX2 + gridDelta[0] >= 0 && this.startingMinX + gridDelta[0] >= 0) {
|
||||||
.some(childId => this.openmct.objects.areIdsEqual(childId, identifier));
|
item.x2 = startingX2 + gridDelta[0];
|
||||||
},
|
}
|
||||||
handleDragOver($event) {
|
|
||||||
// Get the ID of the dragged object
|
if (item.y2 !== undefined && this.startingMinY2 + gridDelta[1] >= 0 && this.startingMinY + gridDelta[1] >= 0) {
|
||||||
let draggedKeyString = $event.dataTransfer.types
|
item.y2 = startingY2 + gridDelta[1];
|
||||||
.filter(type => type.startsWith(DRAG_OBJECT_TRANSFER_PREFIX))
|
}
|
||||||
.map(type => type.substring(DRAG_OBJECT_TRANSFER_PREFIX.length))[0];
|
},
|
||||||
|
endMove() {
|
||||||
|
this.mutate('configuration.items', this.layoutItems);
|
||||||
|
this.initialPositions = undefined;
|
||||||
|
this.startingMinX = undefined;
|
||||||
|
this.startingMinY = undefined;
|
||||||
|
this.startingMinX2 = undefined;
|
||||||
|
this.startingMinY2 = undefined;
|
||||||
|
},
|
||||||
|
mutate(path, value) {
|
||||||
|
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
||||||
|
},
|
||||||
|
handleDrop($event) {
|
||||||
|
if (!$event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event.preventDefault();
|
||||||
|
|
||||||
|
let domainObject = JSON.parse($event.dataTransfer.getData('openmct/domain-object-path'))[0];
|
||||||
|
let elementRect = this.$el.getBoundingClientRect();
|
||||||
|
let droppedObjectPosition = [
|
||||||
|
Math.floor(($event.pageX - elementRect.left) / this.gridSize[0]),
|
||||||
|
Math.floor(($event.pageY - elementRect.top) / this.gridSize[1])
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.isTelemetry(domainObject)) {
|
||||||
|
this.addItem('telemetry-view', domainObject, droppedObjectPosition);
|
||||||
|
} else {
|
||||||
|
let identifier = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
|
||||||
|
if (!this.objectViewMap[identifier]) {
|
||||||
|
this.addItem('subobject-view', domainObject, droppedObjectPosition);
|
||||||
|
} else {
|
||||||
|
let prompt = this.openmct.overlays.dialog({
|
||||||
|
iconClass: 'alert',
|
||||||
|
message: "This item is already in layout and will not be added again.",
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
label: 'OK',
|
||||||
|
callback: function () {
|
||||||
|
prompt.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
containsObject(identifier) {
|
||||||
|
return _.get(this.internalDomainObject, 'composition')
|
||||||
|
.some(childId => this.openmct.objects.areIdsEqual(childId, identifier));
|
||||||
|
},
|
||||||
|
handleDragOver($event) {
|
||||||
|
// Get the ID of the dragged object
|
||||||
|
let draggedKeyString = $event.dataTransfer.types
|
||||||
|
.filter(type => type.startsWith(DRAG_OBJECT_TRANSFER_PREFIX))
|
||||||
|
.map(type => type.substring(DRAG_OBJECT_TRANSFER_PREFIX.length))[0];
|
||||||
|
|
||||||
// If the layout already contains the given object, then shortcut the default dragover behavior and
|
// If the layout already contains the given object, then shortcut the default dragover behavior and
|
||||||
// potentially allow drop. Display layouts allow drag drop of duplicate telemetry objects.
|
// potentially allow drop. Display layouts allow drag drop of duplicate telemetry objects.
|
||||||
if (this.containsObject(draggedKeyString)){
|
if (this.containsObject(draggedKeyString)) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
}
|
|
||||||
},
|
|
||||||
isTelemetry(domainObject) {
|
|
||||||
if (this.openmct.telemetry.isTelemetryObject(domainObject) &&
|
|
||||||
!this.options.showAsView.includes(domainObject.type)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addItem(itemType, ...options) {
|
|
||||||
let item = getItemDefinition(itemType, this.openmct, this.gridSize, ...options);
|
|
||||||
item.type = itemType;
|
|
||||||
item.id = uuid();
|
|
||||||
this.trackItem(item);
|
|
||||||
this.layoutItems.push(item);
|
|
||||||
this.openmct.objects.mutate(this.internalDomainObject, "configuration.items", this.layoutItems);
|
|
||||||
this.initSelectIndex = this.layoutItems.length - 1;
|
|
||||||
},
|
|
||||||
trackItem(item) {
|
|
||||||
if (!item.identifier) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
|
||||||
|
|
||||||
if (item.type === "telemetry-view") {
|
|
||||||
let count = this.telemetryViewMap[keyString] || 0;
|
|
||||||
this.telemetryViewMap[keyString] = ++count;
|
|
||||||
} else if (item.type === "subobject-view") {
|
|
||||||
this.objectViewMap[keyString] = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeItem(selectedItems) {
|
|
||||||
let indices = [];
|
|
||||||
this.initSelectIndex = -1;
|
|
||||||
selectedItems.forEach(selectedItem => {
|
|
||||||
indices.push(selectedItem[0].context.index);
|
|
||||||
this.untrackItem(selectedItem[0].context.layoutItem);
|
|
||||||
});
|
|
||||||
_.pullAt(this.layoutItems, indices);
|
|
||||||
this.mutate("configuration.items", this.layoutItems);
|
|
||||||
this.$el.click();
|
|
||||||
},
|
|
||||||
untrackItem(item) {
|
|
||||||
if (!item.identifier) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
|
||||||
|
|
||||||
if (item.type === 'telemetry-view') {
|
|
||||||
let count = --this.telemetryViewMap[keyString];
|
|
||||||
|
|
||||||
if (count === 0) {
|
|
||||||
delete this.telemetryViewMap[keyString];
|
|
||||||
this.removeFromComposition(keyString);
|
|
||||||
}
|
|
||||||
} else if (item.type === 'subobject-view') {
|
|
||||||
delete this.objectViewMap[keyString];
|
|
||||||
this.removeFromComposition(keyString);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeFromComposition(keyString) {
|
|
||||||
let composition = _.get(this.internalDomainObject, 'composition');
|
|
||||||
composition = composition.filter(identifier => {
|
|
||||||
return this.openmct.objects.makeKeyString(identifier) !== keyString;
|
|
||||||
});
|
|
||||||
this.mutate("composition", composition);
|
|
||||||
},
|
|
||||||
initializeItems() {
|
|
||||||
this.telemetryViewMap = {};
|
|
||||||
this.objectViewMap = {};
|
|
||||||
this.layoutItems.forEach(this.trackItem);
|
|
||||||
},
|
|
||||||
addChild(child) {
|
|
||||||
let identifier = this.openmct.objects.makeKeyString(child.identifier);
|
|
||||||
if (this.isTelemetry(child)) {
|
|
||||||
if (!this.telemetryViewMap[identifier]) {
|
|
||||||
this.addItem('telemetry-view', child);
|
|
||||||
}
|
|
||||||
} else if (!this.objectViewMap[identifier]) {
|
|
||||||
this.addItem('subobject-view', child);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeChild(identifier) {
|
|
||||||
let keyString = this.openmct.objects.makeKeyString(identifier);
|
|
||||||
|
|
||||||
if (this.objectViewMap[keyString]) {
|
|
||||||
delete this.objectViewMap[keyString];
|
|
||||||
this.removeFromConfiguration(keyString);
|
|
||||||
} else if (this.telemetryViewMap[keyString]) {
|
|
||||||
delete this.telemetryViewMap[keyString];
|
|
||||||
this.removeFromConfiguration(keyString);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeFromConfiguration(keyString) {
|
|
||||||
let layoutItems = this.layoutItems.filter(item => {
|
|
||||||
if (!item.identifier) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return this.openmct.objects.makeKeyString(item.identifier) !== keyString;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.mutate("configuration.items", layoutItems);
|
|
||||||
this.$el.click();
|
|
||||||
},
|
|
||||||
orderItem(position, selectedItems) {
|
|
||||||
let delta = ORDERS[position];
|
|
||||||
let indices = [];
|
|
||||||
let newIndex = -1;
|
|
||||||
let items = [];
|
|
||||||
|
|
||||||
Object.assign(items, this.layoutItems);
|
|
||||||
this.selectedLayoutItems.forEach(selectedItem => {
|
|
||||||
indices.push(this.layoutItems.indexOf(selectedItem));
|
|
||||||
});
|
|
||||||
indices.sort((a, b) => a - b);
|
|
||||||
|
|
||||||
if (position === 'top' || position === 'up') {
|
|
||||||
indices.reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position === 'top' || position === 'bottom') {
|
|
||||||
this.moveToTopOrBottom(position, indices, items, delta);
|
|
||||||
} else {
|
|
||||||
this.moveUpOrDown(position, indices, items, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mutate('configuration.items', this.layoutItems);
|
|
||||||
},
|
|
||||||
moveUpOrDown(position, indices, items, delta) {
|
|
||||||
let previousItemIndex = -1;
|
|
||||||
let newIndex = -1;
|
|
||||||
|
|
||||||
indices.forEach((itemIndex, index) => {
|
|
||||||
let isAdjacentItemSelected = position === 'up' ?
|
|
||||||
itemIndex + 1 === previousItemIndex :
|
|
||||||
itemIndex - 1 === previousItemIndex;
|
|
||||||
|
|
||||||
if (index > 0 && isAdjacentItemSelected) {
|
|
||||||
if (position === 'up') {
|
|
||||||
newIndex -= 1;
|
|
||||||
} else {
|
|
||||||
newIndex += 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
previousItemIndex = itemIndex;
|
|
||||||
this.updateItemOrder(newIndex, itemIndex, items);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moveToTopOrBottom(position, indices, items, delta) {
|
|
||||||
let newIndex = -1;
|
|
||||||
|
|
||||||
indices.forEach((itemIndex, index) => {
|
|
||||||
if (index === 0) {
|
|
||||||
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
|
|
||||||
} else {
|
|
||||||
if (position === 'top') {
|
|
||||||
newIndex -= 1;
|
|
||||||
} else {
|
|
||||||
newIndex += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateItemOrder(newIndex, itemIndex, items);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateItemOrder(newIndex, itemIndex, items) {
|
|
||||||
if (newIndex !== itemIndex) {
|
|
||||||
this.layoutItems.splice(itemIndex, 1);
|
|
||||||
this.layoutItems.splice(newIndex, 0, items[itemIndex]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateTelemetryFormat(item, format) {
|
|
||||||
let index = _.findIndex(this.layoutItems, item);
|
|
||||||
item.format = format;
|
|
||||||
this.mutate(`configuration.items[${index}]`, item);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
isTelemetry(domainObject) {
|
||||||
this.unlisten = this.openmct.objects.observe(this.internalDomainObject, '*', function (obj) {
|
if (this.openmct.telemetry.isTelemetryObject(domainObject) &&
|
||||||
this.internalDomainObject = JSON.parse(JSON.stringify(obj));
|
!this.options.showAsView.includes(domainObject.type)) {
|
||||||
}.bind(this));
|
return true;
|
||||||
this.openmct.selection.on('change', this.setSelection);
|
} else {
|
||||||
this.initializeItems();
|
return false;
|
||||||
this.composition = this.openmct.composition.get(this.internalDomainObject);
|
}
|
||||||
this.composition.on('add', this.addChild);
|
|
||||||
this.composition.on('remove', this.removeChild);
|
|
||||||
this.composition.load();
|
|
||||||
},
|
},
|
||||||
destroyed: function () {
|
addItem(itemType, ...options) {
|
||||||
this.openmct.selection.off('change', this.setSelection);
|
let item = getItemDefinition(itemType, this.openmct, this.gridSize, ...options);
|
||||||
this.composition.off('add', this.addChild);
|
item.type = itemType;
|
||||||
this.composition.off('remove', this.removeChild);
|
item.id = uuid();
|
||||||
this.unlisten();
|
this.trackItem(item);
|
||||||
|
this.layoutItems.push(item);
|
||||||
|
this.openmct.objects.mutate(this.internalDomainObject, "configuration.items", this.layoutItems);
|
||||||
|
this.initSelectIndex = this.layoutItems.length - 1;
|
||||||
|
},
|
||||||
|
trackItem(item) {
|
||||||
|
if (!item.identifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||||
|
|
||||||
|
if (item.type === "telemetry-view") {
|
||||||
|
let count = this.telemetryViewMap[keyString] || 0;
|
||||||
|
this.telemetryViewMap[keyString] = ++count;
|
||||||
|
} else if (item.type === "subobject-view") {
|
||||||
|
this.objectViewMap[keyString] = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeItem(selectedItems) {
|
||||||
|
let indices = [];
|
||||||
|
this.initSelectIndex = -1;
|
||||||
|
selectedItems.forEach(selectedItem => {
|
||||||
|
indices.push(selectedItem[0].context.index);
|
||||||
|
this.untrackItem(selectedItem[0].context.layoutItem);
|
||||||
|
});
|
||||||
|
_.pullAt(this.layoutItems, indices);
|
||||||
|
this.mutate("configuration.items", this.layoutItems);
|
||||||
|
this.$el.click();
|
||||||
|
},
|
||||||
|
untrackItem(item) {
|
||||||
|
if (!item.identifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||||
|
|
||||||
|
if (item.type === 'telemetry-view') {
|
||||||
|
let count = --this.telemetryViewMap[keyString];
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
delete this.telemetryViewMap[keyString];
|
||||||
|
this.removeFromComposition(keyString);
|
||||||
|
}
|
||||||
|
} else if (item.type === 'subobject-view') {
|
||||||
|
delete this.objectViewMap[keyString];
|
||||||
|
this.removeFromComposition(keyString);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeFromComposition(keyString) {
|
||||||
|
let composition = _.get(this.internalDomainObject, 'composition');
|
||||||
|
composition = composition.filter(identifier => {
|
||||||
|
return this.openmct.objects.makeKeyString(identifier) !== keyString;
|
||||||
|
});
|
||||||
|
this.mutate("composition", composition);
|
||||||
|
},
|
||||||
|
initializeItems() {
|
||||||
|
this.telemetryViewMap = {};
|
||||||
|
this.objectViewMap = {};
|
||||||
|
this.layoutItems.forEach(this.trackItem);
|
||||||
|
},
|
||||||
|
addChild(child) {
|
||||||
|
let identifier = this.openmct.objects.makeKeyString(child.identifier);
|
||||||
|
if (this.isTelemetry(child)) {
|
||||||
|
if (!this.telemetryViewMap[identifier]) {
|
||||||
|
this.addItem('telemetry-view', child);
|
||||||
|
}
|
||||||
|
} else if (!this.objectViewMap[identifier]) {
|
||||||
|
this.addItem('subobject-view', child);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeChild(identifier) {
|
||||||
|
let keyString = this.openmct.objects.makeKeyString(identifier);
|
||||||
|
|
||||||
|
if (this.objectViewMap[keyString]) {
|
||||||
|
delete this.objectViewMap[keyString];
|
||||||
|
this.removeFromConfiguration(keyString);
|
||||||
|
} else if (this.telemetryViewMap[keyString]) {
|
||||||
|
delete this.telemetryViewMap[keyString];
|
||||||
|
this.removeFromConfiguration(keyString);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeFromConfiguration(keyString) {
|
||||||
|
let layoutItems = this.layoutItems.filter(item => {
|
||||||
|
if (!item.identifier) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return this.openmct.objects.makeKeyString(item.identifier) !== keyString;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.mutate("configuration.items", layoutItems);
|
||||||
|
this.$el.click();
|
||||||
|
},
|
||||||
|
orderItem(position, selectedItems) {
|
||||||
|
let delta = ORDERS[position];
|
||||||
|
let indices = [];
|
||||||
|
let items = [];
|
||||||
|
|
||||||
|
Object.assign(items, this.layoutItems);
|
||||||
|
this.selectedLayoutItems.forEach(selectedItem => {
|
||||||
|
indices.push(this.layoutItems.indexOf(selectedItem));
|
||||||
|
});
|
||||||
|
indices.sort((a, b) => a - b);
|
||||||
|
|
||||||
|
if (position === 'top' || position === 'up') {
|
||||||
|
indices.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position === 'top' || position === 'bottom') {
|
||||||
|
this.moveToTopOrBottom(position, indices, items, delta);
|
||||||
|
} else {
|
||||||
|
this.moveUpOrDown(position, indices, items, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mutate('configuration.items', this.layoutItems);
|
||||||
|
},
|
||||||
|
moveUpOrDown(position, indices, items, delta) {
|
||||||
|
let previousItemIndex = -1;
|
||||||
|
let newIndex = -1;
|
||||||
|
|
||||||
|
indices.forEach((itemIndex, index) => {
|
||||||
|
let isAdjacentItemSelected = position === 'up' ?
|
||||||
|
itemIndex + 1 === previousItemIndex :
|
||||||
|
itemIndex - 1 === previousItemIndex;
|
||||||
|
|
||||||
|
if (index > 0 && isAdjacentItemSelected) {
|
||||||
|
if (position === 'up') {
|
||||||
|
newIndex -= 1;
|
||||||
|
} else {
|
||||||
|
newIndex += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
previousItemIndex = itemIndex;
|
||||||
|
this.updateItemOrder(newIndex, itemIndex, items);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
moveToTopOrBottom(position, indices, items, delta) {
|
||||||
|
let newIndex = -1;
|
||||||
|
|
||||||
|
indices.forEach((itemIndex, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
|
||||||
|
} else {
|
||||||
|
if (position === 'top') {
|
||||||
|
newIndex -= 1;
|
||||||
|
} else {
|
||||||
|
newIndex += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateItemOrder(newIndex, itemIndex, items);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateItemOrder(newIndex, itemIndex, items) {
|
||||||
|
if (newIndex !== itemIndex) {
|
||||||
|
this.layoutItems.splice(itemIndex, 1);
|
||||||
|
this.layoutItems.splice(newIndex, 0, items[itemIndex]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTelemetryFormat(item, format) {
|
||||||
|
let index = _.findIndex(this.layoutItems, item);
|
||||||
|
item.format = format;
|
||||||
|
this.mutate(`configuration.items[${index}]`, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,17 +21,28 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- Resize handles -->
|
<!-- Resize handles -->
|
||||||
<div class="c-frame-edit" :style="style">
|
<div
|
||||||
<div class="c-frame-edit__handle c-frame-edit__handle--nw"
|
class="c-frame-edit"
|
||||||
@mousedown="startResize([1,1], [-1,-1], $event)"></div>
|
:style="marqueeStyle"
|
||||||
<div class="c-frame-edit__handle c-frame-edit__handle--ne"
|
>
|
||||||
@mousedown="startResize([0,1], [1,-1], $event)"></div>
|
<div
|
||||||
<div class="c-frame-edit__handle c-frame-edit__handle--sw"
|
class="c-frame-edit__handle c-frame-edit__handle--nw"
|
||||||
@mousedown="startResize([1,0], [-1,1], $event)"></div>
|
@mousedown="startResize([1,1], [-1,-1], $event)"
|
||||||
<div class="c-frame-edit__handle c-frame-edit__handle--se"
|
></div>
|
||||||
@mousedown="startResize([0,0], [1,1], $event)"></div>
|
<div
|
||||||
</div>
|
class="c-frame-edit__handle c-frame-edit__handle--ne"
|
||||||
|
@mousedown="startResize([0,1], [1,-1], $event)"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="c-frame-edit__handle c-frame-edit__handle--sw"
|
||||||
|
@mousedown="startResize([1,0], [-1,1], $event)"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="c-frame-edit__handle c-frame-edit__handle--se"
|
||||||
|
@mousedown="startResize([0,0], [1,1], $event)"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -95,139 +106,146 @@
|
|||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutDrag from './../LayoutDrag'
|
import LayoutDrag from './../LayoutDrag'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
selectedLayoutItems: Array,
|
selectedLayoutItems: {
|
||||||
gridSize: Array
|
type: Array,
|
||||||
|
default: undefined
|
||||||
},
|
},
|
||||||
data() {
|
gridSize: {
|
||||||
return {
|
type: Array,
|
||||||
dragPosition: undefined
|
required: true,
|
||||||
}
|
validator: (arr) => arr && arr.length === 2
|
||||||
},
|
&& arr.every(el => typeof el === 'number')
|
||||||
computed: {
|
}
|
||||||
style() {
|
},
|
||||||
let x = Number.POSITIVE_INFINITY;
|
data() {
|
||||||
let y = Number.POSITIVE_INFINITY;
|
return {
|
||||||
let width = Number.NEGATIVE_INFINITY;
|
dragPosition: undefined
|
||||||
let height = Number.NEGATIVE_INFINITY;
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
marqueePosition() {
|
||||||
|
let x = Number.POSITIVE_INFINITY;
|
||||||
|
let y = Number.POSITIVE_INFINITY;
|
||||||
|
let width = Number.NEGATIVE_INFINITY;
|
||||||
|
let height = Number.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
this.selectedLayoutItems.forEach(item => {
|
this.selectedLayoutItems.forEach(item => {
|
||||||
if (item.x2 !== undefined) {
|
if (item.x2 !== undefined) {
|
||||||
let lineWidth = Math.abs(item.x - item.x2);
|
let lineWidth = Math.abs(item.x - item.x2);
|
||||||
let lineMinX = Math.min(item.x, item.x2);
|
let lineMinX = Math.min(item.x, item.x2);
|
||||||
x = Math.min(lineMinX, x);
|
x = Math.min(lineMinX, x);
|
||||||
width = Math.max(lineWidth + lineMinX, width);
|
width = Math.max(lineWidth + lineMinX, width);
|
||||||
} else {
|
|
||||||
x = Math.min(item.x, x);
|
|
||||||
width = Math.max(item.width + item.x, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.y2 !== undefined) {
|
|
||||||
let lineHeight = Math.abs(item.y - item.y2);
|
|
||||||
let lineMinY = Math.min(item.y, item.y2);
|
|
||||||
y = Math.min(lineMinY, y);
|
|
||||||
height = Math.max(lineHeight + lineMinY, height);
|
|
||||||
} else {
|
|
||||||
y = Math.min(item.y, y);
|
|
||||||
height = Math.max(item.height + item.y, height);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.dragPosition) {
|
|
||||||
[x, y] = this.dragPosition.position;
|
|
||||||
[width, height] = this.dragPosition.dimensions;
|
|
||||||
} else {
|
} else {
|
||||||
width = width - x;
|
x = Math.min(item.x, x);
|
||||||
height = height - y;
|
width = Math.max(item.width + item.x, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.marqueePosition = {
|
if (item.y2 !== undefined) {
|
||||||
x: x,
|
let lineHeight = Math.abs(item.y - item.y2);
|
||||||
y: y,
|
let lineMinY = Math.min(item.y, item.y2);
|
||||||
width: width,
|
y = Math.min(lineMinY, y);
|
||||||
height: height
|
height = Math.max(lineHeight + lineMinY, height);
|
||||||
|
} else {
|
||||||
|
y = Math.min(item.y, y);
|
||||||
|
height = Math.max(item.height + item.y, height);
|
||||||
}
|
}
|
||||||
return this.getMarqueeStyle(x, y, width, height);
|
});
|
||||||
|
|
||||||
|
if (this.dragPosition) {
|
||||||
|
[x, y] = this.dragPosition.position;
|
||||||
|
[width, height] = this.dragPosition.dimensions;
|
||||||
|
} else {
|
||||||
|
width = width - x;
|
||||||
|
height = height - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
marqueeStyle() {
|
||||||
getMarqueeStyle(x, y, width, height) {
|
return {
|
||||||
return {
|
left: (this.gridSize[0] * this.marqueePosition.x) + 'px',
|
||||||
left: (this.gridSize[0] * x) + 'px',
|
top: (this.gridSize[1] * this.marqueePosition.y) + 'px',
|
||||||
top: (this.gridSize[1] * y) + 'px',
|
width: (this.gridSize[0] * this.marqueePosition.width) + 'px',
|
||||||
width: (this.gridSize[0] * width) + 'px',
|
height: (this.gridSize[1] * this.marqueePosition.height) + 'px'
|
||||||
height: (this.gridSize[1] * height) + 'px'
|
};
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
updatePosition(event) {
|
methods: {
|
||||||
let currentPosition = [event.pageX, event.pageY];
|
updatePosition(event) {
|
||||||
this.initialPosition = this.initialPosition || currentPosition;
|
let currentPosition = [event.pageX, event.pageY];
|
||||||
this.delta = currentPosition.map(function (value, index) {
|
this.initialPosition = this.initialPosition || currentPosition;
|
||||||
return value - this.initialPosition[index];
|
this.delta = currentPosition.map(function (value, index) {
|
||||||
}.bind(this));
|
return value - this.initialPosition[index];
|
||||||
},
|
}.bind(this));
|
||||||
startResize(posFactor, dimFactor, event) {
|
},
|
||||||
document.body.addEventListener('mousemove', this.continueResize);
|
startResize(posFactor, dimFactor, event) {
|
||||||
document.body.addEventListener('mouseup', this.endResize);
|
document.body.addEventListener('mousemove', this.continueResize);
|
||||||
this.marqueeStartPosition = {
|
document.body.addEventListener('mouseup', this.endResize);
|
||||||
position: [this.marqueePosition.x, this.marqueePosition.y],
|
this.marqueeStartPosition = {
|
||||||
dimensions: [this.marqueePosition.width, this.marqueePosition.height]
|
position: [this.marqueePosition.x, this.marqueePosition.y],
|
||||||
};
|
dimensions: [this.marqueePosition.width, this.marqueePosition.height]
|
||||||
this.updatePosition(event);
|
};
|
||||||
this.activeDrag = new LayoutDrag(this.marqueeStartPosition, posFactor, dimFactor, this.gridSize);
|
this.updatePosition(event);
|
||||||
event.preventDefault();
|
this.activeDrag = new LayoutDrag(this.marqueeStartPosition, posFactor, dimFactor, this.gridSize);
|
||||||
},
|
event.preventDefault();
|
||||||
continueResize(event) {
|
},
|
||||||
event.preventDefault();
|
continueResize(event) {
|
||||||
this.updatePosition(event);
|
event.preventDefault();
|
||||||
this.dragPosition = this.activeDrag.getAdjustedPositionAndDimensions(this.delta);
|
this.updatePosition(event);
|
||||||
},
|
this.dragPosition = this.activeDrag.getAdjustedPositionAndDimensions(this.delta);
|
||||||
endResize(event) {
|
},
|
||||||
document.body.removeEventListener('mousemove', this.continueResize);
|
endResize(event) {
|
||||||
document.body.removeEventListener('mouseup', this.endResize);
|
document.body.removeEventListener('mousemove', this.continueResize);
|
||||||
this.continueResize(event);
|
document.body.removeEventListener('mouseup', this.endResize);
|
||||||
|
this.continueResize(event);
|
||||||
|
|
||||||
let marqueeStartWidth = this.marqueeStartPosition.dimensions[0];
|
let marqueeStartWidth = this.marqueeStartPosition.dimensions[0];
|
||||||
let marqueeStartHeight = this.marqueeStartPosition.dimensions[1];
|
let marqueeStartHeight = this.marqueeStartPosition.dimensions[1];
|
||||||
let marqueeStartX = this.marqueeStartPosition.position[0];
|
let marqueeStartX = this.marqueeStartPosition.position[0];
|
||||||
let marqueeStartY = this.marqueeStartPosition.position[1];
|
let marqueeStartY = this.marqueeStartPosition.position[1];
|
||||||
|
|
||||||
let marqueeEndX = this.dragPosition.position[0];
|
let marqueeEndX = this.dragPosition.position[0];
|
||||||
let marqueeEndY = this.dragPosition.position[1];
|
let marqueeEndY = this.dragPosition.position[1];
|
||||||
let marqueeEndWidth = this.dragPosition.dimensions[0];
|
let marqueeEndWidth = this.dragPosition.dimensions[0];
|
||||||
let marqueeEndHeight = this.dragPosition.dimensions[1];
|
let marqueeEndHeight = this.dragPosition.dimensions[1];
|
||||||
|
|
||||||
let scaleWidth = marqueeEndWidth / marqueeStartWidth;
|
let scaleWidth = marqueeEndWidth / marqueeStartWidth;
|
||||||
let scaleHeight = marqueeEndHeight / marqueeStartHeight;
|
let scaleHeight = marqueeEndHeight / marqueeStartHeight;
|
||||||
|
|
||||||
let marqueeStart = {
|
let marqueeStart = {
|
||||||
x: marqueeStartX,
|
x: marqueeStartX,
|
||||||
y: marqueeStartY,
|
y: marqueeStartY,
|
||||||
height: marqueeStartWidth,
|
height: marqueeStartWidth,
|
||||||
width: marqueeStartHeight
|
width: marqueeStartHeight
|
||||||
};
|
};
|
||||||
let marqueeEnd = {
|
let marqueeEnd = {
|
||||||
x: marqueeEndX,
|
x: marqueeEndX,
|
||||||
y: marqueeEndY,
|
y: marqueeEndY,
|
||||||
width: marqueeEndWidth,
|
width: marqueeEndWidth,
|
||||||
height: marqueeEndHeight
|
height: marqueeEndHeight
|
||||||
};
|
};
|
||||||
let marqueeOffset = {
|
let marqueeOffset = {
|
||||||
x: marqueeEnd.x - marqueeStart.x,
|
x: marqueeEnd.x - marqueeStart.x,
|
||||||
y: marqueeEnd.y - marqueeStart.y
|
y: marqueeEnd.y - marqueeStart.y
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
|
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
|
||||||
this.dragPosition = undefined;
|
this.dragPosition = undefined;
|
||||||
this.initialPosition = undefined;
|
this.initialPosition = undefined;
|
||||||
this.marqueeStartPosition = undefined;
|
this.marqueeStartPosition = undefined;
|
||||||
this.delta = undefined;
|
this.delta = undefined;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,15 +21,18 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<layout-frame :item="item"
|
<layout-frame
|
||||||
:grid-size="gridSize"
|
:item="item"
|
||||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
:grid-size="gridSize"
|
||||||
@endMove="() => $emit('endMove')">
|
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||||
<div class="c-image-view"
|
@endMove="() => $emit('endMove')"
|
||||||
:style="style">
|
>
|
||||||
</div>
|
<div
|
||||||
</layout-frame>
|
class="c-image-view"
|
||||||
</template>
|
:style="style"
|
||||||
|
></div>
|
||||||
|
</layout-frame>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~styles/sass-base';
|
@import '~styles/sass-base';
|
||||||
@ -46,59 +49,70 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition(openmct, gridSize, element) {
|
makeDefinition(openmct, gridSize, element) {
|
||||||
|
return {
|
||||||
|
stroke: 'transparent',
|
||||||
|
x: 1,
|
||||||
|
y: 1,
|
||||||
|
width: 10,
|
||||||
|
height: 5,
|
||||||
|
url: element.url
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct'],
|
||||||
|
components: {
|
||||||
|
LayoutFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
gridSize: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
validator: (arr) => arr && arr.length === 2
|
||||||
|
&& arr.every(el => typeof el === 'number')
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
initSelect: Boolean
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
return {
|
return {
|
||||||
stroke: 'transparent',
|
backgroundImage: 'url(' + this.item.url + ')',
|
||||||
x: 1,
|
border: '1px solid ' + this.item.stroke
|
||||||
y: 1,
|
|
||||||
width: 10,
|
|
||||||
height: 5,
|
|
||||||
url: element.url
|
|
||||||
};
|
|
||||||
},
|
|
||||||
inject: ['openmct'],
|
|
||||||
props: {
|
|
||||||
item: Object,
|
|
||||||
gridSize: Array,
|
|
||||||
index: Number,
|
|
||||||
initSelect: Boolean
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
LayoutFrame
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
return {
|
|
||||||
backgroundImage: 'url(' + this.item.url + ')',
|
|
||||||
border: '1px solid ' + this.item.stroke
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.context = {
|
|
||||||
layoutItem: this.item,
|
|
||||||
index: this.index
|
|
||||||
};
|
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
|
||||||
this.$el, this.context, this.initSelect);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
if (this.removeSelectable) {
|
|
||||||
this.removeSelectable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
index(newIndex) {
|
||||||
|
if (!this.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.context.index = newIndex;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.context = {
|
||||||
|
layoutItem: this.item,
|
||||||
|
index: this.index
|
||||||
|
};
|
||||||
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
|
this.$el, this.context, this.initSelect);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.removeSelectable) {
|
||||||
|
this.removeSelectable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
|
@ -21,19 +21,21 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="l-layout__frame c-frame"
|
<div
|
||||||
:class="{
|
class="l-layout__frame c-frame"
|
||||||
'no-frame': !item.hasFrame,
|
:class="{
|
||||||
'u-inspectable': inspectable
|
'no-frame': !item.hasFrame,
|
||||||
}"
|
'u-inspectable': inspectable
|
||||||
:style="style">
|
}"
|
||||||
|
:style="style"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
<slot></slot>
|
<div
|
||||||
|
class="c-frame-edit__move"
|
||||||
<div class="c-frame-edit__move"
|
@mousedown="startMove([1,1], [0,0], $event)"
|
||||||
@mousedown="startMove([1,1], [0,0], $event)">
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -173,73 +175,81 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutDrag from './../LayoutDrag'
|
import LayoutDrag from './../LayoutDrag'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
item: Object,
|
item: {
|
||||||
gridSize: Array
|
type: Object,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
computed: {
|
gridSize: {
|
||||||
style() {
|
type: Array,
|
||||||
let {x, y, width, height} = this.item;
|
required: true,
|
||||||
return {
|
validator: (arr) => arr && arr.length === 2
|
||||||
left: (this.gridSize[0] * x) + 'px',
|
&& arr.every(el => typeof el === 'number')
|
||||||
top: (this.gridSize[1] * y) + 'px',
|
}
|
||||||
width: (this.gridSize[0] * width) + 'px',
|
},
|
||||||
height: (this.gridSize[1] * height) + 'px',
|
computed: {
|
||||||
minWidth: (this.gridSize[0] * width) + 'px',
|
style() {
|
||||||
minHeight: (this.gridSize[1] * height) + 'px'
|
let {x, y, width, height} = this.item;
|
||||||
};
|
return {
|
||||||
},
|
left: (this.gridSize[0] * x) + 'px',
|
||||||
inspectable() {
|
top: (this.gridSize[1] * y) + 'px',
|
||||||
return this.item.type === 'subobject-view' || this.item.type === 'telemetry-view';
|
width: (this.gridSize[0] * width) + 'px',
|
||||||
|
height: (this.gridSize[1] * height) + 'px',
|
||||||
|
minWidth: (this.gridSize[0] * width) + 'px',
|
||||||
|
minHeight: (this.gridSize[1] * height) + 'px'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inspectable() {
|
||||||
|
return this.item.type === 'subobject-view' || this.item.type === 'telemetry-view';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updatePosition(event) {
|
||||||
|
let currentPosition = [event.pageX, event.pageY];
|
||||||
|
this.initialPosition = this.initialPosition || currentPosition;
|
||||||
|
this.delta = currentPosition.map(function (value, index) {
|
||||||
|
return value - this.initialPosition[index];
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
startMove(posFactor, dimFactor, event) {
|
||||||
|
document.body.addEventListener('mousemove', this.continueMove);
|
||||||
|
document.body.addEventListener('mouseup', this.endMove);
|
||||||
|
this.dragPosition = {
|
||||||
|
position: [this.item.x, this.item.y]
|
||||||
|
};
|
||||||
|
this.updatePosition(event);
|
||||||
|
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
continueMove(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.updatePosition(event);
|
||||||
|
let newPosition = this.activeDrag.getAdjustedPosition(this.delta);
|
||||||
|
|
||||||
|
if (!_.isEqual(newPosition, this.dragPosition)) {
|
||||||
|
this.dragPosition = newPosition;
|
||||||
|
this.$emit('move', this.toGridDelta(this.delta));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
endMove(event) {
|
||||||
updatePosition(event) {
|
document.body.removeEventListener('mousemove', this.continueMove);
|
||||||
let currentPosition = [event.pageX, event.pageY];
|
document.body.removeEventListener('mouseup', this.endMove);
|
||||||
this.initialPosition = this.initialPosition || currentPosition;
|
this.continueMove(event);
|
||||||
this.delta = currentPosition.map(function (value, index) {
|
this.$emit('endMove');
|
||||||
return value - this.initialPosition[index];
|
this.dragPosition = undefined;
|
||||||
}.bind(this));
|
this.initialPosition = undefined;
|
||||||
},
|
this.delta = undefined;
|
||||||
startMove(posFactor, dimFactor, event) {
|
event.preventDefault();
|
||||||
document.body.addEventListener('mousemove', this.continueMove);
|
},
|
||||||
document.body.addEventListener('mouseup', this.endMove);
|
toGridDelta(pixelDelta) {
|
||||||
this.dragPosition = {
|
return pixelDelta.map((v, i) => {
|
||||||
position: [this.item.x, this.item.y]
|
return Math.round(v / this.gridSize[i]);
|
||||||
};
|
});
|
||||||
this.updatePosition(event);
|
|
||||||
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
continueMove(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.updatePosition(event);
|
|
||||||
let newPosition = this.activeDrag.getAdjustedPosition(this.delta);
|
|
||||||
|
|
||||||
if (!_.isEqual(newPosition, this.dragPosition)) {
|
|
||||||
this.dragPosition = newPosition;
|
|
||||||
this.$emit('move', this.toGridDelta(this.delta));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
endMove(event) {
|
|
||||||
document.body.removeEventListener('mousemove', this.continueMove);
|
|
||||||
document.body.removeEventListener('mouseup', this.endMove);
|
|
||||||
this.continueMove(event);
|
|
||||||
this.$emit('endMove');
|
|
||||||
this.dragPosition = undefined;
|
|
||||||
this.initialPosition = undefined;
|
|
||||||
this.delta = undefined;
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
toGridDelta(pixelDelta) {
|
|
||||||
return pixelDelta.map((v, i) => {
|
|
||||||
return Math.round(v / this.gridSize[i]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,244 +21,253 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="l-layout__frame c-frame no-frame"
|
<div
|
||||||
:style="style">
|
class="l-layout__frame c-frame no-frame"
|
||||||
<svg width="100%" height="100%">
|
:style="style"
|
||||||
<line v-bind="linePosition"
|
>
|
||||||
:stroke="item.stroke"
|
<svg
|
||||||
stroke-width="2">
|
width="100%"
|
||||||
</line>
|
height="100%"
|
||||||
</svg>
|
>
|
||||||
|
<line
|
||||||
|
v-bind="linePosition"
|
||||||
|
:stroke="item.stroke"
|
||||||
|
stroke-width="2"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
<div class="c-frame-edit__move"
|
<div
|
||||||
@mousedown="startDrag($event)"></div>
|
class="c-frame-edit__move"
|
||||||
<div class="c-frame-edit" v-if="showFrameEdit">
|
@mousedown="startDrag($event)"
|
||||||
<div class="c-frame-edit__handle"
|
></div>
|
||||||
:class="startHandleClass"
|
<div
|
||||||
@mousedown="startDrag($event, 'start')"></div>
|
v-if="showFrameEdit"
|
||||||
<div class="c-frame-edit__handle"
|
class="c-frame-edit"
|
||||||
:class="endHandleClass"
|
>
|
||||||
@mousedown="startDrag($event, 'end')"></div>
|
<div
|
||||||
</div>
|
class="c-frame-edit__handle"
|
||||||
|
:class="startHandleClass"
|
||||||
|
@mousedown="startDrag($event, 'start')"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="c-frame-edit__handle"
|
||||||
|
:class="endHandleClass"
|
||||||
|
@mousedown="startDrag($event, 'end')"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const START_HANDLE_QUADRANTS = {
|
const START_HANDLE_QUADRANTS = {
|
||||||
1: 'c-frame-edit__handle--sw',
|
1: 'c-frame-edit__handle--sw',
|
||||||
2: 'c-frame-edit__handle--se',
|
2: 'c-frame-edit__handle--se',
|
||||||
3: 'c-frame-edit__handle--ne',
|
3: 'c-frame-edit__handle--ne',
|
||||||
4: 'c-frame-edit__handle--nw'
|
4: 'c-frame-edit__handle--nw'
|
||||||
};
|
};
|
||||||
|
|
||||||
const END_HANDLE_QUADRANTS = {
|
const END_HANDLE_QUADRANTS = {
|
||||||
1: 'c-frame-edit__handle--ne',
|
1: 'c-frame-edit__handle--ne',
|
||||||
2: 'c-frame-edit__handle--nw',
|
2: 'c-frame-edit__handle--nw',
|
||||||
3: 'c-frame-edit__handle--sw',
|
3: 'c-frame-edit__handle--sw',
|
||||||
4: 'c-frame-edit__handle--se'
|
4: 'c-frame-edit__handle--se'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition() {
|
makeDefinition() {
|
||||||
|
return {
|
||||||
|
x: 5,
|
||||||
|
y: 10,
|
||||||
|
x2: 10,
|
||||||
|
y2: 5,
|
||||||
|
stroke: '#717171'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct'],
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
gridSize: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
validator: (arr) => arr && arr.length === 2
|
||||||
|
&& arr.every(el => typeof el === 'number')
|
||||||
|
},
|
||||||
|
initSelect: Boolean,
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
multiSelect: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dragPosition: undefined,
|
||||||
|
dragging: undefined,
|
||||||
|
selection: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showFrameEdit() {
|
||||||
|
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
|
||||||
|
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
|
||||||
|
},
|
||||||
|
position() {
|
||||||
|
let {x, y, x2, y2} = this.item;
|
||||||
|
if (this.dragging && this.dragPosition) {
|
||||||
|
({x, y, x2, y2} = this.dragPosition);
|
||||||
|
}
|
||||||
|
return {x, y, x2, y2};
|
||||||
|
},
|
||||||
|
style() {
|
||||||
|
let {x, y, x2, y2} = this.position;
|
||||||
|
let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
|
||||||
|
let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
|
||||||
|
let left = this.gridSize[0] * Math.min(x, x2);
|
||||||
|
let top = this.gridSize[1] * Math.min(y, y2);
|
||||||
return {
|
return {
|
||||||
x: 5,
|
left: `${left}px`,
|
||||||
y: 10,
|
top: `${top}px`,
|
||||||
x2: 10,
|
width: `${width}px`,
|
||||||
y2: 5,
|
height: `${height}px`
|
||||||
stroke: '#717171'
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
inject: ['openmct'],
|
startHandleClass() {
|
||||||
props: {
|
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
|
||||||
item: Object,
|
|
||||||
gridSize: Array,
|
|
||||||
initSelect: Boolean,
|
|
||||||
index: Number,
|
|
||||||
multiSelect: Boolean
|
|
||||||
},
|
},
|
||||||
data() {
|
endHandleClass() {
|
||||||
return {
|
return END_HANDLE_QUADRANTS[this.vectorQuadrant];
|
||||||
dragPosition: undefined,
|
|
||||||
dragging: undefined,
|
|
||||||
selection: []
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
computed: {
|
vectorQuadrant() {
|
||||||
showFrameEdit() {
|
let {x, y, x2, y2} = this.position;
|
||||||
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
|
if (x2 > x) {
|
||||||
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
|
|
||||||
},
|
|
||||||
position() {
|
|
||||||
let {x, y, x2, y2} = this.item;
|
|
||||||
if (this.dragging && this.dragPosition) {
|
|
||||||
({x, y, x2, y2} = this.dragPosition);
|
|
||||||
}
|
|
||||||
return {x, y, x2, y2};
|
|
||||||
},
|
|
||||||
style() {
|
|
||||||
let {x, y, x2, y2} = this.position;
|
|
||||||
let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
|
|
||||||
let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
|
|
||||||
let left = this.gridSize[0] * Math.min(x, x2);
|
|
||||||
let top = this.gridSize[1] * Math.min(y, y2);
|
|
||||||
return {
|
|
||||||
left: `${left}px`,
|
|
||||||
top: `${top}px`,
|
|
||||||
width: `${width}px`,
|
|
||||||
height: `${height}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
startHandleClass() {
|
|
||||||
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
|
|
||||||
},
|
|
||||||
endHandleClass() {
|
|
||||||
return END_HANDLE_QUADRANTS[this.vectorQuadrant];
|
|
||||||
},
|
|
||||||
vectorQuadrant() {
|
|
||||||
let {x, y, x2, y2} = this.position;
|
|
||||||
if (x2 > x) {
|
|
||||||
if (y2 < y) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
if (y2 < y) {
|
if (y2 < y) {
|
||||||
return 2;
|
return 1;
|
||||||
}
|
|
||||||
return 3;
|
|
||||||
},
|
|
||||||
linePosition() {
|
|
||||||
if (this.vectorQuadrant === 1) {
|
|
||||||
return {
|
|
||||||
x1: '0%',
|
|
||||||
y1: '100%',
|
|
||||||
x2: '100%',
|
|
||||||
y2: '0%'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (this.vectorQuadrant === 4) {
|
|
||||||
return {
|
|
||||||
x1: '0%',
|
|
||||||
y1: '0%',
|
|
||||||
x2: '100%',
|
|
||||||
y2: '100%'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (this.vectorQuadrant === 2) {
|
|
||||||
return {
|
|
||||||
x1: '0%',
|
|
||||||
y1: '0%',
|
|
||||||
x2: '100%',
|
|
||||||
y2: '100%'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (this.vectorQuadrant === 3) {
|
|
||||||
return {
|
|
||||||
x1: '100%',
|
|
||||||
y1: '0%',
|
|
||||||
x2: '0%',
|
|
||||||
y2: '100%'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
if (y2 < y) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
},
|
},
|
||||||
methods: {
|
linePosition() {
|
||||||
startDrag(event, position) {
|
return this.vectorQuadrant % 2 !== 0
|
||||||
this.dragging = position;
|
// odd vectorQuadrant slopes up
|
||||||
document.body.addEventListener('mousemove', this.continueDrag);
|
? {
|
||||||
document.body.addEventListener('mouseup', this.endDrag);
|
x1: '0%',
|
||||||
this.startPosition = [event.pageX, event.pageY];
|
y1: '100%',
|
||||||
this.dragPosition = {
|
x2: '100%',
|
||||||
x: this.item.x,
|
y2: '0%'
|
||||||
y: this.item.y,
|
}
|
||||||
x2: this.item.x2,
|
// even vectorQuadrant slopes down
|
||||||
y2: this.item.y2
|
: {
|
||||||
|
x1: '0%',
|
||||||
|
y1: '0%',
|
||||||
|
x2: '100%',
|
||||||
|
y2: '100%'
|
||||||
};
|
};
|
||||||
event.preventDefault();
|
}
|
||||||
},
|
},
|
||||||
continueDrag(event) {
|
watch: {
|
||||||
event.preventDefault();
|
index(newIndex) {
|
||||||
let pxDeltaX = this.startPosition[0] - event.pageX;
|
if (!this.context) {
|
||||||
let pxDeltaY = this.startPosition[1] - event.pageY;
|
return;
|
||||||
let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
|
|
||||||
|
|
||||||
if (!this.dragging) {
|
|
||||||
if (!_.isEqual(newPosition, this.dragPosition)) {
|
|
||||||
let gridDelta = [event.pageX - this.startPosition[0], event.pageY - this.startPosition[1]];
|
|
||||||
this.dragPosition = newPosition;
|
|
||||||
this.$emit('move', this.toGridDelta(gridDelta));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.dragPosition = newPosition;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
endDrag(event) {
|
|
||||||
document.body.removeEventListener('mousemove', this.continueDrag);
|
|
||||||
document.body.removeEventListener('mouseup', this.endDrag);
|
|
||||||
let {x, y, x2, y2} = this.dragPosition;
|
|
||||||
if (!this.dragging) {
|
|
||||||
this.$emit('endMove');
|
|
||||||
} else {
|
|
||||||
this.$emit('endLineResize', this.item, {x, y, x2, y2});
|
|
||||||
}
|
|
||||||
this.dragPosition = undefined;
|
|
||||||
this.dragging = undefined;
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
calculateDragPosition(pxDeltaX, pxDeltaY) {
|
|
||||||
let gridDeltaX = Math.round(pxDeltaX / this.gridSize[0]);
|
|
||||||
let gridDeltaY = Math.round(pxDeltaY / this.gridSize[0]); // TODO: should this be gridSize[1]?
|
|
||||||
let {x, y, x2, y2} = this.item;
|
|
||||||
let dragPosition = {x, y, x2, y2};
|
|
||||||
|
|
||||||
if (this.dragging === 'start') {
|
|
||||||
dragPosition.x -= gridDeltaX;
|
|
||||||
dragPosition.y -= gridDeltaY;
|
|
||||||
} else if (this.dragging === 'end') {
|
|
||||||
dragPosition.x2 -= gridDeltaX;
|
|
||||||
dragPosition.y2 -= gridDeltaY;
|
|
||||||
} else {
|
|
||||||
// dragging entire line.
|
|
||||||
dragPosition.x -= gridDeltaX;
|
|
||||||
dragPosition.y -= gridDeltaY;
|
|
||||||
dragPosition.x2 -= gridDeltaX;
|
|
||||||
dragPosition.y2 -= gridDeltaY;
|
|
||||||
}
|
|
||||||
return dragPosition;
|
|
||||||
},
|
|
||||||
setSelection(selection) {
|
|
||||||
this.selection = selection;
|
|
||||||
},
|
|
||||||
toGridDelta(pixelDelta) {
|
|
||||||
return pixelDelta.map((v, i) => {
|
|
||||||
return Math.round(v / this.gridSize[i]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
this.context.index = newIndex;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.openmct.selection.on('change', this.setSelection);
|
this.openmct.selection.on('change', this.setSelection);
|
||||||
this.context = {
|
this.context = {
|
||||||
layoutItem: this.item,
|
layoutItem: this.item,
|
||||||
index: this.index
|
index: this.index
|
||||||
|
};
|
||||||
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
|
this.$el, this.context, this.initSelect);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.removeSelectable) {
|
||||||
|
this.removeSelectable();
|
||||||
|
}
|
||||||
|
this.openmct.selection.off('change', this.setSelection);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
startDrag(event, position) {
|
||||||
|
this.dragging = position;
|
||||||
|
document.body.addEventListener('mousemove', this.continueDrag);
|
||||||
|
document.body.addEventListener('mouseup', this.endDrag);
|
||||||
|
this.startPosition = [event.pageX, event.pageY];
|
||||||
|
this.dragPosition = {
|
||||||
|
x: this.item.x,
|
||||||
|
y: this.item.y,
|
||||||
|
x2: this.item.x2,
|
||||||
|
y2: this.item.y2
|
||||||
};
|
};
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
event.preventDefault();
|
||||||
this.$el, this.context, this.initSelect);
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
continueDrag(event) {
|
||||||
if (this.removeSelectable) {
|
event.preventDefault();
|
||||||
this.removeSelectable();
|
let pxDeltaX = this.startPosition[0] - event.pageX;
|
||||||
|
let pxDeltaY = this.startPosition[1] - event.pageY;
|
||||||
|
let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
|
||||||
|
|
||||||
|
if (!this.dragging) {
|
||||||
|
if (!_.isEqual(newPosition, this.dragPosition)) {
|
||||||
|
let gridDelta = [event.pageX - this.startPosition[0], event.pageY - this.startPosition[1]];
|
||||||
|
this.dragPosition = newPosition;
|
||||||
|
this.$emit('move', this.toGridDelta(gridDelta));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.dragPosition = newPosition;
|
||||||
}
|
}
|
||||||
this.openmct.selection.off('change', this.setSelection);
|
},
|
||||||
|
endDrag(event) {
|
||||||
|
document.body.removeEventListener('mousemove', this.continueDrag);
|
||||||
|
document.body.removeEventListener('mouseup', this.endDrag);
|
||||||
|
let {x, y, x2, y2} = this.dragPosition;
|
||||||
|
if (!this.dragging) {
|
||||||
|
this.$emit('endMove');
|
||||||
|
} else {
|
||||||
|
this.$emit('endLineResize', this.item, {x, y, x2, y2});
|
||||||
|
}
|
||||||
|
this.dragPosition = undefined;
|
||||||
|
this.dragging = undefined;
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
calculateDragPosition(pxDeltaX, pxDeltaY) {
|
||||||
|
let gridDeltaX = Math.round(pxDeltaX / this.gridSize[0]);
|
||||||
|
let gridDeltaY = Math.round(pxDeltaY / this.gridSize[0]); // TODO: should this be gridSize[1]?
|
||||||
|
let {x, y, x2, y2} = this.item;
|
||||||
|
let dragPosition = {x, y, x2, y2};
|
||||||
|
|
||||||
|
if (this.dragging === 'start') {
|
||||||
|
dragPosition.x -= gridDeltaX;
|
||||||
|
dragPosition.y -= gridDeltaY;
|
||||||
|
} else if (this.dragging === 'end') {
|
||||||
|
dragPosition.x2 -= gridDeltaX;
|
||||||
|
dragPosition.y2 -= gridDeltaY;
|
||||||
|
} else {
|
||||||
|
// dragging entire line.
|
||||||
|
dragPosition.x -= gridDeltaX;
|
||||||
|
dragPosition.y -= gridDeltaY;
|
||||||
|
dragPosition.x2 -= gridDeltaX;
|
||||||
|
dragPosition.y2 -= gridDeltaY;
|
||||||
|
}
|
||||||
|
return dragPosition;
|
||||||
|
},
|
||||||
|
setSelection(selection) {
|
||||||
|
this.selection = selection;
|
||||||
|
},
|
||||||
|
toGridDelta(pixelDelta) {
|
||||||
|
return pixelDelta.map((v, i) => {
|
||||||
|
return Math.round(v / this.gridSize[i]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
|
@ -20,106 +20,120 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<layout-frame :item="item"
|
<layout-frame
|
||||||
:grid-size="gridSize"
|
:item="item"
|
||||||
:title="domainObject && domainObject.name"
|
:grid-size="gridSize"
|
||||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
:title="domainObject && domainObject.name"
|
||||||
@endMove="() => $emit('endMove')">
|
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||||
<object-frame v-if="domainObject"
|
@endMove="() => $emit('endMove')"
|
||||||
:domain-object="domainObject"
|
>
|
||||||
:object-path="currentObjectPath"
|
<object-frame
|
||||||
:has-frame="item.hasFrame"
|
v-if="domainObject"
|
||||||
:show-edit-view="false"
|
ref="objectFrame"
|
||||||
ref="objectFrame">
|
:domain-object="domainObject"
|
||||||
</object-frame>
|
:object-path="currentObjectPath"
|
||||||
</layout-frame>
|
:has-frame="item.hasFrame"
|
||||||
|
:show-edit-view="false"
|
||||||
|
/>
|
||||||
|
</layout-frame>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ObjectFrame from '../../../ui/components/ObjectFrame.vue'
|
import ObjectFrame from '../../../ui/components/ObjectFrame.vue'
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
|
|
||||||
const MINIMUM_FRAME_SIZE = [320, 180],
|
const MINIMUM_FRAME_SIZE = [320, 180],
|
||||||
DEFAULT_DIMENSIONS = [10, 10],
|
DEFAULT_DIMENSIONS = [10, 10],
|
||||||
DEFAULT_POSITION = [1, 1],
|
DEFAULT_POSITION = [1, 1],
|
||||||
DEFAULT_HIDDEN_FRAME_TYPES = ['hyperlink', 'summary-widget'];
|
DEFAULT_HIDDEN_FRAME_TYPES = ['hyperlink', 'summary-widget'];
|
||||||
|
|
||||||
function getDefaultDimensions(gridSize) {
|
function getDefaultDimensions(gridSize) {
|
||||||
return MINIMUM_FRAME_SIZE.map((min, index) => {
|
return MINIMUM_FRAME_SIZE.map((min, index) => {
|
||||||
return Math.max(
|
return Math.max(
|
||||||
Math.ceil(min / gridSize[index]),
|
Math.ceil(min / gridSize[index]),
|
||||||
DEFAULT_DIMENSIONS[index]
|
DEFAULT_DIMENSIONS[index]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasFrameByDefault(type) {
|
function hasFrameByDefault(type) {
|
||||||
return DEFAULT_HIDDEN_FRAME_TYPES.indexOf(type) === -1;
|
return DEFAULT_HIDDEN_FRAME_TYPES.indexOf(type) === -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition(openmct, gridSize, domainObject, position) {
|
makeDefinition(openmct, gridSize, domainObject, position) {
|
||||||
let defaultDimensions = getDefaultDimensions(gridSize);
|
let defaultDimensions = getDefaultDimensions(gridSize);
|
||||||
position = position || DEFAULT_POSITION;
|
position = position || DEFAULT_POSITION;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: defaultDimensions[0],
|
width: defaultDimensions[0],
|
||||||
height: defaultDimensions[1],
|
height: defaultDimensions[1],
|
||||||
x: position[0],
|
x: position[0],
|
||||||
y: position[1],
|
y: position[1],
|
||||||
identifier: domainObject.identifier,
|
identifier: domainObject.identifier,
|
||||||
hasFrame: hasFrameByDefault(domainObject.type)
|
hasFrame: hasFrameByDefault(domainObject.type)
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct', 'objectPath'],
|
||||||
|
components: {
|
||||||
|
ObjectFrame,
|
||||||
|
LayoutFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
inject: ['openmct', 'objectPath'],
|
gridSize: {
|
||||||
props: {
|
type: Array,
|
||||||
item: Object,
|
required: true,
|
||||||
gridSize: Array,
|
validator: (arr) => arr && arr.length === 2
|
||||||
initSelect: Boolean,
|
&& arr.every(el => typeof el === 'number')
|
||||||
index: Number
|
|
||||||
},
|
},
|
||||||
data() {
|
initSelect: Boolean,
|
||||||
return {
|
index: {
|
||||||
domainObject: undefined,
|
type: Number,
|
||||||
currentObjectPath: []
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
domainObject: undefined,
|
||||||
|
currentObjectPath: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
index(newIndex) {
|
||||||
|
if (!this.context) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
components: {
|
|
||||||
ObjectFrame,
|
|
||||||
LayoutFrame
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
this.context.index = newIndex;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
mounted() {
|
||||||
setObject(domainObject) {
|
this.openmct.objects.get(this.item.identifier)
|
||||||
this.domainObject = domainObject;
|
.then(this.setObject);
|
||||||
this.currentObjectPath = [this.domainObject].concat(this.objectPath.slice());
|
},
|
||||||
this.$nextTick(function () {
|
destroyed() {
|
||||||
let childContext = this.$refs.objectFrame.getSelectionContext();
|
if (this.removeSelectable) {
|
||||||
childContext.item = domainObject;
|
this.removeSelectable();
|
||||||
childContext.layoutItem = this.item;
|
}
|
||||||
childContext.index = this.index;
|
},
|
||||||
this.context = childContext;
|
methods: {
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
setObject(domainObject) {
|
||||||
this.$el, this.context, this.initSelect);
|
this.domainObject = domainObject;
|
||||||
});
|
this.currentObjectPath = [this.domainObject].concat(this.objectPath.slice());
|
||||||
}
|
this.$nextTick(function () {
|
||||||
},
|
let childContext = this.$refs.objectFrame.getSelectionContext();
|
||||||
mounted() {
|
childContext.item = domainObject;
|
||||||
this.openmct.objects.get(this.item.identifier)
|
childContext.layoutItem = this.item;
|
||||||
.then(this.setObject);
|
childContext.index = this.index;
|
||||||
},
|
this.context = childContext;
|
||||||
destroyed() {
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
if (this.removeSelectable) {
|
this.$el, this.context, this.initSelect);
|
||||||
this.removeSelectable();
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,29 +20,41 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<layout-frame :item="item"
|
<layout-frame
|
||||||
:grid-size="gridSize"
|
:item="item"
|
||||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
:grid-size="gridSize"
|
||||||
@endMove="() => $emit('endMove')">
|
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||||
<div class="c-telemetry-view"
|
@endMove="() => $emit('endMove')"
|
||||||
:style="styleObject"
|
>
|
||||||
v-if="domainObject"
|
<div
|
||||||
@contextmenu.prevent="showContextMenu">
|
v-if="domainObject"
|
||||||
<div v-if="showLabel"
|
class="c-telemetry-view"
|
||||||
class="c-telemetry-view__label">
|
:style="styleObject"
|
||||||
<div class="c-telemetry-view__label-text">{{ domainObject.name }}</div>
|
@contextmenu.prevent="showContextMenu"
|
||||||
</div>
|
>
|
||||||
|
<div
|
||||||
<div v-if="showValue"
|
v-if="showLabel"
|
||||||
:title="fieldName"
|
class="c-telemetry-view__label"
|
||||||
class="c-telemetry-view__value"
|
>
|
||||||
:class="[telemetryClass]">
|
<div class="c-telemetry-view__label-text">
|
||||||
<div class="c-telemetry-view__value-text">{{ telemetryValue }}</div>
|
{{ domainObject.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</layout-frame>
|
|
||||||
</template>
|
<div
|
||||||
|
v-if="showValue"
|
||||||
|
:title="fieldName"
|
||||||
|
class="c-telemetry-view__value"
|
||||||
|
:class="[telemetryClass]"
|
||||||
|
>
|
||||||
|
<div class="c-telemetry-view__value-text">
|
||||||
|
{{ telemetryValue }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</layout-frame>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~styles/sass-base';
|
@import '~styles/sass-base';
|
||||||
@ -78,189 +90,200 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
import printj from 'printj'
|
import printj from 'printj'
|
||||||
|
|
||||||
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5],
|
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5],
|
||||||
DEFAULT_POSITION = [1, 1],
|
DEFAULT_POSITION = [1, 1],
|
||||||
CONTEXT_MENU_ACTIONS = ['viewHistoricalData'];
|
CONTEXT_MENU_ACTIONS = ['viewHistoricalData'];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition(openmct, gridSize, domainObject, position) {
|
makeDefinition(openmct, gridSize, domainObject, position) {
|
||||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||||
position = position || DEFAULT_POSITION;
|
position = position || DEFAULT_POSITION;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier: domainObject.identifier,
|
||||||
|
x: position[0],
|
||||||
|
y: position[1],
|
||||||
|
width: DEFAULT_TELEMETRY_DIMENSIONS[0],
|
||||||
|
height: DEFAULT_TELEMETRY_DIMENSIONS[1],
|
||||||
|
displayMode: 'all',
|
||||||
|
value: metadata.getDefaultDisplayValue(),
|
||||||
|
stroke: "transparent",
|
||||||
|
fill: "transparent",
|
||||||
|
color: "",
|
||||||
|
size: "13px"
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct', 'objectPath'],
|
||||||
|
components: {
|
||||||
|
LayoutFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
gridSize: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
validator: (arr) => arr && arr.length === 2
|
||||||
|
&& arr.every(el => typeof el === 'number')
|
||||||
|
},
|
||||||
|
initSelect: Boolean,
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
datum: undefined,
|
||||||
|
formats: undefined,
|
||||||
|
domainObject: undefined,
|
||||||
|
currentObjectPath: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showLabel() {
|
||||||
|
let displayMode = this.item.displayMode;
|
||||||
|
return displayMode === 'all' || displayMode === 'label';
|
||||||
|
},
|
||||||
|
showValue() {
|
||||||
|
let displayMode = this.item.displayMode;
|
||||||
|
return displayMode === 'all' || displayMode === 'value';
|
||||||
|
},
|
||||||
|
styleObject() {
|
||||||
return {
|
return {
|
||||||
identifier: domainObject.identifier,
|
backgroundColor: this.item.fill,
|
||||||
x: position[0],
|
borderColor: this.item.stroke,
|
||||||
y: position[1],
|
color: this.item.color,
|
||||||
width: DEFAULT_TELEMETRY_DIMENSIONS[0],
|
fontSize: this.item.size
|
||||||
height: DEFAULT_TELEMETRY_DIMENSIONS[1],
|
}
|
||||||
displayMode: 'all',
|
},
|
||||||
value: metadata.getDefaultDisplayValue(),
|
fieldName() {
|
||||||
stroke: "transparent",
|
return this.valueMetadata && this.valueMetadata.name;
|
||||||
fill: "transparent",
|
},
|
||||||
color: "",
|
valueMetadata() {
|
||||||
size: "13px"
|
return this.datum && this.metadata.value(this.item.value);
|
||||||
|
},
|
||||||
|
valueFormatter() {
|
||||||
|
return this.formats[this.item.value];
|
||||||
|
},
|
||||||
|
telemetryValue() {
|
||||||
|
if (!this.datum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.item.format) {
|
||||||
|
return printj.sprintf(this.item.format, this.datum[this.valueMetadata.key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.valueFormatter && this.valueFormatter.format(this.datum);
|
||||||
|
},
|
||||||
|
telemetryClass() {
|
||||||
|
if (!this.datum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let alarm = this.limitEvaluator && this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
|
||||||
|
return alarm && alarm.cssClass;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
index(newIndex) {
|
||||||
|
if (!this.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.context.index = newIndex;
|
||||||
|
},
|
||||||
|
item(newItem) {
|
||||||
|
this.context.layoutItem = newItem;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.openmct.objects.get(this.item.identifier)
|
||||||
|
.then(this.setObject);
|
||||||
|
this.openmct.time.on("bounds", this.refreshData);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.removeSubscription();
|
||||||
|
|
||||||
|
if (this.removeSelectable) {
|
||||||
|
this.removeSelectable();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.time.off("bounds", this.refreshData);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
requestHistoricalData() {
|
||||||
|
let bounds = this.openmct.time.bounds();
|
||||||
|
let options = {
|
||||||
|
start: bounds.start,
|
||||||
|
end: bounds.end,
|
||||||
|
size: 1,
|
||||||
|
strategy: 'latest'
|
||||||
};
|
};
|
||||||
},
|
this.openmct.telemetry.request(this.domainObject, options)
|
||||||
inject: ['openmct', 'objectPath'],
|
.then(data => {
|
||||||
props: {
|
if (data.length > 0) {
|
||||||
item: Object,
|
this.updateView(data[data.length - 1]);
|
||||||
gridSize: Array,
|
|
||||||
initSelect: Boolean,
|
|
||||||
index: Number
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
LayoutFrame
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
showLabel() {
|
|
||||||
let displayMode = this.item.displayMode;
|
|
||||||
return displayMode === 'all' || displayMode === 'label';
|
|
||||||
},
|
|
||||||
showValue() {
|
|
||||||
let displayMode = this.item.displayMode;
|
|
||||||
return displayMode === 'all' || displayMode === 'value';
|
|
||||||
},
|
|
||||||
styleObject() {
|
|
||||||
return {
|
|
||||||
backgroundColor: this.item.fill,
|
|
||||||
borderColor: this.item.stroke,
|
|
||||||
color: this.item.color,
|
|
||||||
fontSize: this.item.size
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fieldName() {
|
|
||||||
return this.valueMetadata && this.valueMetadata.name;
|
|
||||||
},
|
|
||||||
valueMetadata() {
|
|
||||||
return this.datum && this.metadata.value(this.item.value);
|
|
||||||
},
|
|
||||||
valueFormatter() {
|
|
||||||
return this.formats[this.item.value];
|
|
||||||
},
|
|
||||||
telemetryValue() {
|
|
||||||
if (!this.datum) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.item.format) {
|
|
||||||
return printj.sprintf(this.item.format, this.datum[this.valueMetadata.key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.valueFormatter && this.valueFormatter.format(this.datum);
|
|
||||||
},
|
|
||||||
telemetryClass() {
|
|
||||||
if (!this.datum) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let alarm = this.limitEvaluator && this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
|
|
||||||
return alarm && alarm.cssClass;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
datum: undefined,
|
|
||||||
formats: undefined,
|
|
||||||
domainObject: undefined,
|
|
||||||
currentObjectPath: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
|
||||||
},
|
|
||||||
item(newItem) {
|
|
||||||
this.context.layoutItem = newItem;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
requestHistoricalData() {
|
|
||||||
let bounds = this.openmct.time.bounds();
|
|
||||||
let options = {
|
|
||||||
start: bounds.start,
|
|
||||||
end: bounds.end,
|
|
||||||
size: 1,
|
|
||||||
strategy: 'latest'
|
|
||||||
};
|
|
||||||
this.openmct.telemetry.request(this.domainObject, options)
|
|
||||||
.then(data => {
|
|
||||||
if (data.length > 0) {
|
|
||||||
this.updateView(data[data.length - 1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
subscribeToObject() {
|
|
||||||
this.subscription = this.openmct.telemetry.subscribe(this.domainObject, function (datum) {
|
|
||||||
if (this.openmct.time.clock() !== undefined) {
|
|
||||||
this.updateView(datum);
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
updateView(datum) {
|
subscribeToObject() {
|
||||||
this.datum = datum;
|
this.subscription = this.openmct.telemetry.subscribe(this.domainObject, function (datum) {
|
||||||
},
|
if (this.openmct.time.clock() !== undefined) {
|
||||||
removeSubscription() {
|
this.updateView(datum);
|
||||||
if (this.subscription) {
|
|
||||||
this.subscription();
|
|
||||||
this.subscription = undefined;
|
|
||||||
}
|
}
|
||||||
},
|
}.bind(this));
|
||||||
refreshData(bounds, isTick) {
|
},
|
||||||
if (!isTick) {
|
updateView(datum) {
|
||||||
this.datum = undefined;
|
this.datum = datum;
|
||||||
this.requestHistoricalData(this.domainObject);
|
},
|
||||||
}
|
removeSubscription() {
|
||||||
},
|
if (this.subscription) {
|
||||||
setObject(domainObject) {
|
this.subscription();
|
||||||
this.domainObject = domainObject;
|
this.subscription = undefined;
|
||||||
this.keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
|
||||||
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
|
||||||
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
|
|
||||||
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
|
|
||||||
this.requestHistoricalData();
|
|
||||||
this.subscribeToObject();
|
|
||||||
|
|
||||||
this.currentObjectPath = this.objectPath.slice();
|
|
||||||
this.currentObjectPath.unshift(this.domainObject);
|
|
||||||
|
|
||||||
this.context = {
|
|
||||||
item: domainObject,
|
|
||||||
layoutItem: this.item,
|
|
||||||
index: this.index,
|
|
||||||
updateTelemetryFormat: this.updateTelemetryFormat
|
|
||||||
};
|
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
|
||||||
this.$el, this.context, this.initSelect);
|
|
||||||
},
|
|
||||||
updateTelemetryFormat(format) {
|
|
||||||
this.$emit('formatChanged', this.item, format);
|
|
||||||
},
|
|
||||||
showContextMenu(event) {
|
|
||||||
this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
refreshData(bounds, isTick) {
|
||||||
this.openmct.objects.get(this.item.identifier)
|
if (!isTick) {
|
||||||
.then(this.setObject);
|
this.datum = undefined;
|
||||||
this.openmct.time.on("bounds", this.refreshData);
|
this.requestHistoricalData(this.domainObject);
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.removeSubscription();
|
|
||||||
|
|
||||||
if (this.removeSelectable) {
|
|
||||||
this.removeSelectable();
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setObject(domainObject) {
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
|
||||||
|
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
|
||||||
|
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
|
||||||
|
this.requestHistoricalData();
|
||||||
|
this.subscribeToObject();
|
||||||
|
|
||||||
this.openmct.time.off("bounds", this.refreshData);
|
this.currentObjectPath = this.objectPath.slice();
|
||||||
|
this.currentObjectPath.unshift(this.domainObject);
|
||||||
|
|
||||||
|
this.context = {
|
||||||
|
item: domainObject,
|
||||||
|
layoutItem: this.item,
|
||||||
|
index: this.index,
|
||||||
|
updateTelemetryFormat: this.updateTelemetryFormat
|
||||||
|
};
|
||||||
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
|
this.$el, this.context, this.initSelect);
|
||||||
|
},
|
||||||
|
updateTelemetryFormat(format) {
|
||||||
|
this.$emit('formatChanged', this.item, format);
|
||||||
|
},
|
||||||
|
showContextMenu(event) {
|
||||||
|
this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,17 +20,21 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<layout-frame :item="item"
|
<layout-frame
|
||||||
:grid-size="gridSize"
|
:item="item"
|
||||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
:grid-size="gridSize"
|
||||||
@endMove="() => $emit('endMove')">
|
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||||
<div class="c-text-view"
|
@endMove="() => $emit('endMove')"
|
||||||
:style="style">
|
>
|
||||||
{{ item.text }}
|
<div
|
||||||
</div>
|
class="c-text-view"
|
||||||
</layout-frame>
|
:style="style"
|
||||||
</template>
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</div>
|
||||||
|
</layout-frame>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~styles/sass-base';
|
@import '~styles/sass-base';
|
||||||
@ -46,65 +50,75 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeDefinition(openmct, gridSize, element) {
|
makeDefinition(openmct, gridSize, element) {
|
||||||
|
return {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: 'transparent',
|
||||||
|
size: '13px',
|
||||||
|
color: '',
|
||||||
|
x: 1,
|
||||||
|
y: 1,
|
||||||
|
width: 10,
|
||||||
|
height: 5,
|
||||||
|
text: element.text
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['openmct'],
|
||||||
|
components: {
|
||||||
|
LayoutFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
gridSize: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
validator: (arr) => arr && arr.length === 2
|
||||||
|
&& arr.every(el => typeof el === 'number')
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
initSelect: Boolean
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
return {
|
return {
|
||||||
fill: 'transparent',
|
backgroundColor: this.item.fill,
|
||||||
stroke: 'transparent',
|
borderColor: this.item.stroke,
|
||||||
size: '13px',
|
color: this.item.color,
|
||||||
color: '',
|
fontSize: this.item.size
|
||||||
x: 1,
|
|
||||||
y: 1,
|
|
||||||
width: 10,
|
|
||||||
height: 5,
|
|
||||||
text: element.text
|
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
inject: ['openmct'],
|
},
|
||||||
props: {
|
watch: {
|
||||||
item: Object,
|
index(newIndex) {
|
||||||
gridSize: Array,
|
if (!this.context) {
|
||||||
index: Number,
|
return;
|
||||||
initSelect: Boolean
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
LayoutFrame
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
return {
|
|
||||||
backgroundColor: this.item.fill,
|
|
||||||
borderColor: this.item.stroke,
|
|
||||||
color: this.item.color,
|
|
||||||
fontSize: this.item.size
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
index(newIndex) {
|
|
||||||
if (!this.context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.index = newIndex;
|
this.context.index = newIndex;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.context = {
|
this.context = {
|
||||||
layoutItem: this.item,
|
layoutItem: this.item,
|
||||||
index: this.index
|
index: this.index
|
||||||
};
|
};
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.context, this.initSelect);
|
this.$el, this.context, this.initSelect);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
if (this.removeSelectable) {
|
if (this.removeSelectable) {
|
||||||
this.removeSelectable();
|
this.removeSelectable();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
|
@ -42,22 +42,22 @@ export default function DisplayLayoutPlugin(options) {
|
|||||||
return {
|
return {
|
||||||
show(container) {
|
show(container) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: container,
|
||||||
components: {
|
components: {
|
||||||
Layout
|
Layout
|
||||||
},
|
},
|
||||||
template: '<layout ref="displayLayout" :domain-object="domainObject"></layout>',
|
|
||||||
provide: {
|
provide: {
|
||||||
openmct,
|
openmct,
|
||||||
objectUtils,
|
objectUtils,
|
||||||
options,
|
options,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
el: container,
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
domainObject: domainObject
|
domainObject: domainObject
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
|
template: '<layout ref="displayLayout" :domain-object="domainObject"></layout>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getSelectionContext() {
|
getSelectionContext() {
|
||||||
|
@ -48,11 +48,11 @@ define([
|
|||||||
provide: {
|
provide: {
|
||||||
openmct
|
openmct
|
||||||
},
|
},
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
FiltersView: FiltersView.default
|
FiltersView: FiltersView.default
|
||||||
},
|
},
|
||||||
template: '<filters-view></filters-view>',
|
template: '<filters-view></filters-view>'
|
||||||
el: element
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
|
@ -1,56 +1,66 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-properties__section c-filter-settings">
|
<div class="c-properties__section c-filter-settings">
|
||||||
<li class="c-properties__row c-filter-settings__setting"
|
<li
|
||||||
v-for="(filter, index) in filterField.filters"
|
v-for="(filter, index) in filterField.filters"
|
||||||
:key="index">
|
:key="index"
|
||||||
<div class="c-properties__label label"
|
class="c-properties__row c-filter-settings__setting"
|
||||||
:disabled="useGlobal">
|
>
|
||||||
{{ filterField.name }} =
|
<div
|
||||||
</div>
|
class="c-properties__label label"
|
||||||
<div class="c-properties__value value">
|
:disabled="useGlobal"
|
||||||
<!-- EDITING -->
|
>
|
||||||
<!-- String input, editing -->
|
{{ filterField.name }} =
|
||||||
<template v-if="!filter.possibleValues && isEditing">
|
</div>
|
||||||
<input class="c-input--flex"
|
<div class="c-properties__value value">
|
||||||
type="text"
|
<!-- EDITING -->
|
||||||
:id="`${filter}filterControl`"
|
<!-- String input, editing -->
|
||||||
:disabled="useGlobal"
|
<template v-if="!filter.possibleValues && isEditing">
|
||||||
:value="persistedValue(filter)"
|
<input
|
||||||
@change="updateFilterValue($event, filter)">
|
:id="`${filter}filterControl`"
|
||||||
</template>
|
class="c-input--flex"
|
||||||
|
type="text"
|
||||||
|
:disabled="useGlobal"
|
||||||
|
:value="persistedValue(filter)"
|
||||||
|
@change="updateFilterValue($event, filter)"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Checkbox list, editing -->
|
<!-- Checkbox list, editing -->
|
||||||
<template v-if="filter.possibleValues && isEditing">
|
<template v-if="filter.possibleValues && isEditing">
|
||||||
<div class="c-checkbox-list__row"
|
<div
|
||||||
v-for="option in filter.possibleValues"
|
v-for="option in filter.possibleValues"
|
||||||
:key="option.value">
|
:key="option.value"
|
||||||
<input class="c-checkbox-list__input"
|
class="c-checkbox-list__row"
|
||||||
type="checkbox"
|
>
|
||||||
:id="`${option.value}filterControl`"
|
<input
|
||||||
:disabled="useGlobal"
|
:id="`${option.value}filterControl`"
|
||||||
@change="updateFilterValue($event, filter.comparator, option.value)"
|
class="c-checkbox-list__input"
|
||||||
:checked="isChecked(filter.comparator, option.value)">
|
type="checkbox"
|
||||||
<span class="c-checkbox-list__value">
|
:disabled="useGlobal"
|
||||||
{{ option.label }}
|
:checked="isChecked(filter.comparator, option.value)"
|
||||||
</span>
|
@change="updateFilterValue($event, filter.comparator, option.value)"
|
||||||
</div>
|
>
|
||||||
</template>
|
<span class="c-checkbox-list__value">
|
||||||
|
{{ option.label }}
|
||||||
<!-- BROWSING -->
|
|
||||||
<!-- String input, NOT editing -->
|
|
||||||
<template v-if="!filter.possibleValues && !isEditing">
|
|
||||||
{{ persistedValue(filter) }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Checkbox list, NOT editing -->
|
|
||||||
<template v-if="filter.possibleValues && !isEditing">
|
|
||||||
<span v-if="persistedFilters[filter.comparator]">
|
|
||||||
{{ getFilterLabels(filter) }}
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</li>
|
|
||||||
</div>
|
<!-- BROWSING -->
|
||||||
|
<!-- String input, NOT editing -->
|
||||||
|
<template v-if="!filter.possibleValues && !isEditing">
|
||||||
|
{{ persistedValue(filter) }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Checkbox list, NOT editing -->
|
||||||
|
<template v-if="filter.possibleValues && !isEditing">
|
||||||
|
<span v-if="persistedFilters[filter.comparator]">
|
||||||
|
{{ getFilterLabels(filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -59,7 +69,10 @@ export default {
|
|||||||
'openmct'
|
'openmct'
|
||||||
],
|
],
|
||||||
props: {
|
props: {
|
||||||
filterField: Object,
|
filterField: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
useGlobal: Boolean,
|
useGlobal: Boolean,
|
||||||
persistedFilters: {
|
persistedFilters: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -73,6 +86,12 @@ export default {
|
|||||||
isEditing: this.openmct.editor.isEditing()
|
isEditing: this.openmct.editor.isEditing()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.openmct.editor.on('isEditing', this.toggleIsEditing);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.openmct.editor.off('isEditing', this.toggleIsEditing);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleIsEditing(isEditing) {
|
toggleIsEditing(isEditing) {
|
||||||
this.isEditing = isEditing;
|
this.isEditing = isEditing;
|
||||||
@ -107,12 +126,6 @@ export default {
|
|||||||
return accum;
|
return accum;
|
||||||
}, []).join(', ');
|
}, []).join(', ');
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.openmct.editor.on('isEditing', this.toggleIsEditing);
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.openmct.editor.off('isEditing', this.toggleIsEditing);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,50 +1,62 @@
|
|||||||
<template>
|
<template>
|
||||||
<li class="c-tree__item-h">
|
<li class="c-tree__item-h">
|
||||||
<div class="c-tree__item menus-to-left"
|
<div
|
||||||
@click="toggleExpanded">
|
class="c-tree__item menus-to-left"
|
||||||
<div class="c-filter-tree-item__filter-indicator"
|
@click="toggleExpanded"
|
||||||
:class="{'icon-filter': hasActiveFilters }"></div>
|
>
|
||||||
<span class="c-disclosure-triangle is-enabled flex-elem"
|
<div
|
||||||
:class="{'c-disclosure-triangle--expanded': expanded}"></span>
|
class="c-filter-tree-item__filter-indicator"
|
||||||
<div class="c-tree__item__label c-object-label">
|
:class="{'icon-filter': hasActiveFilters }"
|
||||||
<div class="c-object-label">
|
></div>
|
||||||
<div class="c-object-label__type-icon"
|
<span
|
||||||
:class="objectCssClass">
|
class="c-disclosure-triangle is-enabled flex-elem"
|
||||||
</div>
|
:class="{'c-disclosure-triangle--expanded': expanded}"
|
||||||
<div class="c-object-label__name flex-elem grows">{{ filterObject.name }}</div>
|
></span>
|
||||||
|
<div class="c-tree__item__label c-object-label">
|
||||||
|
<div class="c-object-label">
|
||||||
|
<div
|
||||||
|
class="c-object-label__type-icon"
|
||||||
|
:class="objectCssClass"
|
||||||
|
></div>
|
||||||
|
<div class="c-object-label__name flex-elem grows">
|
||||||
|
{{ filterObject.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="expanded">
|
<div v-if="expanded">
|
||||||
<ul class="c-properties">
|
<ul class="c-properties">
|
||||||
<div class="c-properties__label span-all"
|
<div
|
||||||
v-if="!isEditing && persistedFilters.useGlobal">
|
v-if="!isEditing && persistedFilters.useGlobal"
|
||||||
Uses global filter
|
class="c-properties__label span-all"
|
||||||
</div>
|
>
|
||||||
|
Uses global filter
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="c-properties__label span-all"
|
<div
|
||||||
v-if="isEditing">
|
v-if="isEditing"
|
||||||
<toggle-switch
|
class="c-properties__label span-all"
|
||||||
:id="keyString"
|
>
|
||||||
@change="useGlobalFilter"
|
<toggle-switch
|
||||||
:checked="persistedFilters.useGlobal">
|
:id="keyString"
|
||||||
</toggle-switch>
|
:checked="persistedFilters.useGlobal"
|
||||||
Use global filter
|
@change="useGlobalFilter"
|
||||||
</div>
|
/>
|
||||||
<filter-field
|
Use global filter
|
||||||
v-if="(!persistedFilters.useGlobal && !isEditing) || isEditing"
|
</div>
|
||||||
v-for="metadatum in filterObject.metadataWithFilters"
|
<filter-field
|
||||||
:key="metadatum.key"
|
v-for="metadatum in activeFilters"
|
||||||
:filterField="metadatum"
|
:key="metadatum.key"
|
||||||
:useGlobal="persistedFilters.useGlobal"
|
:filter-field="metadatum"
|
||||||
:persistedFilters="updatedFilters[metadatum.key]"
|
:use-global="persistedFilters.useGlobal"
|
||||||
@filterSelected="updateFiltersWithSelectedValue"
|
:persisted-filters="updatedFilters[metadatum.key]"
|
||||||
@filterTextValueChanged="updateFiltersWithTextValue">
|
@filterSelected="updateFiltersWithSelectedValue"
|
||||||
</filter-field>
|
@filterTextValueChanged="updateFiltersWithTextValue"
|
||||||
</ul>
|
/>
|
||||||
</div>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -58,7 +70,10 @@ export default {
|
|||||||
ToggleSwitch
|
ToggleSwitch
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
filterObject: Object,
|
filterObject: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
persistedFilters: {
|
persistedFilters: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {
|
default: () => {
|
||||||
@ -74,6 +89,23 @@ export default {
|
|||||||
isEditing: this.openmct.editor.isEditing()
|
isEditing: this.openmct.editor.isEditing()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
// do not show filter fields if using global filter
|
||||||
|
// if editing however, show all filter fields
|
||||||
|
activeFilters() {
|
||||||
|
if (!this.isEditing && this.persistedFilters.useGlobal) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.filterObject.metadataWithFilters
|
||||||
|
},
|
||||||
|
hasActiveFilters() {
|
||||||
|
// Should be true when the user has entered any filter values.
|
||||||
|
return Object.values(this.persistedFilters).some(comparator => {
|
||||||
|
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
persistedFilters: {
|
persistedFilters: {
|
||||||
handler: function checkFilters(newpersistedFilters) {
|
handler: function checkFilters(newpersistedFilters) {
|
||||||
@ -82,13 +114,14 @@ export default {
|
|||||||
deep: true
|
deep: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
mounted() {
|
||||||
hasActiveFilters() {
|
let type = this.openmct.types.get(this.filterObject.domainObject.type) || {};
|
||||||
// Should be true when the user has entered any filter values.
|
this.keyString = this.openmct.objects.makeKeyString(this.filterObject.domainObject.identifier);
|
||||||
return Object.values(this.persistedFilters).some(comparator => {
|
this.objectCssClass = type.definition.cssClass;
|
||||||
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
this.openmct.editor.on('isEditing', this.toggleIsEditing);
|
||||||
});
|
},
|
||||||
}
|
beforeDestroy() {
|
||||||
|
this.openmct.editor.off('isEditing', this.toggleIsEditing);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleExpanded() {
|
toggleExpanded() {
|
||||||
@ -128,16 +161,7 @@ export default {
|
|||||||
},
|
},
|
||||||
toggleIsEditing(isEditing) {
|
toggleIsEditing(isEditing) {
|
||||||
this.isEditing = isEditing;
|
this.isEditing = isEditing;
|
||||||
},
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let type = this.openmct.types.get(this.filterObject.domainObject.type) || {};
|
|
||||||
this.keyString = this.openmct.objects.makeKeyString(this.filterObject.domainObject.identifier);
|
|
||||||
this.objectCssClass = type.definition.cssClass;
|
|
||||||
this.openmct.editor.on('isEditing', this.toggleIsEditing);
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.openmct.editor.off('isEditing', this.toggleIsEditing);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul class="c-tree c-filter-tree" v-if="Object.keys(children).length">
|
<ul
|
||||||
<h2>Data Filters</h2>
|
v-if="Object.keys(children).length"
|
||||||
<div class="c-filter-indication"
|
class="c-tree c-filter-tree"
|
||||||
v-if="hasActiveFilters">{{ label }}
|
>
|
||||||
</div>
|
<h2>Data Filters</h2>
|
||||||
<global-filters
|
<div
|
||||||
:globalFilters="globalFilters"
|
v-if="hasActiveFilters"
|
||||||
:globalMetadata="globalMetadata"
|
class="c-filter-indication"
|
||||||
@persistGlobalFilters="persistGlobalFilters">
|
>
|
||||||
</global-filters>
|
{{ label }}
|
||||||
<filter-object
|
</div>
|
||||||
v-for="(child, key) in children"
|
<global-filters
|
||||||
:key="key"
|
:global-filters="globalFilters"
|
||||||
:filterObject="child"
|
:global-metadata="globalMetadata"
|
||||||
:persistedFilters="persistedFilters[key]"
|
@persistGlobalFilters="persistGlobalFilters"
|
||||||
@updateFilters="persistFilters">
|
/>
|
||||||
</filter-object>
|
<filter-object
|
||||||
</ul>
|
v-for="(child, key) in children"
|
||||||
|
:key="key"
|
||||||
|
:filter-object="child"
|
||||||
|
:persisted-filters="persistedFilters[key]"
|
||||||
|
@updateFilters="persistFilters"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -40,210 +46,211 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import FilterObject from './FilterObject.vue';
|
import FilterObject from './FilterObject.vue';
|
||||||
import GlobalFilters from './GlobalFilters.vue'
|
import GlobalFilters from './GlobalFilters.vue'
|
||||||
|
|
||||||
const FILTER_VIEW_TITLE = 'Filters applied';
|
const FILTER_VIEW_TITLE = 'Filters applied';
|
||||||
const FILTER_VIEW_TITLE_MIXED = 'Mixed filters applied';
|
const FILTER_VIEW_TITLE_MIXED = 'Mixed filters applied';
|
||||||
const USE_GLOBAL = 'useGlobal';
|
const USE_GLOBAL = 'useGlobal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FilterObject,
|
FilterObject,
|
||||||
GlobalFilters
|
GlobalFilters
|
||||||
},
|
},
|
||||||
inject: [
|
inject: [
|
||||||
'openmct'
|
'openmct'
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
let providedObject = this.openmct.selection.get()[0][0].context.item;
|
let providedObject = this.openmct.selection.get()[0][0].context.item;
|
||||||
let configuration = providedObject.configuration;
|
let configuration = providedObject.configuration;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
persistedFilters: (configuration && configuration.filters) || {},
|
persistedFilters: (configuration && configuration.filters) || {},
|
||||||
globalFilters: (configuration && configuration.globalFilters) || {},
|
globalFilters: (configuration && configuration.globalFilters) || {},
|
||||||
globalMetadata: {},
|
globalMetadata: {},
|
||||||
providedObject,
|
providedObject,
|
||||||
children: {}
|
children: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hasActiveFilters() {
|
hasActiveFilters() {
|
||||||
// Should be true when the user has entered any filter values.
|
// Should be true when the user has entered any filter values.
|
||||||
return Object.values(this.persistedFilters).some(filters => {
|
return Object.values(this.persistedFilters).some(filters => {
|
||||||
return Object.values(filters).some(comparator => {
|
return Object.values(filters).some(comparator => {
|
||||||
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
hasMixedFilters() {
|
},
|
||||||
// Should be true when filter values are mixed.
|
hasMixedFilters() {
|
||||||
let filtersToCompare = _.omit(this.persistedFilters[Object.keys(this.persistedFilters)[0]], [USE_GLOBAL]);
|
// Should be true when filter values are mixed.
|
||||||
return Object.values(this.persistedFilters).some(filters => {
|
let filtersToCompare = _.omit(this.persistedFilters[Object.keys(this.persistedFilters)[0]], [USE_GLOBAL]);
|
||||||
return !_.isEqual(filtersToCompare, _.omit(filters, [USE_GLOBAL]));
|
return Object.values(this.persistedFilters).some(filters => {
|
||||||
});
|
return !_.isEqual(filtersToCompare, _.omit(filters, [USE_GLOBAL]));
|
||||||
},
|
});
|
||||||
label() {
|
},
|
||||||
if (this.hasActiveFilters) {
|
label() {
|
||||||
if (this.hasMixedFilters) {
|
if (this.hasActiveFilters) {
|
||||||
return FILTER_VIEW_TITLE_MIXED;
|
if (this.hasMixedFilters) {
|
||||||
} else {
|
return FILTER_VIEW_TITLE_MIXED;
|
||||||
return FILTER_VIEW_TITLE;
|
} else {
|
||||||
}
|
return FILTER_VIEW_TITLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
return '';
|
||||||
methods: {
|
}
|
||||||
addChildren(domainObject) {
|
},
|
||||||
let keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
mounted() {
|
||||||
let metadata = this.openmct.telemetry.getMetadata(domainObject);
|
this.composition = this.openmct.composition.get(this.providedObject);
|
||||||
let metadataWithFilters = metadata.valueMetadatas.filter(value => value.filters);
|
this.composition.on('add', this.addChildren);
|
||||||
let hasFiltersWithKeyString = this.persistedFilters[keyString] !== undefined;
|
this.composition.on('remove', this.removeChildren);
|
||||||
let mutateFilters = false;
|
this.composition.load();
|
||||||
let childObject = {
|
this.unobserve = this.openmct.objects.observe(this.providedObject, 'configuration.filters', this.updatePersistedFilters);
|
||||||
name: domainObject.name,
|
this.unobserveGlobalFilters = this.openmct.objects.observe(this.providedObject, 'configuration.globalFilters', this.updateGlobalFilters);
|
||||||
domainObject: domainObject,
|
this.unobserveAllMutation = this.openmct.objects.observe(this.providedObject, '*', (mutatedObject) => this.providedObject = mutatedObject);
|
||||||
metadataWithFilters
|
},
|
||||||
};
|
beforeDestroy() {
|
||||||
|
this.composition.off('add', this.addChildren);
|
||||||
|
this.composition.off('remove', this.removeChildren);
|
||||||
|
this.unobserve();
|
||||||
|
this.unobserveGlobalFilters();
|
||||||
|
this.unobserveAllMutation();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addChildren(domainObject) {
|
||||||
|
let keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
let metadata = this.openmct.telemetry.getMetadata(domainObject);
|
||||||
|
let metadataWithFilters = metadata.valueMetadatas.filter(value => value.filters);
|
||||||
|
let hasFiltersWithKeyString = this.persistedFilters[keyString] !== undefined;
|
||||||
|
let mutateFilters = false;
|
||||||
|
let childObject = {
|
||||||
|
name: domainObject.name,
|
||||||
|
domainObject: domainObject,
|
||||||
|
metadataWithFilters
|
||||||
|
};
|
||||||
|
|
||||||
if (metadataWithFilters.length) {
|
if (metadataWithFilters.length) {
|
||||||
this.$set(this.children, keyString, childObject);
|
this.$set(this.children, keyString, childObject);
|
||||||
|
|
||||||
metadataWithFilters.forEach(metadatum => {
|
metadataWithFilters.forEach(metadatum => {
|
||||||
if (!this.globalFilters[metadatum.key]) {
|
if (!this.globalFilters[metadatum.key]) {
|
||||||
this.$set(this.globalFilters, metadatum.key, {});
|
this.$set(this.globalFilters, metadatum.key, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.globalMetadata[metadatum.key]) {
|
||||||
|
this.$set(this.globalMetadata, metadatum.key, metadatum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasFiltersWithKeyString) {
|
||||||
|
if (!this.persistedFilters[keyString]) {
|
||||||
|
this.$set(this.persistedFilters, keyString, {});
|
||||||
|
this.$set(this.persistedFilters[keyString], 'useGlobal', true);
|
||||||
|
mutateFilters = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.globalMetadata[metadatum.key]) {
|
this.$set(this.persistedFilters[keyString], metadatum.key, this.globalFilters[metadatum.key]);
|
||||||
this.$set(this.globalMetadata, metadatum.key, metadatum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasFiltersWithKeyString) {
|
|
||||||
if (!this.persistedFilters[keyString]) {
|
|
||||||
this.$set(this.persistedFilters, keyString, {});
|
|
||||||
this.$set(this.persistedFilters[keyString], 'useGlobal', true);
|
|
||||||
mutateFilters = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$set(this.persistedFilters[keyString], metadatum.key, this.globalFilters[metadatum.key]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mutateFilters) {
|
|
||||||
this.mutateConfigurationFilters();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeChildren(identifier) {
|
|
||||||
let keyString = this.openmct.objects.makeKeyString(identifier);
|
|
||||||
let globalFiltersToRemove = this.getGlobalFiltersToRemove(keyString);
|
|
||||||
|
|
||||||
if (globalFiltersToRemove.length > 0) {
|
|
||||||
globalFiltersToRemove.forEach(key => {
|
|
||||||
this.$delete(this.globalFilters, key);
|
|
||||||
this.$delete(this.globalMetadata, key);
|
|
||||||
});
|
|
||||||
this.mutateConfigurationGlobalFilters();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$delete(this.children, keyString);
|
|
||||||
this.$delete(this.persistedFilters, keyString);
|
|
||||||
this.mutateConfigurationFilters();
|
|
||||||
},
|
|
||||||
getGlobalFiltersToRemove(keyString) {
|
|
||||||
let filtersToRemove = new Set();
|
|
||||||
|
|
||||||
this.children[keyString].metadataWithFilters.forEach(metadatum => {
|
|
||||||
let keepFilter = false
|
|
||||||
Object.keys(this.children).forEach(childKeyString => {
|
|
||||||
if (childKeyString !== keyString) {
|
|
||||||
let filterMatched = this.children[childKeyString].metadataWithFilters.some(childMetadatum => childMetadatum.key === metadatum.key);
|
|
||||||
|
|
||||||
if (filterMatched) {
|
|
||||||
keepFilter = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!keepFilter) {
|
|
||||||
filtersToRemove.add(metadatum.key);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Array.from(filtersToRemove);
|
if (mutateFilters) {
|
||||||
},
|
|
||||||
persistFilters(keyString, updatedFilters, useGlobalValues) {
|
|
||||||
this.persistedFilters[keyString] = updatedFilters;
|
|
||||||
|
|
||||||
if (useGlobalValues) {
|
|
||||||
Object.keys(this.persistedFilters[keyString]).forEach(key => {
|
|
||||||
if (typeof(this.persistedFilters[keyString][key]) === 'object') {
|
|
||||||
this.persistedFilters[keyString][key] = this.globalFilters[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mutateConfigurationFilters();
|
this.mutateConfigurationFilters();
|
||||||
},
|
}
|
||||||
updatePersistedFilters(filters) {
|
},
|
||||||
this.persistedFilters = filters;
|
removeChildren(identifier) {
|
||||||
},
|
let keyString = this.openmct.objects.makeKeyString(identifier);
|
||||||
persistGlobalFilters(key, filters) {
|
let globalFiltersToRemove = this.getGlobalFiltersToRemove(keyString);
|
||||||
this.globalFilters[key] = filters[key];
|
|
||||||
|
if (globalFiltersToRemove.length > 0) {
|
||||||
|
globalFiltersToRemove.forEach(key => {
|
||||||
|
this.$delete(this.globalFilters, key);
|
||||||
|
this.$delete(this.globalMetadata, key);
|
||||||
|
});
|
||||||
this.mutateConfigurationGlobalFilters();
|
this.mutateConfigurationGlobalFilters();
|
||||||
let mutateFilters = false;
|
}
|
||||||
|
|
||||||
Object.keys(this.children).forEach(keyString => {
|
this.$delete(this.children, keyString);
|
||||||
if (this.persistedFilters[keyString].useGlobal !== false && this.containsField(keyString, key)) {
|
this.$delete(this.persistedFilters, keyString);
|
||||||
if (!this.persistedFilters[keyString][key]) {
|
this.mutateConfigurationFilters();
|
||||||
this.$set(this.persistedFilters[keyString], key, {});
|
},
|
||||||
|
getGlobalFiltersToRemove(keyString) {
|
||||||
|
let filtersToRemove = new Set();
|
||||||
|
|
||||||
|
this.children[keyString].metadataWithFilters.forEach(metadatum => {
|
||||||
|
let keepFilter = false
|
||||||
|
Object.keys(this.children).forEach(childKeyString => {
|
||||||
|
if (childKeyString !== keyString) {
|
||||||
|
let filterMatched = this.children[childKeyString].metadataWithFilters.some(childMetadatum => childMetadatum.key === metadatum.key);
|
||||||
|
|
||||||
|
if (filterMatched) {
|
||||||
|
keepFilter = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$set(this.persistedFilters[keyString], key, filters[key]);
|
|
||||||
mutateFilters = true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mutateFilters) {
|
if (!keepFilter) {
|
||||||
this.mutateConfigurationFilters();
|
filtersToRemove.add(metadatum.key);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
updateGlobalFilters(filters) {
|
|
||||||
this.globalFilters = filters;
|
return Array.from(filtersToRemove);
|
||||||
},
|
},
|
||||||
containsField(keyString, field) {
|
persistFilters(keyString, updatedFilters, useGlobalValues) {
|
||||||
let hasField = false;
|
this.persistedFilters[keyString] = updatedFilters;
|
||||||
this.children[keyString].metadataWithFilters.forEach(metadatum => {
|
|
||||||
if (metadatum.key === field) {
|
if (useGlobalValues) {
|
||||||
hasField = true;
|
Object.keys(this.persistedFilters[keyString]).forEach(key => {
|
||||||
return;
|
if (typeof(this.persistedFilters[keyString][key]) === 'object') {
|
||||||
|
this.persistedFilters[keyString][key] = this.globalFilters[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return hasField;
|
}
|
||||||
},
|
|
||||||
mutateConfigurationFilters() {
|
this.mutateConfigurationFilters();
|
||||||
this.openmct.objects.mutate(this.providedObject, 'configuration.filters', this.persistedFilters);
|
},
|
||||||
},
|
updatePersistedFilters(filters) {
|
||||||
mutateConfigurationGlobalFilters() {
|
this.persistedFilters = filters;
|
||||||
this.openmct.objects.mutate(this.providedObject, 'configuration.globalFilters', this.globalFilters);
|
},
|
||||||
|
persistGlobalFilters(key, filters) {
|
||||||
|
this.globalFilters[key] = filters[key];
|
||||||
|
this.mutateConfigurationGlobalFilters();
|
||||||
|
let mutateFilters = false;
|
||||||
|
|
||||||
|
Object.keys(this.children).forEach(keyString => {
|
||||||
|
if (this.persistedFilters[keyString].useGlobal !== false && this.containsField(keyString, key)) {
|
||||||
|
if (!this.persistedFilters[keyString][key]) {
|
||||||
|
this.$set(this.persistedFilters[keyString], key, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$set(this.persistedFilters[keyString], key, filters[key]);
|
||||||
|
mutateFilters = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mutateFilters) {
|
||||||
|
this.mutateConfigurationFilters();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted(){
|
updateGlobalFilters(filters) {
|
||||||
this.composition = this.openmct.composition.get(this.providedObject);
|
this.globalFilters = filters;
|
||||||
this.composition.on('add', this.addChildren);
|
|
||||||
this.composition.on('remove', this.removeChildren);
|
|
||||||
this.composition.load();
|
|
||||||
this.unobserve = this.openmct.objects.observe(this.providedObject, 'configuration.filters', this.updatePersistedFilters);
|
|
||||||
this.unobserveGlobalFilters = this.openmct.objects.observe(this.providedObject, 'configuration.globalFilters', this.updateGlobalFilters);
|
|
||||||
this.unobserveAllMutation = this.openmct.objects.observe(this.providedObject, '*', (mutatedObject) => this.providedObject = mutatedObject);
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
containsField(keyString, field) {
|
||||||
this.composition.off('add', this.addChildren);
|
let hasField = false;
|
||||||
this.composition.off('remove', this.removeChildren);
|
this.children[keyString].metadataWithFilters.forEach(metadatum => {
|
||||||
this.unobserve();
|
if (metadatum.key === field) {
|
||||||
this.unobserveGlobalFilters();
|
hasField = true;
|
||||||
this.unobserveAllMutation();
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return hasField;
|
||||||
|
},
|
||||||
|
mutateConfigurationFilters() {
|
||||||
|
this.openmct.objects.mutate(this.providedObject, 'configuration.filters', this.persistedFilters);
|
||||||
|
},
|
||||||
|
mutateConfigurationGlobalFilters() {
|
||||||
|
this.openmct.objects.mutate(this.providedObject, 'configuration.globalFilters', this.globalFilters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,29 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<li class="c-tree__item-h">
|
<li class="c-tree__item-h">
|
||||||
<div class="c-tree__item menus-to-left"
|
<div
|
||||||
@click="toggleExpanded">
|
class="c-tree__item menus-to-left"
|
||||||
<div class="c-filter-tree-item__filter-indicator"
|
@click="toggleExpanded"
|
||||||
:class="{'icon-filter': hasActiveGlobalFilters }"></div>
|
>
|
||||||
<span class="c-disclosure-triangle is-enabled flex-elem"
|
<div
|
||||||
:class="{'c-disclosure-triangle--expanded': expanded}"></span>
|
class="c-filter-tree-item__filter-indicator"
|
||||||
<div class="c-tree__item__label c-object-label">
|
:class="{'icon-filter': hasActiveGlobalFilters }"
|
||||||
<div class="c-object-label">
|
></div>
|
||||||
<div class="c-object-label__type-icon icon-gear"></div>
|
<span
|
||||||
<div class="c-object-label__name flex-elem grows">Global Filtering</div>
|
class="c-disclosure-triangle is-enabled flex-elem"
|
||||||
|
:class="{'c-disclosure-triangle--expanded': expanded}"
|
||||||
|
></span>
|
||||||
|
<div class="c-tree__item__label c-object-label">
|
||||||
|
<div class="c-object-label">
|
||||||
|
<div class="c-object-label__type-icon icon-gear"></div>
|
||||||
|
<div class="c-object-label__name flex-elem grows">
|
||||||
|
Global Filtering
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="c-properties" v-if="expanded">
|
</div>
|
||||||
<filter-field
|
<ul
|
||||||
v-for="metadatum in globalMetadata"
|
v-if="expanded"
|
||||||
:key="metadatum.key"
|
class="c-properties"
|
||||||
:filterField="metadatum"
|
>
|
||||||
:persistedFilters="updatedFilters[metadatum.key]"
|
<filter-field
|
||||||
@filterSelected="updateFiltersWithSelectedValue"
|
v-for="metadatum in globalMetadata"
|
||||||
@filterTextValueChanged="updateFiltersWithTextValue">
|
:key="metadatum.key"
|
||||||
</filter-field>
|
:filter-field="metadatum"
|
||||||
</ul>
|
:persisted-filters="updatedFilters[metadatum.key]"
|
||||||
</li>
|
@filterSelected="updateFiltersWithSelectedValue"
|
||||||
|
@filterTextValueChanged="updateFiltersWithTextValue"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -59,77 +70,80 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import FilterField from './FilterField.vue';
|
import FilterField from './FilterField.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
components: {
|
components: {
|
||||||
FilterField
|
FilterField
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
globalMetadata: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
props: {
|
globalFilters: {
|
||||||
globalMetadata: Object,
|
type: Object,
|
||||||
globalFilters: {
|
default: () => {
|
||||||
type: Object,
|
return {};
|
||||||
default: () => {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
expanded: false,
|
|
||||||
updatedFilters: JSON.parse(JSON.stringify(this.globalFilters))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hasActiveGlobalFilters() {
|
|
||||||
return Object.values(this.globalFilters).some(field => {
|
|
||||||
return Object.values(field).some(comparator => {
|
|
||||||
return (comparator && (comparator !== '' || comparator.length > 0));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
globalFilters: {
|
|
||||||
handler: function checkFilters(newGlobalFilters) {
|
|
||||||
this.updatedFilters = JSON.parse(JSON.stringify(newGlobalFilters));
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleExpanded() {
|
|
||||||
this.expanded = !this.expanded;
|
|
||||||
},
|
|
||||||
updateFiltersWithSelectedValue(key, comparator, valueName, value) {
|
|
||||||
let filterValue = this.updatedFilters[key];
|
|
||||||
|
|
||||||
if (filterValue[comparator]) {
|
|
||||||
if (value === true) {
|
|
||||||
filterValue[comparator].push(valueName);
|
|
||||||
} else {
|
|
||||||
if (filterValue[comparator].length === 1) {
|
|
||||||
this.$set(this.updatedFilters, key, {});
|
|
||||||
} else {
|
|
||||||
filterValue[comparator] = filterValue[comparator].filter(v => v !== valueName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$set(this.updatedFilters[key], comparator, [valueName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
|
||||||
},
|
|
||||||
updateFiltersWithTextValue(key, comparator, value) {
|
|
||||||
if (value.trim() === '') {
|
|
||||||
this.$set(this.updatedFilters, key, {});
|
|
||||||
} else {
|
|
||||||
this.$set(this.updatedFilters[key], comparator, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
expanded: false,
|
||||||
|
updatedFilters: JSON.parse(JSON.stringify(this.globalFilters))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasActiveGlobalFilters() {
|
||||||
|
return Object.values(this.globalFilters).some(field => {
|
||||||
|
return Object.values(field).some(comparator => {
|
||||||
|
return (comparator && (comparator !== '' || comparator.length > 0));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
globalFilters: {
|
||||||
|
handler: function checkFilters(newGlobalFilters) {
|
||||||
|
this.updatedFilters = JSON.parse(JSON.stringify(newGlobalFilters));
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleExpanded() {
|
||||||
|
this.expanded = !this.expanded;
|
||||||
|
},
|
||||||
|
updateFiltersWithSelectedValue(key, comparator, valueName, value) {
|
||||||
|
let filterValue = this.updatedFilters[key];
|
||||||
|
|
||||||
|
if (filterValue[comparator]) {
|
||||||
|
if (value === true) {
|
||||||
|
filterValue[comparator].push(valueName);
|
||||||
|
} else {
|
||||||
|
if (filterValue[comparator].length === 1) {
|
||||||
|
this.$set(this.updatedFilters, key, {});
|
||||||
|
} else {
|
||||||
|
filterValue[comparator] = filterValue[comparator].filter(v => v !== valueName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$set(this.updatedFilters[key], comparator, [valueName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||||
|
},
|
||||||
|
updateFiltersWithTextValue(key, comparator, value) {
|
||||||
|
if (value.trim() === '') {
|
||||||
|
this.$set(this.updatedFilters, key, {});
|
||||||
|
} else {
|
||||||
|
this.$set(this.updatedFilters[key], comparator, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,62 +21,65 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-fl-container"
|
<div
|
||||||
:style="[{'flex-basis': sizeString}]"
|
class="c-fl-container"
|
||||||
:class="{'is-empty': !frames.length}">
|
:style="[{'flex-basis': sizeString}]"
|
||||||
<div class="c-fl-container__header"
|
:class="{'is-empty': !frames.length}"
|
||||||
v-show="isEditing"
|
>
|
||||||
draggable="true"
|
<div
|
||||||
@dragstart="startContainerDrag">
|
v-show="isEditing"
|
||||||
<span class="c-fl-container__size-indicator">{{ sizeString }}</span>
|
class="c-fl-container__header"
|
||||||
</div>
|
draggable="true"
|
||||||
|
@dragstart="startContainerDrag"
|
||||||
<drop-hint
|
>
|
||||||
class="c-fl-frame__drop-hint"
|
<span class="c-fl-container__size-indicator">{{ sizeString }}</span>
|
||||||
:index="-1"
|
|
||||||
:allow-drop="allowDrop"
|
|
||||||
@object-drop-to="moveOrCreateNewFrame">
|
|
||||||
</drop-hint>
|
|
||||||
|
|
||||||
<div class="c-fl-container__frames-holder">
|
|
||||||
<template
|
|
||||||
v-for="(frame, i) in frames">
|
|
||||||
|
|
||||||
<frame-component
|
|
||||||
class="c-fl-container__frame"
|
|
||||||
:key="frame.id"
|
|
||||||
:frame="frame"
|
|
||||||
:index="i"
|
|
||||||
:containerIndex="index"
|
|
||||||
:isEditing="isEditing">
|
|
||||||
</frame-component>
|
|
||||||
|
|
||||||
<drop-hint
|
|
||||||
class="c-fl-frame__drop-hint"
|
|
||||||
:key="i"
|
|
||||||
:index="i"
|
|
||||||
:allowDrop="allowDrop"
|
|
||||||
@object-drop-to="moveOrCreateNewFrame">
|
|
||||||
</drop-hint>
|
|
||||||
|
|
||||||
<resize-handle
|
|
||||||
v-if="(i !== frames.length - 1)"
|
|
||||||
:key="i"
|
|
||||||
:index="i"
|
|
||||||
:orientation="rowsLayout ? 'horizontal' : 'vertical'"
|
|
||||||
@init-move="startFrameResizing"
|
|
||||||
@move="frameResizing"
|
|
||||||
@end-move="endFrameResizing"
|
|
||||||
:isEditing="isEditing">
|
|
||||||
</resize-handle>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<drop-hint
|
||||||
|
class="c-fl-frame__drop-hint"
|
||||||
|
:index="-1"
|
||||||
|
:allow-drop="allowDrop"
|
||||||
|
@object-drop-to="moveOrCreateNewFrame"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="c-fl-container__frames-holder">
|
||||||
|
<template
|
||||||
|
v-for="(frame, i) in frames"
|
||||||
|
>
|
||||||
|
<frame-component
|
||||||
|
:key="frame.id"
|
||||||
|
class="c-fl-container__frame"
|
||||||
|
:frame="frame"
|
||||||
|
:index="i"
|
||||||
|
:container-index="index"
|
||||||
|
:is-editing="isEditing"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<drop-hint
|
||||||
|
:key="i"
|
||||||
|
class="c-fl-frame__drop-hint"
|
||||||
|
:index="i"
|
||||||
|
:allow-drop="allowDrop"
|
||||||
|
@object-drop-to="moveOrCreateNewFrame"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<resize-handle
|
||||||
|
v-if="(i !== frames.length - 1)"
|
||||||
|
:key="i"
|
||||||
|
:index="i"
|
||||||
|
:orientation="rowsLayout ? 'horizontal' : 'vertical'"
|
||||||
|
:is-editing="isEditing"
|
||||||
|
@init-move="startFrameResizing"
|
||||||
|
@move="frameResizing"
|
||||||
|
@end-move="endFrameResizing"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import FrameComponent from './frame.vue';
|
import FrameComponent from './frame.vue';
|
||||||
import Frame from '../utils/frame';
|
|
||||||
import ResizeHandle from './resizeHandle.vue';
|
import ResizeHandle from './resizeHandle.vue';
|
||||||
import DropHint from './dropHint.vue';
|
import DropHint from './dropHint.vue';
|
||||||
|
|
||||||
@ -84,12 +87,26 @@ const MIN_FRAME_SIZE = 5;
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject:['openmct'],
|
inject:['openmct'],
|
||||||
props: ['container', 'index', 'rowsLayout', 'isEditing'],
|
|
||||||
components: {
|
components: {
|
||||||
FrameComponent,
|
FrameComponent,
|
||||||
ResizeHandle,
|
ResizeHandle,
|
||||||
DropHint
|
DropHint
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
container: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
rowsLayout: Boolean,
|
||||||
|
isEditing: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
frames() {
|
frames() {
|
||||||
return this.container.frames;
|
return this.container.frames;
|
||||||
@ -98,6 +115,19 @@ export default {
|
|||||||
return `${Math.round(this.container.size)}%`
|
return `${Math.round(this.container.size)}%`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
let context = {
|
||||||
|
item: this.$parent.domainObject,
|
||||||
|
addContainer: this.addContainer,
|
||||||
|
type: 'container',
|
||||||
|
containerId: this.container.id
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unsubscribeSelection = this.openmct.selection.selectable(this.$el, context, false);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.unsubscribeSelection();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
allowDrop(event, index) {
|
allowDrop(event, index) {
|
||||||
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||||
@ -131,7 +161,7 @@ export default {
|
|||||||
insertIndex
|
insertIndex
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
// move frame.
|
// move frame.
|
||||||
let frameId = event.dataTransfer.getData('frameid');
|
let frameId = event.dataTransfer.getData('frameid');
|
||||||
let containerIndex = Number(event.dataTransfer.getData('containerIndex'));
|
let containerIndex = Number(event.dataTransfer.getData('containerIndex'));
|
||||||
@ -182,19 +212,6 @@ export default {
|
|||||||
startContainerDrag(event) {
|
startContainerDrag(event) {
|
||||||
event.dataTransfer.setData('containerid', this.container.id);
|
event.dataTransfer.setData('containerid', this.container.id);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let context = {
|
|
||||||
item: this.$parent.domainObject,
|
|
||||||
addContainer: this.addContainer,
|
|
||||||
type: 'container',
|
|
||||||
containerId: this.container.id
|
|
||||||
}
|
|
||||||
|
|
||||||
this.unsubscribeSelection = this.openmct.selection.selectable(this.$el, context, false);
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.unsubscribeSelection();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,15 +21,16 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-show="isValidTarget">
|
<div v-show="isValidTarget">
|
||||||
<div class="c-drop-hint c-drop-hint--always-show"
|
<div
|
||||||
:class="{'is-mouse-over': isMouseOver}"
|
class="c-drop-hint c-drop-hint--always-show"
|
||||||
@dragover.prevent
|
:class="{'is-mouse-over': isMouseOver}"
|
||||||
@dragenter="dragenter"
|
@dragover.prevent
|
||||||
@dragleave="dragleave"
|
@dragenter="dragenter"
|
||||||
@drop="dropHandler">
|
@dragleave="dragleave"
|
||||||
</div>
|
@drop="dropHandler"
|
||||||
</div>
|
></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -39,7 +40,10 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props:{
|
props:{
|
||||||
index: Number,
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
allowDrop: {
|
allowDrop: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true
|
||||||
@ -51,6 +55,16 @@ export default {
|
|||||||
isValidTarget: false
|
isValidTarget: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener('dragstart', this.dragstart);
|
||||||
|
document.addEventListener('dragend', this.dragend);
|
||||||
|
document.addEventListener('drop', this.dragend);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
document.removeEventListener('dragstart', this.dragstart);
|
||||||
|
document.removeEventListener('dragend', this.dragend);
|
||||||
|
document.removeEventListener('drop', this.dragend);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
dragenter() {
|
dragenter() {
|
||||||
this.isMouseOver = true;
|
this.isMouseOver = true;
|
||||||
@ -68,16 +82,6 @@ export default {
|
|||||||
dragend() {
|
dragend() {
|
||||||
this.isValidTarget = false;
|
this.isValidTarget = false;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.addEventListener('dragstart', this.dragstart);
|
|
||||||
document.addEventListener('dragend', this.dragend);
|
|
||||||
document.addEventListener('drop', this.dragend);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
document.removeEventListener('dragstart', this.dragstart);
|
|
||||||
document.removeEventListener('dragend', this.dragend);
|
|
||||||
document.removeEventListener('drop', this.dragend);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,67 +21,69 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-fl">
|
<div class="c-fl">
|
||||||
<div
|
<div
|
||||||
id="js-fl-drag-ghost"
|
id="js-fl-drag-ghost"
|
||||||
class="c-fl__drag-ghost">
|
class="c-fl__drag-ghost"
|
||||||
</div>
|
></div>
|
||||||
|
|
||||||
<div class="c-fl__empty"
|
<div
|
||||||
v-if="areAllContainersEmpty()">
|
v-if="areAllContainersEmpty()"
|
||||||
<span class="c-fl__empty-message">This Flexible Layout is currently empty</span>
|
class="c-fl__empty"
|
||||||
</div>
|
>
|
||||||
|
<span class="c-fl__empty-message">This Flexible Layout is currently empty</span>
|
||||||
<div class="c-fl__container-holder"
|
|
||||||
:class="{
|
|
||||||
'c-fl--rows': rowsLayout === true
|
|
||||||
}">
|
|
||||||
|
|
||||||
<template v-for="(container, index) in containers">
|
|
||||||
|
|
||||||
<drop-hint
|
|
||||||
class="c-fl-frame__drop-hint"
|
|
||||||
v-if="index === 0 && containers.length > 1"
|
|
||||||
:key="index"
|
|
||||||
:index="-1"
|
|
||||||
:allow-drop="allowContainerDrop"
|
|
||||||
@object-drop-to="moveContainer">
|
|
||||||
</drop-hint>
|
|
||||||
|
|
||||||
<container-component
|
|
||||||
class="c-fl__container"
|
|
||||||
:key="container.id"
|
|
||||||
:index="index"
|
|
||||||
:container="container"
|
|
||||||
:rowsLayout="rowsLayout"
|
|
||||||
:isEditing="isEditing"
|
|
||||||
@move-frame="moveFrame"
|
|
||||||
@new-frame="setFrameLocation"
|
|
||||||
@persist="persist">
|
|
||||||
</container-component>
|
|
||||||
|
|
||||||
<resize-handle
|
|
||||||
v-if="index !== (containers.length - 1)"
|
|
||||||
:key="index"
|
|
||||||
:index="index"
|
|
||||||
:orientation="rowsLayout ? 'vertical' : 'horizontal'"
|
|
||||||
:isEditing="isEditing"
|
|
||||||
@init-move="startContainerResizing"
|
|
||||||
@move="containerResizing"
|
|
||||||
@end-move="endContainerResizing">
|
|
||||||
</resize-handle>
|
|
||||||
|
|
||||||
<drop-hint
|
|
||||||
class="c-fl-frame__drop-hint"
|
|
||||||
v-if="containers.length > 1"
|
|
||||||
:key="index"
|
|
||||||
:index="index"
|
|
||||||
:allowDrop="allowContainerDrop"
|
|
||||||
@object-drop-to="moveContainer">
|
|
||||||
</drop-hint>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="c-fl__container-holder"
|
||||||
|
:class="{
|
||||||
|
'c-fl--rows': rowsLayout === true
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template v-for="(container, index) in containers">
|
||||||
|
<drop-hint
|
||||||
|
v-if="index === 0 && containers.length > 1"
|
||||||
|
:key="index"
|
||||||
|
class="c-fl-frame__drop-hint"
|
||||||
|
:index="-1"
|
||||||
|
:allow-drop="allowContainerDrop"
|
||||||
|
@object-drop-to="moveContainer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<container-component
|
||||||
|
:key="container.id"
|
||||||
|
class="c-fl__container"
|
||||||
|
:index="index"
|
||||||
|
:container="container"
|
||||||
|
:rows-layout="rowsLayout"
|
||||||
|
:is-editing="isEditing"
|
||||||
|
@move-frame="moveFrame"
|
||||||
|
@new-frame="setFrameLocation"
|
||||||
|
@persist="persist"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<resize-handle
|
||||||
|
v-if="index !== (containers.length - 1)"
|
||||||
|
:key="index"
|
||||||
|
:index="index"
|
||||||
|
:orientation="rowsLayout ? 'vertical' : 'horizontal'"
|
||||||
|
:is-editing="isEditing"
|
||||||
|
@init-move="startContainerResizing"
|
||||||
|
@move="containerResizing"
|
||||||
|
@end-move="endContainerResizing"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<drop-hint
|
||||||
|
v-if="containers.length > 1"
|
||||||
|
:key="index"
|
||||||
|
class="c-fl-frame__drop-hint"
|
||||||
|
:index="index"
|
||||||
|
:allow-drop="allowContainerDrop"
|
||||||
|
@object-drop-to="moveContainer"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -465,15 +467,15 @@ export default {
|
|||||||
ResizeHandle,
|
ResizeHandle,
|
||||||
DropHint
|
DropHint
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
isEditing: Boolean
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
domainObject: this.layoutObject,
|
domainObject: this.layoutObject,
|
||||||
newFrameLocation: []
|
newFrameLocation: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
isEditing: Boolean
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
layoutDirectionStr() {
|
layoutDirectionStr() {
|
||||||
if (this.rowsLayout) {
|
if (this.rowsLayout) {
|
||||||
@ -489,9 +491,24 @@ export default {
|
|||||||
return this.domainObject.configuration.rowsLayout;
|
return this.domainObject.configuration.rowsLayout;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
|
this.composition.on('remove', this.removeChildObject);
|
||||||
|
this.composition.on('add', this.addFrame);
|
||||||
|
|
||||||
|
this.RemoveAction = new RemoveAction(this.openmct);
|
||||||
|
|
||||||
|
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.composition.off('remove', this.removeChildObject);
|
||||||
|
this.composition.off('add', this.addFrame);
|
||||||
|
|
||||||
|
this.unobserve();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
areAllContainersEmpty() {
|
areAllContainersEmpty() {
|
||||||
return !!!this.containers.filter(container => container.frames.length).length;
|
return !this.containers.filter(container => container.frames.length).length;
|
||||||
},
|
},
|
||||||
addContainer() {
|
addContainer() {
|
||||||
let container = new Container();
|
let container = new Container();
|
||||||
@ -589,7 +606,7 @@ export default {
|
|||||||
return containerPos !== index && (containerPos - 1) !== index
|
return containerPos !== index && (containerPos - 1) !== index
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
persist(index){
|
persist(index) {
|
||||||
if (index) {
|
if (index) {
|
||||||
this.openmct.objects.mutate(this.domainObject, `configuration.containers[${index}]`, this.containers[index]);
|
this.openmct.objects.mutate(this.domainObject, `configuration.containers[${index}]`, this.containers[index]);
|
||||||
} else {
|
} else {
|
||||||
@ -657,21 +674,6 @@ export default {
|
|||||||
|
|
||||||
this.persist();
|
this.persist();
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
|
||||||
this.composition.on('remove', this.removeChildObject);
|
|
||||||
this.composition.on('add', this.addFrame);
|
|
||||||
|
|
||||||
this.RemoveAction = new RemoveAction(this.openmct);
|
|
||||||
|
|
||||||
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.composition.off('remove', this.removeChildObject);
|
|
||||||
this.composition.off('add', this.addFrame);
|
|
||||||
|
|
||||||
this.unobserve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,56 +21,89 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-fl-frame"
|
<div
|
||||||
:style="{
|
class="c-fl-frame"
|
||||||
'flex-basis': `${frame.size}%`
|
:style="{
|
||||||
}">
|
'flex-basis': `${frame.size}%`
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref="frame"
|
||||||
|
class="c-frame c-fl-frame__drag-wrapper is-selectable u-inspectable is-moveable"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="initDrag"
|
||||||
|
>
|
||||||
|
<object-frame
|
||||||
|
v-if="domainObject"
|
||||||
|
ref="objectFrame"
|
||||||
|
:domain-object="domainObject"
|
||||||
|
:object-path="objectPath"
|
||||||
|
:has-frame="hasFrame"
|
||||||
|
:show-edit-view="false"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="c-frame c-fl-frame__drag-wrapper is-selectable u-inspectable is-moveable"
|
<div
|
||||||
draggable="true"
|
v-if="isEditing"
|
||||||
@dragstart="initDrag"
|
v-show="frame.size && frame.size < 100"
|
||||||
ref="frame">
|
class="c-fl-frame__size-indicator"
|
||||||
|
>
|
||||||
<object-frame
|
{{ frame.size }}%
|
||||||
v-if="domainObject"
|
|
||||||
:domain-object="domainObject"
|
|
||||||
:object-path="objectPath"
|
|
||||||
:has-frame="hasFrame"
|
|
||||||
:show-edit-view="false"
|
|
||||||
ref="objectFrame">
|
|
||||||
</object-frame>
|
|
||||||
|
|
||||||
<div class="c-fl-frame__size-indicator"
|
|
||||||
v-if="isEditing"
|
|
||||||
v-show="frame.size && frame.size < 100">
|
|
||||||
{{frame.size}}%
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ResizeHandle from './resizeHandle.vue';
|
|
||||||
import ObjectFrame from '../../../ui/components/ObjectFrame.vue';
|
import ObjectFrame from '../../../ui/components/ObjectFrame.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: ['frame', 'index', 'containerIndex', 'isEditing'],
|
components: {
|
||||||
|
ObjectFrame
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
frame: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
containerIndex: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
isEditing: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
domainObject: undefined,
|
domainObject: undefined,
|
||||||
objectPath: undefined
|
objectPath: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
|
||||||
ResizeHandle,
|
|
||||||
ObjectFrame
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
hasFrame() {
|
hasFrame() {
|
||||||
return !this.frame.noFrame;
|
return !this.frame.noFrame;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.frame.domainObjectIdentifier) {
|
||||||
|
this.openmct.objects.get(this.frame.domainObjectIdentifier).then((object)=>{
|
||||||
|
this.setDomainObject(object);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dragGhost = document.getElementById('js-fl-drag-ghost');
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.unsubscribeSelection) {
|
||||||
|
this.unsubscribeSelection();
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setDomainObject(object) {
|
setDomainObject(object) {
|
||||||
this.domainObject = object;
|
this.domainObject = object;
|
||||||
@ -105,20 +138,6 @@ export default {
|
|||||||
event.dataTransfer.setData('frameid', this.frame.id);
|
event.dataTransfer.setData('frameid', this.frame.id);
|
||||||
event.dataTransfer.setData('containerIndex', this.containerIndex);
|
event.dataTransfer.setData('containerIndex', this.containerIndex);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.frame.domainObjectIdentifier) {
|
|
||||||
this.openmct.objects.get(this.frame.domainObjectIdentifier).then((object)=>{
|
|
||||||
this.setDomainObject(object);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dragGhost = document.getElementById('js-fl-drag-ghost');
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (this.unsubscribeSelection) {
|
|
||||||
this.unsubscribeSelection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,22 +21,46 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-fl-frame__resize-handle"
|
<div
|
||||||
:class="[orientation]"
|
v-show="isEditing && !isDragging"
|
||||||
v-show="isEditing && !isDragging"
|
class="c-fl-frame__resize-handle"
|
||||||
@mousedown="mousedown">
|
:class="[orientation]"
|
||||||
</div>
|
@mousedown="mousedown"
|
||||||
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ['orientation', 'index', 'isEditing'],
|
props: {
|
||||||
|
orientation: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
isEditing: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
initialPos: 0,
|
initialPos: 0,
|
||||||
isDragging: false,
|
isDragging: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener('dragstart', this.setDragging);
|
||||||
|
document.addEventListener('dragend', this.unsetDragging);
|
||||||
|
document.addEventListener('drop', this.unsetDragging);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
document.removeEventListener('dragstart', this.setDragging);
|
||||||
|
document.removeEventListener('dragend', this.unsetDragging);
|
||||||
|
document.removeEventListener('drop', this.unsetDragging);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
mousedown(event) {
|
mousedown(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -75,16 +99,6 @@ export default {
|
|||||||
unsetDragging(event) {
|
unsetDragging(event) {
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.addEventListener('dragstart', this.setDragging);
|
|
||||||
document.addEventListener('dragend', this.unsetDragging);
|
|
||||||
document.addEventListener('drop', this.unsetDragging);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
document.removeEventListener('dragstart', this.setDragging);
|
|
||||||
document.removeEventListener('dragend', this.unsetDragging);
|
|
||||||
document.removeEventListener('drop', this.unsetDragging);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -44,19 +44,19 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element, isEditing) {
|
show: function (element, isEditing) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isEditing: isEditing
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
FlexibleLayoutComponent: FlexibleLayoutComponent.default
|
|
||||||
},
|
|
||||||
provide: {
|
provide: {
|
||||||
openmct,
|
openmct,
|
||||||
layoutObject: domainObject
|
layoutObject: domainObject
|
||||||
},
|
},
|
||||||
el: element,
|
el: element,
|
||||||
|
components: {
|
||||||
|
FlexibleLayoutComponent: FlexibleLayoutComponent.default
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isEditing: isEditing
|
||||||
|
}
|
||||||
|
},
|
||||||
template: '<flexible-layout-component ref="flexibleLayout" :isEditing="isEditing"></flexible-layout-component>'
|
template: '<flexible-layout-component ref="flexibleLayout" :isEditing="isEditing"></flexible-layout-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
gridViewComponent: GridViewComponent.default
|
gridViewComponent: GridViewComponent.default
|
||||||
},
|
},
|
||||||
@ -48,7 +49,6 @@ define([
|
|||||||
openmct,
|
openmct,
|
||||||
domainObject
|
domainObject
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<grid-view-component></grid-view-component>'
|
template: '<grid-view-component></grid-view-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -43,6 +43,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
listViewComponent: ListViewComponent.default
|
listViewComponent: ListViewComponent.default
|
||||||
},
|
},
|
||||||
@ -51,7 +52,6 @@ define([
|
|||||||
domainObject,
|
domainObject,
|
||||||
Moment
|
Moment
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<list-view-component></list-view-component>'
|
template: '<list-view-component></list-view-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,25 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<a class="l-grid-view__item c-grid-item"
|
<a
|
||||||
:class="{ 'is-alias': item.isAlias === true }"
|
class="l-grid-view__item c-grid-item"
|
||||||
:href="objectLink">
|
:class="{ 'is-alias': item.isAlias === true }"
|
||||||
<div class="c-grid-item__type-icon"
|
:href="objectLink"
|
||||||
:class="(item.type.cssClass != undefined) ? 'bg-' + item.type.cssClass : 'bg-icon-object-unknown'">
|
>
|
||||||
|
<div
|
||||||
|
class="c-grid-item__type-icon"
|
||||||
|
:class="(item.type.cssClass != undefined) ? 'bg-' + item.type.cssClass : 'bg-icon-object-unknown'"
|
||||||
|
></div>
|
||||||
|
<div class="c-grid-item__details">
|
||||||
|
<!-- Name and metadata -->
|
||||||
|
<div
|
||||||
|
class="c-grid-item__name"
|
||||||
|
:title="item.model.name"
|
||||||
|
>{{ item.model.name }}</div>
|
||||||
|
<div
|
||||||
|
class="c-grid-item__metadata"
|
||||||
|
:title="item.type.name"
|
||||||
|
>
|
||||||
|
<span class="c-grid-item__metadata__type">{{ item.type.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="c-grid-item__details">
|
</div>
|
||||||
<!-- Name and metadata -->
|
<div class="c-grid-item__controls">
|
||||||
<div class="c-grid-item__name"
|
<div
|
||||||
:title="item.model.name">{{item.model.name}}</div>
|
class="icon-people"
|
||||||
<div class="c-grid-item__metadata"
|
title="Shared"
|
||||||
:title="item.type.name">
|
></div>
|
||||||
<span class="c-grid-item__metadata__type">{{item.type.name}}</span>
|
<button
|
||||||
</div>
|
class="c-icon-button icon-info c-info-button"
|
||||||
</div>
|
title="More Info"
|
||||||
<div class="c-grid-item__controls">
|
></button>
|
||||||
<div class="icon-people" title='Shared'></div>
|
<div class="icon-pointer-right c-pointer-icon"></div>
|
||||||
<button class="c-icon-button icon-info c-info-button" title='More Info'></button>
|
</div>
|
||||||
<div class="icon-pointer-right c-pointer-icon"></div>
|
</a>
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -154,6 +167,11 @@ import objectLink from '../../../ui/mixins/object-link';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [contextMenuGesture, objectLink],
|
mixins: [contextMenuGesture, objectLink],
|
||||||
props: ['item']
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-grid-view">
|
<div class="l-grid-view">
|
||||||
<grid-item v-for="(item, index) in items"
|
<grid-item
|
||||||
:key="index"
|
v-for="(item, index) in items"
|
||||||
:item="item"
|
:key="index"
|
||||||
:object-path="item.objectPath">
|
:item="item"
|
||||||
</grid-item>
|
:object-path="item.objectPath"
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -1,17 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<tr class="c-list-item"
|
<tr
|
||||||
:class="{ 'is-alias': item.isAlias === true }"
|
class="c-list-item"
|
||||||
@click="navigate">
|
:class="{ 'is-alias': item.isAlias === true }"
|
||||||
<td class="c-list-item__name">
|
@click="navigate"
|
||||||
<a :href="objectLink" ref="objectLink">
|
>
|
||||||
<div class="c-list-item__type-icon" :class="item.type.cssClass"></div>
|
<td class="c-list-item__name">
|
||||||
<div class="c-list-item__name-value">{{item.model.name}}</div>
|
<a
|
||||||
</a>
|
ref="objectLink"
|
||||||
</td>
|
:href="objectLink"
|
||||||
<td class="c-list-item__type">{{ item.type.name }}</td>
|
>
|
||||||
<td class="c-list-item__date-created">{{ formatTime(item.model.persisted, 'YYYY-MM-DD HH:mm:ss:SSS') }}Z</td>
|
<div
|
||||||
<td class="c-list-item__date-updated">{{ formatTime(item.model.modified, 'YYYY-MM-DD HH:mm:ss:SSS') }}Z</td>
|
class="c-list-item__type-icon"
|
||||||
</tr>
|
:class="item.type.cssClass"
|
||||||
|
></div>
|
||||||
|
<div class="c-list-item__name-value">{{ item.model.name }}</div>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="c-list-item__type">
|
||||||
|
{{ item.type.name }}
|
||||||
|
</td>
|
||||||
|
<td class="c-list-item__date-created">
|
||||||
|
{{ formatTime(item.model.persisted, 'YYYY-MM-DD HH:mm:ss:SSS') }}Z
|
||||||
|
</td>
|
||||||
|
<td class="c-list-item__date-updated">
|
||||||
|
{{ formatTime(item.model.modified, 'YYYY-MM-DD HH:mm:ss:SSS') }}Z
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -64,7 +78,12 @@ import objectLink from '../../../ui/mixins/object-link';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [contextMenuGesture, objectLink],
|
mixins: [contextMenuGesture, objectLink],
|
||||||
props: ['item'],
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatTime(timestamp, format) {
|
formatTime(timestamp, format) {
|
||||||
return moment(timestamp).format(format);
|
return moment(timestamp).format(format);
|
||||||
|
@ -1,55 +1,64 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-table c-table--sortable c-list-view">
|
<div class="c-table c-table--sortable c-list-view">
|
||||||
<table class="c-table__body">
|
<table class="c-table__body">
|
||||||
<thead class="c-table__header">
|
<thead class="c-table__header">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="is-sortable"
|
<th
|
||||||
:class="{
|
class="is-sortable"
|
||||||
'is-sorting': sortBy === 'model.name',
|
:class="{
|
||||||
'asc': ascending,
|
'is-sorting': sortBy === 'model.name',
|
||||||
'desc': !ascending
|
'asc': ascending,
|
||||||
}"
|
'desc': !ascending
|
||||||
@click="sort('model.name', true)">
|
}"
|
||||||
Name
|
@click="sort('model.name', true)"
|
||||||
</th>
|
>
|
||||||
<th class="is-sortable"
|
Name
|
||||||
:class="{
|
</th>
|
||||||
'is-sorting': sortBy === 'type.name',
|
<th
|
||||||
'asc': ascending,
|
class="is-sortable"
|
||||||
'desc': !ascending
|
:class="{
|
||||||
}"
|
'is-sorting': sortBy === 'type.name',
|
||||||
@click="sort('type.name', true)">
|
'asc': ascending,
|
||||||
Type
|
'desc': !ascending
|
||||||
</th>
|
}"
|
||||||
<th class="is-sortable"
|
@click="sort('type.name', true)"
|
||||||
:class="{
|
>
|
||||||
'is-sorting': sortBy === 'model.persisted',
|
Type
|
||||||
'asc': ascending,
|
</th>
|
||||||
'desc': !ascending
|
<th
|
||||||
}"
|
class="is-sortable"
|
||||||
@click="sort('model.persisted', false)">
|
:class="{
|
||||||
Created Date
|
'is-sorting': sortBy === 'model.persisted',
|
||||||
</th>
|
'asc': ascending,
|
||||||
<th class="is-sortable"
|
'desc': !ascending
|
||||||
:class="{
|
}"
|
||||||
'is-sorting': sortBy === 'model.modified',
|
@click="sort('model.persisted', false)"
|
||||||
'asc': ascending,
|
>
|
||||||
'desc': !ascending
|
Created Date
|
||||||
}"
|
</th>
|
||||||
@click="sort('model.modified', false)">
|
<th
|
||||||
Updated Date
|
class="is-sortable"
|
||||||
</th>
|
:class="{
|
||||||
</tr>
|
'is-sorting': sortBy === 'model.modified',
|
||||||
</thead>
|
'asc': ascending,
|
||||||
<tbody>
|
'desc': !ascending
|
||||||
<list-item v-for="item in sortedItems"
|
}"
|
||||||
:key="item.objectKeyString"
|
@click="sort('model.modified', false)"
|
||||||
:item="item"
|
>
|
||||||
:object-path="item.objectPath">
|
Updated Date
|
||||||
</list-item>
|
</th>
|
||||||
</tbody>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
</div>
|
<tbody>
|
||||||
|
<list-item
|
||||||
|
v-for="item in sortedItems"
|
||||||
|
:key="item.objectKeyString"
|
||||||
|
:item="item"
|
||||||
|
:object-path="item.objectPath"
|
||||||
|
/>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -93,8 +102,6 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import lodash from 'lodash';
|
|
||||||
import compositionLoader from './composition-loader';
|
import compositionLoader from './composition-loader';
|
||||||
import ListItem from './ListItem.vue';
|
import ListItem from './ListItem.vue';
|
||||||
|
|
||||||
@ -120,7 +127,7 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
sortedItems () {
|
sortedItems() {
|
||||||
let sortedItems = _.sortBy(this.items, this.sortBy);
|
let sortedItems = _.sortBy(this.items, this.sortBy);
|
||||||
if (!this.ascending) {
|
if (!this.ascending) {
|
||||||
sortedItems = sortedItems.reverse();
|
sortedItems = sortedItems.reverse();
|
||||||
|
@ -20,21 +20,30 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-about c-about--licenses">
|
<div class="c-about c-about--licenses">
|
||||||
<h1>Open MCT Third Party Licenses</h1>
|
<h1>Open MCT Third Party Licenses</h1>
|
||||||
<p>This software includes components released under the following licenses:</p>
|
<p>This software includes components released under the following licenses:</p>
|
||||||
<div v-for="(pkg, key) in packages" :key="key" class="c-license">
|
<div
|
||||||
<h2 class="c-license__name">{{key}}</h2>
|
v-for="(pkg, key) in packages"
|
||||||
<div class="c-license__details">
|
:key="key"
|
||||||
<span class="c-license__author"><em>Author</em> {{pkg.publisher}}</span> |
|
class="c-license"
|
||||||
<span class="c-license__license"><em>License(s)</em> {{pkg.licenses}}</span> |
|
>
|
||||||
<span class="c-license__repo"><em>Repository</em> <a :href="pkg.repository" target="_blank">{{pkg.repository}}</a></span>
|
<h2 class="c-license__name">
|
||||||
</div>
|
{{ key }}
|
||||||
<div class="c-license__text">
|
</h2>
|
||||||
<p>{{pkg.licenseText}}</p>
|
<div class="c-license__details">
|
||||||
</div>
|
<span class="c-license__author"><em>Author</em> {{ pkg.publisher }}</span> |
|
||||||
|
<span class="c-license__license"><em>License(s)</em> {{ pkg.licenses }}</span> |
|
||||||
|
<span class="c-license__repo"><em>Repository</em> <a
|
||||||
|
:href="pkg.repository"
|
||||||
|
target="_blank"
|
||||||
|
>{{ pkg.repository }}</a></span>
|
||||||
|
</div>
|
||||||
|
<div class="c-license__text">
|
||||||
|
<p>{{ pkg.licenseText }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
</style>
|
</style>
|
||||||
@ -49,4 +58,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -141,7 +141,6 @@ function (
|
|||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
snapshot = new Vue({
|
snapshot = new Vue({
|
||||||
template: SnapshotTemplate,
|
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
embed: self.embed
|
embed: self.embed
|
||||||
@ -151,7 +150,8 @@ function (
|
|||||||
formatTime: self.formatTime,
|
formatTime: self.formatTime,
|
||||||
annotateSnapshot: annotateSnapshot(self.openmct),
|
annotateSnapshot: annotateSnapshot(self.openmct),
|
||||||
findInArray: self.findInArray
|
findInArray: self.findInArray
|
||||||
}
|
},
|
||||||
|
template: SnapshotTemplate
|
||||||
});
|
});
|
||||||
|
|
||||||
var snapshotOverlay = this.openmct.overlays.overlay({
|
var snapshotOverlay = this.openmct.overlays.overlay({
|
||||||
|
@ -84,7 +84,6 @@ function (
|
|||||||
};
|
};
|
||||||
|
|
||||||
var NotebookVue = Vue.extend({
|
var NotebookVue = Vue.extend({
|
||||||
template: NotebookTemplate,
|
|
||||||
provide: {openmct: self.openmct, domainObject: self.domainObject},
|
provide: {openmct: self.openmct, domainObject: self.domainObject},
|
||||||
components: {
|
components: {
|
||||||
'notebook-entry': entryComponent,
|
'notebook-entry': entryComponent,
|
||||||
@ -111,7 +110,8 @@ function (
|
|||||||
newEntry: self.newEntry,
|
newEntry: self.newEntry,
|
||||||
filterBySearch: self.filterBySearch,
|
filterBySearch: self.filterBySearch,
|
||||||
sort: self.sort
|
sort: self.sort
|
||||||
}
|
},
|
||||||
|
template: NotebookTemplate
|
||||||
});
|
});
|
||||||
|
|
||||||
this.NotebookVue = new NotebookVue();
|
this.NotebookVue = new NotebookVue();
|
||||||
|
@ -1,44 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-tabs-view">
|
<div class="c-tabs-view">
|
||||||
<div class="c-tabs-view__tabs-holder c-tabs"
|
<div
|
||||||
:class="{
|
class="c-tabs-view__tabs-holder c-tabs"
|
||||||
'is-dragging': isDragging,
|
:class="{
|
||||||
'is-mouse-over': allowDrop
|
'is-dragging': isDragging,
|
||||||
}">
|
'is-mouse-over': allowDrop
|
||||||
<div class="c-drop-hint"
|
}"
|
||||||
@drop="onDrop"
|
>
|
||||||
@dragenter="dragenter"
|
<div
|
||||||
@dragleave="dragleave">
|
class="c-drop-hint"
|
||||||
</div>
|
@drop="onDrop"
|
||||||
<div class="c-tabs-view__empty-message"
|
@dragenter="dragenter"
|
||||||
v-if="!tabsList.length > 0">Drag objects here to add them to this view.</div>
|
@dragleave="dragleave"
|
||||||
<button class="c-tabs-view__tab c-tab"
|
></div>
|
||||||
v-for="(tab,index) in tabsList"
|
<div
|
||||||
:key="index"
|
v-if="!tabsList.length > 0"
|
||||||
:class="[
|
class="c-tabs-view__empty-message"
|
||||||
{'is-current': isCurrent(tab)},
|
>
|
||||||
tab.type.definition.cssClass
|
Drag objects here to add them to this view.
|
||||||
]"
|
|
||||||
@click="showTab(tab)">
|
|
||||||
<span class="c-button__label">{{tab.domainObject.name}}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="c-tabs-view__object-holder"
|
<button
|
||||||
v-for="(tab, index) in tabsList"
|
v-for="(tab,index) in tabsList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="{'c-tabs-view__object-holder--hidden': !isCurrent(tab)}">
|
class="c-tabs-view__tab c-tab"
|
||||||
<div v-if="currentTab"
|
:class="[
|
||||||
class="c-tabs-view__object-name l-browse-bar__object-name--w"
|
{'is-current': isCurrent(tab)},
|
||||||
:class="currentTab.type.definition.cssClass">
|
tab.type.definition.cssClass
|
||||||
<div class="l-browse-bar__object-name">
|
]"
|
||||||
{{currentTab.domainObject.name}}
|
@click="showTab(tab)"
|
||||||
</div>
|
>
|
||||||
</div>
|
<span class="c-button__label">{{ tab.domainObject.name }}</span>
|
||||||
<object-view class="c-tabs-view__object"
|
</button>
|
||||||
:object="tab.domainObject">
|
|
||||||
</object-view>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(tab, index) in tabsList"
|
||||||
|
:key="index"
|
||||||
|
class="c-tabs-view__object-holder"
|
||||||
|
:class="{'c-tabs-view__object-holder--hidden': !isCurrent(tab)}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="currentTab"
|
||||||
|
class="c-tabs-view__object-name l-browse-bar__object-name--w"
|
||||||
|
:class="currentTab.type.definition.cssClass"
|
||||||
|
>
|
||||||
|
<div class="l-browse-bar__object-name">
|
||||||
|
{{ currentTab.domainObject.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<object-view
|
||||||
|
class="c-tabs-view__object"
|
||||||
|
:object="tab.domainObject"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -129,6 +143,25 @@ export default {
|
|||||||
allowDrop: false
|
allowDrop: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.composition) {
|
||||||
|
this.composition.on('add', this.addItem);
|
||||||
|
this.composition.on('remove', this.removeItem);
|
||||||
|
this.composition.on('reorder', this.onReorder);
|
||||||
|
this.composition.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('dragstart', this.dragstart);
|
||||||
|
document.addEventListener('dragend', this.dragend);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.composition.off('add', this.addItem);
|
||||||
|
this.composition.off('remove', this.removeItem);
|
||||||
|
this.composition.off('reorder', this.onReorder);
|
||||||
|
|
||||||
|
document.removeEventListener('dragstart', this.dragstart);
|
||||||
|
document.removeEventListener('dragend', this.dragend);
|
||||||
|
},
|
||||||
methods:{
|
methods:{
|
||||||
showTab(tab) {
|
showTab(tab) {
|
||||||
this.currentTab = tab;
|
this.currentTab = tab;
|
||||||
@ -169,7 +202,7 @@ export default {
|
|||||||
onDrop(e) {
|
onDrop(e) {
|
||||||
this.setCurrentTab = true;
|
this.setCurrentTab = true;
|
||||||
},
|
},
|
||||||
dragstart (e) {
|
dragstart(e) {
|
||||||
if (e.dataTransfer.types.includes('openmct/domain-object-path')) {
|
if (e.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
}
|
}
|
||||||
@ -187,25 +220,6 @@ export default {
|
|||||||
isCurrent(tab) {
|
isCurrent(tab) {
|
||||||
return _.isEqual(this.currentTab, tab)
|
return _.isEqual(this.currentTab, tab)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
if (this.composition) {
|
|
||||||
this.composition.on('add', this.addItem);
|
|
||||||
this.composition.on('remove', this.removeItem);
|
|
||||||
this.composition.on('reorder', this.onReorder);
|
|
||||||
this.composition.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('dragstart', this.dragstart);
|
|
||||||
document.addEventListener('dragend', this.dragend);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.composition.off('add', this.addItem);
|
|
||||||
this.composition.off('remove', this.removeItem);
|
|
||||||
this.composition.off('reorder', this.onReorder);
|
|
||||||
|
|
||||||
document.removeEventListener('dragstart', this.dragstart);
|
|
||||||
document.removeEventListener('dragend', this.dragend);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -44,6 +44,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
TabsComponent: TabsComponent.default
|
TabsComponent: TabsComponent.default
|
||||||
},
|
},
|
||||||
@ -52,7 +53,6 @@ define([
|
|||||||
domainObject,
|
domainObject,
|
||||||
composition: openmct.composition.get(domainObject)
|
composition: openmct.composition.get(domainObject)
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<tabs-component></tabs-component>'
|
template: '<tabs-component></tabs-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -54,11 +54,11 @@ define([
|
|||||||
openmct,
|
openmct,
|
||||||
tableConfiguration
|
tableConfiguration
|
||||||
},
|
},
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
TableConfiguration: TableConfigurationComponent.default
|
TableConfiguration: TableConfigurationComponent.default
|
||||||
},
|
},
|
||||||
template: '<table-configuration></table-configuration>',
|
template: '<table-configuration></table-configuration>'
|
||||||
el: element
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
|
@ -54,20 +54,20 @@ define([
|
|||||||
return {
|
return {
|
||||||
show: function (element, editMode) {
|
show: function (element, editMode) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
|
components: {
|
||||||
|
TableComponent: TableComponent.default
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isEditing: editMode
|
isEditing: editMode
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
|
||||||
TableComponent: TableComponent.default
|
|
||||||
},
|
|
||||||
provide: {
|
provide: {
|
||||||
openmct,
|
openmct,
|
||||||
table,
|
table,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<table-component :isEditing="isEditing" :enableMarking="true"></table-component>'
|
template: '<table-component :isEditing="isEditing" :enableMarking="true"></table-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="filterNames.length > 0"
|
<div
|
||||||
:title=title
|
v-if="filterNames.length > 0"
|
||||||
class="c-filter-indication"
|
:title="title"
|
||||||
:class="{ 'c-filter-indication--mixed': hasMixedFilters }">
|
class="c-filter-indication"
|
||||||
<span class="c-filter-indication__mixed">{{ label }}</span>
|
:class="{ 'c-filter-indication--mixed': hasMixedFilters }"
|
||||||
<span v-for="(name, index) in filterNames"
|
>
|
||||||
class="c-filter-indication__label">
|
<span class="c-filter-indication__mixed">{{ label }}</span>
|
||||||
{{ name }}
|
<span
|
||||||
</span>
|
v-for="(name, index) in filterNames"
|
||||||
</div>
|
:key="index"
|
||||||
|
class="c-filter-indication__label"
|
||||||
|
>
|
||||||
|
{{ name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -53,113 +58,113 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const FILTER_INDICATOR_LABEL = 'Filters:';
|
const FILTER_INDICATOR_LABEL = 'Filters:';
|
||||||
const FILTER_INDICATOR_LABEL_MIXED = 'Mixed Filters:';
|
const FILTER_INDICATOR_LABEL_MIXED = 'Mixed Filters:';
|
||||||
const FILTER_INDICATOR_TITLE = 'Data filters are being applied to this view.';
|
const FILTER_INDICATOR_TITLE = 'Data filters are being applied to this view.';
|
||||||
const FILTER_INDICATOR_TITLE_MIXED = 'A mix of data filter values are being applied to this view.';
|
const FILTER_INDICATOR_TITLE_MIXED = 'A mix of data filter values are being applied to this view.';
|
||||||
const USE_GLOBAL = 'useGlobal';
|
const USE_GLOBAL = 'useGlobal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'table'],
|
inject: ['openmct', 'table'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
filterNames: [],
|
filterNames: [],
|
||||||
filteredTelemetry: {}
|
filteredTelemetry: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasMixedFilters() {
|
||||||
|
let filtersToCompare = _.omit(this.filteredTelemetry[Object.keys(this.filteredTelemetry)[0]], [USE_GLOBAL]);
|
||||||
|
return Object.values(this.filteredTelemetry).some(filters => {
|
||||||
|
return !_.isEqual(filtersToCompare, _.omit(filters, [USE_GLOBAL]));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
label() {
|
||||||
|
if (this.hasMixedFilters) {
|
||||||
|
return FILTER_INDICATOR_LABEL_MIXED;
|
||||||
|
} else {
|
||||||
|
return FILTER_INDICATOR_LABEL;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
title() {
|
||||||
hasMixedFilters() {
|
if (this.hasMixedFilters) {
|
||||||
let filtersToCompare = _.omit(this.filteredTelemetry[Object.keys(this.filteredTelemetry)[0]], [USE_GLOBAL]);
|
return FILTER_INDICATOR_TITLE_MIXED;
|
||||||
return Object.values(this.filteredTelemetry).some(filters => {
|
} else {
|
||||||
return !_.isEqual(filtersToCompare, _.omit(filters, [USE_GLOBAL]));
|
return FILTER_INDICATOR_TITLE;
|
||||||
});
|
|
||||||
},
|
|
||||||
label() {
|
|
||||||
if (this.hasMixedFilters) {
|
|
||||||
return FILTER_INDICATOR_LABEL_MIXED;
|
|
||||||
} else {
|
|
||||||
return FILTER_INDICATOR_LABEL;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title() {
|
|
||||||
if (this.hasMixedFilters) {
|
|
||||||
return FILTER_INDICATOR_TITLE_MIXED;
|
|
||||||
} else {
|
|
||||||
return FILTER_INDICATOR_TITLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
methods: {
|
},
|
||||||
setFilterNames() {
|
mounted() {
|
||||||
let names = [];
|
let filters = this.table.configuration.getConfiguration().filters || {};
|
||||||
let composition = this.openmct.composition.get(this.table.configuration.domainObject);
|
this.table.configuration.on('change', this.handleConfigurationChanges);
|
||||||
|
this.updateFilters(filters);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.table.configuration.off('change', this.handleConfigurationChanges);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setFilterNames() {
|
||||||
|
let names = [];
|
||||||
|
let composition = this.openmct.composition.get(this.table.configuration.domainObject);
|
||||||
|
|
||||||
composition && composition.load().then((domainObjects) => {
|
composition && composition.load().then((domainObjects) => {
|
||||||
domainObjects.forEach(telemetryObject => {
|
domainObjects.forEach(telemetryObject => {
|
||||||
let keyString= this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
let keyString= this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||||
let filters = this.filteredTelemetry[keyString];
|
let filters = this.filteredTelemetry[keyString];
|
||||||
|
|
||||||
if (filters !== undefined) {
|
if (filters !== undefined) {
|
||||||
names.push(this.getFilterNamesFromMetadata(filters, metadataValues));
|
names.push(this.getFilterNamesFromMetadata(filters, metadataValues));
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
names = _.flatten(names);
|
|
||||||
this.filterNames = names.length === 0 ? names : Array.from(new Set(names));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getFilterNamesFromMetadata(filters, metadataValues) {
|
|
||||||
let filterNames = [];
|
|
||||||
filters = _.omit(filters, [USE_GLOBAL]);
|
|
||||||
|
|
||||||
Object.keys(filters).forEach(key => {
|
|
||||||
if (!_.isEmpty(filters[key])) {
|
|
||||||
metadataValues.forEach(metadatum => {
|
|
||||||
if (key === metadatum.key) {
|
|
||||||
if (typeof metadatum.filters[0] === "object") {
|
|
||||||
filterNames.push(this.getFilterLabels(filters[key], metadatum));
|
|
||||||
} else {
|
|
||||||
filterNames.push(metadatum.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return _.flatten(filterNames);
|
names = _.flatten(names);
|
||||||
},
|
this.filterNames = names.length === 0 ? names : Array.from(new Set(names));
|
||||||
getFilterLabels(filterObject, metadatum, ) {
|
});
|
||||||
let filterLabels = [];
|
},
|
||||||
Object.values(filterObject).forEach(comparator => {
|
getFilterNamesFromMetadata(filters, metadataValues) {
|
||||||
comparator.forEach(filterValue => {
|
let filterNames = [];
|
||||||
metadatum.filters[0].possibleValues.forEach(option => {
|
filters = _.omit(filters, [USE_GLOBAL]);
|
||||||
if (option.value === filterValue) {
|
|
||||||
filterLabels.push(option.label);
|
Object.keys(filters).forEach(key => {
|
||||||
|
if (!_.isEmpty(filters[key])) {
|
||||||
|
metadataValues.forEach(metadatum => {
|
||||||
|
if (key === metadatum.key) {
|
||||||
|
if (typeof metadatum.filters[0] === "object") {
|
||||||
|
filterNames.push(this.getFilterLabels(filters[key], metadatum));
|
||||||
|
} else {
|
||||||
|
filterNames.push(metadatum.name);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return _.flatten(filterNames);
|
||||||
|
},
|
||||||
|
getFilterLabels(filterObject, metadatum,) {
|
||||||
|
let filterLabels = [];
|
||||||
|
Object.values(filterObject).forEach(comparator => {
|
||||||
|
comparator.forEach(filterValue => {
|
||||||
|
metadatum.filters[0].possibleValues.forEach(option => {
|
||||||
|
if (option.value === filterValue) {
|
||||||
|
filterLabels.push(option.label);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return filterLabels;
|
return filterLabels;
|
||||||
},
|
},
|
||||||
handleConfigurationChanges(configuration) {
|
handleConfigurationChanges(configuration) {
|
||||||
if (!_.eq(this.filteredTelemetry, configuration.filters)) {
|
if (!_.eq(this.filteredTelemetry, configuration.filters)) {
|
||||||
this.updateFilters(configuration.filters || {});
|
this.updateFilters(configuration.filters || {});
|
||||||
}
|
|
||||||
},
|
|
||||||
updateFilters(filters) {
|
|
||||||
this.filteredTelemetry = JSON.parse(JSON.stringify(filters));
|
|
||||||
this.setFilterNames();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
updateFilters(filters) {
|
||||||
let filters = this.table.configuration.getConfiguration().filters || {};
|
this.filteredTelemetry = JSON.parse(JSON.stringify(filters));
|
||||||
this.table.configuration.on('change', this.handleConfigurationChanges);
|
this.setFilterNames();
|
||||||
this.updateFilters(filters);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.table.configuration.off('change', this.handleConfigurationChanges);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,7 +20,12 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<td @click="selectCell($event.currentTarget, columnKey)" :title="formattedValue">{{formattedValue}}</td>
|
<td
|
||||||
|
:title="formattedValue"
|
||||||
|
@click="selectCell($event.currentTarget, columnKey)"
|
||||||
|
>
|
||||||
|
{{ formattedValue }}
|
||||||
|
</td>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
@ -32,11 +37,20 @@ export default {
|
|||||||
},
|
},
|
||||||
columnKey: {
|
columnKey: {
|
||||||
type: String,
|
type: String,
|
||||||
require: true
|
required: true
|
||||||
},
|
},
|
||||||
objectPath: {
|
objectPath: {
|
||||||
type: Array,
|
type: Array,
|
||||||
require: false
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
formattedValue() {
|
||||||
|
return this.row.getFormattedValue(this.columnKey);
|
||||||
|
},
|
||||||
|
isSelectable() {
|
||||||
|
let column = this.row.columns[this.columnKey];
|
||||||
|
return column && column.selectable;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -57,15 +71,6 @@ export default {
|
|||||||
}], false);
|
}], false);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
formattedValue() {
|
|
||||||
return this.row.getFormattedValue(this.columnKey);
|
|
||||||
},
|
|
||||||
isSelectable() {
|
|
||||||
let column = this.row.columns[this.columnKey];
|
|
||||||
return column && column.selectable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -29,30 +29,49 @@
|
|||||||
drop: columnMoveEnd,
|
drop: columnMoveEnd,
|
||||||
dragleave: hideDropTarget,
|
dragleave: hideDropTarget,
|
||||||
dragover: dragOverColumn
|
dragover: dragOverColumn
|
||||||
} : {}">
|
} : {}"
|
||||||
<div class="c-telemetry-table__headers__content" :class="[
|
>
|
||||||
|
<div
|
||||||
|
class="c-telemetry-table__headers__content"
|
||||||
|
:class="[
|
||||||
isSortable ? 'is-sortable' : '',
|
isSortable ? 'is-sortable' : '',
|
||||||
isSortable && sortOptions.key === headerKey ? 'is-sorting' : '',
|
isSortable && sortOptions.key === headerKey ? 'is-sorting' : '',
|
||||||
isSortable && sortOptions.direction].join(' ')">
|
isSortable && sortOptions.direction].join(' ')"
|
||||||
<div class="c-telemetry-table__resize-hitarea"
|
>
|
||||||
@mousedown="resizeColumnStart"
|
<div
|
||||||
></div>
|
class="c-telemetry-table__resize-hitarea"
|
||||||
<slot></slot>
|
@mousedown="resizeColumnStart"
|
||||||
</div>
|
></div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash';
|
|
||||||
const MOVE_COLUMN_DT_TYPE = 'movecolumnfromindex';
|
const MOVE_COLUMN_DT_TYPE = 'movecolumnfromindex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
headerKey: String,
|
headerKey: {
|
||||||
headerIndex: Number,
|
type: String,
|
||||||
isHeaderTitle: Boolean,
|
default: undefined
|
||||||
sortOptions: Object,
|
},
|
||||||
columnWidth: Number,
|
headerIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
isHeaderTitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
sortOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
columnWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
hotzone: Boolean,
|
hotzone: Boolean,
|
||||||
isEditing: Boolean
|
isEditing: Boolean
|
||||||
},
|
},
|
||||||
@ -71,13 +90,13 @@ export default {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
resizeColumnEnd(event) {
|
resizeColumnEnd(event) {
|
||||||
this.resizeStartX = undefined;
|
this.resizeStartX = undefined;
|
||||||
this.resizeStartWidth = undefined;
|
this.resizeStartWidth = undefined;
|
||||||
document.removeEventListener('mousemove', this.resizeColumn);
|
document.removeEventListener('mousemove', this.resizeColumn);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
this.$emit('resizeColumnEnd');
|
this.$emit('resizeColumnEnd');
|
||||||
},
|
},
|
||||||
resizeColumn(event) {
|
resizeColumn(event) {
|
||||||
let delta = event.clientX - this.resizeStartX;
|
let delta = event.clientX - this.resizeStartX;
|
||||||
@ -94,7 +113,7 @@ export default {
|
|||||||
return [...event.dataTransfer.types].includes(MOVE_COLUMN_DT_TYPE);
|
return [...event.dataTransfer.types].includes(MOVE_COLUMN_DT_TYPE);
|
||||||
},
|
},
|
||||||
dragOverColumn(event) {
|
dragOverColumn(event) {
|
||||||
if (this.isColumnMoveEvent(event)){
|
if (this.isColumnMoveEvent(event)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.updateDropOffset(event.currentTarget, event.clientX);
|
this.updateDropOffset(event.currentTarget, event.clientX);
|
||||||
} else {
|
} else {
|
||||||
@ -114,19 +133,19 @@ export default {
|
|||||||
this.$emit('dropTargetOffsetChanged', dropOffsetLeft);
|
this.$emit('dropTargetOffsetChanged', dropOffsetLeft);
|
||||||
this.$emit('dropTargetActive', true);
|
this.$emit('dropTargetActive', true);
|
||||||
},
|
},
|
||||||
hideDropTarget(){
|
hideDropTarget() {
|
||||||
this.$emit('dropTargetActive', false);
|
this.$emit('dropTargetActive', false);
|
||||||
},
|
},
|
||||||
columnMoveEnd(event){
|
columnMoveEnd(event) {
|
||||||
if (this.isColumnMoveEvent(event)){
|
if (this.isColumnMoveEvent(event)) {
|
||||||
let toIndex = this.headerIndex;
|
let toIndex = this.headerIndex;
|
||||||
let fromIndex = event.dataTransfer.getData(MOVE_COLUMN_DT_TYPE);
|
let fromIndex = event.dataTransfer.getData(MOVE_COLUMN_DT_TYPE);
|
||||||
if (event.offsetX < event.target.offsetWidth / 2) {
|
if (event.offsetX < event.target.offsetWidth / 2) {
|
||||||
if (toIndex > fromIndex){
|
if (toIndex > fromIndex) {
|
||||||
toIndex--;
|
toIndex--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (toIndex < fromIndex){
|
if (toIndex < fromIndex) {
|
||||||
toIndex++;
|
toIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-properties">
|
<div class="c-properties">
|
||||||
<template v-if="isEditing">
|
<template v-if="isEditing">
|
||||||
<div class="c-properties__header">Table Column Size</div>
|
<div class="c-properties__header">
|
||||||
|
Table Column Size
|
||||||
|
</div>
|
||||||
<ul class="c-properties__section">
|
<ul class="c-properties__section">
|
||||||
<li class="c-properties__row">
|
<li class="c-properties__row">
|
||||||
<div class="c-properties__label" title="Auto-size table"><label for="AutoSizeControl">Auto-size</label></div>
|
<div
|
||||||
<div class="c-properties__value"><input type="checkbox" id="AutoSizeControl" :checked="configuration.autosize !== false" @change="toggleAutosize()"></div>
|
class="c-properties__label"
|
||||||
|
title="Auto-size table"
|
||||||
|
>
|
||||||
|
<label for="AutoSizeControl">Auto-size</label>
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
<input
|
||||||
|
id="AutoSizeControl"
|
||||||
|
type="checkbox"
|
||||||
|
:checked="configuration.autosize !== false"
|
||||||
|
@change="toggleAutosize()"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="c-properties__header">Table Column Visibility</div>
|
<div class="c-properties__header">
|
||||||
|
Table Column Visibility
|
||||||
|
</div>
|
||||||
<ul class="c-properties__section">
|
<ul class="c-properties__section">
|
||||||
<li class="c-properties__row" v-for="(title, key) in headers">
|
<li
|
||||||
<div class="c-properties__label" title="Show or hide column"><label :for="key + 'ColumnControl'">{{title}}</label></div>
|
v-for="(title, key) in headers"
|
||||||
<div class="c-properties__value"><input type="checkbox" :id="key + 'ColumnControl'" :checked="configuration.hiddenColumns[key] !== true" @change="toggleColumn(key)"></div>
|
:key="key"
|
||||||
|
class="c-properties__row"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="c-properties__label"
|
||||||
|
title="Show or hide column"
|
||||||
|
>
|
||||||
|
<label :for="key + 'ColumnControl'">{{ title }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
<input
|
||||||
|
:id="key + 'ColumnControl'"
|
||||||
|
type="checkbox"
|
||||||
|
:checked="configuration.hiddenColumns[key] !== true"
|
||||||
|
@change="toggleColumn(key)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
@ -34,6 +66,28 @@ export default {
|
|||||||
configuration: this.tableConfiguration.getConfiguration()
|
configuration: this.tableConfiguration.getConfiguration()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.unlisteners = [];
|
||||||
|
this.openmct.editor.on('isEditing', this.toggleEdit);
|
||||||
|
let compositionCollection = this.openmct.composition.get(this.tableConfiguration.domainObject);
|
||||||
|
|
||||||
|
compositionCollection.load()
|
||||||
|
.then((composition) => {
|
||||||
|
this.addColumnsForAllObjects(composition);
|
||||||
|
this.updateHeaders(this.tableConfiguration.getAllHeaders());
|
||||||
|
|
||||||
|
compositionCollection.on('add', this.addObject);
|
||||||
|
this.unlisteners.push(compositionCollection.off.bind(compositionCollection, 'add', this.addObject));
|
||||||
|
|
||||||
|
compositionCollection.on('remove', this.removeObject);
|
||||||
|
this.unlisteners.push(compositionCollection.off.bind(compositionCollection, 'remove', this.removeObject));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.tableConfiguration.destroy();
|
||||||
|
this.openmct.editor.off('isEditing', this.toggleEdit);
|
||||||
|
this.unlisteners.forEach((unlisten) => unlisten());
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateHeaders(headers) {
|
updateHeaders(headers) {
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
@ -45,7 +99,7 @@ export default {
|
|||||||
this.tableConfiguration.updateConfiguration(this.configuration);
|
this.tableConfiguration.updateConfiguration(this.configuration);
|
||||||
},
|
},
|
||||||
addObject(domainObject) {
|
addObject(domainObject) {
|
||||||
this.addColumnsForObject(domainObject, true);
|
this.addColumnsForObject(domainObject, true);
|
||||||
this.updateHeaders(this.tableConfiguration.getAllHeaders());
|
this.updateHeaders(this.tableConfiguration.getAllHeaders());
|
||||||
},
|
},
|
||||||
removeObject(objectIdentifier) {
|
removeObject(objectIdentifier) {
|
||||||
@ -70,28 +124,6 @@ export default {
|
|||||||
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.unlisteners = [];
|
|
||||||
this.openmct.editor.on('isEditing', this.toggleEdit);
|
|
||||||
let compositionCollection = this.openmct.composition.get(this.tableConfiguration.domainObject);
|
|
||||||
|
|
||||||
compositionCollection.load()
|
|
||||||
.then((composition) => {
|
|
||||||
this.addColumnsForAllObjects(composition);
|
|
||||||
this.updateHeaders(this.tableConfiguration.getAllHeaders());
|
|
||||||
|
|
||||||
compositionCollection.on('add', this.addObject);
|
|
||||||
this.unlisteners.push(compositionCollection.off.bind(compositionCollection, 'add', this.addObject));
|
|
||||||
|
|
||||||
compositionCollection.on('remove', this.removeObject);
|
|
||||||
this.unlisteners.push(compositionCollection.off.bind(compositionCollection, 'remove', this.removeObject));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.tableConfiguration.destroy();
|
|
||||||
this.openmct.editor.off('isEditing', this.toggleEdit);
|
|
||||||
this.unlisteners.forEach((unlisten) => unlisten());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,22 +20,25 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<tr :style="{ top: rowTop }"
|
<tr
|
||||||
|
:style="{ top: rowTop }"
|
||||||
class="noselect"
|
class="noselect"
|
||||||
:class="[
|
:class="[
|
||||||
rowClass,
|
rowClass,
|
||||||
{'is-selected': marked}
|
{'is-selected': marked}
|
||||||
]"
|
]"
|
||||||
v-on="listeners">
|
v-on="listeners"
|
||||||
<component v-for="(title, key) in headers"
|
>
|
||||||
:key="key"
|
<component
|
||||||
:is="componentList[key]"
|
:is="componentList[key]"
|
||||||
:columnKey="key"
|
v-for="(title, key) in headers"
|
||||||
|
:key="key"
|
||||||
|
:column-key="key"
|
||||||
:style="columnWidths[key] === undefined ? {} : { width: columnWidths[key] + 'px', 'max-width': columnWidths[key] + 'px'}"
|
:style="columnWidths[key] === undefined ? {} : { width: columnWidths[key] + 'px', 'max-width': columnWidths[key] + 'px'}"
|
||||||
:class="[cellLimitClasses[key], selectableColumns[key] ? 'is-selectable' : '']"
|
:class="[cellLimitClasses[key], selectableColumns[key] ? 'is-selectable' : '']"
|
||||||
:objectPath="objectPath"
|
:object-path="objectPath"
|
||||||
:row="row">
|
:row="row"
|
||||||
</component>
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -55,21 +58,9 @@
|
|||||||
import TableCell from './table-cell.vue';
|
import TableCell from './table-cell.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'objectPath'],
|
inject: ['openmct'],
|
||||||
data: function () {
|
components: {
|
||||||
return {
|
TableCell
|
||||||
rowTop: (this.rowOffset + this.rowIndex) * this.rowHeight + 'px',
|
|
||||||
rowClass: this.row.getRowClass(),
|
|
||||||
cellLimitClasses: this.row.getCellLimitClasses(),
|
|
||||||
componentList: Object.keys(this.headers).reduce((components, header) => {
|
|
||||||
components[header] = this.row.getCellComponentName(header) || 'table-cell';
|
|
||||||
return components
|
|
||||||
}, {}),
|
|
||||||
selectableColumns : Object.keys(this.row.columns).reduce((selectable, columnKeys) => {
|
|
||||||
selectable[columnKeys] = this.row.columns[columnKeys].selectable;
|
|
||||||
return selectable;
|
|
||||||
}, {})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
headers: {
|
headers: {
|
||||||
@ -86,7 +77,7 @@ export default {
|
|||||||
},
|
},
|
||||||
objectPath: {
|
objectPath: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false
|
required: true
|
||||||
},
|
},
|
||||||
rowIndex: {
|
rowIndex: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -109,6 +100,42 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
rowTop: (this.rowOffset + this.rowIndex) * this.rowHeight + 'px',
|
||||||
|
rowClass: this.row.getRowClass(),
|
||||||
|
cellLimitClasses: this.row.getCellLimitClasses(),
|
||||||
|
componentList: Object.keys(this.headers).reduce((components, header) => {
|
||||||
|
components[header] = this.row.getCellComponentName(header) || 'table-cell';
|
||||||
|
return components
|
||||||
|
}, {}),
|
||||||
|
selectableColumns : Object.keys(this.row.columns).reduce((selectable, columnKeys) => {
|
||||||
|
selectable[columnKeys] = this.row.columns[columnKeys].selectable;
|
||||||
|
return selectable;
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
listeners() {
|
||||||
|
let listenersObject = {
|
||||||
|
click: this.markRow
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.row.getContextMenuActions().length) {
|
||||||
|
listenersObject.contextmenu = this.showContextMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listenersObject;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// TODO: use computed properties
|
||||||
|
watch: {
|
||||||
|
rowOffset: 'calculateRowTop',
|
||||||
|
row: {
|
||||||
|
handler: 'formatRow',
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
calculateRowTop: function (rowOffset) {
|
calculateRowTop: function (rowOffset) {
|
||||||
this.rowTop = (rowOffset + this.rowIndex) * this.rowHeight + 'px';
|
this.rowTop = (rowOffset + this.rowIndex) * this.rowHeight + 'px';
|
||||||
@ -136,7 +163,7 @@ export default {
|
|||||||
},
|
},
|
||||||
selectCell(element, columnKey) {
|
selectCell(element, columnKey) {
|
||||||
if (this.selectableColumns[columnKey]) {
|
if (this.selectableColumns[columnKey]) {
|
||||||
//TODO: This is a hack. Cannot get parent this way.
|
//TODO: This is a hack. Cannot get parent this way.
|
||||||
this.openmct.selection.select([{
|
this.openmct.selection.select([{
|
||||||
element: element,
|
element: element,
|
||||||
context: {
|
context: {
|
||||||
@ -153,7 +180,7 @@ export default {
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showContextMenu: function (event) {
|
showContextMenu: function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
this.openmct.objects.get(this.row.objectKeyString).then((domainObject) => {
|
this.openmct.objects.get(this.row.objectKeyString).then((domainObject) => {
|
||||||
@ -163,30 +190,6 @@ export default {
|
|||||||
this.openmct.contextMenu._showContextMenuForObjectPath(contextualObjectPath, event.x, event.y, this.row.getContextMenuActions());
|
this.openmct.contextMenu._showContextMenuForObjectPath(contextualObjectPath, event.x, event.y, this.row.getContextMenuActions());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// TODO: use computed properties
|
|
||||||
watch: {
|
|
||||||
rowOffset: 'calculateRowTop',
|
|
||||||
row: {
|
|
||||||
handler: 'formatRow',
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
TableCell
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
listeners() {
|
|
||||||
let listenersObject = {
|
|
||||||
click: this.markRow
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.row.getContextMenuActions().length) {
|
|
||||||
listenersObject.contextmenu = this.showContextMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
return listenersObject;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,131 +22,178 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-table-wrapper">
|
<div class="c-table-wrapper">
|
||||||
<div class="c-table-control-bar c-control-bar">
|
<div class="c-table-control-bar c-control-bar">
|
||||||
<button class="c-button icon-download labeled"
|
<button
|
||||||
v-if="allowExport"
|
v-if="allowExport"
|
||||||
v-on:click="exportAllDataAsCSV()"
|
class="c-button icon-download labeled"
|
||||||
title="Export This View's Data">
|
title="Export This View's Data"
|
||||||
|
@click="exportAllDataAsCSV()"
|
||||||
|
>
|
||||||
<span class="c-button__label">Export Table Data</span>
|
<span class="c-button__label">Export Table Data</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="c-button icon-download labeled"
|
<button
|
||||||
v-if="allowExport"
|
v-if="allowExport"
|
||||||
v-show="markedRows.length"
|
v-show="markedRows.length"
|
||||||
v-on:click="exportMarkedDataAsCSV()"
|
class="c-button icon-download labeled"
|
||||||
title="Export Marked Rows As CSV">
|
title="Export Marked Rows As CSV"
|
||||||
|
@click="exportMarkedDataAsCSV()"
|
||||||
|
>
|
||||||
<span class="c-button__label">Export Marked Rows</span>
|
<span class="c-button__label">Export Marked Rows</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="c-button icon-x labeled"
|
<button
|
||||||
v-show="markedRows.length"
|
v-show="markedRows.length"
|
||||||
v-on:click="unmarkAllRows()"
|
class="c-button icon-x labeled"
|
||||||
title="Unmark All Rows">
|
title="Unmark All Rows"
|
||||||
|
@click="unmarkAllRows()"
|
||||||
|
>
|
||||||
<span class="c-button__label">Unmark All Rows</span>
|
<span class="c-button__label">Unmark All Rows</span>
|
||||||
</button>
|
</button>
|
||||||
<div v-if="enableMarking"
|
<div
|
||||||
class="c-separator">
|
v-if="enableMarking"
|
||||||
</div>
|
class="c-separator"
|
||||||
<button v-if="enableMarking"
|
></div>
|
||||||
class="c-button icon-pause pause-play labeled"
|
<button
|
||||||
:class=" paused ? 'icon-play is-paused' : 'icon-pause'"
|
v-if="enableMarking"
|
||||||
v-on:click="togglePauseByButton()"
|
class="c-button icon-pause pause-play labeled"
|
||||||
:title="paused ? 'Continue Data Flow' : 'Pause Data Flow'">
|
:class=" paused ? 'icon-play is-paused' : 'icon-pause'"
|
||||||
<span class="c-button__label">
|
:title="paused ? 'Continue Data Flow' : 'Pause Data Flow'"
|
||||||
{{paused ? 'Play' : 'Pause'}}
|
@click="togglePauseByButton()"
|
||||||
</span>
|
>
|
||||||
|
<span class="c-button__label">
|
||||||
|
{{ paused ? 'Play' : 'Pause' }}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<slot name="buttons"></slot>
|
<slot name="buttons"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="c-table c-telemetry-table c-table--filterable c-table--sortable has-control-bar"
|
<div
|
||||||
:class="{
|
class="c-table c-telemetry-table c-table--filterable c-table--sortable has-control-bar"
|
||||||
'loading': loading,
|
:class="{
|
||||||
'paused' : paused
|
'loading': loading,
|
||||||
}">
|
'paused' : paused
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :style="{ 'max-width': widthWithScroll, 'min-width': '150px'}">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div :style="{ 'max-width': widthWithScroll, 'min-width': '150px'}"><slot></slot></div>
|
<div
|
||||||
|
v-if="isDropTargetActive"
|
||||||
<div v-if="isDropTargetActive" class="c-telemetry-table__drop-target" :style="dropTargetStyle"></div>
|
class="c-telemetry-table__drop-target"
|
||||||
|
:style="dropTargetStyle"
|
||||||
|
></div>
|
||||||
<!-- Headers table -->
|
<!-- Headers table -->
|
||||||
<div class="c-telemetry-table__headers-w js-table__headers-w" ref="headersTable" :style="{ 'max-width': widthWithScroll}">
|
<div
|
||||||
|
ref="headersTable"
|
||||||
|
class="c-telemetry-table__headers-w js-table__headers-w"
|
||||||
|
:style="{ 'max-width': widthWithScroll}"
|
||||||
|
>
|
||||||
<table class="c-table__headers c-telemetry-table__headers">
|
<table class="c-table__headers c-telemetry-table__headers">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="c-telemetry-table__headers__labels">
|
<tr class="c-telemetry-table__headers__labels">
|
||||||
<table-column-header
|
<table-column-header
|
||||||
v-for="(title, key, headerIndex) in headers"
|
v-for="(title, key, headerIndex) in headers"
|
||||||
:key="key"
|
:key="key"
|
||||||
:headerKey="key"
|
:header-key="key"
|
||||||
:headerIndex="headerIndex"
|
:header-index="headerIndex"
|
||||||
|
:column-width="columnWidths[key]"
|
||||||
|
:sort-options="sortOptions"
|
||||||
|
:is-editing="isEditing"
|
||||||
@sort="allowSorting && sortBy(key)"
|
@sort="allowSorting && sortBy(key)"
|
||||||
@resizeColumn="resizeColumn"
|
@resizeColumn="resizeColumn"
|
||||||
@dropTargetOffsetChanged="setDropTargetOffset"
|
@dropTargetOffsetChanged="setDropTargetOffset"
|
||||||
@dropTargetActive="dropTargetActive"
|
@dropTargetActive="dropTargetActive"
|
||||||
@reorderColumn="reorderColumn"
|
@reorderColumn="reorderColumn"
|
||||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||||
:columnWidth="columnWidths[key]"
|
>
|
||||||
:sortOptions="sortOptions"
|
<span class="c-telemetry-table__headers__label">{{ title }}</span>
|
||||||
:isEditing="isEditing"
|
|
||||||
><span class="c-telemetry-table__headers__label">{{title}}</span>
|
|
||||||
</table-column-header>
|
</table-column-header>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="allowFiltering" class="c-telemetry-table__headers__filter">
|
<tr
|
||||||
|
v-if="allowFiltering"
|
||||||
|
class="c-telemetry-table__headers__filter"
|
||||||
|
>
|
||||||
<table-column-header
|
<table-column-header
|
||||||
v-for="(title, key, headerIndex) in headers"
|
v-for="(title, key, headerIndex) in headers"
|
||||||
:key="key"
|
:key="key"
|
||||||
:headerKey="key"
|
:header-key="key"
|
||||||
:headerIndex="headerIndex"
|
:header-index="headerIndex"
|
||||||
|
:column-width="columnWidths[key]"
|
||||||
|
:is-editing="isEditing"
|
||||||
@resizeColumn="resizeColumn"
|
@resizeColumn="resizeColumn"
|
||||||
@dropTargetOffsetChanged="setDropTargetOffset"
|
@dropTargetOffsetChanged="setDropTargetOffset"
|
||||||
@dropTargetActive="dropTargetActive"
|
@dropTargetActive="dropTargetActive"
|
||||||
@reorderColumn="reorderColumn"
|
@reorderColumn="reorderColumn"
|
||||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||||
:columnWidth="columnWidths[key]"
|
>
|
||||||
:isEditing="isEditing"
|
<search
|
||||||
>
|
|
||||||
<search class="c-table__search"
|
|
||||||
v-model="filters[key]"
|
v-model="filters[key]"
|
||||||
v-on:input="filterChanged(key)"
|
class="c-table__search"
|
||||||
v-on:clear="clearFilter(key)" />
|
@input="filterChanged(key)"
|
||||||
|
@clear="clearFilter(key)"
|
||||||
|
/>
|
||||||
</table-column-header>
|
</table-column-header>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<!-- Content table -->
|
<!-- Content table -->
|
||||||
<div class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w" @scroll="scroll" :style="{ 'max-width': widthWithScroll}">
|
<div
|
||||||
<div class="c-telemetry-table__scroll-forcer" :style="{ width: totalWidth + 'px' }"></div>
|
class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w"
|
||||||
<table class="c-table__body c-telemetry-table__body js-telemetry-table__content"
|
:style="{ 'max-width': widthWithScroll}"
|
||||||
:style="{ height: totalHeight + 'px'}">
|
@scroll="scroll"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="c-telemetry-table__scroll-forcer"
|
||||||
|
:style="{ width: totalWidth + 'px' }"
|
||||||
|
></div>
|
||||||
|
<table
|
||||||
|
class="c-table__body c-telemetry-table__body js-telemetry-table__content"
|
||||||
|
:style="{ height: totalHeight + 'px'}"
|
||||||
|
>
|
||||||
<tbody>
|
<tbody>
|
||||||
<telemetry-table-row v-for="(row, rowIndex) in visibleRows"
|
<telemetry-table-row
|
||||||
|
v-for="(row, rowIndex) in visibleRows"
|
||||||
|
:key="rowIndex"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:columnWidths="columnWidths"
|
:column-widths="columnWidths"
|
||||||
:rowIndex="rowIndex"
|
:row-index="rowIndex"
|
||||||
:objectPath="objectPath"
|
:object-path="objectPath"
|
||||||
:rowOffset="rowOffset"
|
:row-offset="rowOffset"
|
||||||
:rowHeight="rowHeight"
|
:row-height="rowHeight"
|
||||||
:row="row"
|
:row="row"
|
||||||
:marked="row.marked"
|
:marked="row.marked"
|
||||||
@mark="markRow"
|
@mark="markRow"
|
||||||
@unmark="unmarkRow"
|
@unmark="unmarkRow"
|
||||||
@markMultipleConcurrent="markMultipleConcurrentRows">
|
@markMultipleConcurrent="markMultipleConcurrentRows"
|
||||||
</telemetry-table-row>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<!-- Sizing table -->
|
<!-- Sizing table -->
|
||||||
<table class="c-telemetry-table__sizing js-telemetry-table__sizing" :style="sizingTableWidth">
|
<table
|
||||||
|
class="c-telemetry-table__sizing js-telemetry-table__sizing"
|
||||||
|
:style="sizingTableWidth"
|
||||||
|
>
|
||||||
<tr>
|
<tr>
|
||||||
<template v-for="(title, key) in headers">
|
<template v-for="(title, key) in headers">
|
||||||
<th :key="key" :style="{ width: configuredColumnWidths[key] + 'px', 'max-width': configuredColumnWidths[key] + 'px'}">{{title}}</th>
|
<th
|
||||||
|
:key="key"
|
||||||
|
:style="{ width: configuredColumnWidths[key] + 'px', 'max-width': configuredColumnWidths[key] + 'px'}"
|
||||||
|
>
|
||||||
|
{{ title }}
|
||||||
|
</th>
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
<telemetry-table-row v-for="(sizingRowData, objectKeyString) in sizingRows"
|
<telemetry-table-row
|
||||||
|
v-for="(sizingRowData, objectKeyString) in sizingRows"
|
||||||
:key="objectKeyString"
|
:key="objectKeyString"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:columnWidths="configuredColumnWidths"
|
:column-widths="configuredColumnWidths"
|
||||||
:row="sizingRowData">
|
:row="sizingRowData"
|
||||||
</telemetry-table-row>
|
:object-path="objectPath"
|
||||||
|
/>
|
||||||
</table>
|
</table>
|
||||||
<telemetry-filter-indicator></telemetry-filter-indicator>
|
<telemetry-filter-indicator />
|
||||||
</div>
|
</div>
|
||||||
</div><!-- closes c-table-wrapper -->
|
</div><!-- closes c-table-wrapper -->
|
||||||
</template>
|
</template>
|
||||||
@ -343,9 +390,6 @@ const VISIBLE_ROW_COUNT = 100;
|
|||||||
const ROW_HEIGHT = 17;
|
const ROW_HEIGHT = 17;
|
||||||
const RESIZE_POLL_INTERVAL = 200;
|
const RESIZE_POLL_INTERVAL = 200;
|
||||||
const AUTO_SCROLL_TRIGGER_HEIGHT = 100;
|
const AUTO_SCROLL_TRIGGER_HEIGHT = 100;
|
||||||
const RESIZE_HOT_ZONE = 10;
|
|
||||||
const MOVE_TRIGGER_WAIT = 500;
|
|
||||||
const VERTICAL_SCROLL_WIDTH = 30;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -440,6 +484,59 @@ export default {
|
|||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.filterChanged = _.debounce(this.filterChanged, 500);
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.csvExporter = new CSVExporter();
|
||||||
|
this.rowsAdded = _.throttle(this.rowsAdded, 200);
|
||||||
|
this.rowsRemoved = _.throttle(this.rowsRemoved, 200);
|
||||||
|
this.scroll = _.throttle(this.scroll, 100);
|
||||||
|
|
||||||
|
this.table.on('object-added', this.addObject);
|
||||||
|
this.table.on('object-removed', this.removeObject);
|
||||||
|
this.table.on('outstanding-requests', this.outstandingRequests);
|
||||||
|
this.table.on('refresh', this.clearRowsAndRerender);
|
||||||
|
|
||||||
|
this.table.filteredRows.on('add', this.rowsAdded);
|
||||||
|
this.table.filteredRows.on('remove', this.rowsRemoved);
|
||||||
|
this.table.filteredRows.on('sort', this.updateVisibleRows);
|
||||||
|
this.table.filteredRows.on('filter', this.updateVisibleRows);
|
||||||
|
|
||||||
|
//Default sort
|
||||||
|
this.sortOptions = this.table.filteredRows.sortBy();
|
||||||
|
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
||||||
|
this.contentTable = this.$el.querySelector('.js-telemetry-table__content');
|
||||||
|
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
||||||
|
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
||||||
|
|
||||||
|
this.table.configuration.on('change', this.updateConfiguration);
|
||||||
|
|
||||||
|
this.calculateTableSize();
|
||||||
|
this.pollForResize();
|
||||||
|
this.calculateScrollbarWidth();
|
||||||
|
|
||||||
|
this.table.initialize();
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.table.off('object-added', this.addObject);
|
||||||
|
this.table.off('object-removed', this.removeObject);
|
||||||
|
this.table.off('outstanding-requests', this.outstandingRequests);
|
||||||
|
this.table.off('refresh', this.clearRowsAndRerender);
|
||||||
|
|
||||||
|
this.table.filteredRows.off('add', this.rowsAdded);
|
||||||
|
this.table.filteredRows.off('remove', this.rowsRemoved);
|
||||||
|
this.table.filteredRows.off('sort', this.updateVisibleRows);
|
||||||
|
this.table.filteredRows.off('filter', this.updateVisibleRows);
|
||||||
|
|
||||||
|
this.table.configuration.off('change', this.updateConfiguration);
|
||||||
|
|
||||||
|
clearInterval(this.resizePollHandle);
|
||||||
|
|
||||||
|
this.table.configuration.destroy();
|
||||||
|
|
||||||
|
this.table.destroy();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateVisibleRows() {
|
updateVisibleRows() {
|
||||||
if (!this.updatingView) {
|
if (!this.updatingView) {
|
||||||
@ -527,7 +624,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.table.sortBy(this.sortOptions);
|
this.table.sortBy(this.sortOptions);
|
||||||
},
|
},
|
||||||
scroll () {
|
scroll() {
|
||||||
this.updateVisibleRows();
|
this.updateVisibleRows();
|
||||||
this.synchronizeScrollX();
|
this.synchronizeScrollX();
|
||||||
|
|
||||||
@ -557,7 +654,7 @@ export default {
|
|||||||
this.table.filteredRows.setColumnFilter(columnKey, '');
|
this.table.filteredRows.setColumnFilter(columnKey, '');
|
||||||
this.setHeight();
|
this.setHeight();
|
||||||
},
|
},
|
||||||
rowsAdded (rows) {
|
rowsAdded(rows) {
|
||||||
this.setHeight();
|
this.setHeight();
|
||||||
|
|
||||||
let sizingRow;
|
let sizingRow;
|
||||||
@ -578,7 +675,7 @@ export default {
|
|||||||
|
|
||||||
this.updateVisibleRows();
|
this.updateVisibleRows();
|
||||||
},
|
},
|
||||||
rowsRemoved (rows) {
|
rowsRemoved(rows) {
|
||||||
this.setHeight();
|
this.setHeight();
|
||||||
this.updateVisibleRows();
|
this.updateVisibleRows();
|
||||||
},
|
},
|
||||||
@ -811,66 +908,12 @@ export default {
|
|||||||
let row = allRows[i];
|
let row = allRows[i];
|
||||||
row.marked = true;
|
row.marked = true;
|
||||||
|
|
||||||
if (row !== baseRow){
|
if (row !== baseRow) {
|
||||||
this.markedRows.push(row);
|
this.markedRows.push(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.filterChanged = _.debounce(this.filterChanged, 500);
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
console.log("Table mounted");
|
|
||||||
this.csvExporter = new CSVExporter();
|
|
||||||
this.rowsAdded = _.throttle(this.rowsAdded, 200);
|
|
||||||
this.rowsRemoved = _.throttle(this.rowsRemoved, 200);
|
|
||||||
this.scroll = _.throttle(this.scroll, 100);
|
|
||||||
|
|
||||||
this.table.on('object-added', this.addObject);
|
|
||||||
this.table.on('object-removed', this.removeObject);
|
|
||||||
this.table.on('outstanding-requests', this.outstandingRequests);
|
|
||||||
this.table.on('refresh', this.clearRowsAndRerender);
|
|
||||||
|
|
||||||
this.table.filteredRows.on('add', this.rowsAdded);
|
|
||||||
this.table.filteredRows.on('remove', this.rowsRemoved);
|
|
||||||
this.table.filteredRows.on('sort', this.updateVisibleRows);
|
|
||||||
this.table.filteredRows.on('filter', this.updateVisibleRows);
|
|
||||||
|
|
||||||
//Default sort
|
|
||||||
this.sortOptions = this.table.filteredRows.sortBy();
|
|
||||||
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
|
||||||
this.contentTable = this.$el.querySelector('.js-telemetry-table__content');
|
|
||||||
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
|
||||||
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
|
||||||
|
|
||||||
this.table.configuration.on('change', this.updateConfiguration);
|
|
||||||
|
|
||||||
this.calculateTableSize();
|
|
||||||
this.pollForResize();
|
|
||||||
this.calculateScrollbarWidth();
|
|
||||||
|
|
||||||
this.table.initialize();
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.table.off('object-added', this.addObject);
|
|
||||||
this.table.off('object-removed', this.removeObject);
|
|
||||||
this.table.off('outstanding-requests', this.outstandingRequests);
|
|
||||||
this.table.off('refresh', this.clearRowsAndRerender);
|
|
||||||
|
|
||||||
this.table.filteredRows.off('add', this.rowsAdded);
|
|
||||||
this.table.filteredRows.off('remove', this.rowsRemoved);
|
|
||||||
this.table.filteredRows.off('sort', this.updateVisibleRows);
|
|
||||||
this.table.filteredRows.off('filter', this.updateVisibleRows);
|
|
||||||
|
|
||||||
this.table.configuration.off('change', this.updateConfiguration);
|
|
||||||
|
|
||||||
clearInterval(this.resizePollHandle);
|
|
||||||
|
|
||||||
this.table.configuration.destroy();
|
|
||||||
|
|
||||||
this.table.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,87 +20,123 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-conductor"
|
<div
|
||||||
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']">
|
class="c-conductor"
|
||||||
<form class="u-contents" ref="conductorForm" @submit.prevent="updateTimeFromConductor">
|
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']"
|
||||||
<div class="c-conductor__time-bounds">
|
>
|
||||||
<button class="c-input--submit" type="submit" ref="submitButton"></button>
|
<form
|
||||||
<ConductorModeIcon class="c-conductor__mode-icon"></ConductorModeIcon>
|
ref="conductorForm"
|
||||||
|
class="u-contents"
|
||||||
|
@submit.prevent="updateTimeFromConductor"
|
||||||
|
>
|
||||||
|
<div class="c-conductor__time-bounds">
|
||||||
|
<button
|
||||||
|
ref="submitButton"
|
||||||
|
class="c-input--submit"
|
||||||
|
type="submit"
|
||||||
|
></button>
|
||||||
|
<ConductorModeIcon class="c-conductor__mode-icon" />
|
||||||
|
|
||||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__start-fixed"
|
<div
|
||||||
v-if="isFixed">
|
v-if="isFixed"
|
||||||
<!-- Fixed start -->
|
class="c-ctrl-wrapper c-conductor-input c-conductor__start-fixed"
|
||||||
<div class="c-conductor__start-fixed__label">Start</div>
|
>
|
||||||
<input class="c-input--datetime"
|
<!-- Fixed start -->
|
||||||
type="text" autocorrect="off" spellcheck="false"
|
<div class="c-conductor__start-fixed__label">
|
||||||
ref="startDate"
|
Start
|
||||||
v-model="formattedBounds.start"
|
|
||||||
@change="validateAllBounds(); submitForm()" />
|
|
||||||
<date-picker
|
|
||||||
v-if="isFixed && isUTCBased"
|
|
||||||
:default-date-time="formattedBounds.start"
|
|
||||||
:formatter="timeFormatter"
|
|
||||||
@date-selected="startDateSelected"></date-picker>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input
|
||||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__start-delta"
|
ref="startDate"
|
||||||
v-if="!isFixed">
|
v-model="formattedBounds.start"
|
||||||
<!-- RT start -->
|
class="c-input--datetime"
|
||||||
<div class="c-direction-indicator icon-minus"></div>
|
type="text"
|
||||||
<input class="c-input--hrs-min-sec"
|
autocorrect="off"
|
||||||
type="text" autocorrect="off"
|
spellcheck="false"
|
||||||
ref="startOffset"
|
@change="validateAllBounds(); submitForm()"
|
||||||
spellcheck="false"
|
>
|
||||||
v-model="offsets.start"
|
<date-picker
|
||||||
@change="validateAllOffsets(); submitForm()">
|
v-if="isFixed && isUTCBased"
|
||||||
</div>
|
:default-date-time="formattedBounds.start"
|
||||||
|
:formatter="timeFormatter"
|
||||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-fixed">
|
@date-selected="startDateSelected"
|
||||||
<!-- Fixed end and RT 'last update' display -->
|
/>
|
||||||
<div class="c-conductor__end-fixed__label">
|
|
||||||
{{ isFixed ? 'End' : 'Updated' }}
|
|
||||||
</div>
|
|
||||||
<input class="c-input--datetime"
|
|
||||||
type="text" autocorrect="off" spellcheck="false"
|
|
||||||
v-model="formattedBounds.end"
|
|
||||||
:disabled="!isFixed"
|
|
||||||
ref="endDate"
|
|
||||||
@change="validateAllBounds(); submitForm()">
|
|
||||||
<date-picker
|
|
||||||
v-if="isFixed && isUTCBased"
|
|
||||||
class="c-ctrl-wrapper--menus-left"
|
|
||||||
:default-date-time="formattedBounds.end"
|
|
||||||
:formatter="timeFormatter"
|
|
||||||
@date-selected="endDateSelected"></date-picker>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-delta"
|
|
||||||
v-if="!isFixed">
|
|
||||||
<!-- RT end -->
|
|
||||||
<div class="c-direction-indicator icon-plus"></div>
|
|
||||||
<input class="c-input--hrs-min-sec"
|
|
||||||
type="text"
|
|
||||||
autocorrect="off"
|
|
||||||
spellcheck="false"
|
|
||||||
ref="endOffset"
|
|
||||||
v-model="offsets.end"
|
|
||||||
@change="validateAllOffsets(); submitForm()">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<conductor-axis
|
|
||||||
class="c-conductor__ticks"
|
|
||||||
:bounds="rawBounds"
|
|
||||||
@panAxis="setViewFromBounds"></conductor-axis>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="c-conductor__controls">
|
|
||||||
<!-- Mode, time system menu buttons and duration slider -->
|
<div
|
||||||
<ConductorMode class="c-conductor__mode-select"></ConductorMode>
|
v-if="!isFixed"
|
||||||
<ConductorTimeSystem class="c-conductor__time-system-select"></ConductorTimeSystem>
|
class="c-ctrl-wrapper c-conductor-input c-conductor__start-delta"
|
||||||
|
>
|
||||||
|
<!-- RT start -->
|
||||||
|
<div class="c-direction-indicator icon-minus"></div>
|
||||||
|
<input
|
||||||
|
ref="startOffset"
|
||||||
|
v-model="offsets.start"
|
||||||
|
class="c-input--hrs-min-sec"
|
||||||
|
type="text"
|
||||||
|
autocorrect="off"
|
||||||
|
spellcheck="false"
|
||||||
|
@change="validateAllOffsets(); submitForm()"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="invisible">
|
|
||||||
</form>
|
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-fixed">
|
||||||
</div>
|
<!-- Fixed end and RT 'last update' display -->
|
||||||
|
<div class="c-conductor__end-fixed__label">
|
||||||
|
{{ isFixed ? 'End' : 'Updated' }}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
ref="endDate"
|
||||||
|
v-model="formattedBounds.end"
|
||||||
|
class="c-input--datetime"
|
||||||
|
type="text"
|
||||||
|
autocorrect="off"
|
||||||
|
spellcheck="false"
|
||||||
|
:disabled="!isFixed"
|
||||||
|
@change="validateAllBounds(); submitForm()"
|
||||||
|
>
|
||||||
|
<date-picker
|
||||||
|
v-if="isFixed && isUTCBased"
|
||||||
|
class="c-ctrl-wrapper--menus-left"
|
||||||
|
:default-date-time="formattedBounds.end"
|
||||||
|
:formatter="timeFormatter"
|
||||||
|
@date-selected="endDateSelected"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!isFixed"
|
||||||
|
class="c-ctrl-wrapper c-conductor-input c-conductor__end-delta"
|
||||||
|
>
|
||||||
|
<!-- RT end -->
|
||||||
|
<div class="c-direction-indicator icon-plus"></div>
|
||||||
|
<input
|
||||||
|
ref="endOffset"
|
||||||
|
v-model="offsets.end"
|
||||||
|
class="c-input--hrs-min-sec"
|
||||||
|
type="text"
|
||||||
|
autocorrect="off"
|
||||||
|
spellcheck="false"
|
||||||
|
@change="validateAllOffsets(); submitForm()"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<conductor-axis
|
||||||
|
class="c-conductor__ticks"
|
||||||
|
:bounds="rawBounds"
|
||||||
|
@panAxis="setViewFromBounds"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="c-conductor__controls">
|
||||||
|
<!-- Mode, time system menu buttons and duration slider -->
|
||||||
|
<ConductorMode class="c-conductor__mode-select" />
|
||||||
|
<ConductorTimeSystem class="c-conductor__time-system-select" />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
class="invisible"
|
||||||
|
>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -288,7 +324,6 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import moment from 'moment';
|
|
||||||
import ConductorMode from './ConductorMode.vue';
|
import ConductorMode from './ConductorMode.vue';
|
||||||
import ConductorTimeSystem from './ConductorTimeSystem.vue';
|
import ConductorTimeSystem from './ConductorTimeSystem.vue';
|
||||||
import DatePicker from './DatePicker.vue';
|
import DatePicker from './DatePicker.vue';
|
||||||
@ -296,11 +331,6 @@ import ConductorAxis from './ConductorAxis.vue';
|
|||||||
import ConductorModeIcon from './ConductorModeIcon.vue';
|
import ConductorModeIcon from './ConductorModeIcon.vue';
|
||||||
|
|
||||||
const DEFAULT_DURATION_FORMATTER = 'duration';
|
const DEFAULT_DURATION_FORMATTER = 'duration';
|
||||||
const SECONDS = 1000;
|
|
||||||
const DAYS = 24 * 60 * 60 * SECONDS;
|
|
||||||
const YEARS = 365 * DAYS;
|
|
||||||
|
|
||||||
const RESIZE_POLL_INTERVAL = 200;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'configuration'],
|
inject: ['openmct', 'configuration'],
|
||||||
@ -323,7 +353,7 @@ export default {
|
|||||||
durationFormatter: durationFormatter,
|
durationFormatter: durationFormatter,
|
||||||
offsets: {
|
offsets: {
|
||||||
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
|
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
|
||||||
end: offsets && durationFormatter.format(Math.abs(offsets.end)),
|
end: offsets && durationFormatter.format(Math.abs(offsets.end))
|
||||||
},
|
},
|
||||||
formattedBounds: {
|
formattedBounds: {
|
||||||
start: timeFormatter.format(bounds.start),
|
start: timeFormatter.format(bounds.start),
|
||||||
@ -338,6 +368,14 @@ export default {
|
|||||||
showDatePicker: false
|
showDatePicker: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
||||||
|
|
||||||
|
this.openmct.time.on('bounds', this.setViewFromBounds);
|
||||||
|
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
||||||
|
this.openmct.time.on('clock', this.setViewFromClock);
|
||||||
|
this.openmct.time.on('clockOffsets', this.setViewFromOffsets)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setTimeSystem(timeSystem) {
|
setTimeSystem(timeSystem) {
|
||||||
this.timeFormatter = this.getFormatter(timeSystem.timeFormat);
|
this.timeFormatter = this.getFormatter(timeSystem.timeFormat);
|
||||||
@ -347,7 +385,7 @@ export default {
|
|||||||
this.isUTCBased = timeSystem.isUTCBased;
|
this.isUTCBased = timeSystem.isUTCBased;
|
||||||
},
|
},
|
||||||
setOffsetsFromView($event) {
|
setOffsetsFromView($event) {
|
||||||
if (this.$refs.conductorForm.checkValidity()){
|
if (this.$refs.conductorForm.checkValidity()) {
|
||||||
let startOffset = 0 - this.durationFormatter.parse(this.offsets.start);
|
let startOffset = 0 - this.durationFormatter.parse(this.offsets.start);
|
||||||
let endOffset = this.durationFormatter.parse(this.offsets.end);
|
let endOffset = this.durationFormatter.parse(this.offsets.end);
|
||||||
|
|
||||||
@ -362,7 +400,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setBoundsFromView($event) {
|
setBoundsFromView($event) {
|
||||||
if (this.$refs.conductorForm.checkValidity()){
|
if (this.$refs.conductorForm.checkValidity()) {
|
||||||
let start = this.timeFormatter.parse(this.formattedBounds.start);
|
let start = this.timeFormatter.parse(this.formattedBounds.start);
|
||||||
let end = this.timeFormatter.parse(this.formattedBounds.end);
|
let end = this.timeFormatter.parse(this.formattedBounds.end);
|
||||||
|
|
||||||
@ -404,7 +442,7 @@ export default {
|
|||||||
[this.$refs.startOffset, this.$refs.endOffset].forEach(this.clearValidationForInput);
|
[this.$refs.startOffset, this.$refs.endOffset].forEach(this.clearValidationForInput);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clearValidationForInput(input){
|
clearValidationForInput(input) {
|
||||||
input.setCustomValidity('');
|
input.setCustomValidity('');
|
||||||
input.title = '';
|
input.title = '';
|
||||||
},
|
},
|
||||||
@ -419,7 +457,7 @@ export default {
|
|||||||
formattedDate = this.formattedBounds.end;
|
formattedDate = this.formattedBounds.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.timeFormatter.validate(formattedDate)){
|
if (!this.timeFormatter.validate(formattedDate)) {
|
||||||
validationResult = 'Invalid date';
|
validationResult = 'Invalid date';
|
||||||
} else {
|
} else {
|
||||||
let boundsValues = {
|
let boundsValues = {
|
||||||
@ -429,7 +467,7 @@ export default {
|
|||||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validationResult !== true){
|
if (validationResult !== true) {
|
||||||
input.setCustomValidity(validationResult);
|
input.setCustomValidity(validationResult);
|
||||||
input.title = validationResult;
|
input.title = validationResult;
|
||||||
return false;
|
return false;
|
||||||
@ -461,7 +499,7 @@ export default {
|
|||||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validationResult !== true){
|
if (validationResult !== true) {
|
||||||
input.setCustomValidity(validationResult);
|
input.setCustomValidity(validationResult);
|
||||||
input.title = validationResult;
|
input.title = validationResult;
|
||||||
return false;
|
return false;
|
||||||
@ -482,24 +520,16 @@ export default {
|
|||||||
format: key
|
format: key
|
||||||
}).formatter;
|
}).formatter;
|
||||||
},
|
},
|
||||||
startDateSelected(date){
|
startDateSelected(date) {
|
||||||
this.formattedBounds.start = this.timeFormatter.format(date);
|
this.formattedBounds.start = this.timeFormatter.format(date);
|
||||||
this.validateAllBounds();
|
this.validateAllBounds();
|
||||||
this.submitForm();
|
this.submitForm();
|
||||||
},
|
},
|
||||||
endDateSelected(date){
|
endDateSelected(date) {
|
||||||
this.formattedBounds.end = this.timeFormatter.format(date);
|
this.formattedBounds.end = this.timeFormatter.format(date);
|
||||||
this.validateAllBounds();
|
this.validateAllBounds();
|
||||||
this.submitForm();
|
this.submitForm();
|
||||||
},
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
|
||||||
|
|
||||||
this.openmct.time.on('bounds', this.setViewFromBounds);
|
|
||||||
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
|
||||||
this.openmct.time.on('clock', this.setViewFromClock);
|
|
||||||
this.openmct.time.on('clockOffsets', this.setViewFromOffsets)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,10 +20,11 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-conductor-axis"
|
<div
|
||||||
ref="axisHolder"
|
ref="axisHolder"
|
||||||
@mousedown="dragStart($event)">
|
class="c-conductor-axis"
|
||||||
</div>
|
@mousedown="dragStart($event)"
|
||||||
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -126,106 +127,9 @@ const PIXELS_PER_TICK_WIDE = 200;
|
|||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
bounds: Object
|
bounds: {
|
||||||
},
|
type: Object,
|
||||||
methods: {
|
required: true
|
||||||
setScale() {
|
|
||||||
let timeSystem = this.openmct.time.timeSystem();
|
|
||||||
let bounds = this.bounds;
|
|
||||||
|
|
||||||
if (timeSystem.isUTCBased) {
|
|
||||||
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
|
|
||||||
} else {
|
|
||||||
this.xScale.domain([bounds.start, bounds.end]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xAxis.scale(this.xScale);
|
|
||||||
|
|
||||||
this.xScale.range([PADDING, this.width - PADDING * 2]);
|
|
||||||
this.axisElement.call(this.xAxis);
|
|
||||||
|
|
||||||
if (this.width > 1800) {
|
|
||||||
this.xAxis.ticks(this.width / PIXELS_PER_TICK_WIDE);
|
|
||||||
} else {
|
|
||||||
this.xAxis.ticks(this.width / PIXELS_PER_TICK);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.msPerPixel = (bounds.end - bounds.start) / this.width;
|
|
||||||
},
|
|
||||||
setViewFromTimeSystem(timeSystem) {
|
|
||||||
let format = this.getActiveFormatter();
|
|
||||||
let bounds = this.openmct.time.bounds();
|
|
||||||
|
|
||||||
//The D3 scale used depends on the type of time system as d3
|
|
||||||
// supports UTC out of the box.
|
|
||||||
if (timeSystem.isUTCBased) {
|
|
||||||
this.xScale = d3Scale.scaleUtc();
|
|
||||||
} else {
|
|
||||||
this.xScale = d3Scale.scaleLinear();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xAxis.scale(this.xScale);
|
|
||||||
this.xAxis.tickFormat(utcMultiTimeFormat);
|
|
||||||
this.axisElement.call(this.xAxis);
|
|
||||||
this.setScale();
|
|
||||||
},
|
|
||||||
getActiveFormatter() {
|
|
||||||
let timeSystem = this.openmct.time.timeSystem();
|
|
||||||
let isFixed = this.openmct.time.clock() === undefined;
|
|
||||||
|
|
||||||
if (isFixed) {
|
|
||||||
return this.getFormatter(timeSystem.timeFormat);
|
|
||||||
} else {
|
|
||||||
return this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getFormatter(key) {
|
|
||||||
return this.openmct.telemetry.getValueFormatter({
|
|
||||||
format: key
|
|
||||||
}).formatter;
|
|
||||||
},
|
|
||||||
dragStart($event){
|
|
||||||
let isFixed = this.openmct.time.clock() === undefined;
|
|
||||||
if (isFixed){
|
|
||||||
this.dragStartX = $event.clientX;
|
|
||||||
|
|
||||||
document.addEventListener('mousemove', this.drag);
|
|
||||||
document.addEventListener('mouseup', this.dragEnd, {
|
|
||||||
once: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
drag($event) {
|
|
||||||
if (!this.dragging){
|
|
||||||
this.dragging = true;
|
|
||||||
requestAnimationFrame(()=>{
|
|
||||||
let deltaX = $event.clientX - this.dragStartX;
|
|
||||||
let percX = deltaX / this.width;
|
|
||||||
let bounds = this.openmct.time.bounds();
|
|
||||||
let deltaTime = bounds.end - bounds.start;
|
|
||||||
let newStart = bounds.start - percX * deltaTime;
|
|
||||||
this.$emit('panAxis',{
|
|
||||||
start: newStart,
|
|
||||||
end: newStart + deltaTime
|
|
||||||
});
|
|
||||||
this.dragging = false;
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.log('Rejected drag due to RAF cap');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dragEnd() {
|
|
||||||
document.removeEventListener('mousemove', this.drag);
|
|
||||||
this.openmct.time.bounds({
|
|
||||||
start: this.bounds.start,
|
|
||||||
end: this.bounds.end
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resize() {
|
|
||||||
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
|
||||||
this.width = this.$refs.axisHolder.clientWidth;
|
|
||||||
this.setScale();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -259,6 +163,103 @@ export default {
|
|||||||
setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setScale() {
|
||||||
|
let timeSystem = this.openmct.time.timeSystem();
|
||||||
|
let bounds = this.bounds;
|
||||||
|
|
||||||
|
if (timeSystem.isUTCBased) {
|
||||||
|
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
|
||||||
|
} else {
|
||||||
|
this.xScale.domain([bounds.start, bounds.end]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xAxis.scale(this.xScale);
|
||||||
|
|
||||||
|
this.xScale.range([PADDING, this.width - PADDING * 2]);
|
||||||
|
this.axisElement.call(this.xAxis);
|
||||||
|
|
||||||
|
if (this.width > 1800) {
|
||||||
|
this.xAxis.ticks(this.width / PIXELS_PER_TICK_WIDE);
|
||||||
|
} else {
|
||||||
|
this.xAxis.ticks(this.width / PIXELS_PER_TICK);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.msPerPixel = (bounds.end - bounds.start) / this.width;
|
||||||
|
},
|
||||||
|
setViewFromTimeSystem(timeSystem) {
|
||||||
|
//The D3 scale used depends on the type of time system as d3
|
||||||
|
// supports UTC out of the box.
|
||||||
|
if (timeSystem.isUTCBased) {
|
||||||
|
this.xScale = d3Scale.scaleUtc();
|
||||||
|
} else {
|
||||||
|
this.xScale = d3Scale.scaleLinear();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xAxis.scale(this.xScale);
|
||||||
|
this.xAxis.tickFormat(utcMultiTimeFormat);
|
||||||
|
this.axisElement.call(this.xAxis);
|
||||||
|
this.setScale();
|
||||||
|
},
|
||||||
|
getActiveFormatter() {
|
||||||
|
let timeSystem = this.openmct.time.timeSystem();
|
||||||
|
let isFixed = this.openmct.time.clock() === undefined;
|
||||||
|
|
||||||
|
if (isFixed) {
|
||||||
|
return this.getFormatter(timeSystem.timeFormat);
|
||||||
|
} else {
|
||||||
|
return this.getFormatter(timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getFormatter(key) {
|
||||||
|
return this.openmct.telemetry.getValueFormatter({
|
||||||
|
format: key
|
||||||
|
}).formatter;
|
||||||
|
},
|
||||||
|
dragStart($event) {
|
||||||
|
let isFixed = this.openmct.time.clock() === undefined;
|
||||||
|
if (isFixed) {
|
||||||
|
this.dragStartX = $event.clientX;
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', this.drag);
|
||||||
|
document.addEventListener('mouseup', this.dragEnd, {
|
||||||
|
once: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
drag($event) {
|
||||||
|
if (!this.dragging) {
|
||||||
|
this.dragging = true;
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
let deltaX = $event.clientX - this.dragStartX;
|
||||||
|
let percX = deltaX / this.width;
|
||||||
|
let bounds = this.openmct.time.bounds();
|
||||||
|
let deltaTime = bounds.end - bounds.start;
|
||||||
|
let newStart = bounds.start - percX * deltaTime;
|
||||||
|
this.$emit('panAxis',{
|
||||||
|
start: newStart,
|
||||||
|
end: newStart + deltaTime
|
||||||
|
});
|
||||||
|
this.dragging = false;
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('Rejected drag due to RAF cap');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dragEnd() {
|
||||||
|
document.removeEventListener('mousemove', this.drag);
|
||||||
|
this.openmct.time.bounds({
|
||||||
|
start: this.bounds.start,
|
||||||
|
end: this.bounds.end
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resize() {
|
||||||
|
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
||||||
|
this.width = this.$refs.axisHolder.clientWidth;
|
||||||
|
this.setScale();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,33 +20,43 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
|
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
|
||||||
<button class="c-button--menu c-mode-button"
|
<button
|
||||||
@click.prevent="toggle">
|
class="c-button--menu c-mode-button"
|
||||||
<span class="c-button__label">{{selectedMode.name}}</span>
|
@click.prevent="toggle"
|
||||||
</button>
|
>
|
||||||
<div class="c-menu c-super-menu c-conductor__mode-menu"
|
<span class="c-button__label">{{ selectedMode.name }}</span>
|
||||||
v-if="open">
|
</button>
|
||||||
<div class="c-super-menu__menu">
|
<div
|
||||||
<ul>
|
v-if="open"
|
||||||
<li v-for="mode in modes"
|
class="c-menu c-super-menu c-conductor__mode-menu"
|
||||||
:key="mode.key"
|
>
|
||||||
@click="setOption(mode)"
|
<div class="c-super-menu__menu">
|
||||||
@mouseover="hoveredMode = mode"
|
<ul>
|
||||||
@mouseleave="hoveredMode = {}"
|
<li
|
||||||
class="menu-item-a"
|
v-for="mode in modes"
|
||||||
:class="mode.cssClass">
|
:key="mode.key"
|
||||||
{{mode.name}}
|
class="menu-item-a"
|
||||||
</li>
|
:class="mode.cssClass"
|
||||||
</ul>
|
@click="setOption(mode)"
|
||||||
|
@mouseover="hoveredMode = mode"
|
||||||
|
@mouseleave="hoveredMode = {}"
|
||||||
|
>
|
||||||
|
{{ mode.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="c-super-menu__item-description">
|
||||||
|
<div :class="['l-item-description__icon', 'bg-' + hoveredMode.cssClass]"></div>
|
||||||
|
<div class="l-item-description__name">
|
||||||
|
{{ hoveredMode.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="c-super-menu__item-description">
|
<div class="l-item-description__description">
|
||||||
<div :class="['l-item-description__icon', 'bg-' + hoveredMode.cssClass]"></div>
|
{{ hoveredMode.description }}
|
||||||
<div class="l-item-description__name">{{hoveredMode.name}}</div>
|
|
||||||
<div class="l-item-description__description">{{hoveredMode.description}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -87,6 +97,14 @@ export default {
|
|||||||
hoveredMode: {}
|
hoveredMode: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.loadClocksFromConfiguration();
|
||||||
|
|
||||||
|
this.openmct.time.on('clock', this.setViewFromClock);
|
||||||
|
},
|
||||||
|
destroyed: function () {
|
||||||
|
this.openmct.time.off('clock', this.setViewFromClock);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadClocksFromConfiguration() {
|
loadClocksFromConfiguration() {
|
||||||
let clocks = this.configuration.menuOptions
|
let clocks = this.configuration.menuOptions
|
||||||
@ -180,14 +198,6 @@ export default {
|
|||||||
setViewFromClock(clock) {
|
setViewFromClock(clock) {
|
||||||
this.selectedMode = this.getModeOptionForClock(clock);
|
this.selectedMode = this.getModeOptionForClock(clock);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
this.loadClocksFromConfiguration();
|
|
||||||
|
|
||||||
this.openmct.time.on('clock', this.setViewFromClock);
|
|
||||||
},
|
|
||||||
destroyed: function () {
|
|
||||||
this.openmct.time.off('clock', this.setViewFromClock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-clock-symbol">
|
<div class="c-clock-symbol">
|
||||||
<div class="hand-little"></div>
|
<div class="hand-little"></div>
|
||||||
<div class="hand-big"></div>
|
<div class="hand-big"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -20,24 +20,33 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up"
|
<div
|
||||||
v-if="selectedTimeSystem.name">
|
v-if="selectedTimeSystem.name"
|
||||||
<button class="c-button--menu c-time-system-button"
|
class="c-ctrl-wrapper c-ctrl-wrapper--menus-up"
|
||||||
:class="selectedTimeSystem.cssClass"
|
>
|
||||||
@click.prevent="toggle">
|
<button
|
||||||
<span class="c-button__label">{{selectedTimeSystem.name}}</span>
|
class="c-button--menu c-time-system-button"
|
||||||
</button>
|
:class="selectedTimeSystem.cssClass"
|
||||||
<div class="c-menu" v-if="open">
|
@click.prevent="toggle"
|
||||||
<ul>
|
>
|
||||||
<li @click="setTimeSystemFromView(timeSystem)"
|
<span class="c-button__label">{{ selectedTimeSystem.name }}</span>
|
||||||
v-for="timeSystem in timeSystems"
|
</button>
|
||||||
:key="timeSystem.key"
|
<div
|
||||||
:class="timeSystem.cssClass">
|
v-if="open"
|
||||||
{{timeSystem.name}}
|
class="c-menu"
|
||||||
</li>
|
>
|
||||||
</ul>
|
<ul>
|
||||||
</div>
|
<li
|
||||||
|
v-for="timeSystem in timeSystems"
|
||||||
|
:key="timeSystem.key"
|
||||||
|
:class="timeSystem.cssClass"
|
||||||
|
@click="setTimeSystemFromView(timeSystem)"
|
||||||
|
>
|
||||||
|
{{ timeSystem.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -54,6 +63,14 @@ export default {
|
|||||||
timeSystems: this.getValidTimesystemsForClock(activeClock)
|
timeSystems: this.getValidTimesystemsForClock(activeClock)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.openmct.time.on('timeSystem', this.setViewFromTimeSystem);
|
||||||
|
this.openmct.time.on('clock', this.setViewFromClock);
|
||||||
|
},
|
||||||
|
destroyed: function () {
|
||||||
|
this.openmct.time.off('timeSystem', this.setViewFromTimeSystem);
|
||||||
|
this.openmct.time.on('clock', this.setViewFromClock);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getValidTimesystemsForClock(clock) {
|
getValidTimesystemsForClock(clock) {
|
||||||
return this.configuration.menuOptions
|
return this.configuration.menuOptions
|
||||||
@ -111,14 +128,6 @@ export default {
|
|||||||
let activeClock = this.openmct.time.clock();
|
let activeClock = this.openmct.time.clock();
|
||||||
this.timeSystems = this.getValidTimesystemsForClock(activeClock);
|
this.timeSystems = this.getValidTimesystemsForClock(activeClock);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
this.openmct.time.on('timeSystem', this.setViewFromTimeSystem);
|
|
||||||
this.openmct.time.on('clock', this.setViewFromClock);
|
|
||||||
},
|
|
||||||
destroyed: function () {
|
|
||||||
this.openmct.time.off('timeSystem', this.setViewFromTimeSystem);
|
|
||||||
this.openmct.time.on('clock', this.setViewFromClock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,41 +20,68 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up c-datetime-picker__wrapper" ref="calendarHolder">
|
<div
|
||||||
<a class="c-icon-button icon-calendar"
|
ref="calendarHolder"
|
||||||
@click="toggle"></a>
|
class="c-ctrl-wrapper c-ctrl-wrapper--menus-up c-datetime-picker__wrapper"
|
||||||
<div class="c-menu c-menu--mobile-modal c-datetime-picker"
|
>
|
||||||
v-if="open">
|
<a
|
||||||
<div class="c-datetime-picker__close-button">
|
class="c-icon-button icon-calendar"
|
||||||
<button class="c-click-icon icon-x-in-circle"
|
@click="toggle"
|
||||||
@click="toggle"></button>
|
></a>
|
||||||
</div>
|
<div
|
||||||
<div class="c-datetime-picker__pager c-pager l-month-year-pager">
|
v-if="open"
|
||||||
<div class="c-pager__prev c-icon-button icon-arrow-left"
|
class="c-menu c-menu--mobile-modal c-datetime-picker"
|
||||||
@click.stop="changeMonth(-1)"></div>
|
>
|
||||||
<div class="c-pager__month-year">{{model.month}} {{model.year}}</div>
|
<div class="c-datetime-picker__close-button">
|
||||||
<div class="c-pager__next c-icon-button icon-arrow-right"
|
<button
|
||||||
@click.stop="changeMonth(1)"></div>
|
class="c-click-icon icon-x-in-circle"
|
||||||
</div>
|
@click="toggle"
|
||||||
<div class="c-datetime-picker__calendar c-calendar">
|
></button>
|
||||||
<ul class="c-calendar__row--header l-cal-row">
|
</div>
|
||||||
<li v-for="day in ['Su','Mo','Tu','We','Th','Fr','Sa']"
|
<div class="c-datetime-picker__pager c-pager l-month-year-pager">
|
||||||
:key="day">{{day}}</li>
|
<div
|
||||||
</ul>
|
class="c-pager__prev c-icon-button icon-arrow-left"
|
||||||
<ul class="c-calendar__row--body"
|
@click.stop="changeMonth(-1)"
|
||||||
v-for="(row, index) in table"
|
></div>
|
||||||
:key="index">
|
<div class="c-pager__month-year">
|
||||||
<li v-for="(cell, index) in row"
|
{{ model.month }} {{ model.year }}
|
||||||
:key="index"
|
|
||||||
@click="select(cell)"
|
|
||||||
:class="{ 'is-in-month': isInCurrentMonth(cell), selected: isSelected(cell) }">
|
|
||||||
<div class="c-calendar__day--prime">{{cell.day}}</div>
|
|
||||||
<div class="c-calendar__day--sub">{{cell.dayOfYear}}</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="c-pager__next c-icon-button icon-arrow-right"
|
||||||
|
@click.stop="changeMonth(1)"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="c-datetime-picker__calendar c-calendar">
|
||||||
|
<ul class="c-calendar__row--header l-cal-row">
|
||||||
|
<li
|
||||||
|
v-for="day in ['Su','Mo','Tu','We','Th','Fr','Sa']"
|
||||||
|
:key="day"
|
||||||
|
>
|
||||||
|
{{ day }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul
|
||||||
|
v-for="(row, tableIndex) in table"
|
||||||
|
:key="tableIndex"
|
||||||
|
class="c-calendar__row--body"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-for="(cell, rowIndex) in row"
|
||||||
|
:key="rowIndex"
|
||||||
|
:class="{ 'is-in-month': isInCurrentMonth(cell), selected: isSelected(cell) }"
|
||||||
|
@click="select(cell)"
|
||||||
|
>
|
||||||
|
<div class="c-calendar__day--prime">
|
||||||
|
{{ cell.day }}
|
||||||
|
</div>
|
||||||
|
<div class="c-calendar__day--sub">
|
||||||
|
{{ cell.dayOfYear }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -163,10 +190,10 @@ import moment from 'moment';
|
|||||||
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
import toggleMixin from '../../ui/mixins/toggle-mixin';
|
||||||
|
|
||||||
const TIME_NAMES = {
|
const TIME_NAMES = {
|
||||||
'hours': "Hour",
|
'hours': "Hour",
|
||||||
'minutes': "Minute",
|
'minutes': "Minute",
|
||||||
'seconds': "Second"
|
'seconds': "Second"
|
||||||
};
|
};
|
||||||
const MONTHS = moment.months();
|
const MONTHS = moment.months();
|
||||||
const TIME_OPTIONS = (function makeRanges() {
|
const TIME_OPTIONS = (function makeRanges() {
|
||||||
let arr = [];
|
let arr = [];
|
||||||
@ -184,8 +211,14 @@ export default {
|
|||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
mixins: [toggleMixin],
|
mixins: [toggleMixin],
|
||||||
props: {
|
props: {
|
||||||
defaultDateTime: String,
|
defaultDateTime: {
|
||||||
formatter: Object
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
formatter: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
@ -196,13 +229,17 @@ export default {
|
|||||||
},
|
},
|
||||||
model: {
|
model: {
|
||||||
year: undefined,
|
year: undefined,
|
||||||
month: undefined,
|
month: undefined
|
||||||
},
|
},
|
||||||
table: undefined,
|
table: undefined,
|
||||||
date: undefined,
|
date: undefined,
|
||||||
time: undefined
|
time: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.updateFromModel(this.defaultDateTime);
|
||||||
|
this.updateViewForMonth();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
generateTable() {
|
generateTable() {
|
||||||
let m = moment.utc({ year: this.picker.year, month: this.picker.month }).day(0),
|
let m = moment.utc({ year: this.picker.year, month: this.picker.month }).day(0),
|
||||||
@ -233,9 +270,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateFromModel(defaultDateTime) {
|
updateFromModel(defaultDateTime) {
|
||||||
let m;
|
let m = moment.utc(defaultDateTime);
|
||||||
|
|
||||||
m = moment.utc(defaultDateTime);
|
|
||||||
|
|
||||||
this.date = {
|
this.date = {
|
||||||
year: m.year(),
|
year: m.year(),
|
||||||
@ -314,11 +349,7 @@ export default {
|
|||||||
|
|
||||||
optionsFor(key) {
|
optionsFor(key) {
|
||||||
return TIME_OPTIONS[key];
|
return TIME_OPTIONS[key];
|
||||||
},
|
}
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
this.updateFromModel(this.defaultDateTime);
|
|
||||||
this.updateViewForMonth();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -37,6 +37,7 @@ export default function WebPage(openmct) {
|
|||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
WebPageComponent: WebPageComponent
|
WebPageComponent: WebPageComponent
|
||||||
},
|
},
|
||||||
@ -44,7 +45,6 @@ export default function WebPage(openmct) {
|
|||||||
openmct,
|
openmct,
|
||||||
domainObject
|
domainObject
|
||||||
},
|
},
|
||||||
el: element,
|
|
||||||
template: '<web-page-component></web-page-component>'
|
template: '<web-page-component></web-page-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-iframe abs">
|
<div class="l-iframe abs">
|
||||||
<iframe :src="currentDomainObject.url"></iframe>
|
<iframe :src="currentDomainObject.url"></iframe>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -20,34 +20,40 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-so-view has-local-controls"
|
<div
|
||||||
:class="{
|
class="c-so-view has-local-controls"
|
||||||
'c-so-view--no-frame': !hasFrame,
|
:class="{
|
||||||
'has-complex-content': complexContent
|
'c-so-view--no-frame': !hasFrame,
|
||||||
}">
|
'has-complex-content': complexContent
|
||||||
<div class="c-so-view__header">
|
}"
|
||||||
<div class="c-so-view__header__icon" :class="cssClass"></div>
|
>
|
||||||
<div class="c-so-view__header__name">
|
<div class="c-so-view__header">
|
||||||
{{ domainObject && domainObject.name }}
|
<div
|
||||||
</div>
|
class="c-so-view__header__icon"
|
||||||
<context-menu-drop-down
|
:class="cssClass"
|
||||||
:object-path="objectPath">
|
></div>
|
||||||
</context-menu-drop-down>
|
<div class="c-so-view__header__name">
|
||||||
|
{{ domainObject && domainObject.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="c-so-view__local-controls c-so-view__view-large h-local-controls c-local-controls--show-on-hover">
|
<context-menu-drop-down
|
||||||
<button class="c-button icon-expand"
|
:object-path="objectPath"
|
||||||
title="View Large"
|
/>
|
||||||
@click="expand">
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<object-view
|
|
||||||
class="c-so-view__object-view"
|
|
||||||
ref="objectView"
|
|
||||||
:object="domainObject"
|
|
||||||
:show-edit-view="showEditView"
|
|
||||||
:object-path="objectPath">
|
|
||||||
</object-view>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="c-so-view__local-controls c-so-view__view-large h-local-controls c-local-controls--show-on-hover">
|
||||||
|
<button
|
||||||
|
class="c-button icon-expand"
|
||||||
|
title="View Large"
|
||||||
|
@click="expand"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<object-view
|
||||||
|
ref="objectView"
|
||||||
|
class="c-so-view__object-view"
|
||||||
|
:object="domainObject"
|
||||||
|
:show-edit-view="showEditView"
|
||||||
|
:object-path="objectPath"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -131,58 +137,64 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ObjectView from './ObjectView.vue'
|
import ObjectView from './ObjectView.vue'
|
||||||
import ContextMenuDropDown from './contextMenuDropDown.vue';
|
import ContextMenuDropDown from './contextMenuDropDown.vue';
|
||||||
|
|
||||||
const SIMPLE_CONTENT_TYPES = [
|
const SIMPLE_CONTENT_TYPES = [
|
||||||
'clock',
|
'clock',
|
||||||
'timer',
|
'timer',
|
||||||
'summary-widget',
|
'summary-widget',
|
||||||
'hyperlink'
|
'hyperlink'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
components: {
|
||||||
domainObject: Object,
|
ObjectView,
|
||||||
objectPath: Array,
|
ContextMenuDropDown
|
||||||
hasFrame: Boolean,
|
},
|
||||||
showEditView: {
|
props: {
|
||||||
type: Boolean,
|
domainObject: {
|
||||||
default: () => true
|
type: Object,
|
||||||
}
|
required: true
|
||||||
},
|
},
|
||||||
components: {
|
objectPath: {
|
||||||
ObjectView,
|
type: Array,
|
||||||
ContextMenuDropDown,
|
required: true
|
||||||
},
|
},
|
||||||
methods: {
|
hasFrame: Boolean,
|
||||||
expand() {
|
showEditView: {
|
||||||
let objectView = this.$refs.objectView,
|
type: Boolean,
|
||||||
parentElement = objectView.$el,
|
default: true
|
||||||
childElement = parentElement.children[0];
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
let objectType = this.openmct.types.get(this.domainObject.type),
|
||||||
|
cssClass = objectType && objectType.definition ? objectType.definition.cssClass : 'icon-object-unknown',
|
||||||
|
complexContent = !SIMPLE_CONTENT_TYPES.includes(this.domainObject.type);
|
||||||
|
|
||||||
this.openmct.overlays.overlay({
|
return {
|
||||||
element: childElement,
|
cssClass,
|
||||||
size: 'large',
|
complexContent
|
||||||
onDestroy() {
|
}
|
||||||
parentElement.append(childElement);
|
},
|
||||||
}
|
methods: {
|
||||||
});
|
expand() {
|
||||||
},
|
let objectView = this.$refs.objectView,
|
||||||
getSelectionContext() {
|
parentElement = objectView.$el,
|
||||||
return this.$refs.objectView.getSelectionContext();
|
childElement = parentElement.children[0];
|
||||||
}
|
|
||||||
|
this.openmct.overlays.overlay({
|
||||||
|
element: childElement,
|
||||||
|
size: 'large',
|
||||||
|
onDestroy() {
|
||||||
|
parentElement.append(childElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
data() {
|
getSelectionContext() {
|
||||||
let objectType = this.openmct.types.get(this.domainObject.type),
|
return this.$refs.objectView.getSelectionContext();
|
||||||
cssClass = objectType && objectType.definition ? objectType.definition.cssClass : 'icon-object-unknown',
|
|
||||||
complexContent = !SIMPLE_CONTENT_TYPES.includes(this.domainObject.type);
|
|
||||||
|
|
||||||
return {
|
|
||||||
cssClass,
|
|
||||||
complexContent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<a class="c-tree__item__label c-object-label"
|
<a
|
||||||
|
class="c-tree__item__label c-object-label"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
|
:href="objectLink"
|
||||||
@dragstart="dragStart"
|
@dragstart="dragStart"
|
||||||
@click="navigateOrPreview"
|
@click="navigateOrPreview"
|
||||||
:href="objectLink">
|
>
|
||||||
<div class="c-tree__item__type-icon c-object-label__type-icon"
|
<div
|
||||||
:class="typeClass"></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">{{ observedObject.name }}</div>
|
<div class="c-tree__item__name c-object-label__name">{{ observedObject.name }}</div>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
@ -53,29 +57,24 @@ export default {
|
|||||||
mixins: [ObjectLink, ContextMenuGesture],
|
mixins: [ObjectLink, ContextMenuGesture],
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
domainObject: Object,
|
domainObject: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
objectPath: {
|
objectPath: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
required: true
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
navigateToPath: String
|
navigateToPath: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
observedObject: this.domainObject
|
observedObject: this.domainObject
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
if (this.observedObject) {
|
|
||||||
let removeListener = this.openmct.objects.observe(this.observedObject, '*', (newObject) => {
|
|
||||||
this.observedObject = newObject;
|
|
||||||
});
|
|
||||||
this.$once('hook:destroyed', removeListener);
|
|
||||||
}
|
|
||||||
this.previewAction = new PreviewAction(this.openmct);
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
typeClass() {
|
typeClass() {
|
||||||
let type = this.openmct.types.get(this.observedObject.type);
|
let type = this.openmct.types.get(this.observedObject.type);
|
||||||
@ -85,15 +84,24 @@ export default {
|
|||||||
return type.definition.cssClass;
|
return type.definition.cssClass;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.observedObject) {
|
||||||
|
let removeListener = this.openmct.objects.observe(this.observedObject, '*', (newObject) => {
|
||||||
|
this.observedObject = newObject;
|
||||||
|
});
|
||||||
|
this.$once('hook:destroyed', removeListener);
|
||||||
|
}
|
||||||
|
this.previewAction = new PreviewAction(this.openmct);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
navigateOrPreview(event) {
|
navigateOrPreview(event) {
|
||||||
if (this.openmct.editor.isEditing()){
|
if (this.openmct.editor.isEditing()) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.preview();
|
this.preview();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
preview() {
|
preview() {
|
||||||
if (this.previewAction.appliesTo(this.objectPath)){
|
if (this.previewAction.appliesTo(this.objectPath)) {
|
||||||
this.previewAction.invoke(this.objectPath);
|
this.previewAction.invoke(this.objectPath);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -7,10 +8,23 @@ import _ from "lodash"
|
|||||||
export default {
|
export default {
|
||||||
inject: ["openmct"],
|
inject: ["openmct"],
|
||||||
props: {
|
props: {
|
||||||
view: String,
|
object: {
|
||||||
object: Object,
|
type: Object,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
showEditView: Boolean,
|
showEditView: Boolean,
|
||||||
objectPath: Array
|
objectPath: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
object(newObject, oldObject) {
|
||||||
|
this.currentObject = newObject;
|
||||||
|
this.debounceUpdateView();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.clear();
|
this.clear();
|
||||||
@ -18,16 +32,6 @@ export default {
|
|||||||
this.releaseEditModeHandler();
|
this.releaseEditModeHandler();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
view(newView, oldView) {
|
|
||||||
this.viewKey = newView;
|
|
||||||
this.debounceUpdateView();
|
|
||||||
},
|
|
||||||
object(newObject, oldObject) {
|
|
||||||
this.currentObject = newObject;
|
|
||||||
this.debounceUpdateView();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
created() {
|
||||||
this.debounceUpdateView = _.debounce(this.updateView, 10);
|
this.debounceUpdateView = _.debounce(this.updateView, 10);
|
||||||
},
|
},
|
||||||
@ -114,7 +118,7 @@ export default {
|
|||||||
this.currentView.show(this.viewContainer, this.openmct.editor.isEditing());
|
this.currentView.show(this.viewContainer, this.openmct.editor.isEditing());
|
||||||
|
|
||||||
if (immediatelySelect) {
|
if (immediatelySelect) {
|
||||||
this.removeSelectable = openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.getSelectionContext(), true);
|
this.$el, this.getSelectionContext(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +194,7 @@ export default {
|
|||||||
provider.canEdit &&
|
provider.canEdit &&
|
||||||
provider.canEdit(this.currentObject) &&
|
provider.canEdit(this.currentObject) &&
|
||||||
!this.openmct.editor.isEditing()) {
|
!this.openmct.editor.isEditing()) {
|
||||||
this.openmct.editor.edit();
|
this.openmct.editor.edit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasComposableDomainObject(event) {
|
hasComposableDomainObject(event) {
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-progress-bar">
|
<div class="c-progress-bar">
|
||||||
<div class="c-progress-bar__holder">
|
<div class="c-progress-bar__holder">
|
||||||
<div class="c-progress-bar__bar"
|
<div
|
||||||
:class="{'--indeterminate': model.progressPerc === 'unknown'}"
|
class="c-progress-bar__bar"
|
||||||
:style="`width: ${model.progressPerc}%;`">
|
:class="{'--indeterminate': model.progressPerc === 'unknown'}"
|
||||||
</div>
|
:style="styleBarWidth"
|
||||||
</div>
|
></div>
|
||||||
<div class="c-progress-bar__text"
|
|
||||||
v-if="model.progressText !== undefined">
|
|
||||||
<span v-if="model.progressPerc > 0">{{model.progressPerc}}% complete.</span>
|
|
||||||
{{model.progressText}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="model.progressText !== undefined"
|
||||||
|
class="c-progress-bar__text"
|
||||||
|
>
|
||||||
|
<span v-if="model.progressPerc > 0">{{ model.progressPerc }}% complete.</span>
|
||||||
|
{{ model.progressText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -64,6 +67,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props:['model']
|
props: {
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
styleBarWidth() {
|
||||||
|
return `width: ${this.model.progressPerc}%;`
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<label class="c-toggle-switch">
|
<label class="c-toggle-switch">
|
||||||
<input type="checkbox"
|
<input
|
||||||
:id="id"
|
:id="id"
|
||||||
:checked="checked"
|
type="checkbox"
|
||||||
@change="onUserSelect($event)"/>
|
:checked="checked"
|
||||||
<span class="c-toggle-switch__slider"></span>
|
@change="onUserSelect($event)"
|
||||||
</label>
|
>
|
||||||
|
<span class="c-toggle-switch__slider"></span>
|
||||||
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -63,16 +65,19 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
id: String,
|
id: {
|
||||||
checked: Boolean
|
type: String,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
methods: {
|
checked: Boolean
|
||||||
onUserSelect(event) {
|
},
|
||||||
this.$emit('change', event.target.checked);
|
methods: {
|
||||||
}
|
onUserSelect(event) {
|
||||||
|
this.$emit('change', event.target.checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@ -1,14 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-so-view__context-actions c-disclosure-button"
|
<div
|
||||||
@click="showContextMenu"></div>
|
class="c-so-view__context-actions c-disclosure-button"
|
||||||
|
@click="showContextMenu"
|
||||||
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import contextMenu from '../mixins/context-menu-gesture'
|
import contextMenu from '../mixins/context-menu-gesture'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['objectPath'],
|
|
||||||
mixins: [contextMenu],
|
mixins: [contextMenu],
|
||||||
|
props: {
|
||||||
|
objectPath: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-search"
|
<div
|
||||||
:class="{ 'is-active': active === true }">
|
class="c-search"
|
||||||
<input class="c-search__input"
|
:class="{ 'is-active': active === true }"
|
||||||
tabindex="10000"
|
>
|
||||||
type="search"
|
<input
|
||||||
v-bind="$attrs"
|
class="c-search__input"
|
||||||
v-bind:value="value"
|
tabindex="10000"
|
||||||
v-on="inputListeners"/>
|
type="search"
|
||||||
<a class="c-search__clear-input icon-x-in-circle"
|
v-bind="$attrs"
|
||||||
v-on:click="clearInput"></a>
|
:value="value"
|
||||||
</div>
|
v-on="inputListeners"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="c-search__clear-input icon-x-in-circle"
|
||||||
|
@click="clearInput"
|
||||||
|
></a>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -44,37 +50,40 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* Emits input and clear events */
|
/* Emits input and clear events */
|
||||||
export default {
|
export default {
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: {
|
props: {
|
||||||
value: String
|
value: {
|
||||||
},
|
type: String,
|
||||||
computed: {
|
default: ''
|
||||||
inputListeners: function () {
|
}
|
||||||
let vm = this;
|
},
|
||||||
return Object.assign({},
|
data: function () {
|
||||||
this.$listeners,
|
return {
|
||||||
{
|
active: false
|
||||||
input: function (event) {
|
}
|
||||||
vm.$emit('input', event.target.value);
|
},
|
||||||
vm.active = (event.target.value.length > 0);
|
computed: {
|
||||||
}
|
inputListeners: function () {
|
||||||
|
let vm = this;
|
||||||
|
return Object.assign({},
|
||||||
|
this.$listeners,
|
||||||
|
{
|
||||||
|
input: function (event) {
|
||||||
|
vm.$emit('input', event.target.value);
|
||||||
|
vm.active = (event.target.value.length > 0);
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
},
|
}
|
||||||
data: function() {
|
},
|
||||||
return {
|
methods: {
|
||||||
active: false
|
clearInput() {
|
||||||
}
|
// Clear the user's input and set 'active' to false
|
||||||
},
|
this.$emit('clear','');
|
||||||
methods: {
|
this.active = false;
|
||||||
clearInput() {
|
|
||||||
// Clear the user's input and set 'active' to false
|
|
||||||
this.$emit('clear','');
|
|
||||||
this.active = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="c-disclosure-triangle"
|
<span
|
||||||
|
class="c-disclosure-triangle"
|
||||||
:class="{
|
:class="{
|
||||||
'c-disclosure-triangle--expanded' : value,
|
'c-disclosure-triangle--expanded' : value,
|
||||||
'is-enabled' : enabled
|
'is-enabled' : enabled
|
||||||
}"
|
}"
|
||||||
@click="$emit('input', !value)"></span>
|
@click="$emit('input', !value)"
|
||||||
|
></span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
enabled: {
|
enabled: {
|
||||||
// Provided to allow the view-control to still occupy space without displaying a control icon.
|
// Provided to allow the view-control to still occupy space without displaying a control icon.
|
||||||
// Used as such in the tree - when a node doesn't have children, set disabled to true.
|
// Used as such in the tree - when a node doesn't have children, set disabled to true.
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,29 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-elements-pool">
|
<div class="c-elements-pool">
|
||||||
<Search class="c-elements-pool__search"
|
<Search
|
||||||
|
class="c-elements-pool__search"
|
||||||
:value="currentSearch"
|
:value="currentSearch"
|
||||||
@input="applySearch"
|
@input="applySearch"
|
||||||
@clear="applySearch">
|
@clear="applySearch"
|
||||||
</Search>
|
/>
|
||||||
<div class="c-elements-pool__elements"
|
<div
|
||||||
:class="{'is-dragging': isDragging}">
|
class="c-elements-pool__elements"
|
||||||
<ul class="c-tree c-elements-pool__tree" id="inspector-elements-tree"
|
:class="{'is-dragging': isDragging}"
|
||||||
v-if="elements.length > 0">
|
>
|
||||||
<li :key="element.identifier.key" v-for="(element, index) in elements"
|
<ul
|
||||||
|
v-if="elements.length > 0"
|
||||||
|
id="inspector-elements-tree"
|
||||||
|
class="c-tree c-elements-pool__tree"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-for="(element, index) in elements"
|
||||||
|
:key="element.identifier.key"
|
||||||
@drop="moveTo(index)"
|
@drop="moveTo(index)"
|
||||||
@dragover="allowDrop">
|
@dragover="allowDrop"
|
||||||
<div class="c-tree__item c-elements-pool__item"
|
>
|
||||||
draggable="true"
|
<div
|
||||||
@dragstart="moveFrom(index)">
|
class="c-tree__item c-elements-pool__item"
|
||||||
<span class="c-elements-pool__grippy"
|
draggable="true"
|
||||||
v-if="elements.length > 1 && isEditing">
|
@dragstart="moveFrom(index)"
|
||||||
</span>
|
>
|
||||||
<object-label :domainObject="element" :objectPath="[element, parentObject]"></object-label>
|
<span
|
||||||
|
v-if="elements.length > 1 && isEditing"
|
||||||
|
class="c-elements-pool__grippy"
|
||||||
|
></span>
|
||||||
|
<object-label
|
||||||
|
:domain-object="element"
|
||||||
|
:object-path="[element, parentObject]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="js-last-place" @drop="moveToIndex(elements.length)"></li>
|
<li
|
||||||
|
class="js-last-place"
|
||||||
|
@drop="moveToIndex(elements.length)"
|
||||||
|
></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div v-if="elements.length === 0">No contained elements</div>
|
<div v-if="elements.length === 0">
|
||||||
|
No contained elements
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -89,12 +109,23 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let selection = this.openmct.selection.get();
|
let selection = this.openmct.selection.get();
|
||||||
if (selection && selection.length > 0){
|
if (selection && selection.length > 0) {
|
||||||
this.showSelection(selection);
|
this.showSelection(selection);
|
||||||
}
|
}
|
||||||
this.openmct.selection.on('change', this.showSelection);
|
this.openmct.selection.on('change', this.showSelection);
|
||||||
this.openmct.editor.on('isEditing', this.setEditState);
|
this.openmct.editor.on('isEditing', this.setEditState);
|
||||||
},
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.editor.off('isEditing', this.setEditState);
|
||||||
|
this.openmct.selection.off('change', this.showSelection);
|
||||||
|
|
||||||
|
if (this.mutationUnobserver) {
|
||||||
|
this.mutationUnobserver();
|
||||||
|
}
|
||||||
|
if (this.compositionUnlistener) {
|
||||||
|
this.compositionUnlistener();
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setEditState(isEditing) {
|
setEditState(isEditing) {
|
||||||
this.isEditing = isEditing;
|
this.isEditing = isEditing;
|
||||||
@ -168,7 +199,7 @@ export default {
|
|||||||
moveTo(moveToIndex) {
|
moveTo(moveToIndex) {
|
||||||
this.composition.reorder(this.moveFromIndex, moveToIndex);
|
this.composition.reorder(this.moveFromIndex, moveToIndex);
|
||||||
},
|
},
|
||||||
moveFrom(index){
|
moveFrom(index) {
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
this.moveFromIndex = index;
|
this.moveFromIndex = index;
|
||||||
document.addEventListener('dragend', this.hideDragStyling);
|
document.addEventListener('dragend', this.hideDragStyling);
|
||||||
@ -177,17 +208,6 @@ export default {
|
|||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
document.removeEventListener('dragend', this.hideDragStyling);
|
document.removeEventListener('dragend', this.hideDragStyling);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.openmct.editor.off('isEditing', this.setEditState);
|
|
||||||
this.openmct.selection.off('change', this.showSelection);
|
|
||||||
|
|
||||||
if (this.mutationUnobserver) {
|
|
||||||
this.mutationUnobserver();
|
|
||||||
}
|
|
||||||
if (this.compositionUnlistener) {
|
|
||||||
this.compositionUnlistener();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<multipane class="c-inspector"
|
<multipane
|
||||||
type="vertical">
|
class="c-inspector"
|
||||||
<pane class="c-inspector__properties">
|
type="vertical"
|
||||||
<properties></properties>
|
>
|
||||||
<location></location>
|
<pane class="c-inspector__properties">
|
||||||
<inspector-views></inspector-views>
|
<properties />
|
||||||
</pane>
|
<location />
|
||||||
<pane class="c-inspector__elements"
|
<inspector-views />
|
||||||
handle="before"
|
</pane>
|
||||||
label="Elements" v-if="isEditing && hasComposition">
|
<pane
|
||||||
<elements></elements>
|
v-if="isEditing && hasComposition"
|
||||||
</pane>
|
class="c-inspector__elements"
|
||||||
</multipane>
|
handle="before"
|
||||||
|
label="Elements"
|
||||||
|
>
|
||||||
|
<elements />
|
||||||
|
</pane>
|
||||||
|
</multipane>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -174,46 +179,46 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import multipane from '../layout/multipane.vue';
|
import multipane from '../layout/multipane.vue';
|
||||||
import pane from '../layout/pane.vue';
|
import pane from '../layout/pane.vue';
|
||||||
import Elements from './Elements.vue';
|
import Elements from './Elements.vue';
|
||||||
import Location from './Location.vue';
|
import Location from './Location.vue';
|
||||||
import Properties from './Properties.vue';
|
import Properties from './Properties.vue';
|
||||||
import InspectorViews from './InspectorViews.vue';
|
import InspectorViews from './InspectorViews.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
components: {
|
||||||
'isEditing': Boolean
|
multipane,
|
||||||
},
|
pane,
|
||||||
components: {
|
Elements,
|
||||||
multipane,
|
Properties,
|
||||||
pane,
|
Location,
|
||||||
Elements,
|
InspectorViews
|
||||||
Properties,
|
},
|
||||||
Location,
|
props: {
|
||||||
InspectorViews
|
'isEditing': Boolean
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hasComposition: false
|
hasComposition: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
mounted() {
|
||||||
refreshComposition(selection) {
|
this.openmct.selection.on('change', this.refreshComposition);
|
||||||
if (selection.length > 0 && selection[0].length > 0) {
|
this.refreshComposition(this.openmct.selection.get());
|
||||||
let parentObject = selection[0][0].context.item;
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.selection.off('change', this.refreshComposition);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
refreshComposition(selection) {
|
||||||
|
if (selection.length > 0 && selection[0].length > 0) {
|
||||||
|
let parentObject = selection[0][0].context.item;
|
||||||
|
|
||||||
this.hasComposition = !!(parentObject && this.openmct.composition.get(parentObject));
|
this.hasComposition = !!(parentObject && this.openmct.composition.get(parentObject));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.openmct.selection.on('change', this.refreshComposition);
|
|
||||||
this.refreshComposition(this.openmct.selection.get());
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.openmct.selection.off('change', this.refreshComposition);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,46 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div></div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash';
|
export default {
|
||||||
|
inject: ['openmct'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selection: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.openmct.selection.on('change', this.updateSelection);
|
||||||
|
this.updateSelection(this.openmct.selection.get());
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.selection.off('change', this.updateSelection);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateSelection(selection) {
|
||||||
|
this.selection = selection;
|
||||||
|
|
||||||
export default {
|
if (this.selectedViews) {
|
||||||
inject: ['openmct'],
|
|
||||||
mounted() {
|
|
||||||
this.openmct.selection.on('change', this.updateSelection);
|
|
||||||
this.updateSelection(this.openmct.selection.get());
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.openmct.selection.off('change', this.updateSelection);
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selection: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateSelection(selection) {
|
|
||||||
this.selection = selection;
|
|
||||||
|
|
||||||
if (this.selectedViews) {
|
|
||||||
this.selectedViews.forEach(selectedView => {
|
|
||||||
selectedView.destroy();
|
|
||||||
});
|
|
||||||
this.$el.innerHTML = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectedViews = this.openmct.inspectorViews.get(selection);
|
|
||||||
this.selectedViews.forEach(selectedView => {
|
this.selectedViews.forEach(selectedView => {
|
||||||
let viewContainer = document.createElement('div');
|
selectedView.destroy();
|
||||||
this.$el.append(viewContainer)
|
|
||||||
selectedView.show(viewContainer);
|
|
||||||
});
|
});
|
||||||
|
this.$el.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.selectedViews = this.openmct.inspectorViews.get(selection);
|
||||||
|
this.selectedViews.forEach(selectedView => {
|
||||||
|
let viewContainer = document.createElement('div');
|
||||||
|
this.$el.append(viewContainer)
|
||||||
|
selectedView.show(viewContainer);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,21 +1,39 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-properties c-properties--location">
|
<div class="c-properties c-properties--location">
|
||||||
<div class="c-properties__header" title="The location of this linked object.">Original Location</div>
|
<div
|
||||||
<ul class="c-properties__section" v-if="!multiSelect">
|
class="c-properties__header"
|
||||||
<li class="c-properties__row" v-if="originalPath.length">
|
title="The location of this linked object."
|
||||||
|
>
|
||||||
|
Original Location
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
v-if="!multiSelect"
|
||||||
|
class="c-properties__section"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-if="originalPath.length"
|
||||||
|
class="c-properties__row"
|
||||||
|
>
|
||||||
<ul class="c-properties__value c-location">
|
<ul class="c-properties__value c-location">
|
||||||
<li v-for="pathObject in orderedOriginalPath"
|
<li
|
||||||
|
v-for="pathObject in orderedOriginalPath"
|
||||||
|
:key="pathObject.key"
|
||||||
class="c-location__item"
|
class="c-location__item"
|
||||||
:key="pathObject.key">
|
>
|
||||||
<object-label
|
<object-label
|
||||||
:domainObject="pathObject.domainObject"
|
:domain-object="pathObject.domainObject"
|
||||||
:objectPath="pathObject.objectPath">
|
:object-path="pathObject.objectPath"
|
||||||
</object-label>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="c-properties__row--span-all" v-if="multiSelect">No location to display for multiple items</div>
|
<div
|
||||||
|
v-if="multiSelect"
|
||||||
|
class="c-properties__row--span-all"
|
||||||
|
>
|
||||||
|
No location to display for multiple items
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -78,6 +96,11 @@ export default {
|
|||||||
keyString: ''
|
keyString: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
orderedOriginalPath() {
|
||||||
|
return this.originalPath.slice().reverse();
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.openmct.selection.on('change', this.updateSelection);
|
this.openmct.selection.on('change', this.updateSelection);
|
||||||
this.updateSelection(this.openmct.selection.get());
|
this.updateSelection(this.openmct.selection.get());
|
||||||
@ -139,11 +162,6 @@ export default {
|
|||||||
.then(this.setOriginalPath);
|
.then(this.setOriginalPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
orderedOriginalPath() {
|
|
||||||
return this.originalPath.reverse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,32 +1,75 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-properties c-properties--properties">
|
<div class="c-properties c-properties--properties">
|
||||||
<div class="c-properties__header">Properties</div>
|
<div class="c-properties__header">
|
||||||
<ul class="c-properties__section" v-if="!multiSelect && !singleSelectNonObject">
|
Properties
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
v-if="!multiSelect && !singleSelectNonObject"
|
||||||
|
class="c-properties__section"
|
||||||
|
>
|
||||||
<li class="c-properties__row">
|
<li class="c-properties__row">
|
||||||
<div class="c-properties__label">Title</div>
|
<div class="c-properties__label">
|
||||||
<div class="c-properties__value">{{ item.name }}</div>
|
Title
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-properties__row">
|
<li class="c-properties__row">
|
||||||
<div class="c-properties__label">Type</div>
|
<div class="c-properties__label">
|
||||||
<div class="c-properties__value">{{ typeName }}</div>
|
Type
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
{{ typeName }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-properties__row" v-if="item.created">
|
<li
|
||||||
<div class="c-properties__label">Created</div>
|
v-if="item.created"
|
||||||
<div class="c-properties__value c-ne__text">{{ formatTime(item.created) }}</div>
|
class="c-properties__row"
|
||||||
|
>
|
||||||
|
<div class="c-properties__label">
|
||||||
|
Created
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value c-ne__text">
|
||||||
|
{{ formatTime(item.created) }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-properties__row" v-if="item.modified">
|
<li
|
||||||
<div class="c-properties__label">Modified</div>
|
v-if="item.modified"
|
||||||
<div class="c-properties__value c-ne__text">{{ formatTime(item.modified) }}</div>
|
class="c-properties__row"
|
||||||
|
>
|
||||||
|
<div class="c-properties__label">
|
||||||
|
Modified
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value c-ne__text">
|
||||||
|
{{ formatTime(item.modified) }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-properties__row"
|
<li
|
||||||
v-for="prop in typeProperties"
|
v-for="prop in typeProperties"
|
||||||
:key="prop.name">
|
:key="prop.name"
|
||||||
<div class="c-properties__label">{{ prop.name }}</div>
|
class="c-properties__row"
|
||||||
<div class="c-properties__value">{{ prop.value }}</div>
|
>
|
||||||
|
<div class="c-properties__label">
|
||||||
|
{{ prop.name }}
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
{{ prop.value }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="c-properties__row--span-all" v-if="multiSelect">No properties to display for multiple items</div>
|
<div
|
||||||
<div class="c-properties__row--span-all" v-if="singleSelectNonObject">No properties to display for this item</div>
|
v-if="multiSelect"
|
||||||
|
class="c-properties__row--span-all"
|
||||||
|
>
|
||||||
|
No properties to display for multiple items
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="singleSelectNonObject"
|
||||||
|
class="c-properties__row--span-all"
|
||||||
|
>
|
||||||
|
No properties to display for this item
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -77,8 +120,8 @@ export default {
|
|||||||
.map((field) => {
|
.map((field) => {
|
||||||
return {
|
return {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
value: field.path.reduce((object, field) => {
|
value: field.path.reduce((object, key) => {
|
||||||
return object[field];
|
return object[key];
|
||||||
}, this.item)
|
}, this.item)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,22 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<div class="c-about c-about--splash">
|
<div class="c-about c-about--splash">
|
||||||
<div class="c-about__image c-splash-image"></div>
|
<div class="c-about__image c-splash-image"></div>
|
||||||
<div class="c-about__text s-text">
|
<div class="c-about__text s-text">
|
||||||
<div class="c-about__text__element" v-if="branding.aboutHtml" v-html="branding.aboutHtml"></div>
|
<div
|
||||||
|
v-if="branding.aboutHtml"
|
||||||
|
class="c-about__text__element"
|
||||||
|
v-html="branding.aboutHtml"
|
||||||
|
></div>
|
||||||
<div class="c-about__text__element">
|
<div class="c-about__text__element">
|
||||||
<h1 class="l-title s-title">Open MCT</h1>
|
<h1 class="l-title s-title">
|
||||||
|
Open MCT
|
||||||
|
</h1>
|
||||||
<div class="l-description s-description">
|
<div class="l-description s-description">
|
||||||
<p>Open MCT, Copyright © 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>
|
<p>Open MCT, Copyright © 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>
|
||||||
<p>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 <a target="_blank" href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>.</p>
|
<p>
|
||||||
|
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 <a
|
||||||
|
target="_blank"
|
||||||
|
href="http://www.apache.org/licenses/LICENSE-2.0"
|
||||||
|
>http://www.apache.org/licenses/LICENSE-2.0</a>.
|
||||||
|
</p>
|
||||||
<p>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.</p>
|
<p>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.</p>
|
||||||
<p>Open MCT includes source code licensed under additional open source licenses. See the Open Source Licenses file included with this distribution or <a @click="showLicenses">click here for third party licensing information</a>.</p>
|
<p>Open MCT includes source code licensed under additional open source licenses. See the Open Source Licenses file included with this distribution or <a @click="showLicenses">click here for third party licensing information</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
<h2>Version Information</h2>
|
<h2>Version Information</h2>
|
||||||
<ul class="t-info l-info s-info">
|
<ul class="t-info l-info s-info">
|
||||||
<li>Version: {{buildInfo.version || 'Unknown'}}</li>
|
<li>Version: {{ buildInfo.version || 'Unknown' }}</li>
|
||||||
<li>Build Date: {{buildInfo.buildDate || 'Unknown'}}</li>
|
<li>Build Date: {{ buildInfo.buildDate || 'Unknown' }}</li>
|
||||||
<li>Revision: {{buildInfo.revision || 'Unknown'}}</li>
|
<li>Revision: {{ buildInfo.revision || 'Unknown' }}</li>
|
||||||
<li>Branch: {{buildInfo.branch || 'Unknown'}}</li>
|
<li>Branch: {{ buildInfo.branch || 'Unknown' }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,7 +20,11 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="l-shell__app-logo" @click="launchAbout" ref="aboutLogo"></div>
|
<div
|
||||||
|
ref="aboutLogo"
|
||||||
|
class="l-shell__app-logo"
|
||||||
|
@click="launchAbout"
|
||||||
|
></div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.l-shell__app-logo {
|
.l-shell__app-logo {
|
||||||
@ -38,12 +42,12 @@ export default {
|
|||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
mounted() {
|
mounted() {
|
||||||
let branding = this.openmct.branding();
|
let branding = this.openmct.branding();
|
||||||
if (branding.smallLogoImage){
|
if (branding.smallLogoImage) {
|
||||||
this.$refs.aboutLogo.style.backgroundImage = `url('${branding.smallLogoImage}')`
|
this.$refs.aboutLogo.style.backgroundImage = `url('${branding.smallLogoImage}')`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
launchAbout(){
|
launchAbout() {
|
||||||
let vm = new Vue({
|
let vm = new Vue({
|
||||||
provide: {
|
provide: {
|
||||||
openmct: this.openmct
|
openmct: this.openmct
|
||||||
|
@ -1,61 +1,93 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-browse-bar">
|
<div class="l-browse-bar">
|
||||||
<div class="l-browse-bar__start">
|
<div class="l-browse-bar__start">
|
||||||
<button v-if="hasParent"
|
<button
|
||||||
class="l-browse-bar__nav-to-parent-button c-icon-button c-icon-button--major icon-pointer-left"
|
v-if="hasParent"
|
||||||
@click="goToParent"></button>
|
class="l-browse-bar__nav-to-parent-button c-icon-button c-icon-button--major icon-pointer-left"
|
||||||
<div class="l-browse-bar__object-name--w"
|
@click="goToParent"
|
||||||
:class="type.cssClass">
|
></button>
|
||||||
<span
|
<div
|
||||||
class="l-browse-bar__object-name c-input-inline"
|
class="l-browse-bar__object-name--w"
|
||||||
@blur="updateName"
|
:class="type.cssClass"
|
||||||
@keydown.enter.prevent
|
>
|
||||||
@keyup.enter.prevent="updateNameOnEnterKeyPress"
|
<span
|
||||||
contenteditable>
|
class="l-browse-bar__object-name c-input-inline"
|
||||||
{{ domainObject.name }}
|
contenteditable
|
||||||
</span>
|
@blur="updateName"
|
||||||
</div>
|
@keydown.enter.prevent
|
||||||
<div class="l-browse-bar__context-actions c-disclosure-button" @click.prevent.stop="showContextMenu"></div>
|
@keyup.enter.prevent="updateNameOnEnterKeyPress"
|
||||||
|
>
|
||||||
|
{{ domainObject.name }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="l-browse-bar__context-actions c-disclosure-button"
|
||||||
|
@click.prevent.stop="showContextMenu"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="l-browse-bar__end">
|
<div class="l-browse-bar__end">
|
||||||
<view-switcher
|
<view-switcher
|
||||||
:currentView="currentView"
|
:current-view="currentView"
|
||||||
:views="views"
|
:views="views"
|
||||||
@setView="setView">
|
@setView="setView"
|
||||||
</view-switcher>
|
/>
|
||||||
<!-- Action buttons -->
|
<!-- Action buttons -->
|
||||||
<div class="l-browse-bar__actions">
|
<div class="l-browse-bar__actions">
|
||||||
<button v-if="notebookEnabled"
|
<button
|
||||||
class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
|
v-if="notebookEnabled"
|
||||||
title="New Notebook entry"
|
class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
|
||||||
@click="snapshot()">
|
title="New Notebook entry"
|
||||||
</button>
|
@click="snapshot()"
|
||||||
<button class="l-browse-bar__actions__edit c-button c-button--major icon-pencil" title="Edit" v-if="isViewEditable & !isEditing" @click="edit()"></button>
|
></button>
|
||||||
|
<button
|
||||||
|
v-if="isViewEditable & !isEditing"
|
||||||
|
class="l-browse-bar__actions__edit c-button c-button--major icon-pencil"
|
||||||
|
title="Edit"
|
||||||
|
@click="edit()"
|
||||||
|
></button>
|
||||||
|
|
||||||
<div class="l-browse-bar__view-switcher c-ctrl-wrapper c-ctrl-wrapper--menus-left"
|
<div
|
||||||
v-if="isEditing">
|
v-if="isEditing"
|
||||||
<button class="c-button--menu c-button--major icon-save" title="Save" @click.stop="toggleSaveMenu"></button>
|
class="l-browse-bar__view-switcher c-ctrl-wrapper c-ctrl-wrapper--menus-left"
|
||||||
<div class="c-menu" v-show="showSaveMenu">
|
>
|
||||||
<ul>
|
<button
|
||||||
<li @click="saveAndFinishEditing"
|
class="c-button--menu c-button--major icon-save"
|
||||||
class="icon-save"
|
title="Save"
|
||||||
title="Save and Finish Editing">
|
@click.stop="toggleSaveMenu"
|
||||||
Save and Finish Editing
|
></button>
|
||||||
</li>
|
<div
|
||||||
<li @click="saveAndContinueEditing"
|
v-show="showSaveMenu"
|
||||||
class="icon-save"
|
class="c-menu"
|
||||||
title="Save and Continue Editing">
|
>
|
||||||
Save and Continue Editing
|
<ul>
|
||||||
</li>
|
<li
|
||||||
</ul>
|
class="icon-save"
|
||||||
</div>
|
title="Save and Finish Editing"
|
||||||
|
@click="saveAndFinishEditing"
|
||||||
|
>
|
||||||
|
Save and Finish Editing
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="icon-save"
|
||||||
|
title="Save and Continue Editing"
|
||||||
|
@click="saveAndContinueEditing"
|
||||||
|
>
|
||||||
|
Save and Continue Editing
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="l-browse-bar__actions c-button icon-x" title="Cancel Editing" v-if="isEditing" @click="promptUserandCancelEditing()"></button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="isEditing"
|
||||||
|
class="l-browse-bar__actions c-button icon-x"
|
||||||
|
title="Cancel Editing"
|
||||||
|
@click="promptUserandCancelEditing()"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -63,187 +95,186 @@ import NotebookSnapshot from '../utils/notebook-snapshot';
|
|||||||
import ViewSwitcher from './ViewSwitcher.vue';
|
import ViewSwitcher from './ViewSwitcher.vue';
|
||||||
const PLACEHOLDER_OBJECT = {};
|
const PLACEHOLDER_OBJECT = {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
components: {
|
components: {
|
||||||
ViewSwitcher
|
ViewSwitcher
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
showViewMenu: false,
|
||||||
|
showSaveMenu: false,
|
||||||
|
domainObject: PLACEHOLDER_OBJECT,
|
||||||
|
viewKey: undefined,
|
||||||
|
isEditing: this.openmct.editor.isEditing(),
|
||||||
|
notebookEnabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentView() {
|
||||||
|
return this.views.filter(v => v.key === this.viewKey)[0] || {};
|
||||||
},
|
},
|
||||||
methods: {
|
views() {
|
||||||
toggleSaveMenu() {
|
return this
|
||||||
this.showSaveMenu = !this.showSaveMenu;
|
.openmct
|
||||||
},
|
.objectViews
|
||||||
closeViewAndSaveMenu() {
|
.get(this.domainObject)
|
||||||
this.showViewMenu = false;
|
.map((p) => {
|
||||||
this.showSaveMenu = false;
|
return {
|
||||||
},
|
key: p.key,
|
||||||
updateName(event) {
|
cssClass: p.cssClass,
|
||||||
if (event.target.innerText !== this.domainObject.name && event.target.innerText.match(/\S/)) {
|
name: p.name
|
||||||
this.openmct.objects.mutate(this.domainObject, 'name', event.target.innerText);
|
};
|
||||||
} else {
|
|
||||||
event.target.innerText = this.domainObject.name;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateNameOnEnterKeyPress (event) {
|
|
||||||
event.target.blur();
|
|
||||||
},
|
|
||||||
setView(view) {
|
|
||||||
this.viewKey = view.key;
|
|
||||||
this.openmct.router.updateParams({
|
|
||||||
view: this.viewKey
|
|
||||||
});
|
});
|
||||||
},
|
|
||||||
edit() {
|
|
||||||
this.openmct.editor.edit();
|
|
||||||
},
|
|
||||||
promptUserandCancelEditing() {
|
|
||||||
let dialog = this.openmct.overlays.dialog({
|
|
||||||
iconClass: 'alert',
|
|
||||||
message: 'Any unsaved changes will be lost. Are you sure you want to continue?',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
label: 'Ok',
|
|
||||||
emphasis: true,
|
|
||||||
callback: () => {
|
|
||||||
this.openmct.editor.cancel().then(() => {
|
|
||||||
//refresh object view
|
|
||||||
this.openmct.layout.$refs.browseObject.show(this.domainObject, this.viewKey, true);
|
|
||||||
});
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Cancel',
|
|
||||||
callback: () => {
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
},
|
|
||||||
promptUserbeforeNavigatingAway(event) {
|
|
||||||
if(this.openmct.editor.isEditing()) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.returnValue = '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveAndFinishEditing() {
|
|
||||||
let dialog = this.openmct.overlays.progressDialog({
|
|
||||||
progressPerc: 'unknown',
|
|
||||||
message: 'Do not navigate away from this page or close this browser tab while this message is displayed.',
|
|
||||||
iconClass: 'info',
|
|
||||||
title: 'Saving',
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.openmct.editor.save()
|
|
||||||
.then(()=> {
|
|
||||||
dialog.dismiss();
|
|
||||||
this.openmct.notifications.info('Save successful');
|
|
||||||
}).catch((error) => {
|
|
||||||
dialog.dismiss();
|
|
||||||
this.openmct.notifications.error('Error saving objects');
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
saveAndContinueEditing() {
|
|
||||||
this.saveAndFinishEditing().then(() => {
|
|
||||||
this.openmct.editor.edit();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showContextMenu(event) {
|
|
||||||
this.openmct.contextMenu._showContextMenuForObjectPath(this.openmct.router.path, event.clientX, event.clientY);
|
|
||||||
},
|
|
||||||
snapshot() {
|
|
||||||
let element = document.getElementsByClassName("l-shell__main-container")[0];
|
|
||||||
this.notebookSnapshot.capture(this.domainObject, element);
|
|
||||||
},
|
|
||||||
goToParent(){
|
|
||||||
window.location.hash = this.parentUrl;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data: function () {
|
hasParent() {
|
||||||
return {
|
return this.domainObject !== PLACEHOLDER_OBJECT &&
|
||||||
showViewMenu: false,
|
|
||||||
showSaveMenu: false,
|
|
||||||
domainObject: PLACEHOLDER_OBJECT,
|
|
||||||
viewKey: undefined,
|
|
||||||
isEditing: this.openmct.editor.isEditing(),
|
|
||||||
notebookEnabled: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
currentView() {
|
|
||||||
return this.views.filter(v => v.key === this.viewKey)[0] || {};
|
|
||||||
},
|
|
||||||
views() {
|
|
||||||
return this
|
|
||||||
.openmct
|
|
||||||
.objectViews
|
|
||||||
.get(this.domainObject)
|
|
||||||
.map((p) => {
|
|
||||||
return {
|
|
||||||
key: p.key,
|
|
||||||
cssClass: p.cssClass,
|
|
||||||
name: p.name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hasParent() {
|
|
||||||
return this.domainObject !== PLACEHOLDER_OBJECT &&
|
|
||||||
this.parentUrl !== '#/browse'
|
this.parentUrl !== '#/browse'
|
||||||
},
|
|
||||||
parentUrl() {
|
|
||||||
let objectKeyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
|
||||||
let hash = window.location.hash;
|
|
||||||
return hash.slice(0, hash.lastIndexOf('/' + objectKeyString));
|
|
||||||
},
|
|
||||||
type() {
|
|
||||||
let objectType = this.openmct.types.get(this.domainObject.type);
|
|
||||||
if (!objectType) {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
return objectType.definition;
|
|
||||||
},
|
|
||||||
isViewEditable() {
|
|
||||||
let currentViewKey = this.currentView.key;
|
|
||||||
if (currentViewKey !== undefined) {
|
|
||||||
let currentViewProvider = this.openmct.objectViews.getByProviderKey(currentViewKey);
|
|
||||||
return currentViewProvider.canEdit && currentViewProvider.canEdit(this.domainObject);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted: function () {
|
parentUrl() {
|
||||||
|
let objectKeyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||||
if (this.openmct.types.get('notebook')) {
|
let hash = window.location.hash;
|
||||||
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
|
return hash.slice(0, hash.lastIndexOf('/' + objectKeyString));
|
||||||
this.notebookEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('click', this.closeViewAndSaveMenu);
|
|
||||||
window.addEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
|
|
||||||
|
|
||||||
this.openmct.editor.on('isEditing', (isEditing) => {
|
|
||||||
this.isEditing = isEditing;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
watch: {
|
type() {
|
||||||
domainObject() {
|
let objectType = this.openmct.types.get(this.domainObject.type);
|
||||||
if (this.mutationObserver) {
|
if (!objectType) {
|
||||||
this.mutationObserver();
|
return {}
|
||||||
}
|
|
||||||
this.mutationObserver = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
|
|
||||||
this.domainObject = domainObject;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return objectType.definition;
|
||||||
},
|
},
|
||||||
beforeDestroy: function () {
|
isViewEditable() {
|
||||||
|
let currentViewKey = this.currentView.key;
|
||||||
|
if (currentViewKey !== undefined) {
|
||||||
|
let currentViewProvider = this.openmct.objectViews.getByProviderKey(currentViewKey);
|
||||||
|
return currentViewProvider.canEdit && currentViewProvider.canEdit(this.domainObject);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
domainObject() {
|
||||||
if (this.mutationObserver) {
|
if (this.mutationObserver) {
|
||||||
this.mutationObserver();
|
this.mutationObserver();
|
||||||
}
|
}
|
||||||
document.removeEventListener('click', this.closeViewAndSaveMenu);
|
this.mutationObserver = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
|
||||||
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
|
this.domainObject = domainObject;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
|
||||||
|
if (this.openmct.types.get('notebook')) {
|
||||||
|
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
|
||||||
|
this.notebookEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', this.closeViewAndSaveMenu);
|
||||||
|
window.addEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
|
||||||
|
|
||||||
|
this.openmct.editor.on('isEditing', (isEditing) => {
|
||||||
|
this.isEditing = isEditing;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy: function () {
|
||||||
|
if (this.mutationObserver) {
|
||||||
|
this.mutationObserver();
|
||||||
|
}
|
||||||
|
document.removeEventListener('click', this.closeViewAndSaveMenu);
|
||||||
|
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleSaveMenu() {
|
||||||
|
this.showSaveMenu = !this.showSaveMenu;
|
||||||
|
},
|
||||||
|
closeViewAndSaveMenu() {
|
||||||
|
this.showViewMenu = false;
|
||||||
|
this.showSaveMenu = false;
|
||||||
|
},
|
||||||
|
updateName(event) {
|
||||||
|
if (event.target.innerText !== this.domainObject.name && event.target.innerText.match(/\S/)) {
|
||||||
|
this.openmct.objects.mutate(this.domainObject, 'name', event.target.innerText);
|
||||||
|
} else {
|
||||||
|
event.target.innerText = this.domainObject.name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateNameOnEnterKeyPress(event) {
|
||||||
|
event.target.blur();
|
||||||
|
},
|
||||||
|
setView(view) {
|
||||||
|
this.viewKey = view.key;
|
||||||
|
this.openmct.router.updateParams({
|
||||||
|
view: this.viewKey
|
||||||
|
});
|
||||||
|
},
|
||||||
|
edit() {
|
||||||
|
this.openmct.editor.edit();
|
||||||
|
},
|
||||||
|
promptUserandCancelEditing() {
|
||||||
|
let dialog = this.openmct.overlays.dialog({
|
||||||
|
iconClass: 'alert',
|
||||||
|
message: 'Any unsaved changes will be lost. Are you sure you want to continue?',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
label: 'Ok',
|
||||||
|
emphasis: true,
|
||||||
|
callback: () => {
|
||||||
|
this.openmct.editor.cancel().then(() => {
|
||||||
|
//refresh object view
|
||||||
|
this.openmct.layout.$refs.browseObject.show(this.domainObject, this.viewKey, true);
|
||||||
|
});
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cancel',
|
||||||
|
callback: () => {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
},
|
||||||
|
promptUserbeforeNavigatingAway(event) {
|
||||||
|
if(this.openmct.editor.isEditing()) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveAndFinishEditing() {
|
||||||
|
let dialog = this.openmct.overlays.progressDialog({
|
||||||
|
progressPerc: 'unknown',
|
||||||
|
message: 'Do not navigate away from this page or close this browser tab while this message is displayed.',
|
||||||
|
iconClass: 'info',
|
||||||
|
title: 'Saving'
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.openmct.editor.save().then(()=> {
|
||||||
|
dialog.dismiss();
|
||||||
|
this.openmct.notifications.info('Save successful');
|
||||||
|
}).catch((error) => {
|
||||||
|
dialog.dismiss();
|
||||||
|
this.openmct.notifications.error('Error saving objects');
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
saveAndContinueEditing() {
|
||||||
|
this.saveAndFinishEditing().then(() => {
|
||||||
|
this.openmct.editor.edit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showContextMenu(event) {
|
||||||
|
this.openmct.contextMenu._showContextMenuForObjectPath(this.openmct.router.path, event.clientX, event.clientY);
|
||||||
|
},
|
||||||
|
snapshot() {
|
||||||
|
let element = document.getElementsByClassName("l-shell__main-container")[0];
|
||||||
|
this.notebookSnapshot.capture(this.domainObject, element);
|
||||||
|
},
|
||||||
|
goToParent() {
|
||||||
|
window.location.hash = this.parentUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -1,30 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-create-button--w">
|
<div class="c-create-button--w">
|
||||||
<button class="c-create-button c-button--menu c-button--major icon-plus"
|
<button
|
||||||
@click="open">
|
class="c-create-button c-button--menu c-button--major icon-plus"
|
||||||
<span class="c-button__label">Create</span>
|
@click="open"
|
||||||
</button>
|
>
|
||||||
<div class="c-create-menu c-super-menu"
|
<span class="c-button__label">Create</span>
|
||||||
v-if="opened">
|
</button>
|
||||||
<div class="c-super-menu__menu">
|
<div
|
||||||
<ul>
|
v-if="opened"
|
||||||
<li v-for="(item, index) in sortedItems"
|
class="c-create-menu c-super-menu"
|
||||||
:key="index"
|
>
|
||||||
:class="item.class"
|
<div class="c-super-menu__menu">
|
||||||
:title="item.title"
|
<ul>
|
||||||
@mouseover="showItemDescription(item)"
|
<li
|
||||||
@click="create(item)">
|
v-for="(item, index) in sortedItems"
|
||||||
{{ item.name }}
|
:key="index"
|
||||||
</li>
|
:class="item.class"
|
||||||
</ul>
|
:title="item.title"
|
||||||
|
@mouseover="showItemDescription(item)"
|
||||||
|
@click="create(item)"
|
||||||
|
>
|
||||||
|
{{ item.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="c-super-menu__item-description">
|
||||||
|
<div :class="['l-item-description__icon', 'bg-' + selectedMenuItem.class]"></div>
|
||||||
|
<div class="l-item-description__name">
|
||||||
|
{{ selectedMenuItem.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="c-super-menu__item-description">
|
<div class="l-item-description__description">
|
||||||
<div :class="['l-item-description__icon', 'bg-' + selectedMenuItem.class]"></div>
|
{{ selectedMenuItem.title }}
|
||||||
<div class="l-item-description__name">{{selectedMenuItem.name}}</div>
|
|
||||||
<div class="l-item-description__description">{{selectedMenuItem.title}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -62,102 +72,97 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CreateAction from '../../../platform/commonUI/edit/src/creation/CreateAction';
|
import CreateAction from '../../../platform/commonUI/edit/src/creation/CreateAction';
|
||||||
import objectUtils from '../../api/objects/object-utils';
|
import objectUtils from '../../api/objects/object-utils';
|
||||||
|
|
||||||
function convertToLegacyObject(domainObject) {
|
export default {
|
||||||
let keyString = objectUtils.makeKeyString(domainObject.identifier);
|
inject: ['openmct'],
|
||||||
let oldModel = objectUtils.toOldFormat(domainObject);
|
data: function () {
|
||||||
return instantiate(oldModel, keyString);
|
let items = [];
|
||||||
}
|
|
||||||
export default {
|
this.openmct.types.listKeys().forEach(key => {
|
||||||
inject: ['openmct'],
|
let menuItem = this.openmct.types.get(key).definition;
|
||||||
methods: {
|
|
||||||
open: function () {
|
if (menuItem.creatable) {
|
||||||
if (this.opened) {
|
let menuItemTemplate = {
|
||||||
return;
|
key: key,
|
||||||
}
|
name: menuItem.name,
|
||||||
this.opened = true;
|
class: menuItem.cssClass,
|
||||||
setTimeout(() => document.addEventListener('click', this.close));
|
title: menuItem.description
|
||||||
},
|
};
|
||||||
close: function () {
|
|
||||||
if (!this.opened) {
|
items.push(menuItemTemplate);
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.opened = false;
|
|
||||||
document.removeEventListener('click', this.close);
|
|
||||||
},
|
|
||||||
showItemDescription: function (menuItem) {
|
|
||||||
this.selectedMenuItem = menuItem;
|
|
||||||
},
|
|
||||||
create: function (item) {
|
|
||||||
// Hack for support. TODO: rewrite create action.
|
|
||||||
// 1. Get contextual object from navigation
|
|
||||||
// 2. Get legacy type from legacy api
|
|
||||||
// 3. Instantiate create action with type, parent, context
|
|
||||||
// 4. perform action.
|
|
||||||
return this.openmct.objects.get(this.openmct.router.path[0].identifier)
|
|
||||||
.then((currentObject) => {
|
|
||||||
let legacyContextualParent = this.convertToLegacy(currentObject);
|
|
||||||
let legacyType = this.openmct.$injector.get('typeService').getType(item.key);
|
|
||||||
let context = {
|
|
||||||
key: "create",
|
|
||||||
domainObject: legacyContextualParent // should be same as parent object.
|
|
||||||
};
|
|
||||||
let action = new CreateAction(
|
|
||||||
legacyType,
|
|
||||||
legacyContextualParent,
|
|
||||||
context,
|
|
||||||
this.openmct
|
|
||||||
);
|
|
||||||
return action.perform();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
convertToLegacy (domainObject) {
|
|
||||||
let keyString = objectUtils.makeKeyString(domainObject.identifier);
|
|
||||||
let oldModel = objectUtils.toOldFormat(domainObject);
|
|
||||||
return this.openmct.$injector.get('instantiate')(oldModel, keyString);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
destroyed () {
|
|
||||||
document.removeEventListener('click', this.close);
|
|
||||||
},
|
|
||||||
data: function() {
|
|
||||||
let items = [];
|
|
||||||
|
|
||||||
this.openmct.types.listKeys().forEach(key => {
|
return {
|
||||||
let menuItem = this.openmct.types.get(key).definition;
|
items: items,
|
||||||
|
selectedMenuItem: {},
|
||||||
if (menuItem.creatable) {
|
opened: false
|
||||||
let menuItemTemplate = {
|
}
|
||||||
key: key,
|
},
|
||||||
name: menuItem.name,
|
computed: {
|
||||||
class: menuItem.cssClass,
|
sortedItems() {
|
||||||
title: menuItem.description
|
return this.items.slice().sort((a,b) => {
|
||||||
};
|
if (a.name < b.name) {
|
||||||
|
return -1;
|
||||||
items.push(menuItemTemplate);
|
} else if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return {
|
},
|
||||||
items: items,
|
destroyed() {
|
||||||
selectedMenuItem: {},
|
document.removeEventListener('click', this.close);
|
||||||
opened: false
|
},
|
||||||
|
methods: {
|
||||||
|
open: function () {
|
||||||
|
if (this.opened) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.opened = true;
|
||||||
|
setTimeout(() => document.addEventListener('click', this.close));
|
||||||
},
|
},
|
||||||
computed: {
|
close: function () {
|
||||||
sortedItems () {
|
if (!this.opened) {
|
||||||
return this.items.sort((a,b) => {
|
return;
|
||||||
if (a.name < b.name) {
|
|
||||||
return -1;
|
|
||||||
} else if (a.name > b.name) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.opened = false;
|
||||||
|
document.removeEventListener('click', this.close);
|
||||||
|
},
|
||||||
|
showItemDescription: function (menuItem) {
|
||||||
|
this.selectedMenuItem = menuItem;
|
||||||
|
},
|
||||||
|
create: function (item) {
|
||||||
|
// Hack for support. TODO: rewrite create action.
|
||||||
|
// 1. Get contextual object from navigation
|
||||||
|
// 2. Get legacy type from legacy api
|
||||||
|
// 3. Instantiate create action with type, parent, context
|
||||||
|
// 4. perform action.
|
||||||
|
return this.openmct.objects.get(this.openmct.router.path[0].identifier)
|
||||||
|
.then((currentObject) => {
|
||||||
|
let legacyContextualParent = this.convertToLegacy(currentObject);
|
||||||
|
let legacyType = this.openmct.$injector.get('typeService').getType(item.key);
|
||||||
|
let context = {
|
||||||
|
key: "create",
|
||||||
|
domainObject: legacyContextualParent // should be same as parent object.
|
||||||
|
};
|
||||||
|
let action = new CreateAction(
|
||||||
|
legacyType,
|
||||||
|
legacyContextualParent,
|
||||||
|
context,
|
||||||
|
this.openmct
|
||||||
|
);
|
||||||
|
return action.perform();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
convertToLegacy(domainObject) {
|
||||||
|
let keyString = objectUtils.makeKeyString(domainObject.identifier);
|
||||||
|
let oldModel = objectUtils.toOldFormat(domainObject);
|
||||||
|
return this.openmct.$injector.get('instantiate')(oldModel, keyString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,60 +1,84 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-shell" :class="{
|
<div
|
||||||
'is-editing': isEditing
|
class="l-shell"
|
||||||
}">
|
:class="{
|
||||||
<div class="l-shell__head" :class="{
|
'is-editing': isEditing
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="l-shell__head"
|
||||||
|
:class="{
|
||||||
'l-shell__head--expanded': headExpanded,
|
'l-shell__head--expanded': headExpanded,
|
||||||
'l-shell__head--minify-indicators': !headExpanded
|
'l-shell__head--minify-indicators': !headExpanded
|
||||||
}">
|
}"
|
||||||
<CreateButton class="l-shell__create-button"></CreateButton>
|
>
|
||||||
<indicators class="l-shell__head-section l-shell__indicators">
|
<CreateButton class="l-shell__create-button" />
|
||||||
</indicators>
|
<indicators class="l-shell__head-section l-shell__indicators" />
|
||||||
<button class="l-shell__head__collapse-button c-button"
|
<button
|
||||||
@click="toggleShellHead"></button>
|
class="l-shell__head__collapse-button c-button"
|
||||||
<notification-banner></notification-banner>
|
@click="toggleShellHead"
|
||||||
<div class="l-shell__head-section l-shell__controls">
|
></button>
|
||||||
<button class="c-icon-button c-icon-button--major icon-new-window" title="Open in a new browser tab"
|
<notification-banner />
|
||||||
@click="openInNewTab"
|
<div class="l-shell__head-section l-shell__controls">
|
||||||
target="_blank">
|
<button
|
||||||
</button>
|
class="c-icon-button c-icon-button--major icon-new-window"
|
||||||
<button v-bind:class="['c-icon-button c-icon-button--major', fullScreen ? 'icon-fullscreen-collapse' : 'icon-fullscreen-expand']"
|
title="Open in a new browser tab"
|
||||||
v-bind:title="`${fullScreen ? 'Exit' : 'Enable'} full screen mode`"
|
target="_blank"
|
||||||
@click="fullScreenToggle">
|
@click="openInNewTab"
|
||||||
</button>
|
></button>
|
||||||
</div>
|
<button
|
||||||
<app-logo></app-logo>
|
:class="['c-icon-button c-icon-button--major', fullScreen ? 'icon-fullscreen-collapse' : 'icon-fullscreen-expand']"
|
||||||
|
:title="`${fullScreen ? 'Exit' : 'Enable'} full screen mode`"
|
||||||
|
@click="fullScreenToggle"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<multipane class="l-shell__main"
|
<app-logo />
|
||||||
type="horizontal">
|
|
||||||
<pane class="l-shell__pane-tree"
|
|
||||||
handle="after"
|
|
||||||
label="Browse"
|
|
||||||
collapsable>
|
|
||||||
<mct-tree class="l-shell__tree"></mct-tree>
|
|
||||||
</pane>
|
|
||||||
<pane class="l-shell__pane-main">
|
|
||||||
<browse-bar class="l-shell__main-view-browse-bar"
|
|
||||||
ref="browseBar">
|
|
||||||
</browse-bar>
|
|
||||||
<toolbar v-if="toolbar" class="l-shell__toolbar"></toolbar>
|
|
||||||
<object-view class="l-shell__main-container"
|
|
||||||
ref="browseObject"
|
|
||||||
:showEditView="true"
|
|
||||||
data-selectable
|
|
||||||
>
|
|
||||||
</object-view>
|
|
||||||
<component class="l-shell__time-conductor"
|
|
||||||
:is="conductorComponent">
|
|
||||||
</component>
|
|
||||||
</pane>
|
|
||||||
<pane class="l-shell__pane-inspector l-pane--holds-multipane"
|
|
||||||
handle="before"
|
|
||||||
label="Inspect"
|
|
||||||
collapsable>
|
|
||||||
<Inspector :isEditing="isEditing" ref="inspector"></Inspector>
|
|
||||||
</pane>
|
|
||||||
</multipane>
|
|
||||||
</div>
|
</div>
|
||||||
|
<multipane
|
||||||
|
class="l-shell__main"
|
||||||
|
type="horizontal"
|
||||||
|
>
|
||||||
|
<pane
|
||||||
|
class="l-shell__pane-tree"
|
||||||
|
handle="after"
|
||||||
|
label="Browse"
|
||||||
|
collapsable
|
||||||
|
>
|
||||||
|
<mct-tree class="l-shell__tree" />
|
||||||
|
</pane>
|
||||||
|
<pane class="l-shell__pane-main">
|
||||||
|
<browse-bar
|
||||||
|
ref="browseBar"
|
||||||
|
class="l-shell__main-view-browse-bar"
|
||||||
|
/>
|
||||||
|
<toolbar
|
||||||
|
v-if="toolbar"
|
||||||
|
class="l-shell__toolbar"
|
||||||
|
/>
|
||||||
|
<object-view
|
||||||
|
ref="browseObject"
|
||||||
|
class="l-shell__main-container"
|
||||||
|
:show-edit-view="true"
|
||||||
|
data-selectable
|
||||||
|
/>
|
||||||
|
<component
|
||||||
|
:is="conductorComponent"
|
||||||
|
class="l-shell__time-conductor"
|
||||||
|
/>
|
||||||
|
</pane>
|
||||||
|
<pane
|
||||||
|
class="l-shell__pane-inspector l-pane--holds-multipane"
|
||||||
|
handle="before"
|
||||||
|
label="Inspect"
|
||||||
|
collapsable
|
||||||
|
>
|
||||||
|
<Inspector
|
||||||
|
ref="inspector"
|
||||||
|
:is-editing="isEditing"
|
||||||
|
/>
|
||||||
|
</pane>
|
||||||
|
</multipane>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -302,126 +326,126 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Inspector from '../inspector/Inspector.vue';
|
import Inspector from '../inspector/Inspector.vue';
|
||||||
import MctTree from './mct-tree.vue';
|
import MctTree from './mct-tree.vue';
|
||||||
import ObjectView from '../components/ObjectView.vue';
|
import ObjectView from '../components/ObjectView.vue';
|
||||||
import MctTemplate from '../legacy/mct-template.vue';
|
import MctTemplate from '../legacy/mct-template.vue';
|
||||||
import CreateButton from './CreateButton.vue';
|
import CreateButton from './CreateButton.vue';
|
||||||
import multipane from './multipane.vue';
|
import multipane from './multipane.vue';
|
||||||
import pane from './pane.vue';
|
import pane from './pane.vue';
|
||||||
import BrowseBar from './BrowseBar.vue';
|
import BrowseBar from './BrowseBar.vue';
|
||||||
import Toolbar from '../toolbar/Toolbar.vue';
|
import Toolbar from '../toolbar/Toolbar.vue';
|
||||||
import AppLogo from './AppLogo.vue';
|
import AppLogo from './AppLogo.vue';
|
||||||
import Indicators from './status-bar/Indicators.vue';
|
import Indicators from './status-bar/Indicators.vue';
|
||||||
import NotificationBanner from './status-bar/NotificationBanner.vue';
|
import NotificationBanner from './status-bar/NotificationBanner.vue';
|
||||||
|
|
||||||
var enterFullScreen = () => {
|
var enterFullScreen = () => {
|
||||||
var docElm = document.documentElement;
|
var docElm = document.documentElement;
|
||||||
|
|
||||||
if (docElm.requestFullscreen) {
|
if (docElm.requestFullscreen) {
|
||||||
docElm.requestFullscreen();
|
docElm.requestFullscreen();
|
||||||
} else if (docElm.mozRequestFullScreen) { /* Firefox */
|
} else if (docElm.mozRequestFullScreen) { /* Firefox */
|
||||||
docElm.mozRequestFullScreen();
|
docElm.mozRequestFullScreen();
|
||||||
} else if (docElm.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
|
} else if (docElm.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
|
||||||
docElm.webkitRequestFullscreen();
|
docElm.webkitRequestFullscreen();
|
||||||
} else if (docElm.msRequestFullscreen) { /* IE/Edge */
|
} else if (docElm.msRequestFullscreen) { /* IE/Edge */
|
||||||
docElm.msRequestFullscreen();
|
docElm.msRequestFullscreen();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var exitFullScreen = () => {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
else if (document.mozCancelFullScreen) {
|
||||||
|
document.mozCancelFullScreen();
|
||||||
|
}
|
||||||
|
else if (document.webkitCancelFullScreen) {
|
||||||
|
document.webkitCancelFullScreen();
|
||||||
|
}
|
||||||
|
else if (document.msExitFullscreen) {
|
||||||
|
document.msExitFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
inject: ['openmct'],
|
||||||
|
components: {
|
||||||
|
Inspector,
|
||||||
|
MctTree,
|
||||||
|
ObjectView,
|
||||||
|
'mct-template': MctTemplate,
|
||||||
|
CreateButton,
|
||||||
|
multipane,
|
||||||
|
pane,
|
||||||
|
BrowseBar,
|
||||||
|
Toolbar,
|
||||||
|
AppLogo,
|
||||||
|
Indicators,
|
||||||
|
NotificationBanner
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
let storedHeadProps = window.localStorage.getItem('openmct-shell-head');
|
||||||
|
let headExpanded = true;
|
||||||
|
if (storedHeadProps) {
|
||||||
|
headExpanded = JSON.parse(storedHeadProps).expanded;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
var exitFullScreen = () => {
|
return {
|
||||||
if (document.exitFullscreen) {
|
fullScreen: false,
|
||||||
document.exitFullscreen();
|
conductorComponent: undefined,
|
||||||
|
isEditing: false,
|
||||||
|
hasToolbar: false,
|
||||||
|
headExpanded
|
||||||
}
|
}
|
||||||
else if (document.mozCancelFullScreen) {
|
},
|
||||||
document.mozCancelFullScreen();
|
computed: {
|
||||||
|
toolbar() {
|
||||||
|
return this.hasToolbar && this.isEditing;
|
||||||
}
|
}
|
||||||
else if (document.webkitCancelFullScreen) {
|
},
|
||||||
document.webkitCancelFullScreen();
|
mounted() {
|
||||||
}
|
this.openmct.editor.on('isEditing', (isEditing)=>{
|
||||||
else if (document.msExitFullscreen) {
|
this.isEditing = isEditing;
|
||||||
document.msExitFullscreen();
|
});
|
||||||
}
|
|
||||||
}
|
this.openmct.selection.on('change', this.toggleHasToolbar);
|
||||||
|
},
|
||||||
export default {
|
methods: {
|
||||||
inject: ['openmct'],
|
toggleShellHead() {
|
||||||
components: {
|
this.headExpanded = !this.headExpanded;
|
||||||
Inspector,
|
|
||||||
MctTree,
|
window.localStorage.setItem(
|
||||||
ObjectView,
|
'openmct-shell-head',
|
||||||
'mct-template': MctTemplate,
|
JSON.stringify(
|
||||||
CreateButton,
|
{
|
||||||
multipane,
|
expanded: this.headExpanded
|
||||||
pane,
|
}
|
||||||
BrowseBar,
|
)
|
||||||
Toolbar,
|
);
|
||||||
AppLogo,
|
},
|
||||||
Indicators,
|
fullScreenToggle() {
|
||||||
NotificationBanner
|
if (this.fullScreen) {
|
||||||
},
|
this.fullScreen = false;
|
||||||
mounted() {
|
exitFullScreen();
|
||||||
this.openmct.editor.on('isEditing', (isEditing)=>{
|
} else {
|
||||||
this.isEditing = isEditing;
|
this.fullScreen = true;
|
||||||
});
|
enterFullScreen();
|
||||||
|
}
|
||||||
this.openmct.selection.on('change', this.toggleHasToolbar);
|
},
|
||||||
},
|
openInNewTab(event) {
|
||||||
data: function () {
|
window.open(window.location.href);
|
||||||
let storedHeadProps = window.localStorage.getItem('openmct-shell-head');
|
},
|
||||||
let headExpanded = true;
|
toggleHasToolbar(selection) {
|
||||||
if (storedHeadProps) {
|
let structure = undefined;
|
||||||
headExpanded = JSON.parse(storedHeadProps).expanded;
|
|
||||||
}
|
if (!selection || !selection[0]) {
|
||||||
|
structure = [];
|
||||||
return {
|
} else {
|
||||||
fullScreen: false,
|
structure = this.openmct.toolbars.get(selection);
|
||||||
conductorComponent: undefined,
|
}
|
||||||
isEditing: false,
|
|
||||||
hasToolbar: false,
|
this.hasToolbar = structure.length > 0;
|
||||||
headExpanded
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
toolbar() {
|
|
||||||
return this.hasToolbar && this.isEditing;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleShellHead() {
|
|
||||||
this.headExpanded = !this.headExpanded;
|
|
||||||
|
|
||||||
window.localStorage.setItem(
|
|
||||||
'openmct-shell-head',
|
|
||||||
JSON.stringify(
|
|
||||||
{
|
|
||||||
expanded: this.headExpanded
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
fullScreenToggle() {
|
|
||||||
if (this.fullScreen) {
|
|
||||||
this.fullScreen = false;
|
|
||||||
exitFullScreen();
|
|
||||||
} else {
|
|
||||||
this.fullScreen = true;
|
|
||||||
enterFullScreen();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openInNewTab(event) {
|
|
||||||
window.open(window.location.href);
|
|
||||||
},
|
|
||||||
toggleHasToolbar(selection) {
|
|
||||||
let structure = undefined;
|
|
||||||
|
|
||||||
if (!selection || !selection[0]) {
|
|
||||||
structure = [];
|
|
||||||
} else {
|
|
||||||
structure = this.openmct.toolbars.get(selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hasToolbar = structure.length > 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-search c-search--major">
|
<div class="c-search c-search--major">
|
||||||
<input type="search" placeholder="Search"/>
|
<input
|
||||||
</div>
|
type="search"
|
||||||
|
placeholder="Search"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -20,6 +23,6 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,39 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-browse-bar__view-switcher c-ctrl-wrapper c-ctrl-wrapper--menus-left"
|
<div
|
||||||
v-if="views.length > 1">
|
v-if="views.length > 1"
|
||||||
<button class="c-button--menu"
|
class="l-browse-bar__view-switcher c-ctrl-wrapper c-ctrl-wrapper--menus-left"
|
||||||
:class="currentView.cssClass"
|
>
|
||||||
title="Switch view type"
|
<button
|
||||||
@click.stop="toggleViewMenu">
|
class="c-button--menu"
|
||||||
<span class="c-button__label">
|
:class="currentView.cssClass"
|
||||||
{{ currentView.name }}
|
title="Switch view type"
|
||||||
</span>
|
@click.stop="toggleViewMenu"
|
||||||
</button>
|
>
|
||||||
<div class="c-menu" v-show="showViewMenu">
|
<span class="c-button__label">
|
||||||
<ul>
|
{{ currentView.name }}
|
||||||
<li v-for="(view, index) in views"
|
</span>
|
||||||
@click="setView(view)"
|
</button>
|
||||||
:key="index"
|
<div
|
||||||
:class="view.cssClass"
|
v-show="showViewMenu"
|
||||||
:title="view.name">
|
class="c-menu"
|
||||||
{{ view.name }}
|
>
|
||||||
</li>
|
<ul>
|
||||||
</ul>
|
<li
|
||||||
</div>
|
v-for="(view, index) in views"
|
||||||
|
:key="index"
|
||||||
|
:class="view.cssClass"
|
||||||
|
:title="view.name"
|
||||||
|
@click="setView(view)"
|
||||||
|
>
|
||||||
|
{{ view.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: {
|
||||||
'currentView',
|
currentView: {
|
||||||
'views'
|
type: Object,
|
||||||
],
|
required: true
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showViewMenu: false
|
showViewMenu: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener('click', this.hideViewMenu);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
document.removeEventListener('click', this.hideViewMenu);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setView(view) {
|
setView(view) {
|
||||||
this.$emit('setView', view);
|
this.$emit('setView', view);
|
||||||
@ -44,12 +65,6 @@ export default {
|
|||||||
hideViewMenu() {
|
hideViewMenu() {
|
||||||
this.showViewMenu = false;
|
this.showViewMenu = false;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.addEventListener('click', this.hideViewMenu);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
document.removeEventListener('click', this.hideViewMenu);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,44 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-tree-and-search">
|
<div class="c-tree-and-search">
|
||||||
<div class="c-tree-and-search__search">
|
<div class="c-tree-and-search__search">
|
||||||
<search class="c-search" ref="shell-search"
|
<search
|
||||||
:value="searchValue"
|
ref="shell-search"
|
||||||
@input="searchTree"
|
class="c-search"
|
||||||
@clear="searchTree">
|
:value="searchValue"
|
||||||
</search>
|
@input="searchTree"
|
||||||
</div>
|
@clear="searchTree"
|
||||||
|
/>
|
||||||
<!-- loading -->
|
|
||||||
<div class="c-tree-and-search__loading loading"
|
|
||||||
v-if="isLoading"></div>
|
|
||||||
<!-- end loading -->
|
|
||||||
|
|
||||||
<div class="c-tree-and-search__no-results"
|
|
||||||
v-if="(allTreeItems.length === 0) || (searchValue && filteredTreeItems.length === 0)">
|
|
||||||
No results found
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- main tree -->
|
|
||||||
<ul class="c-tree-and-search__tree c-tree"
|
|
||||||
v-if="!isLoading"
|
|
||||||
v-show="!searchValue">
|
|
||||||
<tree-item v-for="treeItem in allTreeItems"
|
|
||||||
:key="treeItem.id"
|
|
||||||
:node="treeItem">
|
|
||||||
</tree-item>
|
|
||||||
</ul>
|
|
||||||
<!-- end main tree -->
|
|
||||||
|
|
||||||
<!-- search tree -->
|
|
||||||
<ul class="c-tree-and-search__tree c-tree"
|
|
||||||
v-if="searchValue">
|
|
||||||
<tree-item v-for="treeItem in filteredTreeItems"
|
|
||||||
:key="treeItem.id"
|
|
||||||
:node="treeItem">
|
|
||||||
</tree-item>
|
|
||||||
</ul>
|
|
||||||
<!-- end search tree -->
|
|
||||||
</div>
|
</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"
|
||||||
|
>
|
||||||
|
<tree-item
|
||||||
|
v-for="treeItem in allTreeItems"
|
||||||
|
:key="treeItem.id"
|
||||||
|
:node="treeItem"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
<!-- end main tree -->
|
||||||
|
|
||||||
|
<!-- search tree -->
|
||||||
|
<ul
|
||||||
|
v-if="searchValue"
|
||||||
|
class="c-tree-and-search__tree c-tree"
|
||||||
|
>
|
||||||
|
<tree-item
|
||||||
|
v-for="treeItem in filteredTreeItems"
|
||||||
|
:key="treeItem.id"
|
||||||
|
:node="treeItem"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
<!-- end search tree -->
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -185,81 +197,81 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import treeItem from './tree-item.vue'
|
import treeItem from './tree-item.vue'
|
||||||
import search from '../components/search.vue';
|
import search from '../components/search.vue';
|
||||||
|
|
||||||
export default {
|
|
||||||
inject: ['openmct'],
|
|
||||||
name: 'mct-tree',
|
|
||||||
components: {
|
|
||||||
search,
|
|
||||||
treeItem
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
searchValue: '',
|
|
||||||
allTreeItems: [],
|
|
||||||
filteredTreeItems: [],
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
inject: ['openmct'],
|
||||||
|
name: 'MctTree',
|
||||||
|
components: {
|
||||||
|
search,
|
||||||
|
treeItem
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchValue: '',
|
||||||
|
allTreeItems: [],
|
||||||
|
filteredTreeItems: [],
|
||||||
|
isLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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 {
|
return {
|
||||||
id: this.openmct.objects.makeKeyString(object.identifier),
|
id: this.openmct.objects.makeKeyString(c.identifier),
|
||||||
object,
|
object: c,
|
||||||
objectPath,
|
objectPath: [c],
|
||||||
navigateToParent
|
navigateToParent: '/browse'
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
|
||||||
searchTree(value) {
|
|
||||||
this.searchValue = value;
|
|
||||||
|
|
||||||
if (this.searchValue !== '') {
|
|
||||||
this.getFilteredChildren();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
getFilteredChildren() {
|
||||||
this.searchService = this.openmct.$injector.get('searchService');
|
this.searchService.query(this.searchValue).then(children => {
|
||||||
this.getAllChildren();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-multipane"
|
<div
|
||||||
:class="{
|
class="l-multipane"
|
||||||
'l-multipane--vertical': type === 'vertical',
|
:class="{
|
||||||
'l-multipane--horizontal': type === 'horizontal'
|
'l-multipane--vertical': type === 'vertical',
|
||||||
}">
|
'l-multipane--horizontal': type === 'horizontal'
|
||||||
<slot></slot>
|
}"
|
||||||
</div>
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -13,6 +15,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
|
required: true,
|
||||||
validator: function (value) {
|
validator: function (value) {
|
||||||
return ['vertical', 'horizontal'].indexOf(value) !== -1;
|
return ['vertical', 'horizontal'].indexOf(value) !== -1;
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="l-pane"
|
<div
|
||||||
:class="{
|
class="l-pane"
|
||||||
'l-pane--horizontal-handle-before': type === 'horizontal' && handle === 'before',
|
:class="{
|
||||||
'l-pane--horizontal-handle-after': type === 'horizontal' && handle === 'after',
|
'l-pane--horizontal-handle-before': type === 'horizontal' && handle === 'before',
|
||||||
'l-pane--vertical-handle-before': type === 'vertical' && handle === 'before',
|
'l-pane--horizontal-handle-after': type === 'horizontal' && handle === 'after',
|
||||||
'l-pane--vertical-handle-after': type === 'vertical' && handle === 'after',
|
'l-pane--vertical-handle-before': type === 'vertical' && handle === 'before',
|
||||||
'l-pane--collapsed': collapsed,
|
'l-pane--vertical-handle-after': type === 'vertical' && handle === 'after',
|
||||||
'l-pane--reacts': !handle,
|
'l-pane--collapsed': collapsed,
|
||||||
'l-pane--resizing': resizing === true
|
'l-pane--reacts': !handle,
|
||||||
}">
|
'l-pane--resizing': resizing === true
|
||||||
<div v-if="handle"
|
}"
|
||||||
class="l-pane__handle"
|
>
|
||||||
@mousedown="start">
|
<div
|
||||||
</div>
|
v-if="handle"
|
||||||
<div class="l-pane__header"
|
class="l-pane__handle"
|
||||||
v-if="label">
|
@mousedown="start"
|
||||||
<span class="l-pane__label">{{ label }}</span>
|
></div>
|
||||||
<button class="l-pane__collapse-button c-button"
|
<div
|
||||||
v-if="collapsable"
|
v-if="label"
|
||||||
@click="toggleCollapse"></button>
|
class="l-pane__header"
|
||||||
</div>
|
>
|
||||||
<div class="l-pane__contents">
|
<span class="l-pane__label">{{ label }}</span>
|
||||||
<slot></slot>
|
<button
|
||||||
</div>
|
v-if="collapsable"
|
||||||
|
class="l-pane__collapse-button c-button"
|
||||||
|
@click="toggleCollapse"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="l-pane__contents">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -350,15 +357,19 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
handle: {
|
handle: {
|
||||||
type: String,
|
type: String,
|
||||||
|
default: '',
|
||||||
validator: function (value) {
|
validator: function (value) {
|
||||||
return ['before', 'after'].indexOf(value) !== -1;
|
return ['', 'before', 'after'].indexOf(value) !== -1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
collapsable: {
|
collapsable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
label: String
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -384,7 +395,7 @@ export default {
|
|||||||
delete this.dragCollapse;
|
delete this.dragCollapse;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
trackSize: function() {
|
trackSize: function () {
|
||||||
if (!this.dragCollapse === true) {
|
if (!this.dragCollapse === true) {
|
||||||
if (this.type === 'vertical') {
|
if (this.type === 'vertical') {
|
||||||
this.initial = this.$el.offsetHeight;
|
this.initial = this.$el.offsetHeight;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -152,13 +153,13 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.openmct.indicators.indicatorObjects.forEach((indicator) => {
|
this.openmct.indicators.indicatorObjects.forEach((indicator) => {
|
||||||
this.$el.appendChild(indicator.element);
|
this.$el.appendChild(indicator.element);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,22 +17,27 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="c-message-banner"
|
<div
|
||||||
|
v-if="activeModel.message"
|
||||||
|
class="c-message-banner"
|
||||||
:class="[
|
:class="[
|
||||||
activeModel.severity,
|
activeModel.severity,
|
||||||
{
|
{
|
||||||
'minimized': activeModel.minimized,
|
'minimized': activeModel.minimized,
|
||||||
'new': !activeModel.minimized
|
'new': !activeModel.minimized
|
||||||
}]"
|
}]"
|
||||||
@click="maximize()"
|
@click="maximize()"
|
||||||
v-if="activeModel.message">
|
>
|
||||||
<span class="c-message-banner__message">{{activeModel.message}}</span>
|
<span class="c-message-banner__message">{{ activeModel.message }}</span>
|
||||||
<progress-bar
|
<progress-bar
|
||||||
class="c-message-banner__progress-bar"
|
v-if="activeModel.progressPerc !== undefined"
|
||||||
v-if="activeModel.progressPerc !== undefined" :model="activeModel">
|
class="c-message-banner__progress-bar"
|
||||||
</progress-bar>
|
:model="activeModel"
|
||||||
<button class="c-message-banner__close-button c-click-icon icon-x-in-circle"
|
/>
|
||||||
@click.stop="dismiss()"></button>
|
<button
|
||||||
|
class="c-message-banner__close-button c-click-icon icon-x-in-circle"
|
||||||
|
@click.stop="dismiss()"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -116,127 +121,126 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ProgressBar from '../../components/ProgressBar.vue';
|
import ProgressBar from '../../components/ProgressBar.vue';
|
||||||
let activeNotification = undefined;
|
let activeNotification = undefined;
|
||||||
let dialogService = undefined;
|
let maximizedDialog = undefined;
|
||||||
let maximizedDialog = undefined;
|
let minimizeButton = {
|
||||||
let minimizeButton = {
|
label: 'Dismiss',
|
||||||
label: 'Dismiss',
|
callback: dismissMaximizedDialog
|
||||||
callback: dismissMaximizedDialog
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function dismissMaximizedDialog() {
|
function dismissMaximizedDialog() {
|
||||||
if (maximizedDialog) {
|
if (maximizedDialog) {
|
||||||
maximizedDialog.dismiss();
|
maximizedDialog.dismiss();
|
||||||
maximizedDialog = undefined;
|
maximizedDialog = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMaxProgressBar(progressPerc, progressText) {
|
||||||
|
if (maximizedDialog) {
|
||||||
|
maximizedDialog.updateProgress(progressPerc, progressText);
|
||||||
|
|
||||||
|
if (progressPerc >= 100) {
|
||||||
|
dismissMaximizedDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateMaxProgressBar(progressPerc, progressText) {
|
export default {
|
||||||
if (maximizedDialog) {
|
inject: ['openmct'],
|
||||||
maximizedDialog.updateProgress(progressPerc, progressText);
|
components: {
|
||||||
|
ProgressBar: ProgressBar
|
||||||
if (progressPerc >= 100) {
|
},
|
||||||
dismissMaximizedDialog();
|
data() {
|
||||||
|
return {
|
||||||
|
activeModel: {
|
||||||
|
message: undefined,
|
||||||
|
progressPerc: undefined,
|
||||||
|
progressText: undefined,
|
||||||
|
minimized: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
computed: {
|
||||||
export default {
|
progressWidth() {
|
||||||
inject: ['openmct'],
|
|
||||||
components: {
|
|
||||||
ProgressBar: ProgressBar
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
return {
|
||||||
activeModel: {
|
width: this.activeModel.progress + '%'
|
||||||
message: undefined,
|
};
|
||||||
progressPerc: undefined,
|
}
|
||||||
progressText: undefined,
|
},
|
||||||
minimized: undefined
|
mounted() {
|
||||||
}
|
this.openmct.notifications.on('notification', this.showNotification);
|
||||||
}
|
},
|
||||||
},
|
methods: {
|
||||||
methods: {
|
showNotification(notification) {
|
||||||
showNotification(notification) {
|
if (activeNotification) {
|
||||||
if (activeNotification) {
|
|
||||||
activeNotification.off('progress', this.updateProgress);
|
|
||||||
activeNotification.off('minimized', this.minimized);
|
|
||||||
activeNotification.off('destroy', this.destroyActiveNotification);
|
|
||||||
}
|
|
||||||
activeNotification = notification;
|
|
||||||
this.clearModel();
|
|
||||||
this.applyModel(notification.model);
|
|
||||||
|
|
||||||
activeNotification.once('destroy', this.destroyActiveNotification);
|
|
||||||
activeNotification.on('progress', this.updateProgress);
|
|
||||||
activeNotification.on('minimized', this.minimized);
|
|
||||||
},
|
|
||||||
isEqual(modelA, modelB) {
|
|
||||||
return modelA.message === modelB.message &&
|
|
||||||
modelA.timestamp === modelB.timestamp;
|
|
||||||
},
|
|
||||||
applyModel(model) {
|
|
||||||
Object.keys(model).forEach((key) => this.activeModel[key] = model[key]);
|
|
||||||
},
|
|
||||||
clearModel() {
|
|
||||||
Object.keys(this.activeModel).forEach((key) => this.activeModel[key] = undefined);
|
|
||||||
},
|
|
||||||
updateProgress(progressPerc, progressText) {
|
|
||||||
this.activeModel.progressPerc = progressPerc;
|
|
||||||
this.activeModel.progressText = progressText;
|
|
||||||
},
|
|
||||||
destroyActiveNotification() {
|
|
||||||
this.clearModel();
|
|
||||||
activeNotification.off('destroy', this.destroyActiveNotification);
|
|
||||||
activeNotification = undefined;
|
|
||||||
},
|
|
||||||
dismiss() {
|
|
||||||
if (activeNotification.model.severity === 'info') {
|
|
||||||
activeNotification.dismiss();
|
|
||||||
} else {
|
|
||||||
this.openmct.notifications._minimize(activeNotification);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minimized() {
|
|
||||||
this.activeModel.minimized = true;
|
|
||||||
activeNotification.off('progress', this.updateProgress);
|
activeNotification.off('progress', this.updateProgress);
|
||||||
activeNotification.off('minimized', this.minimized);
|
activeNotification.off('minimized', this.minimized);
|
||||||
|
activeNotification.off('destroy', this.destroyActiveNotification);
|
||||||
|
}
|
||||||
|
activeNotification = notification;
|
||||||
|
this.clearModel();
|
||||||
|
this.applyModel(notification.model);
|
||||||
|
|
||||||
activeNotification.off('progress', updateMaxProgressBar);
|
activeNotification.once('destroy', this.destroyActiveNotification);
|
||||||
activeNotification.off('minimized', dismissMaximizedDialog);
|
activeNotification.on('progress', this.updateProgress);
|
||||||
activeNotification.off('destroy', dismissMaximizedDialog);
|
activeNotification.on('minimized', this.minimized);
|
||||||
},
|
},
|
||||||
maximize() {
|
isEqual(modelA, modelB) {
|
||||||
if (this.activeModel.progressPerc !== undefined) {
|
return modelA.message === modelB.message &&
|
||||||
maximizedDialog = this.openmct.overlays.progressDialog({
|
modelA.timestamp === modelB.timestamp;
|
||||||
buttons: [minimizeButton],
|
},
|
||||||
...this.activeModel
|
applyModel(model) {
|
||||||
});
|
Object.keys(model).forEach((key) => this.activeModel[key] = model[key]);
|
||||||
|
},
|
||||||
activeNotification.on('progress', updateMaxProgressBar);
|
clearModel() {
|
||||||
activeNotification.on('minimized', dismissMaximizedDialog);
|
Object.keys(this.activeModel).forEach((key) => this.activeModel[key] = undefined);
|
||||||
activeNotification.on('destroy', dismissMaximizedDialog);
|
},
|
||||||
|
updateProgress(progressPerc, progressText) {
|
||||||
} else {
|
this.activeModel.progressPerc = progressPerc;
|
||||||
maximizedDialog = this.openmct.overlays.dialog({
|
this.activeModel.progressText = progressText;
|
||||||
iconClass: this.activeModel.severity,
|
},
|
||||||
buttons: [minimizeButton],
|
destroyActiveNotification() {
|
||||||
...this.activeModel
|
this.clearModel();
|
||||||
})
|
activeNotification.off('destroy', this.destroyActiveNotification);
|
||||||
}
|
activeNotification = undefined;
|
||||||
|
},
|
||||||
|
dismiss() {
|
||||||
|
if (activeNotification.model.severity === 'info') {
|
||||||
|
activeNotification.dismiss();
|
||||||
|
} else {
|
||||||
|
this.openmct.notifications._minimize(activeNotification);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
minimized() {
|
||||||
progressWidth() {
|
this.activeModel.minimized = true;
|
||||||
return {
|
activeNotification.off('progress', this.updateProgress);
|
||||||
width: this.activeModel.progress + '%'
|
activeNotification.off('minimized', this.minimized);
|
||||||
};
|
|
||||||
}
|
activeNotification.off('progress', updateMaxProgressBar);
|
||||||
|
activeNotification.off('minimized', dismissMaximizedDialog);
|
||||||
|
activeNotification.off('destroy', dismissMaximizedDialog);
|
||||||
},
|
},
|
||||||
mounted() {
|
maximize() {
|
||||||
this.openmct.notifications.on('notification', this.showNotification);
|
if (this.activeModel.progressPerc !== undefined) {
|
||||||
|
maximizedDialog = this.openmct.overlays.progressDialog({
|
||||||
|
buttons: [minimizeButton],
|
||||||
|
...this.activeModel
|
||||||
|
});
|
||||||
|
|
||||||
|
activeNotification.on('progress', updateMaxProgressBar);
|
||||||
|
activeNotification.on('minimized', dismissMaximizedDialog);
|
||||||
|
activeNotification.on('destroy', dismissMaximizedDialog);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
maximizedDialog = this.openmct.overlays.dialog({
|
||||||
|
iconClass: this.activeModel.severity,
|
||||||
|
buttons: [minimizeButton],
|
||||||
|
...this.activeModel
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,136 +1,149 @@
|
|||||||
<template>
|
<template>
|
||||||
<li class="c-tree__item-h">
|
<li class="c-tree__item-h">
|
||||||
<div class="c-tree__item"
|
<div
|
||||||
:class="{ 'is-alias': isAlias, 'is-navigated-object': isNavigated }">
|
class="c-tree__item"
|
||||||
<view-control class="c-tree__item__view-control"
|
:class="{ 'is-alias': isAlias, 'is-navigated-object': isNavigated }"
|
||||||
:enabled="hasChildren"
|
>
|
||||||
v-model="expanded">
|
<view-control
|
||||||
</view-control>
|
v-model="expanded"
|
||||||
<object-label :domainObject="node.object"
|
class="c-tree__item__view-control"
|
||||||
:objectPath="node.objectPath"
|
:enabled="hasChildren"
|
||||||
:navigateToPath="navigateToPath">
|
/>
|
||||||
</object-label>
|
<object-label
|
||||||
</div>
|
:domain-object="node.object"
|
||||||
<ul v-if="expanded" class="c-tree">
|
:object-path="node.objectPath"
|
||||||
<li class="c-tree__item-h"
|
:navigate-to-path="navigateToPath"
|
||||||
v-if="isLoading && !loaded">
|
/>
|
||||||
<div class="c-tree__item loading">
|
</div>
|
||||||
<span class="c-tree__item__label">Loading...</span>
|
<ul
|
||||||
</div>
|
v-if="expanded"
|
||||||
</li>
|
class="c-tree"
|
||||||
<tree-item v-for="child in children"
|
>
|
||||||
:key="child.id"
|
<li
|
||||||
:node="child">
|
v-if="isLoading && !loaded"
|
||||||
</tree-item>
|
class="c-tree__item-h"
|
||||||
</ul>
|
>
|
||||||
</li>
|
<div class="c-tree__item loading">
|
||||||
|
<span class="c-tree__item__label">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<tree-item
|
||||||
|
v-for="child in children"
|
||||||
|
:key="child.id"
|
||||||
|
:node="child"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import viewControl from '../components/viewControl.vue';
|
import viewControl from '../components/viewControl.vue';
|
||||||
import ObjectLabel from '../components/ObjectLabel.vue';
|
import ObjectLabel from '../components/ObjectLabel.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'tree-item',
|
name: 'TreeItem',
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
components: {
|
||||||
node: Object
|
viewControl,
|
||||||
},
|
ObjectLabel
|
||||||
data() {
|
},
|
||||||
this.navigateToPath = this.buildPathString(this.node.navigateToParent)
|
props: {
|
||||||
return {
|
node: {
|
||||||
hasChildren: false,
|
type: Object,
|
||||||
isLoading: false,
|
required: true
|
||||||
loaded: false,
|
}
|
||||||
isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path,
|
},
|
||||||
children: [],
|
data() {
|
||||||
expanded: false
|
this.navigateToPath = this.buildPathString(this.node.navigateToParent)
|
||||||
|
return {
|
||||||
|
hasChildren: false,
|
||||||
|
isLoading: false,
|
||||||
|
loaded: false,
|
||||||
|
isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path,
|
||||||
|
children: [],
|
||||||
|
expanded: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isAlias() {
|
||||||
|
let parent = this.node.objectPath[1];
|
||||||
|
if (!parent) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
},
|
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
|
||||||
computed: {
|
return parentKeyString !== this.node.object.location;
|
||||||
isAlias() {
|
}
|
||||||
let parent = this.node.objectPath[1];
|
},
|
||||||
if (!parent) {
|
watch: {
|
||||||
return false;
|
expanded(isExpanded) {
|
||||||
}
|
if (!this.hasChildren) {
|
||||||
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
|
return;
|
||||||
return parentKeyString !== this.node.object.location;
|
|
||||||
}
|
}
|
||||||
},
|
if (!this.loaded && !this.isLoading) {
|
||||||
mounted() {
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
// TODO: should update on mutation.
|
this.composition.on('add', this.addChild);
|
||||||
// TODO: click navigation should not fubar hash quite so much.
|
this.composition.on('remove', this.removeChild);
|
||||||
// TODO: should highlight if navigated to.
|
this.composition.load().then(this.finishLoading);
|
||||||
// TODO: should have context menu.
|
this.isLoading = true;
|
||||||
// TODO: should support drag/drop composition
|
}
|
||||||
// TODO: set isAlias per tree-item
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// TODO: should update on mutation.
|
||||||
|
// TODO: click navigation should not fubar hash quite so much.
|
||||||
|
// TODO: should highlight if navigated to.
|
||||||
|
// TODO: should have context menu.
|
||||||
|
// TODO: should support drag/drop composition
|
||||||
|
// TODO: set isAlias per tree-item
|
||||||
|
|
||||||
this.domainObject = this.node.object;
|
this.domainObject = this.node.object;
|
||||||
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
||||||
this.domainObject = newObject;
|
this.domainObject = newObject;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$once('hook:destroyed', removeListener);
|
||||||
|
if (this.openmct.composition.get(this.node.object)) {
|
||||||
|
this.hasChildren = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
||||||
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$once('hook:destroyed', removeListener);
|
|
||||||
if (this.openmct.composition.get(this.node.object)) {
|
|
||||||
this.hasChildren = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
removeChild(identifier) {
|
||||||
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
let removeId = this.openmct.objects.makeKeyString(identifier);
|
||||||
if (this.composition) {
|
this.children = this.children
|
||||||
this.composition.off('add', this.addChild);
|
.filter(c => c.id !== removeId);
|
||||||
this.composition.off('remove', this.removeChild);
|
|
||||||
delete this.composition;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
finishLoading() {
|
||||||
expanded(isExpanded) {
|
this.isLoading = false;
|
||||||
if (!this.hasChildren) {
|
this.loaded = true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
buildPathString(parentPath) {
|
||||||
addChild (child) {
|
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
|
||||||
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;
|
|
||||||
},
|
|
||||||
buildPathString(parentPath) {
|
|
||||||
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
|
|
||||||
},
|
|
||||||
highlightIfNavigated(newPath, oldPath){
|
|
||||||
if (newPath === this.navigateToPath) {
|
|
||||||
this.isNavigated = true;
|
|
||||||
} else if (oldPath === this.navigateToPath) {
|
|
||||||
this.isNavigated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
components: {
|
highlightIfNavigated(newPath, oldPath) {
|
||||||
viewControl,
|
if (newPath === this.navigateToPath) {
|
||||||
ObjectLabel
|
this.isNavigated = true;
|
||||||
|
} else if (oldPath === this.navigateToPath) {
|
||||||
|
this.isNavigated = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
templateKey: String
|
templateKey: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let openmct = this.openmct;
|
let openmct = this.openmct;
|
||||||
|
@ -19,37 +19,40 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="l-preview-window">
|
<div class="l-preview-window">
|
||||||
<div class="l-browse-bar">
|
<div class="l-browse-bar">
|
||||||
<div class="l-browse-bar__start">
|
<div class="l-browse-bar__start">
|
||||||
<div class="l-browse-bar__object-name--w"
|
<div
|
||||||
:class="type.cssClass">
|
class="l-browse-bar__object-name--w"
|
||||||
<span class="l-browse-bar__object-name">
|
:class="type.cssClass"
|
||||||
{{ domainObject.name }}
|
>
|
||||||
</span>
|
<span class="l-browse-bar__object-name">
|
||||||
<context-menu-drop-down :object-path="objectPath"></context-menu-drop-down>
|
{{ domainObject.name }}
|
||||||
</div>
|
</span>
|
||||||
</div>
|
<context-menu-drop-down :object-path="objectPath" />
|
||||||
<div class="l-browse-bar__end">
|
|
||||||
<div class="l-browse-bar__actions">
|
|
||||||
<view-switcher
|
|
||||||
:views="views"
|
|
||||||
:currentView="currentView"
|
|
||||||
@setView="setView">
|
|
||||||
</view-switcher>
|
|
||||||
<button v-if="notebookEnabled"
|
|
||||||
class="l-browse-bar__actions__edit c-button icon-notebook"
|
|
||||||
title="New Notebook entry"
|
|
||||||
@click="snapshot">
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="l-preview-window__object-view">
|
<div class="l-browse-bar__end">
|
||||||
<div ref="objectView"></div>
|
<div class="l-browse-bar__actions">
|
||||||
|
<view-switcher
|
||||||
|
:views="views"
|
||||||
|
:current-view="currentView"
|
||||||
|
@setView="setView"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="notebookEnabled"
|
||||||
|
class="l-browse-bar__actions__edit c-button icon-notebook"
|
||||||
|
title="New Notebook entry"
|
||||||
|
@click="snapshot"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="l-preview-window__object-view">
|
||||||
|
<div ref="objectView"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~styles/sass-base';
|
@import '~styles/sass-base';
|
||||||
@ -83,78 +86,78 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContextMenuDropDown from '../../ui/components/contextMenuDropDown.vue';
|
import ContextMenuDropDown from '../../ui/components/contextMenuDropDown.vue';
|
||||||
import ViewSwitcher from '../../ui/layout/ViewSwitcher.vue';
|
import ViewSwitcher from '../../ui/layout/ViewSwitcher.vue';
|
||||||
import NotebookSnapshot from '../utils/notebook-snapshot';
|
import NotebookSnapshot from '../utils/notebook-snapshot';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ContextMenuDropDown,
|
ContextMenuDropDown,
|
||||||
ViewSwitcher
|
ViewSwitcher
|
||||||
|
},
|
||||||
|
inject: [
|
||||||
|
'openmct',
|
||||||
|
'objectPath'
|
||||||
|
],
|
||||||
|
data() {
|
||||||
|
let domainObject = this.objectPath[0];
|
||||||
|
let type = this.openmct.types.get(domainObject.type);
|
||||||
|
|
||||||
|
return {
|
||||||
|
domainObject: domainObject,
|
||||||
|
type: type,
|
||||||
|
notebookEnabled: false,
|
||||||
|
viewKey: undefined
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
views() {
|
||||||
|
return this
|
||||||
|
.openmct
|
||||||
|
.objectViews
|
||||||
|
.get(this.domainObject);
|
||||||
},
|
},
|
||||||
inject: [
|
currentView() {
|
||||||
'openmct',
|
return this.views.filter(v => v.key === this.viewKey)[0] || {};
|
||||||
'objectPath'
|
}
|
||||||
],
|
},
|
||||||
computed: {
|
mounted() {
|
||||||
views() {
|
let view = this.openmct.objectViews.get(this.domainObject)[0];
|
||||||
return this
|
this.setView(view);
|
||||||
.openmct
|
|
||||||
.objectViews
|
if (this.openmct.types.get('notebook')) {
|
||||||
.get(this.domainObject);
|
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
|
||||||
},
|
this.notebookEnabled = true;
|
||||||
currentView() {
|
}
|
||||||
return this.views.filter(v => v.key === this.viewKey)[0] || {};
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.view.destroy();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
snapshot() {
|
||||||
|
let element = document.getElementsByClassName("l-preview-window__object-view")[0];
|
||||||
|
this.notebookSnapshot.capture(this.domainObject, element);
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
if (this.view) {
|
||||||
|
this.view.destroy();
|
||||||
|
this.$refs.objectView.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
delete this.view;
|
||||||
|
delete this.viewContainer;
|
||||||
},
|
},
|
||||||
methods: {
|
setView(view) {
|
||||||
snapshot() {
|
this.clear();
|
||||||
let element = document.getElementsByClassName("l-preview-window__object-view")[0];
|
|
||||||
this.notebookSnapshot.capture(this.domainObject, element);
|
|
||||||
},
|
|
||||||
clear() {
|
|
||||||
if (this.view) {
|
|
||||||
this.view.destroy();
|
|
||||||
this.$refs.objectView.innerHTML = '';
|
|
||||||
}
|
|
||||||
delete this.view;
|
|
||||||
delete this.viewContainer;
|
|
||||||
},
|
|
||||||
setView(view) {
|
|
||||||
this.clear();
|
|
||||||
|
|
||||||
this.viewKey = view.key;
|
this.viewKey = view.key;
|
||||||
this.viewContainer = document.createElement('div');
|
this.viewContainer = document.createElement('div');
|
||||||
this.viewContainer.classList.add('c-object-view','u-contents');
|
this.viewContainer.classList.add('c-object-view','u-contents');
|
||||||
this.$refs.objectView.append(this.viewContainer);
|
this.$refs.objectView.append(this.viewContainer);
|
||||||
|
|
||||||
this.view = this.currentView.view(this.domainObject, this.objectPath);
|
this.view = this.currentView.view(this.domainObject, this.objectPath);
|
||||||
this.view.show(this.viewContainer, false);
|
this.view.show(this.viewContainer, false);
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
let domainObject = this.objectPath[0];
|
|
||||||
let type = this.openmct.types.get(domainObject.type);
|
|
||||||
|
|
||||||
return {
|
|
||||||
domainObject: domainObject,
|
|
||||||
type: type,
|
|
||||||
notebookEnabled: false,
|
|
||||||
viewKey: undefined
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let view = this.openmct.objectViews.get(this.domainObject)[0];
|
|
||||||
this.setView(view);
|
|
||||||
|
|
||||||
if (this.openmct.types.get('notebook')) {
|
|
||||||
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
|
|
||||||
this.notebookEnabled = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.view.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
|
@ -1,267 +1,270 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-toolbar">
|
<div class="c-toolbar">
|
||||||
<component v-for="item in structure"
|
<component
|
||||||
:is="item.control"
|
:is="item.control"
|
||||||
:options="item"
|
v-for="(item, index) in structure"
|
||||||
@click="triggerMethod(item, $event)"
|
:key="index"
|
||||||
@change="updateObjectValue"></component>
|
:options="item"
|
||||||
</div>
|
@click="triggerMethod(item, $event)"
|
||||||
|
@change="updateObjectValue"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import toolbarButton from './components/toolbar-button.vue';
|
import toolbarButton from './components/toolbar-button.vue';
|
||||||
import toolbarColorPicker from './components/toolbar-color-picker.vue';
|
import toolbarColorPicker from './components/toolbar-color-picker.vue';
|
||||||
import toolbarCheckbox from './components/toolbar-checkbox.vue';
|
import toolbarCheckbox from './components/toolbar-checkbox.vue';
|
||||||
import toolbarInput from './components/toolbar-input.vue';
|
import toolbarInput from './components/toolbar-input.vue';
|
||||||
import toolbarMenu from './components/toolbar-menu.vue';
|
import toolbarMenu from './components/toolbar-menu.vue';
|
||||||
import toolbarSelectMenu from './components/toolbar-select-menu.vue';
|
import toolbarSelectMenu from './components/toolbar-select-menu.vue';
|
||||||
import toolbarSeparator from './components/toolbar-separator.vue';
|
import toolbarSeparator from './components/toolbar-separator.vue';
|
||||||
import toolbarToggleButton from './components/toolbar-toggle-button.vue';
|
import toolbarToggleButton from './components/toolbar-toggle-button.vue';
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
components: {
|
components: {
|
||||||
toolbarButton,
|
toolbarButton,
|
||||||
toolbarColorPicker,
|
toolbarColorPicker,
|
||||||
toolbarCheckbox,
|
toolbarCheckbox,
|
||||||
toolbarInput,
|
toolbarInput,
|
||||||
toolbarMenu,
|
toolbarMenu,
|
||||||
toolbarSelectMenu,
|
toolbarSelectMenu,
|
||||||
toolbarSeparator,
|
toolbarSeparator,
|
||||||
toolbarToggleButton
|
toolbarToggleButton
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
structure: []
|
structure: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
mounted() {
|
||||||
handleSelection(selection) {
|
this.openmct.selection.on('change', this.handleSelection);
|
||||||
this.removeListeners();
|
this.handleSelection(this.openmct.selection.get());
|
||||||
this.domainObjectsById = {};
|
|
||||||
|
|
||||||
if (selection.length === 0 || !selection[0][0]) {
|
// Toolbars may change when edit mode is enabled/disabled, so listen
|
||||||
this.structure = [];
|
// for edit mode changes and update toolbars if necessary.
|
||||||
return;
|
this.openmct.editor.on('isEditing', this.handleEditing);
|
||||||
}
|
},
|
||||||
|
methods: {
|
||||||
|
handleSelection(selection) {
|
||||||
|
this.removeListeners();
|
||||||
|
this.domainObjectsById = {};
|
||||||
|
|
||||||
let structure = this.openmct.toolbars.get(selection) || [];
|
if (selection.length === 0 || !selection[0][0]) {
|
||||||
this.structure = structure.map(toolbarItem => {
|
this.structure = [];
|
||||||
let domainObject = toolbarItem.domainObject;
|
return;
|
||||||
let formKeys = [];
|
}
|
||||||
toolbarItem.control = "toolbar-" + toolbarItem.control;
|
|
||||||
|
|
||||||
if (toolbarItem.dialog) {
|
let structure = this.openmct.toolbars.get(selection) || [];
|
||||||
toolbarItem.dialog.sections.forEach(section => {
|
this.structure = structure.map(toolbarItem => {
|
||||||
section.rows.forEach(row => {
|
let domainObject = toolbarItem.domainObject;
|
||||||
formKeys.push(row.key);
|
let formKeys = [];
|
||||||
})
|
toolbarItem.control = "toolbar-" + toolbarItem.control;
|
||||||
});
|
|
||||||
toolbarItem.formKeys = formKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domainObject) {
|
if (toolbarItem.dialog) {
|
||||||
toolbarItem.value = this.getValue(domainObject, toolbarItem);
|
toolbarItem.dialog.sections.forEach(section => {
|
||||||
this.registerListener(domainObject);
|
section.rows.forEach(row => {
|
||||||
}
|
formKeys.push(row.key);
|
||||||
|
})
|
||||||
return toolbarItem;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
registerListener(domainObject) {
|
|
||||||
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
|
||||||
|
|
||||||
if (!this.domainObjectsById[id]) {
|
|
||||||
this.domainObjectsById[id] = {
|
|
||||||
domainObject: domainObject
|
|
||||||
}
|
|
||||||
this.observeObject(domainObject, id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
observeObject(domainObject, id) {
|
|
||||||
let unobserveObject = this.openmct.objects.observe(domainObject, '*', function(newObject) {
|
|
||||||
this.domainObjectsById[id].newObject = JSON.parse(JSON.stringify(newObject));
|
|
||||||
this.updateToolbarAfterMutation();
|
|
||||||
}.bind(this));
|
|
||||||
this.unObserveObjects.push(unobserveObject);
|
|
||||||
},
|
|
||||||
updateToolbarAfterMutation() {
|
|
||||||
this.structure = this.structure.map(toolbarItem => {
|
|
||||||
let domainObject = toolbarItem.domainObject;
|
|
||||||
|
|
||||||
if (domainObject) {
|
|
||||||
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
|
||||||
let newObject = this.domainObjectsById[id].newObject;
|
|
||||||
|
|
||||||
if (newObject) {
|
|
||||||
toolbarItem.domainObject = newObject;
|
|
||||||
toolbarItem.value = this.getValue(newObject, toolbarItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toolbarItem;
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(this.domainObjectsById).forEach(function (tracker) {
|
|
||||||
if (tracker.newObject) {
|
|
||||||
tracker.domainObject = tracker.newObject;
|
|
||||||
delete tracker.newObject;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getValue(domainObject, toolbarItem) {
|
|
||||||
let value = undefined;
|
|
||||||
let applicableSelectedItems = toolbarItem.applicableSelectedItems;
|
|
||||||
|
|
||||||
if (!applicableSelectedItems && !toolbarItem.property) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toolbarItem.formKeys) {
|
|
||||||
value = this.getFormValue(domainObject, toolbarItem);
|
|
||||||
} else {
|
|
||||||
let values = [];
|
|
||||||
|
|
||||||
if (applicableSelectedItems) {
|
|
||||||
applicableSelectedItems.forEach(selectionPath => {
|
|
||||||
values.push(this.getPropertyValue(domainObject, toolbarItem, selectionPath));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
values.push(this.getPropertyValue(domainObject, toolbarItem));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all values are the same, use it, otherwise mark the item as non-specific.
|
|
||||||
if (values.every(value => value === values[0])) {
|
|
||||||
value = values[0];
|
|
||||||
toolbarItem.nonSpecific = false;
|
|
||||||
} else {
|
|
||||||
toolbarItem.nonSpecific = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
getPropertyValue(domainObject, toolbarItem, selectionPath, formKey) {
|
|
||||||
let property = this.getItemProperty(toolbarItem, selectionPath);
|
|
||||||
|
|
||||||
if (formKey) {
|
|
||||||
property = property + "." + formKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _.get(domainObject, property);
|
|
||||||
},
|
|
||||||
getFormValue(domainObject, toolbarItem) {
|
|
||||||
let value = {};
|
|
||||||
let values = {};
|
|
||||||
|
|
||||||
toolbarItem.formKeys.map(key => {
|
|
||||||
values[key] = [];
|
|
||||||
|
|
||||||
if (toolbarItem.applicableSelectedItems) {
|
|
||||||
toolbarItem.applicableSelectedItems.forEach(selectionPath => {
|
|
||||||
values[key].push(this.getPropertyValue(domainObject, toolbarItem, selectionPath, key));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
values[key].push(this.getPropertyValue(domainObject, toolbarItem, undefined, key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const key in values) {
|
|
||||||
if (values[key].every(value => value === values[key][0])) {
|
|
||||||
value[key] = values[key][0];
|
|
||||||
toolbarItem.nonSpecific = false;
|
|
||||||
} else {
|
|
||||||
toolbarItem.nonSpecific = true;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
getItemProperty(item, selectionPath) {
|
|
||||||
return (typeof item.property === "function") ? item.property(selectionPath) : item.property;
|
|
||||||
},
|
|
||||||
removeListeners() {
|
|
||||||
if (this.unObserveObjects) {
|
|
||||||
this.unObserveObjects.forEach((unObserveObject) => {
|
|
||||||
unObserveObject();
|
|
||||||
});
|
});
|
||||||
}
|
toolbarItem.formKeys = formKeys;
|
||||||
this.unObserveObjects = [];
|
|
||||||
},
|
|
||||||
updateObjectValue(value, item) {
|
|
||||||
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
|
||||||
|
|
||||||
this.structure = this.structure.map(toolbarItem => {
|
|
||||||
if (toolbarItem.domainObject) {
|
|
||||||
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
|
||||||
|
|
||||||
if (changedItemId === id && _.isEqual(toolbarItem, item)) {
|
|
||||||
toolbarItem.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toolbarItem;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If value is an object, iterate the toolbar structure and mutate all keys in form.
|
|
||||||
// Otherwise, mutate the property.
|
|
||||||
if (value === Object(value)) {
|
|
||||||
this.structure.map(s => {
|
|
||||||
if (s.formKeys) {
|
|
||||||
s.formKeys.forEach(key => {
|
|
||||||
if (item.applicableSelectedItems) {
|
|
||||||
item.applicableSelectedItems.forEach(selectionPath => {
|
|
||||||
this.mutateObject(item, value[key], selectionPath, key);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.mutateObject(item, value[key], undefined, key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (item.applicableSelectedItems) {
|
|
||||||
item.applicableSelectedItems.forEach(selectionPath => {
|
|
||||||
this.mutateObject(item, value, selectionPath);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.mutateObject(item, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mutateObject(item, value, selectionPath, formKey) {
|
|
||||||
let property = this.getItemProperty(item, selectionPath);
|
|
||||||
|
|
||||||
if (formKey) {
|
|
||||||
property = property + "." + formKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.openmct.objects.mutate(item.domainObject, property, value);
|
if (domainObject) {
|
||||||
},
|
toolbarItem.value = this.getValue(domainObject, toolbarItem);
|
||||||
triggerMethod(item, event) {
|
this.registerListener(domainObject);
|
||||||
if (item.method) {
|
|
||||||
item.method({...event});
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
handleEditing(isEditing) {
|
return toolbarItem;
|
||||||
this.handleSelection(this.openmct.selection.get());
|
});
|
||||||
|
},
|
||||||
|
registerListener(domainObject) {
|
||||||
|
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
|
||||||
|
if (!this.domainObjectsById[id]) {
|
||||||
|
this.domainObjectsById[id] = {
|
||||||
|
domainObject: domainObject
|
||||||
|
}
|
||||||
|
this.observeObject(domainObject, id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
observeObject(domainObject, id) {
|
||||||
this.openmct.selection.on('change', this.handleSelection);
|
let unobserveObject = this.openmct.objects.observe(domainObject, '*', function (newObject) {
|
||||||
this.handleSelection(this.openmct.selection.get());
|
this.domainObjectsById[id].newObject = JSON.parse(JSON.stringify(newObject));
|
||||||
|
this.updateToolbarAfterMutation();
|
||||||
// Toolbars may change when edit mode is enabled/disabled, so listen
|
}.bind(this));
|
||||||
// for edit mode changes and update toolbars if necessary.
|
this.unObserveObjects.push(unobserveObject);
|
||||||
this.openmct.editor.on('isEditing', this.handleEditing);
|
|
||||||
},
|
},
|
||||||
detroyed() {
|
updateToolbarAfterMutation() {
|
||||||
this.openmct.selection.off('change', this.handleSelection);
|
this.structure = this.structure.map(toolbarItem => {
|
||||||
this.openmct.editor.off('isEditing', this.handleEditing);
|
let domainObject = toolbarItem.domainObject;
|
||||||
this.removeListeners();
|
|
||||||
|
if (domainObject) {
|
||||||
|
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
let newObject = this.domainObjectsById[id].newObject;
|
||||||
|
|
||||||
|
if (newObject) {
|
||||||
|
toolbarItem.domainObject = newObject;
|
||||||
|
toolbarItem.value = this.getValue(newObject, toolbarItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolbarItem;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.values(this.domainObjectsById).forEach(function (tracker) {
|
||||||
|
if (tracker.newObject) {
|
||||||
|
tracker.domainObject = tracker.newObject;
|
||||||
|
delete tracker.newObject;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getValue(domainObject, toolbarItem) {
|
||||||
|
let value = undefined;
|
||||||
|
let applicableSelectedItems = toolbarItem.applicableSelectedItems;
|
||||||
|
|
||||||
|
if (!applicableSelectedItems && !toolbarItem.property) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbarItem.formKeys) {
|
||||||
|
value = this.getFormValue(domainObject, toolbarItem);
|
||||||
|
} else {
|
||||||
|
let values = [];
|
||||||
|
|
||||||
|
if (applicableSelectedItems) {
|
||||||
|
applicableSelectedItems.forEach(selectionPath => {
|
||||||
|
values.push(this.getPropertyValue(domainObject, toolbarItem, selectionPath));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
values.push(this.getPropertyValue(domainObject, toolbarItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all values are the same, use it, otherwise mark the item as non-specific.
|
||||||
|
if (values.every(val => val === values[0])) {
|
||||||
|
value = values[0];
|
||||||
|
toolbarItem.nonSpecific = false;
|
||||||
|
} else {
|
||||||
|
toolbarItem.nonSpecific = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
getPropertyValue(domainObject, toolbarItem, selectionPath, formKey) {
|
||||||
|
let property = this.getItemProperty(toolbarItem, selectionPath);
|
||||||
|
|
||||||
|
if (formKey) {
|
||||||
|
property = property + "." + formKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _.get(domainObject, property);
|
||||||
|
},
|
||||||
|
getFormValue(domainObject, toolbarItem) {
|
||||||
|
let value = {};
|
||||||
|
let values = {};
|
||||||
|
|
||||||
|
toolbarItem.formKeys.map(key => {
|
||||||
|
values[key] = [];
|
||||||
|
|
||||||
|
if (toolbarItem.applicableSelectedItems) {
|
||||||
|
toolbarItem.applicableSelectedItems.forEach(selectionPath => {
|
||||||
|
values[key].push(this.getPropertyValue(domainObject, toolbarItem, selectionPath, key));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
values[key].push(this.getPropertyValue(domainObject, toolbarItem, undefined, key));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const key in values) {
|
||||||
|
if (values[key].every(val => val === values[key][0])) {
|
||||||
|
value[key] = values[key][0];
|
||||||
|
toolbarItem.nonSpecific = false;
|
||||||
|
} else {
|
||||||
|
toolbarItem.nonSpecific = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
getItemProperty(item, selectionPath) {
|
||||||
|
return (typeof item.property === "function") ? item.property(selectionPath) : item.property;
|
||||||
|
},
|
||||||
|
removeListeners() {
|
||||||
|
if (this.unObserveObjects) {
|
||||||
|
this.unObserveObjects.forEach((unObserveObject) => {
|
||||||
|
unObserveObject();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.unObserveObjects = [];
|
||||||
|
},
|
||||||
|
updateObjectValue(value, item) {
|
||||||
|
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
||||||
|
|
||||||
|
this.structure = this.structure.map(toolbarItem => {
|
||||||
|
if (toolbarItem.domainObject) {
|
||||||
|
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
||||||
|
|
||||||
|
if (changedItemId === id && _.isEqual(toolbarItem, item)) {
|
||||||
|
toolbarItem.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolbarItem;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If value is an object, iterate the toolbar structure and mutate all keys in form.
|
||||||
|
// Otherwise, mutate the property.
|
||||||
|
if (value === Object(value)) {
|
||||||
|
this.structure.map(s => {
|
||||||
|
if (s.formKeys) {
|
||||||
|
s.formKeys.forEach(key => {
|
||||||
|
if (item.applicableSelectedItems) {
|
||||||
|
item.applicableSelectedItems.forEach(selectionPath => {
|
||||||
|
this.mutateObject(item, value[key], selectionPath, key);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.mutateObject(item, value[key], undefined, key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (item.applicableSelectedItems) {
|
||||||
|
item.applicableSelectedItems.forEach(selectionPath => {
|
||||||
|
this.mutateObject(item, value, selectionPath);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.mutateObject(item, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutateObject(item, value, selectionPath, formKey) {
|
||||||
|
let property = this.getItemProperty(item, selectionPath);
|
||||||
|
|
||||||
|
if (formKey) {
|
||||||
|
property = property + "." + formKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.objects.mutate(item.domainObject, property, value);
|
||||||
|
},
|
||||||
|
triggerMethod(item, event) {
|
||||||
|
if (item.method) {
|
||||||
|
item.method({...event});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleEditing(isEditing) {
|
||||||
|
this.handleSelection(this.openmct.selection.get());
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
detroyed() {
|
||||||
|
this.openmct.selection.off('change', this.handleSelection);
|
||||||
|
this.openmct.editor.off('isEditing', this.handleEditing);
|
||||||
|
this.removeListeners();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,26 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper">
|
<div class="c-ctrl-wrapper">
|
||||||
<div class="c-icon-button"
|
<div
|
||||||
:title="options.title"
|
class="c-icon-button"
|
||||||
:class="{
|
:title="options.title"
|
||||||
[options.icon]: true,
|
:class="{
|
||||||
'c-icon-button--caution': options.modifier === 'caution',
|
[options.icon]: true,
|
||||||
'c-icon-button--mixed': nonSpecific
|
'c-icon-button--caution': options.modifier === 'caution',
|
||||||
}"
|
'c-icon-button--mixed': nonSpecific
|
||||||
@click="onClick">
|
}"
|
||||||
<div class="c-icon-button__label"
|
@click="onClick"
|
||||||
v-if="options.label">
|
>
|
||||||
{{ options.label }}
|
<div
|
||||||
</div>
|
v-if="options.label"
|
||||||
|
class="c-icon-button__label"
|
||||||
|
>
|
||||||
|
{{ options.label }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
options: Object
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
nonSpecific() {
|
nonSpecific() {
|
||||||
@ -31,10 +38,10 @@ export default {
|
|||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (this.options.dialog) {
|
if (this.options.dialog) {
|
||||||
this.openmct.$injector.get('dialogService')
|
this.openmct.$injector.get('dialogService')
|
||||||
.getUserInput(this.options.dialog, this.options.value)
|
.getUserInput(this.options.dialog, this.options.value)
|
||||||
.then(value => {
|
.then(value => {
|
||||||
this.$emit('change', {...value}, this.options);
|
this.$emit('change', {...value}, this.options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.$emit('click', this.options);
|
this.$emit('click', this.options);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-custom-checkbox">
|
<div class="c-custom-checkbox">
|
||||||
<input type="checkbox"
|
<input
|
||||||
:id="uid"
|
:id="uid"
|
||||||
:name="options.name"
|
type="checkbox"
|
||||||
:checked="options.value"
|
:name="options.name"
|
||||||
:disabled="options.disabled"
|
:checked="options.value"
|
||||||
@change="onChange">
|
:disabled="options.disabled"
|
||||||
|
@change="onChange"
|
||||||
|
>
|
||||||
|
|
||||||
<label :for="uid">
|
<label :for="uid">
|
||||||
<div class="c-custom-checkbox__box"></div>
|
<div class="c-custom-checkbox__box"></div>
|
||||||
<div class="c-custom-checkbox__label-text">
|
<div class="c-custom-checkbox__label-text">
|
||||||
{{options.name}}
|
{{ options.name }}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -72,7 +74,10 @@ let uniqueId = 100;
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
options: Object
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
uniqueId++;
|
uniqueId++;
|
||||||
|
@ -1,30 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper">
|
<div class="c-ctrl-wrapper">
|
||||||
<div class="c-icon-button c-icon-button--swatched"
|
<div
|
||||||
:class="[options.icon, {'c-icon-button--mixed': nonSpecific}]"
|
class="c-icon-button c-icon-button--swatched"
|
||||||
:title="options.title"
|
:class="[options.icon, {'c-icon-button--mixed': nonSpecific}]"
|
||||||
@click="toggle">
|
:title="options.title"
|
||||||
<div class="c-swatch" :style="{
|
@click="toggle"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="c-swatch"
|
||||||
|
:style="{
|
||||||
background: options.value
|
background: options.value
|
||||||
}"></div>
|
}"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="open"
|
||||||
|
class="c-menu c-palette c-palette--color"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="!options.preventNone"
|
||||||
|
class="c-palette__item-none"
|
||||||
|
@click="select({value: 'transparent'})"
|
||||||
|
>
|
||||||
|
<div class="c-palette__item"></div>
|
||||||
|
None
|
||||||
</div>
|
</div>
|
||||||
<div class="c-menu c-palette c-palette--color"
|
<div class="c-palette__items">
|
||||||
v-if="open">
|
<div
|
||||||
<div class="c-palette__item-none"
|
v-for="(color, index) in colorPalette"
|
||||||
v-if="!this.options.preventNone"
|
:key="index"
|
||||||
@click="select({value: 'transparent'})">
|
class="c-palette__item"
|
||||||
<div class="c-palette__item"></div>
|
:style="{ background: color.value }"
|
||||||
None
|
@click="select(color)"
|
||||||
</div>
|
></div>
|
||||||
<div class="c-palette__items">
|
|
||||||
<div class="c-palette__item"
|
|
||||||
v-for="color in colorPalette"
|
|
||||||
:style="{ background: color.value }"
|
|
||||||
@click="select(color)"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -34,18 +45,9 @@ import toggleMixin from '../../mixins/toggle-mixin';
|
|||||||
export default {
|
export default {
|
||||||
mixins: [toggleMixin],
|
mixins: [toggleMixin],
|
||||||
props: {
|
props: {
|
||||||
options: Object
|
options: {
|
||||||
},
|
type: Object,
|
||||||
computed: {
|
required: true
|
||||||
nonSpecific() {
|
|
||||||
return this.options.nonSpecific === true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
select(color) {
|
|
||||||
if (color.value !== this.options.value) {
|
|
||||||
this.$emit('change', color.value, this.options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -133,6 +135,18 @@ export default {
|
|||||||
{ value: '#4c1130' }
|
{ value: '#4c1130' }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
nonSpecific() {
|
||||||
|
return this.options.nonSpecific === true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
select(color) {
|
||||||
|
if (color.value !== this.options.value) {
|
||||||
|
this.$emit('change', color.value, this.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-labeled-input"
|
<div
|
||||||
:title="options.title">
|
class="c-labeled-input"
|
||||||
<label :for="uid">
|
:title="options.title"
|
||||||
<div class="c-labeled-input__label">{{ options.label }}</div>
|
>
|
||||||
</label>
|
<label :for="uid">
|
||||||
<input :id="uid"
|
<div class="c-labeled-input__label">{{ options.label }}</div>
|
||||||
:type="options.type"
|
</label>
|
||||||
:value="options.value"
|
<input
|
||||||
v-bind="options.attrs"/>
|
:id="uid"
|
||||||
</div>
|
:type="options.type"
|
||||||
|
:value="options.value"
|
||||||
|
v-bind="options.attrs"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -19,6 +23,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
required: true,
|
||||||
validator(value) {
|
validator(value) {
|
||||||
return ['number', 'text'].indexOf(value.type) !== -1;
|
return ['number', 'text'].indexOf(value.type) !== -1;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper">
|
<div class="c-ctrl-wrapper">
|
||||||
<div class="c-icon-button c-icon-button--menu"
|
<div
|
||||||
:class="options.icon"
|
class="c-icon-button c-icon-button--menu"
|
||||||
:title="options.title"
|
:class="options.icon"
|
||||||
@click="toggle">
|
:title="options.title"
|
||||||
<div class="c-icon-button__label"
|
@click="toggle"
|
||||||
v-if="options.label">
|
>
|
||||||
{{ options.label }}
|
<div
|
||||||
</div>
|
v-if="options.label"
|
||||||
</div>
|
class="c-icon-button__label"
|
||||||
<div class="c-menu" v-if="open">
|
>
|
||||||
<ul>
|
{{ options.label }}
|
||||||
<li v-for="option in options.options"
|
|
||||||
@click="onClick(option)"
|
|
||||||
:class="option.class">
|
|
||||||
{{ option.name }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="open"
|
||||||
|
class="c-menu"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="(option, index) in options.options"
|
||||||
|
:key="index"
|
||||||
|
:class="option.class"
|
||||||
|
@click="onClick(option)"
|
||||||
|
>
|
||||||
|
{{ option.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -28,6 +38,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
required: true,
|
||||||
validator(value) {
|
validator(value) {
|
||||||
// must pass valid options array.
|
// must pass valid options array.
|
||||||
return Array.isArray(value.options) &&
|
return Array.isArray(value.options) &&
|
||||||
|
@ -1,21 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper">
|
<div class="c-ctrl-wrapper">
|
||||||
<div class="c-icon-button c-icon-button--menu"
|
<div
|
||||||
:class="[options.icon, {'c-click-icon--mixed': nonSpecific}]"
|
class="c-icon-button c-icon-button--menu"
|
||||||
:title="options.title"
|
:class="[options.icon, {'c-click-icon--mixed': nonSpecific}]"
|
||||||
@click="toggle">
|
:title="options.title"
|
||||||
<div class="c-button__label">{{ selectedName }}</div>
|
@click="toggle"
|
||||||
</div>
|
>
|
||||||
<div class="c-menu" v-if="open">
|
<div class="c-button__label">
|
||||||
<ul>
|
{{ selectedName }}
|
||||||
<li v-for="option in options.options"
|
|
||||||
:key="option.value"
|
|
||||||
@click="select(option)">
|
|
||||||
{{ option.name || option.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="open"
|
||||||
|
class="c-menu"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="option in options.options"
|
||||||
|
:key="option.value"
|
||||||
|
@click="select(option)"
|
||||||
|
>
|
||||||
|
{{ option.name || option.value }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -26,6 +35,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
required: true,
|
||||||
validator(value) {
|
validator(value) {
|
||||||
// must pass valid options array.
|
// must pass valid options array.
|
||||||
return Array.isArray(value.options) &&
|
return Array.isArray(value.options) &&
|
||||||
@ -33,14 +43,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
select(option) {
|
|
||||||
if (this.options.value === option.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$emit('change', option.value, this.options);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
selectedName() {
|
selectedName() {
|
||||||
let selectedOption = this.options.options.filter((o) => o.value === this.options.value)[0];
|
let selectedOption = this.options.options.filter((o) => o.value === this.options.value)[0];
|
||||||
@ -53,6 +55,14 @@ export default {
|
|||||||
nonSpecific() {
|
nonSpecific() {
|
||||||
return this.options.nonSpecific === true;
|
return this.options.nonSpecific === true;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
select(option) {
|
||||||
|
if (this.options.value === option.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('change', option.value, this.options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-toolbar__separator"></div>
|
<div class="c-toolbar__separator"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
options: Object
|
options: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-ctrl-wrapper">
|
<div class="c-ctrl-wrapper">
|
||||||
<div class="c-icon-button"
|
<div
|
||||||
:title="nextValue.title"
|
class="c-icon-button"
|
||||||
:class="[nextValue.icon, {'c-icon-button--mixed': nonSpecific}]"
|
:title="nextValue.title"
|
||||||
@click="cycle">
|
:class="[nextValue.icon, {'c-icon-button--mixed': nonSpecific}]"
|
||||||
</div>
|
@click="cycle"
|
||||||
</div>
|
></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
options: {
|
options: {
|
||||||
type: Object
|
type: Object,
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
Loading…
Reference in New Issue
Block a user