mirror of
https://github.com/nasa/openmct.git
synced 2025-04-10 21:00:16 +00:00
Object views (#2165)
* Use new style view providers for all object views. * support legacy views with deprecation warning * tidy deprecation warnings
This commit is contained in:
parent
07ca60e13a
commit
40b7117987
28
src/MCT.js
28
src/MCT.js
@ -35,6 +35,7 @@ define([
|
||||
'./ui/registries/InspectorViewRegistry',
|
||||
'./ui/registries/ToolbarRegistry',
|
||||
'./ui/router/ApplicationRouter',
|
||||
'./ui/router/Browse',
|
||||
'../platform/framework/src/Main',
|
||||
'./styles-new/core.scss',
|
||||
'./ui/components/layout/Layout.vue',
|
||||
@ -54,6 +55,7 @@ define([
|
||||
InspectorViewRegistry,
|
||||
ToolbarRegistry,
|
||||
ApplicationRouter,
|
||||
Browse,
|
||||
Main,
|
||||
coreStyles,
|
||||
Layout,
|
||||
@ -273,6 +275,7 @@ define([
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
// TODO: remove with legacy types.
|
||||
this.types.listKeys().forEach(function (typeKey) {
|
||||
var type = this.types.get(typeKey);
|
||||
var legacyDefinition = type.toLegacyDefinition();
|
||||
@ -280,26 +283,6 @@ define([
|
||||
this.legacyExtension('types', legacyDefinition);
|
||||
}.bind(this));
|
||||
|
||||
// TODO: move this to adapter bundle.
|
||||
this.legacyExtension('runs', {
|
||||
depends: ['types[]'],
|
||||
implementation: (types) => {
|
||||
this.types.importLegacyTypes(types);
|
||||
}
|
||||
});
|
||||
|
||||
this.objectViews.getAllProviders().forEach(function (p) {
|
||||
this.legacyExtension('views', {
|
||||
key: p.key,
|
||||
provider: p,
|
||||
name: p.name,
|
||||
cssClass: p.cssClass,
|
||||
description: p.description,
|
||||
editable: p.editable,
|
||||
template: '<mct-view mct-provider-key="' + p.key + '"/>'
|
||||
});
|
||||
}, this);
|
||||
|
||||
legacyRegistry.register('adapter', this.legacyBundle);
|
||||
legacyRegistry.enable('adapter');
|
||||
|
||||
@ -324,8 +307,6 @@ define([
|
||||
// something has depended upon objectService. Cool, right?
|
||||
this.$injector.get('objectService');
|
||||
|
||||
console.log('Rendering app layout.');
|
||||
|
||||
var appLayout = new Vue({
|
||||
mixins: [Layout.default],
|
||||
provide: {
|
||||
@ -334,7 +315,8 @@ define([
|
||||
});
|
||||
domElement.appendChild(appLayout.$mount().$el);
|
||||
|
||||
|
||||
this.layout = appLayout;
|
||||
Browse(this);
|
||||
this.router.start();
|
||||
this.emit('start');
|
||||
}.bind(this));
|
||||
|
@ -34,7 +34,9 @@ define([
|
||||
'./runs/TimeSettingsURLHandler',
|
||||
'./runs/TypeDeprecationChecker',
|
||||
'./runs/LegacyTelemetryProvider',
|
||||
'./services/LegacyObjectAPIInterceptor'
|
||||
'./runs/RegisterLegacyTypes',
|
||||
'./services/LegacyObjectAPIInterceptor',
|
||||
'./views/installLegacyViews'
|
||||
], function (
|
||||
legacyRegistry,
|
||||
ActionDialogDecorator,
|
||||
@ -49,7 +51,9 @@ define([
|
||||
TimeSettingsURLHandler,
|
||||
TypeDeprecationChecker,
|
||||
LegacyTelemetryProvider,
|
||||
LegacyObjectAPIInterceptor
|
||||
RegisterLegacyTypes,
|
||||
LegacyObjectAPIInterceptor,
|
||||
installLegacyViews
|
||||
) {
|
||||
legacyRegistry.register('src/adapter', {
|
||||
"extensions": {
|
||||
@ -149,6 +153,21 @@ define([
|
||||
"openmct",
|
||||
"instantiate"
|
||||
]
|
||||
},
|
||||
{
|
||||
implementation: installLegacyViews,
|
||||
depends: [
|
||||
"openmct",
|
||||
"views[]",
|
||||
"instantiate"
|
||||
]
|
||||
},
|
||||
{
|
||||
implementation: RegisterLegacyTypes,
|
||||
depends: [
|
||||
"types[]",
|
||||
"openmct"
|
||||
]
|
||||
}
|
||||
],
|
||||
licenses: [
|
||||
|
17
src/adapter/runs/RegisterLegacyTypes.js
Normal file
17
src/adapter/runs/RegisterLegacyTypes.js
Normal file
@ -0,0 +1,17 @@
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
function RegisterLegacyTypes(types, openmct) {
|
||||
types.forEach(function (legacyDefinition) {
|
||||
if (!openmct.types.get(legacyDefinition.key)) {
|
||||
console.warn(`DEPRECATION WARNING: Migrate type ${legacyDefinition.key} from ${legacyDefinition.bundle.path} to use the new Types API. Legacy type support will be removed soon.`);
|
||||
}
|
||||
});
|
||||
|
||||
openmct.types.importLegacyTypes(types);
|
||||
}
|
||||
|
||||
return RegisterLegacyTypes;
|
||||
});
|
93
src/adapter/views/LegacyViewProvider.js
Normal file
93
src/adapter/views/LegacyViewProvider.js
Normal file
@ -0,0 +1,93 @@
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
function LegacyViewProvider(legacyView, openmct, convertToLegacyObject) {
|
||||
console.warn(`DEPRECATION WARNING: Migrate ${legacyView.key} from ${legacyView.bundle.path} to use the new View APIs. Legacy view support will be removed soon.`);
|
||||
return {
|
||||
key: legacyView.key,
|
||||
name: legacyView.name,
|
||||
cssClass: legacyView.cssClass,
|
||||
description: legacyView.description,
|
||||
editable: legacyView.editable,
|
||||
canView: function (domainObject) {
|
||||
if (!domainObject || !domainObject.identifier) {
|
||||
return false;
|
||||
}
|
||||
if (legacyView.type) {
|
||||
return domainObject.type === legacyView.type;
|
||||
}
|
||||
let legacyObject = convertToLegacyObject(domainObject);
|
||||
if (legacyView.needs) {
|
||||
let meetsNeeds = legacyView.needs.every(k => legacyObject.hasCapability(k));
|
||||
if (!meetsNeeds) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return openmct.$injector.get('policyService').allow(
|
||||
'view', legacyView, legacyObject
|
||||
);
|
||||
},
|
||||
view: function (domainObject) {
|
||||
let $rootScope = openmct.$injector.get('$rootScope');
|
||||
let templateLinker = openmct.$injector.get('templateLinker');
|
||||
let scope = $rootScope.$new();
|
||||
let legacyObject = convertToLegacyObject(domainObject);
|
||||
let isDestroyed = false;
|
||||
scope.domainObject = legacyObject;
|
||||
scope.model = legacyObject.getModel();
|
||||
|
||||
|
||||
return {
|
||||
show: function (container) {
|
||||
// TODO: implement "gestures" support ?
|
||||
let uses = legacyView.uses || [];
|
||||
let promises = [];
|
||||
let results = uses.map(function (capabilityKey, i) {
|
||||
let result = legacyObject.useCapability(capabilityKey);
|
||||
if (result.then) {
|
||||
promises.push(result.then(function (r) {
|
||||
results[i] = r;
|
||||
}));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
function link() {
|
||||
if (isDestroyed) {
|
||||
return;
|
||||
}
|
||||
uses.forEach(function (key, i) {
|
||||
scope[key] = results[i];
|
||||
});
|
||||
templateLinker.link(
|
||||
scope,
|
||||
openmct.$angular.element(container),
|
||||
legacyView
|
||||
);
|
||||
container.style.height = '100%';
|
||||
}
|
||||
|
||||
if (promises.length) {
|
||||
Promise.all(promises)
|
||||
.then(function () {
|
||||
link();
|
||||
scope.$digest();
|
||||
});
|
||||
} else {
|
||||
link();
|
||||
}
|
||||
},
|
||||
destroy: function () {
|
||||
scope.$destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return LegacyViewProvider;
|
||||
|
||||
});
|
22
src/adapter/views/installLegacyViews.js
Normal file
22
src/adapter/views/installLegacyViews.js
Normal file
@ -0,0 +1,22 @@
|
||||
define([
|
||||
'./LegacyViewProvider',
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
LegacyViewProvider,
|
||||
objectUtils
|
||||
) {
|
||||
function installLegacyViews(openmct, legacyViews, instantiate) {
|
||||
|
||||
function convertToLegacyObject(domainObject) {
|
||||
let keyString = objectUtils.makeKeyString(domainObject.identifier);
|
||||
let oldModel = objectUtils.toOldFormat(domainObject);
|
||||
return instantiate(oldModel, keyString);
|
||||
}
|
||||
|
||||
legacyViews.forEach(function (legacyView) {
|
||||
openmct.objectViews.addProvider(new LegacyViewProvider(legacyView, openmct, convertToLegacyObject));
|
||||
});
|
||||
}
|
||||
|
||||
return installLegacyViews;
|
||||
});
|
@ -15,7 +15,8 @@ define([
|
||||
function SummaryWidgetViewProvider(openmct) {
|
||||
return {
|
||||
key: 'summary-widget-viewer',
|
||||
name: 'Widget View',
|
||||
name: 'Summary View',
|
||||
cssClass: 'icon-summary-widget',
|
||||
canView: function (domainObject) {
|
||||
return domainObject.type === 'summary-widget';
|
||||
},
|
||||
|
@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<div class="c-splitter" :class="{
|
||||
'c-splitter-vertical' : align === 'vertical',
|
||||
'c-splitter-horizontal' : align === 'horizontal',
|
||||
'c-splitter-collapse-left' : collapse === 'to-left',
|
||||
'c-splitter-collapse-right' : collapse === 'to-right',
|
||||
}">
|
||||
<a class="c-splitter__btn"></a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/constants";
|
||||
@import "~styles/constants-snow";
|
||||
@import "~styles/mixins";
|
||||
@import "~styles/glyphs";
|
||||
|
||||
$c: #06f;
|
||||
$size: $splitterHandleD;
|
||||
$margin: 0px;
|
||||
$hitMargin: 4px;
|
||||
|
||||
|
||||
.c-splitter {
|
||||
background: $colorSplitterBg;
|
||||
transition: $transOut;
|
||||
|
||||
&:before {
|
||||
// Bigger hit area
|
||||
//@include test();
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:active, &:hover {
|
||||
transition: $transIn;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: $colorSplitterActive;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $colorSplitterHover;
|
||||
}
|
||||
|
||||
&-vertical {
|
||||
cursor: col-resize;
|
||||
width: $size;
|
||||
margin: 0 $margin;
|
||||
&:before {
|
||||
top: 0;
|
||||
right: $hitMargin * -1;
|
||||
bottom: 0;
|
||||
left: $hitMargin * -1;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal {
|
||||
cursor: row-resize;
|
||||
height: $size;
|
||||
margin: $margin 0;
|
||||
&:before {
|
||||
top: $hitMargin * -1;
|
||||
right: 0;
|
||||
bottom: $hitMargin * -1;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-splitter__btn {
|
||||
// Collapse button
|
||||
background: $colorSplitterBg;
|
||||
display: none; // Only display if splitter is collapsible, see below
|
||||
width: $splitterD;
|
||||
height: 40px;
|
||||
transition: $transOut;
|
||||
|
||||
&:active, &:hover {
|
||||
transition: $transIn;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $colorSplitterHover;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: $colorSplitterActive;
|
||||
}
|
||||
|
||||
[class*="collapse"] & {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
&:before {
|
||||
color: $colorSplitterFg;
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
font-family: symbolsfont;
|
||||
}
|
||||
}
|
||||
|
||||
[class*="collapse-left"] & {
|
||||
border-bottom-left-radius: $controlCr;
|
||||
right: 0;
|
||||
&:before {
|
||||
content: $glyph-icon-arrow-left;
|
||||
}
|
||||
}
|
||||
|
||||
[class*="collapse-right"] & {
|
||||
border-bottom-right-radius: $controlCr;
|
||||
left: 0;
|
||||
&:before {
|
||||
content: $glyph-icon-arrow-right;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
align: String,
|
||||
collapse: String
|
||||
}
|
||||
}
|
||||
</script>
|
@ -2,10 +2,11 @@
|
||||
<div class="l-browse-bar">
|
||||
<div class="l-browse-bar__start">
|
||||
<a class="l-browse-bar__nav-to-parent-button c-icon-button icon-pointer-left"></a>
|
||||
<div v-bind:class="['l-browse-bar__object-name--w', type.cssClass]">
|
||||
<span
|
||||
<div class="l-browse-bar__object-name--w"
|
||||
:class="type.cssClass">
|
||||
<span
|
||||
class="l-browse-bar__object-name c-input-inline"
|
||||
v-on:blur="updateName"
|
||||
v-on:blur="updateName"
|
||||
contenteditable>
|
||||
{{ domainObject.name }}
|
||||
</span>
|
||||
@ -15,19 +16,22 @@
|
||||
|
||||
<div class="l-browse-bar__end">
|
||||
<div class="l-browse-bar__view-switcher c-menu-button--w c-menu-button--menus-left"
|
||||
v-if="domainObjectViews.length > 1">
|
||||
<div v-bind:class="['c-menu-button', currentView.cssClass]"
|
||||
v-if="views.length > 1">
|
||||
<div class="c-menu-button"
|
||||
:class="currentView.cssClass"
|
||||
title="Switch view type"
|
||||
@click="toggleViewMenu">
|
||||
<span class="c-button__label">{{ currentView.name }}</span>
|
||||
<span class="c-button__label">
|
||||
{{ currentView.name }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="c-menu" v-if="showViewMenu">
|
||||
<div class="c-menu" v-show="showViewMenu">
|
||||
<ul>
|
||||
<li v-for="(view,index) in domainObjectViews"
|
||||
@click="updateViewParams(view)"
|
||||
<li v-for="(view, index) in views"
|
||||
@click="setView(view)"
|
||||
:key="index"
|
||||
:class="view.cssClass"
|
||||
:title="view.title">
|
||||
:title="view.name">
|
||||
{{ view.name }}
|
||||
</li>
|
||||
</ul>
|
||||
@ -44,69 +48,64 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuPlaceholder from '../controls/ContextMenu.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
editNameEnabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleViewMenu: function (event) {
|
||||
event.stopPropagation();
|
||||
this.showViewMenu = !this.showViewMenu;
|
||||
},
|
||||
updateName: function (event) {
|
||||
// TODO: handle isssues with contenteditable text escaping.
|
||||
if (event.target.innerText !== this.domainObject.name) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'name', event.target.innerText);
|
||||
}
|
||||
},
|
||||
updateViewParams: function (view) {
|
||||
this.openmct.router.updateParams({view: view.key});
|
||||
},
|
||||
updateCurrentView: function (viewKey) {
|
||||
viewKey = viewKey || this.openmct.router.getParams().view;
|
||||
|
||||
if (viewKey) {
|
||||
this.currentView = this.domainObjectViews.find((view) => view.key === viewKey) || {};
|
||||
}
|
||||
setView: function (view) {
|
||||
this.viewKey = view.key;
|
||||
this.openmct.router.updateParams({
|
||||
view: this.viewKey
|
||||
});
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
showViewMenu: false,
|
||||
domainObject: {},
|
||||
domainObjectViews: [],
|
||||
currentView: {}
|
||||
viewKey: undefined
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MenuPlaceholder
|
||||
},
|
||||
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
|
||||
};
|
||||
});
|
||||
},
|
||||
type() {
|
||||
return this.openmct.types.get(this.domainObject.type).definition;
|
||||
let objectType = this.openmct.types.get(this.domainObject.type);
|
||||
if (!objectType) {
|
||||
return {}
|
||||
}
|
||||
return objectType.definition;
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$root.$on('main-view-domain-object', (domainObject) => {
|
||||
this.legacyObject = domainObject;
|
||||
this.domainObject = domainObject.useCapability('adapter');
|
||||
this.domainObjectViews = domainObject.useCapability('view');
|
||||
|
||||
this.updateCurrentView();
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
if (this.showViewMenu) {
|
||||
this.showViewMenu = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.openmct.router.on('change:params', (params) => {this.updateCurrentView(params.view)});
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
// Find an object in an array of objects.
|
||||
function findObject(domainObjects, id) {
|
||||
var i;
|
||||
for (i = 0; i < domainObjects.length; i += 1) {
|
||||
if (domainObjects[i].getId() === id) {
|
||||
return domainObjects[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recursively locate and return an object inside of a container
|
||||
// via a path. If at any point in the recursion it fails to find
|
||||
// the next object, it will return the parent.
|
||||
function findViaComposition(containerObject, path) {
|
||||
var nextId = path.shift();
|
||||
if (!nextId) {
|
||||
return containerObject;
|
||||
}
|
||||
return containerObject.useCapability('composition')
|
||||
.then(function (composees) {
|
||||
var nextObject = findObject(composees, nextId);
|
||||
if (!nextObject) {
|
||||
return containerObject;
|
||||
}
|
||||
if (!nextObject.hasCapability('composition')) {
|
||||
return nextObject;
|
||||
}
|
||||
return findViaComposition(nextObject, path);
|
||||
});
|
||||
}
|
||||
|
||||
function getLastChildIfRoot(object) {
|
||||
if (object.getId() !== 'ROOT') {
|
||||
return object;
|
||||
}
|
||||
return object.useCapability('composition')
|
||||
.then(function (composees) {
|
||||
return composees[composees.length - 1];
|
||||
});
|
||||
}
|
||||
|
||||
function pathForObject(domainObject) {
|
||||
var context = domainObject.getCapability('context'),
|
||||
objectPath = context ? context.getPath() : [],
|
||||
ids = objectPath.map(function (domainObj) {
|
||||
return domainObj.getId();
|
||||
});
|
||||
return "/browse/" + ids.slice(1).join("/");
|
||||
}
|
||||
|
||||
export default {
|
||||
inject: ["openmct"],
|
||||
mounted() {
|
||||
let openmct = this.openmct;
|
||||
let $injector = openmct.$injector;
|
||||
let angular = openmct.$angular;
|
||||
|
||||
this.objectService = $injector.get('objectService');
|
||||
this.templateLinker = $injector.get('templateLinker');
|
||||
this.navigationService = $injector.get('navigationService');
|
||||
this.$timeout = $injector.get('$timeout');
|
||||
|
||||
this.templateMap = {};
|
||||
$injector.get('templates[]').forEach((t) => {
|
||||
this.templateMap[t.key] = this.templateMap[t.key] || t;
|
||||
});
|
||||
|
||||
this.$rootScope = $injector.get('$rootScope');
|
||||
this.$scope = this.$rootScope.$new();
|
||||
this.$scope.representation = {};
|
||||
|
||||
openmct.router.route(/^\/browse\/(.*)$/, (path, results) => {
|
||||
let navigatePath = results[1];
|
||||
if (!navigatePath) {
|
||||
navigatePath = 'mine';
|
||||
}
|
||||
this.navigateToPath(navigatePath);
|
||||
});
|
||||
|
||||
this.navigationService.addListener(o => this.navigateToObject(o));
|
||||
},
|
||||
destroyed() {
|
||||
},
|
||||
methods: {
|
||||
navigateToPath(path) {
|
||||
if (!Array.isArray(path)) {
|
||||
path = path.split('/');
|
||||
}
|
||||
return this.getObject('ROOT')
|
||||
.then(root => {
|
||||
return findViaComposition(root, path);
|
||||
})
|
||||
.then(getLastChildIfRoot)
|
||||
.then(object => {
|
||||
this.setMainViewObject(object);
|
||||
});
|
||||
},
|
||||
|
||||
setMainViewObject(object) {
|
||||
this.$scope.domainObject = object;
|
||||
this.$scope.navigatedObject = object;
|
||||
this.templateLinker.link(
|
||||
this.$scope,
|
||||
this.openmct.$angular.element(this.$el),
|
||||
this.templateMap["browseObject"]
|
||||
);
|
||||
document.title = object.getModel().name;
|
||||
this.$root.$emit('main-view-domain-object', object);
|
||||
this.scheduleDigest();
|
||||
},
|
||||
|
||||
idsForObject(domainObject) {
|
||||
return this.urlService
|
||||
.urlForLocation("", domainObject)
|
||||
.replace('/', '');
|
||||
},
|
||||
|
||||
navigateToObject(object) {
|
||||
let path = pathForObject(object);
|
||||
let views = object.useCapability('view');
|
||||
let params = this.openmct.router.getParams();
|
||||
let currentViewIsValid = views.some(v => v.key === params['view']);
|
||||
if (!currentViewIsValid) {
|
||||
this.scope.representation = {
|
||||
selected: views[0]
|
||||
}
|
||||
this.openmct.router.update(path, {
|
||||
view: views[0].key
|
||||
});
|
||||
} else {
|
||||
this.openmct.router.setPath(path);
|
||||
}
|
||||
},
|
||||
|
||||
scheduleDigest() {
|
||||
this.$timeout(function () {
|
||||
// digest done!
|
||||
});
|
||||
},
|
||||
|
||||
getObject(id) {
|
||||
return this.objectService.getObjects([id])
|
||||
.then(function (results) {
|
||||
return results[id];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -22,8 +22,12 @@
|
||||
</div>
|
||||
</pane>
|
||||
<pane class="l-shell__pane-main">
|
||||
<MainViewBrowseBar class="l-shell__main-view-browse-bar"></MainViewBrowseBar>
|
||||
<browse-object class="l-shell__main-container"></browse-object>
|
||||
<browse-bar class="l-shell__main-view-browse-bar"
|
||||
ref="browseBar">
|
||||
</browse-bar>
|
||||
<object-view class="l-shell__main-container"
|
||||
ref="browseObject">
|
||||
</object-view>
|
||||
<mct-template template-key="conductor"
|
||||
class="l-shell__time-conductor">
|
||||
</mct-template>
|
||||
@ -184,28 +188,28 @@
|
||||
import Inspector from '../inspector/Inspector.vue';
|
||||
import MctStatus from './MctStatus.vue';
|
||||
import MctTree from './mct-tree.vue';
|
||||
import BrowseObject from './BrowseObject.vue';
|
||||
import ObjectView from './ObjectView.vue';
|
||||
import MctTemplate from '../legacy/mct-template.vue';
|
||||
import ContextMenu from '../controls/ContextMenu.vue';
|
||||
import CreateButton from '../controls/CreateButton.vue';
|
||||
import search from '../controls/search.vue';
|
||||
import multipane from '../controls/multipane.vue';
|
||||
import pane from '../controls/pane.vue';
|
||||
import MainViewBrowseBar from '../controls/MainViewBrowseBar.vue';
|
||||
import BrowseBar from './BrowseBar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Inspector,
|
||||
MctStatus,
|
||||
MctTree,
|
||||
BrowseObject,
|
||||
ObjectView,
|
||||
'mct-template': MctTemplate,
|
||||
ContextMenu,
|
||||
CreateButton,
|
||||
search,
|
||||
multipane,
|
||||
pane,
|
||||
MainViewBrowseBar
|
||||
BrowseBar
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
38
src/ui/components/layout/ObjectView.vue
Normal file
38
src/ui/components/layout/ObjectView.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="abs l-flex-col ng-scope" ref="mountPoint">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: ["openmct"],
|
||||
destroyed() {
|
||||
this.clear();
|
||||
},
|
||||
methods: {
|
||||
clear() {
|
||||
if (this.currentView) {
|
||||
this.currentView.destroy();
|
||||
this.$refs.mountPoint.innerHTML = '';
|
||||
}
|
||||
delete this.viewContainer;
|
||||
delete this.currentView;
|
||||
},
|
||||
show(object, provider) {
|
||||
this.clear();
|
||||
this.currentObject = object;
|
||||
this.viewContainer = document.createElement('div');
|
||||
this.$refs.mountPoint.append(this.viewContainer);
|
||||
this.currentView = provider.view(object);
|
||||
this.currentView.show(this.viewContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -22,8 +22,6 @@ export default {
|
||||
|
||||
let $rootScope = $injector.get('$rootScope');
|
||||
this.$scope = $rootScope.$new();
|
||||
console.log('mounting', this.templateKey);
|
||||
console.log('template:', templateMap[this.templateKey]);
|
||||
|
||||
templateLinker.link(
|
||||
this.$scope,
|
||||
|
@ -101,7 +101,7 @@ class ApplicationRouter extends EventEmitter {
|
||||
doPathChange(newPath, oldPath, newLocation) {
|
||||
let route = this.routes.filter(r => r.matcher.test(newPath))[0];
|
||||
if (route) {
|
||||
route.callback(newPath, route.matcher.exec(newPath));
|
||||
route.callback(newPath, route.matcher.exec(newPath), this.currentLocation.params);
|
||||
}
|
||||
this.emit('change:path', newPath, oldPath);
|
||||
}
|
||||
|
80
src/ui/router/Browse.js
Normal file
80
src/ui/router/Browse.js
Normal file
@ -0,0 +1,80 @@
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
return function install(openmct) {
|
||||
let navigateCall = 0;
|
||||
let browseObject;
|
||||
|
||||
|
||||
function viewObject(object, viewProvider) {
|
||||
openmct.layout.$refs.browseObject.show(object, viewProvider);
|
||||
openmct.layout.$refs.browseBar.domainObject = object;
|
||||
openmct.layout.$refs.browseBar.viewKey = viewProvider.key;
|
||||
};
|
||||
|
||||
function navigateToPath(path, currentViewKey) {
|
||||
navigateCall++;
|
||||
let currentNavigation = navigateCall;
|
||||
|
||||
if (!Array.isArray(path)) {
|
||||
path = path.split('/');
|
||||
}
|
||||
let keyString = path[path.length - 1];
|
||||
// TODO: retain complete path in navigation.
|
||||
return openmct.objects.get(keyString)
|
||||
.then((object) => {
|
||||
if (currentNavigation !== navigateCall) {
|
||||
return; // Prevent race.
|
||||
}
|
||||
openmct.layout.$refs.browseBar.domainObject = object;
|
||||
browseObject = object;
|
||||
if (!object) {
|
||||
openmct.layout.$refs.browseObject.clear();
|
||||
return;
|
||||
}
|
||||
let currentProvider = openmct
|
||||
.objectViews
|
||||
.getByProviderKey(currentViewKey)
|
||||
|
||||
if (currentProvider && currentProvider.canView(object)) {
|
||||
viewObject(object, currentProvider);
|
||||
return;
|
||||
}
|
||||
|
||||
let defaultProvider = openmct.objectViews.get(object)[0];
|
||||
if (defaultProvider) {
|
||||
openmct.router.updateParams({
|
||||
view: defaultProvider.key
|
||||
});
|
||||
} else {
|
||||
openmct.router.updateParams({
|
||||
view: undefined
|
||||
});
|
||||
openmct.layout.$refs.browseObject.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openmct.router.route(/^\/browse\/(.*)$/, (path, results, params) => {
|
||||
let navigatePath = results[1];
|
||||
if (!navigatePath) {
|
||||
navigatePath = 'mine';
|
||||
}
|
||||
navigateToPath(navigatePath, params.view);
|
||||
});
|
||||
|
||||
openmct.router.on('change:params', function (newParams, oldParams, changed) {
|
||||
if (changed.view && browseObject) {
|
||||
let provider = openmct
|
||||
.objectViews
|
||||
.getByProviderKey(changed.view);
|
||||
viewObject(browseObject, provider);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user