Merge branch 'topic-core-refactor' into misc-ui-8

This commit is contained in:
Charles Hacskaylo
2019-04-05 17:30:42 -07:00
committed by GitHub
49 changed files with 1681 additions and 818 deletions

View File

@ -103,7 +103,7 @@
&__local-controls {
position: absolute;
top: 0; right: 0;
top: $interiorMargin; right: $interiorMargin;
z-index: 2;
}
@ -112,7 +112,7 @@
}
&.has-complex-content {
.c-so-view__view-large { display: block; }
> .c-so-view__view-large { display: block; }
}
/*************************** OBJECT VIEW */

View File

@ -59,7 +59,8 @@ export default {
default() {
return [];
}
}
},
navigateToPath: String
},
data() {
return {

View File

@ -102,7 +102,8 @@ export default {
this.elements = [];
this.elementsCache = {};
this.listeners = [];
this.parentObject = selection[0].context.item;
this.parentObject = selection && selection[0] && selection[0][0].context.item;
if (this.mutationUnobserver) {
this.mutationUnobserver();
}

View File

@ -199,8 +199,8 @@
},
methods: {
refreshComposition(selection) {
if (selection[0]) {
let parentObject = selection[0].context.item;
if (selection.length > 0 && selection[0].length > 0) {
let parentObject = selection[0][0].context.item;
this.hasComposition = !!(parentObject && this.openmct.composition.get(parentObject));
}

View File

@ -7,30 +7,44 @@
</style>
<script>
import _ from 'lodash';
export default {
inject: ['openmct'],
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection();
this.updateSelection(this.openmct.selection.get());
},
destroyed() {
this.openmct.selection.off('change', this.updateSelection);
},
data() {
return {
selection: []
}
},
methods: {
updateSelection() {
let selection = this.openmct.selection.get();
updateSelection(selection) {
if (_.isEqual(this.selection, selection)) {
return;
}
this.selection = selection;
if (this.selectedViews) {
this.selectedViews.forEach(selectedView => {
selectedView.destroy();
});
this.$el.innerHTML = '';
}
this.viewContainers = [];
if (selection.length > 1) {
return;
}
this.selectedViews = this.openmct.inspectorViews.get(selection);
this.selectedViews.forEach(selectedView => {
let viewContainer = document.createElement('div');
this.viewContainers.push(viewContainer);
this.$el.append(viewContainer)
selectedView.show(viewContainer);
});

View File

@ -1,7 +1,7 @@
<template>
<div class="c-properties c-properties--location">
<div class="c-properties__header" title="The location of this linked object.">Original Location</div>
<ul class="c-properties__section">
<ul class="c-properties__section" v-if="!multiSelect">
<li class="c-properties__row" v-if="originalPath.length">
<ul class="c-properties__value c-location">
<li v-for="pathObject in orderedOriginalPath"
@ -15,6 +15,7 @@
</ul>
</li>
</ul>
<div class="c-properties__row--span-all" v-if="multiSelect">No location to display for multiple items</div>
</div>
</template>
@ -72,6 +73,7 @@ export default {
data() {
return {
domainObject: {},
multiSelect: false,
originalPath: [],
keyString: ''
}
@ -106,16 +108,27 @@ export default {
this.keyString = '';
},
updateSelection(selection) {
if (!selection.length) {
if (!selection.length || !selection[0].length) {
this.clearData();
return;
} else if (!selection[0].context.item && selection[1] && selection[1].context.item) {
this.setOriginalPath([selection[1].context.item], true);
}
if (selection.length > 1) {
this.multiSelect = true;
return;
} else {
this.multiSelect = false;
}
this.domainObject = selection[0][0].context.item;
let parentObject = selection[0][1];
if (!this.domainObject && parentObject && parentObject.context.item) {
this.setOriginalPath([parentObject.context.item], true);
this.keyString = '';
return;
}
this.domainObject = selection[0].context.item;
let keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
if (keyString && this.keyString !== keyString) {

View File

@ -1,7 +1,7 @@
<template>
<div class="c-properties c-properties--properties">
<div class="c-properties__header">Properties</div>
<ul class="c-properties__section">
<ul class="c-properties__section" v-if="!multiSelect">
<li class="c-properties__row">
<div class="c-properties__label">Title</div>
<div class="c-properties__value">{{ item.name }}</div>
@ -25,6 +25,7 @@
<div class="c-properties__value">{{ prop.value }}</div>
</li>
</ul>
<div class="c-properties__row--span-all" v-if="multiSelect">No properties to display for multiple items</div>
</div>
</template>
@ -35,7 +36,8 @@ export default {
inject: ['openmct'],
data() {
return {
domainObject: {}
domainObject: {},
multiSelect: false
}
},
computed: {
@ -90,11 +92,19 @@ export default {
},
methods: {
updateSelection(selection) {
if (selection.length === 0) {
if (selection.length === 0 || selection[0].length === 0) {
this.domainObject = {};
return;
}
this.domainObject = selection[0].context.item;
if (selection.length > 1) {
this.multiSelect = true;
this.domainObject = {};
return;
} else {
this.multiSelect = false;
this.domainObject = selection[0][0].context.item;
}
},
formatTime(unixTime) {
return Moment.utc(unixTime).format('YYYY-MM-DD[\n]HH:mm:ss') + ' UTC';

View File

@ -43,7 +43,8 @@
</div>
<!-- Action buttons -->
<div class="l-browse-bar__actions">
<button class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
<button v-if="notebookEnabled"
class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
title="New Notebook entry"
@click="snapshot()">
</button>
@ -118,7 +119,10 @@ const PLACEHOLDER_OBJECT = {};
label: 'Ok',
emphasis: true,
callback: () => {
this.openmct.editor.cancel();
this.openmct.editor.cancel().then(() => {
//refresh object view
this.openmct.layout.$refs.browseObject.show(this.domainObject, this.viewKey, false);
});
dialog.dismiss();
}
},
@ -167,7 +171,8 @@ const PLACEHOLDER_OBJECT = {};
showSaveMenu: false,
domainObject: PLACEHOLDER_OBJECT,
viewKey: undefined,
isEditing: this.openmct.editor.isEditing()
isEditing: this.openmct.editor.isEditing(),
notebookEnabled: false
}
},
computed: {
@ -213,7 +218,11 @@ const PLACEHOLDER_OBJECT = {};
}
},
mounted: function () {
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
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);
@ -222,7 +231,20 @@ const PLACEHOLDER_OBJECT = {};
this.isEditing = isEditing;
});
},
watch: {
domainObject() {
if (this.mutationObserver) {
this.mutationObserver();
}
this.mutationObserver = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
this.domainObject = domainObject;
});
}
},
beforeDestroy: function () {
if (this.mutationObserver) {
this.mutationObserver();
}
document.removeEventListener('click', this.closeViewAndSaveMenu);
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
}

View File

@ -348,7 +348,7 @@
toggleHasToolbar(selection) {
let structure = undefined;
if (!selection[0]) {
if (!selection || !selection[0]) {
structure = [];
} else {
structure = this.openmct.toolbars.get(selection);

View File

@ -211,7 +211,8 @@
return {
id: this.openmct.objects.makeKeyString(c.identifier),
object: c,
objectPath: [c]
objectPath: [c],
navigateToParent: '/browse'
};
});
});

View File

@ -7,7 +7,8 @@
v-model="expanded">
</view-control>
<object-label :domainObject="node.object"
:objectPath="node.objectPath">
:objectPath="node.objectPath"
:navigateToPath="navigateToPath">
</object-label>
</div>
<ul v-if="expanded" class="c-tree">
@ -36,13 +37,12 @@
node: Object
},
data() {
this.pathToObject = this.buildPathString(this.node.objectPath);
this.navigateToPath = this.buildPathString(this.node.navigateToParent)
return {
hasChildren: false,
isLoading: false,
loaded: false,
isNavigated: this.pathToObject === this.openmct.router.currentLocation.path,
isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path,
children: [],
expanded: false
}
@ -103,7 +103,8 @@
this.children.push({
id: this.openmct.objects.makeKeyString(child.identifier),
object: child,
objectPath: [child].concat(this.node.objectPath)
objectPath: [child].concat(this.node.objectPath),
navigateToParent: this.navigateToPath
});
},
removeChild(identifier) {
@ -115,15 +116,13 @@
this.isLoading = false;
this.loaded = true;
},
buildPathString(path) {
return '/browse/' + path.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
.reverse()
.join('/');
buildPathString(parentPath) {
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
},
highlightIfNavigated(newPath, oldPath){
if (newPath === this.pathToObject) {
if (newPath === this.navigateToPath) {
this.isNavigated = true;
} else if (oldPath === this.pathToObject) {
} else if (oldPath === this.navigateToPath) {
this.isNavigated = false;
}
}

View File

@ -13,6 +13,9 @@ export default {
if (!this.objectPath.length) {
return;
}
if (this.navigateToPath) {
return '#' + this.navigateToPath;
}
return '#/browse/' + this.objectPath
.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
.reverse()

View File

@ -42,14 +42,13 @@
this.removeListeners();
this.domainObjectsById = {};
if (!selection[0]) {
if (selection.length === 0 || !selection[0][0]) {
this.structure = [];
return;
}
let structure = this.openmct.toolbars.get(selection) || [];
this.structure = structure.map(item => {
let toolbarItem = {...item};
this.structure = structure.map(toolbarItem => {
let domainObject = toolbarItem.domainObject;
let formKeys = [];
toolbarItem.control = "toolbar-" + toolbarItem.control;
@ -64,12 +63,7 @@
}
if (domainObject) {
if (formKeys.length > 0) {
toolbarItem.value = this.getFormValue(domainObject, toolbarItem);
} else {
toolbarItem.value = _.get(domainObject, this.getItemProperty(item));
}
toolbarItem.value = this.getValue(domainObject, toolbarItem);
this.registerListener(domainObject);
}
@ -89,21 +83,12 @@
observeObject(domainObject, id) {
let unobserveObject = this.openmct.objects.observe(domainObject, '*', function(newObject) {
this.domainObjectsById[id].newObject = JSON.parse(JSON.stringify(newObject));
this.scheduleToolbarUpdate();
this.updateToolbarAfterMutation();
}.bind(this));
this.unObserveObjects.push(unobserveObject);
},
scheduleToolbarUpdate() {
if (this.toolbarUpdateScheduled) {
return;
}
this.toolbarUpdateScheduled = true;
setTimeout(this.updateToolbarAfterMutation.bind(this));
},
updateToolbarAfterMutation() {
this.structure = this.structure.map(item => {
let toolbarItem = {...item};
this.structure = this.structure.map(toolbarItem => {
let domainObject = toolbarItem.domainObject;
if (domainObject) {
@ -112,12 +97,7 @@
if (newObject) {
toolbarItem.domainObject = newObject;
if (toolbarItem.formKeys) {
toolbarItem.value = this.getFormValue(newObject, toolbarItem);
} else {
toolbarItem.value = _.get(newObject, this.getItemProperty(item));
}
toolbarItem.value = this.getValue(newObject, toolbarItem);
}
}
@ -130,17 +110,58 @@
delete tracker.newObject;
}
});
this.toolbarUpdateScheduled = false;
},
getValue(domainObject, toolbarItem) {
let value = undefined;
let applicableSelectedItems = toolbarItem.applicableSelectedItems;
if (!applicableSelectedItems) {
return value;
}
if (toolbarItem.formKeys) {
value = this.getFormValue(domainObject, toolbarItem);
} else {
let values = [];
applicableSelectedItems.forEach(selectionPath => {
values.push(_.get(domainObject, this.getItemProperty(toolbarItem, selectionPath)));
});
// 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;
},
getFormValue(domainObject, toolbarItem) {
let value = {};
let values = {};
toolbarItem.formKeys.map(key => {
value[key] = _.get(domainObject, this.getItemProperty(toolbarItem) + "." + key);
values[key] = [];
toolbarItem.applicableSelectedItems.forEach(selectionPath => {
values[key].push(_.get(domainObject, this.getItemProperty(toolbarItem, selectionPath) + "." + 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) {
return (typeof item.property === "function") ? item.property() : item.property;
getItemProperty(item, selectionPath) {
return (typeof item.property === "function") ? item.property(selectionPath) : item.property;
},
removeListeners() {
if (this.unObserveObjects) {
@ -152,14 +173,12 @@
},
updateObjectValue(value, item) {
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
this.structure = this.structure.map((s) => {
let toolbarItem = {...s};
let domainObject = toolbarItem.domainObject;
if (domainObject) {
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
this.structure = this.structure.map(toolbarItem => {
if (toolbarItem.domainObject) {
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
if (changedItemId === id && this.getItemProperty(item) === this.getItemProperty(s)) {
if (changedItemId === id && _.isEqual(toolbarItem, item)) {
toolbarItem.value = value;
}
}
@ -173,12 +192,17 @@
this.structure.map(s => {
if (s.formKeys) {
s.formKeys.forEach(key => {
this.openmct.objects.mutate(item.domainObject, this.getItemProperty(item) + "." + key, value[key]);
item.applicableSelectedItems.forEach(selectionPath => {
this.openmct.objects.mutate(item.domainObject,
this.getItemProperty(item, selectionPath) + "." + key, value[key]);
});
});
}
});
} else {
this.openmct.objects.mutate(item.domainObject, this.getItemProperty(item), value);
item.applicableSelectedItems.forEach(selectionPath => {
this.openmct.objects.mutate(item.domainObject, this.getItemProperty(item, selectionPath), value);
});
}
},
triggerMethod(item, event) {

View File

@ -4,14 +4,14 @@
:title="options.title"
:class="{
[options.icon]: true,
'c-icon-button--caution': options.modifier === 'caution'
'c-icon-button--caution': options.modifier === 'caution',
'c-icon-button--mixed': nonSpecific
}"
@click="onClick">
<div class="c-icon-button__label"
v-if="options.label">
{{ options.label }}
</div>
</div>
</div>
</template>
@ -22,6 +22,11 @@ export default {
props: {
options: Object
},
computed: {
nonSpecific() {
return this.options.nonSpecific === true;
}
},
methods: {
onClick(event) {
if (this.options.dialog) {

View File

@ -1,7 +1,7 @@
<template>
<div class="c-ctrl-wrapper">
<div class="c-icon-button c-icon-button--swatched"
:class="options.icon"
:class="[options.icon, {'c-icon-button--mixed': nonSpecific}]"
:title="options.title"
@click="toggle">
<div class="c-swatch" :style="{
@ -36,6 +36,11 @@ export default {
props: {
options: Object
},
computed: {
nonSpecific() {
return this.options.nonSpecific === true;
}
},
methods: {
select(color) {
if (color.value !== this.options.value) {

View File

@ -1,7 +1,7 @@
<template>
<div class="c-ctrl-wrapper">
<div class="c-icon-button c-icon-button--menu"
:class="options.icon"
:class="[options.icon, {'c-click-icon--mixed': nonSpecific}]"
:title="options.title"
@click="toggle">
<div class="c-button__label">{{ selectedName }}</div>
@ -47,7 +47,11 @@ export default {
if (selectedOption) {
return selectedOption.name || selectedOption.value
}
return '';
// If no selected option, then options are non-specific
return '??px';
},
nonSpecific() {
return this.options.nonSpecific === true;
}
}
}

View File

@ -2,7 +2,7 @@
<div class="c-ctrl-wrapper">
<div class="c-icon-button"
:title="nextValue.title"
:class="nextValue.icon"
:class="[nextValue.icon, {'c-click-icon--mixed': nonSpecific}]"
@click="cycle">
</div>
</div>
@ -23,6 +23,9 @@ export default {
nextIndex = 0;
}
return this.options.options[nextIndex];
},
nonSpecific() {
return this.options.nonSpecific === true;
}
},
methods: {