mirror of
https://github.com/nasa/openmct.git
synced 2025-04-14 22:46:44 +00:00
[Imagery] Click on image to get a large view (#3770)
* [Imagery] Click on image to get a large view #3582 * Created new viewLargeAction. * Changes in view registry to add parent element property inside view object. * Separate class for views and added missing changes for LadTableSet. * Renamed callBack to onItemClicked. Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
ca66898e51
commit
071a13b219
example/simpleVuePlugin
src
MCT.js
api
actions
menu
plugins
LADTable
condition/components
displayLayout
imagery
notebook
plugins.jstelemetryTable
timeConductor
viewDatumAction
viewLargeAction
ui
components
inspector/styles
layout
mixins
preview
registries
@ -1,4 +1,4 @@
|
||||
import Vue from 'Vue';
|
||||
import Vue from 'vue';
|
||||
import HelloWorld from './HelloWorld.vue';
|
||||
|
||||
function SimpleVuePlugin() {
|
||||
|
@ -262,7 +262,7 @@ define([
|
||||
// Plugins that are installed by default
|
||||
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
this.install(this.plugins.TelemetryTable.default());
|
||||
this.install(PreviewPlugin.default());
|
||||
this.install(LegacyIndicatorsPlugin());
|
||||
this.install(LicensesPlugin.default());
|
||||
@ -283,6 +283,7 @@ define([
|
||||
this.install(this.plugins.NotificationIndicator());
|
||||
this.install(this.plugins.NewFolderAction());
|
||||
this.install(this.plugins.ViewDatumAction());
|
||||
this.install(this.plugins.ViewLargeAction());
|
||||
this.install(this.plugins.ObjectInterceptors());
|
||||
this.install(this.plugins.NonEditableFolder());
|
||||
}
|
||||
|
@ -46,8 +46,6 @@ class ActionCollection extends EventEmitter {
|
||||
this._observeObjectPath();
|
||||
this.openmct.editor.on('isEditing', this._updateActions);
|
||||
}
|
||||
|
||||
this._initializeActions();
|
||||
}
|
||||
|
||||
disable(actionKeys) {
|
||||
@ -156,19 +154,10 @@ class ActionCollection extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
_initializeActions() {
|
||||
Object.keys(this.applicableActions).forEach(key => {
|
||||
this.applicableActions[key].callBack = () => {
|
||||
return this.applicableActions[key].invoke(this.objectPath, this.view);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
_updateActions() {
|
||||
let newApplicableActions = this.openmct.actions._applicableActions(this.objectPath, this.view);
|
||||
|
||||
this.applicableActions = this._mergeOldAndNewActions(this.applicableActions, newApplicableActions);
|
||||
this._initializeActions();
|
||||
this._update();
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class ActionsAPI extends EventEmitter {
|
||||
this._groupOrder = ['windowing', 'undefined', 'view', 'action', 'json'];
|
||||
|
||||
this.register = this.register.bind(this);
|
||||
this.get = this.get.bind(this);
|
||||
this.getActionsCollection = this.getActionsCollection.bind(this);
|
||||
this._applicableActions = this._applicableActions.bind(this);
|
||||
this._updateCachedActionCollections = this._updateCachedActionCollections.bind(this);
|
||||
}
|
||||
@ -43,12 +43,14 @@ class ActionsAPI extends EventEmitter {
|
||||
this._allActions[actionDefinition.key] = actionDefinition;
|
||||
}
|
||||
|
||||
get(objectPath, view) {
|
||||
if (view) {
|
||||
getAction(key) {
|
||||
return this._allActions[key];
|
||||
}
|
||||
|
||||
getActionsCollection(objectPath, view) {
|
||||
if (view) {
|
||||
return this._getCachedActionCollection(objectPath, view) || this._newActionCollection(objectPath, view, true);
|
||||
} else {
|
||||
|
||||
return this._newActionCollection(objectPath, view, true);
|
||||
}
|
||||
}
|
||||
@ -57,15 +59,6 @@ class ActionsAPI extends EventEmitter {
|
||||
this._groupOrder = groupArray;
|
||||
}
|
||||
|
||||
_get(objectPath, view) {
|
||||
let actionCollection = this._newActionCollection(objectPath, view);
|
||||
|
||||
this._actionCollections.set(view, actionCollection);
|
||||
actionCollection.on('destroy', this._updateCachedActionCollections);
|
||||
|
||||
return actionCollection;
|
||||
}
|
||||
|
||||
_getCachedActionCollection(objectPath, view) {
|
||||
let cachedActionCollection = this._actionCollections.get(view);
|
||||
|
||||
@ -75,7 +68,17 @@ class ActionsAPI extends EventEmitter {
|
||||
_newActionCollection(objectPath, view, skipEnvironmentObservers) {
|
||||
let applicableActions = this._applicableActions(objectPath, view);
|
||||
|
||||
return new ActionCollection(applicableActions, objectPath, view, this._openmct, skipEnvironmentObservers);
|
||||
const actionCollection = new ActionCollection(applicableActions, objectPath, view, this._openmct, skipEnvironmentObservers);
|
||||
if (view) {
|
||||
this._cacheActionCollection(view, actionCollection);
|
||||
}
|
||||
|
||||
return actionCollection;
|
||||
}
|
||||
|
||||
_cacheActionCollection(view, actionCollection) {
|
||||
this._actionCollections.set(view, actionCollection);
|
||||
actionCollection.on('destroy', this._updateCachedActionCollections);
|
||||
}
|
||||
|
||||
_updateCachedActionCollections(key) {
|
||||
|
@ -106,7 +106,7 @@ describe('The Actions API', () => {
|
||||
it("adds action to ActionsAPI", () => {
|
||||
actionsAPI.register(mockAction);
|
||||
|
||||
let actionCollection = actionsAPI.get(mockObjectPath, mockViewContext1);
|
||||
let actionCollection = actionsAPI.getActionsCollection(mockObjectPath, mockViewContext1);
|
||||
let action = actionCollection.getActionsObject()[mockAction.key];
|
||||
|
||||
expect(action.key).toEqual(mockAction.key);
|
||||
@ -121,21 +121,21 @@ describe('The Actions API', () => {
|
||||
});
|
||||
|
||||
it("returns an ActionCollection when invoked with an objectPath only", () => {
|
||||
let actionCollection = actionsAPI.get(mockObjectPath);
|
||||
let actionCollection = actionsAPI.getActionsCollection(mockObjectPath);
|
||||
let instanceOfActionCollection = actionCollection instanceof ActionCollection;
|
||||
|
||||
expect(instanceOfActionCollection).toBeTrue();
|
||||
});
|
||||
|
||||
it("returns an ActionCollection when invoked with an objectPath and view", () => {
|
||||
let actionCollection = actionsAPI.get(mockObjectPath, mockViewContext1);
|
||||
let actionCollection = actionsAPI.getActionsCollection(mockObjectPath, mockViewContext1);
|
||||
let instanceOfActionCollection = actionCollection instanceof ActionCollection;
|
||||
|
||||
expect(instanceOfActionCollection).toBeTrue();
|
||||
});
|
||||
|
||||
it("returns relevant actions when invoked with objectPath only", () => {
|
||||
let actionCollection = actionsAPI.get(mockObjectPath);
|
||||
let actionCollection = actionsAPI.getActionsCollection(mockObjectPath);
|
||||
let action = actionCollection.getActionsObject()[mockObjectPathAction.key];
|
||||
|
||||
expect(action.key).toEqual(mockObjectPathAction.key);
|
||||
@ -143,7 +143,7 @@ describe('The Actions API', () => {
|
||||
});
|
||||
|
||||
it("returns relevant actions when invoked with objectPath and view", () => {
|
||||
let actionCollection = actionsAPI.get(mockObjectPath, mockViewContext1);
|
||||
let actionCollection = actionsAPI.getActionsCollection(mockObjectPath, mockViewContext1);
|
||||
let action = actionCollection.getActionsObject()[mockAction.key];
|
||||
|
||||
expect(action.key).toEqual(mockAction.key);
|
||||
|
@ -37,7 +37,7 @@ import Menu, { MENU_PLACEMENT } from './menu.js';
|
||||
* @property {Boolean} isDisabled adds disable class if true
|
||||
* @property {String} name Menu item text
|
||||
* @property {String} description Menu item description
|
||||
* @property {Function} callBack callback function: invoked when item is clicked
|
||||
* @property {Function} onItemClicked callback function: invoked when item is clicked
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -66,12 +66,27 @@ class MenuAPI {
|
||||
* @param {Array.<Action>|Array.<Array.<Action>>} actions collection of actions{@link Action} or collection of groups of actions {@link Action}
|
||||
* @param {MenuOptions} [menuOptions] [Optional] The {@link MenuOptions} options for Menu
|
||||
*/
|
||||
showMenu(x, y, actions, menuOptions) {
|
||||
this._createMenuComponent(x, y, actions, menuOptions);
|
||||
showMenu(x, y, items, menuOptions) {
|
||||
this._createMenuComponent(x, y, items, menuOptions);
|
||||
|
||||
this.menuComponent.showMenu();
|
||||
}
|
||||
|
||||
actionsToMenuItems(actions, objectPath, view) {
|
||||
return actions.map(action => {
|
||||
const isActionGroup = Array.isArray(action);
|
||||
if (isActionGroup) {
|
||||
action = this.actionsToMenuItems(action, objectPath, view);
|
||||
} else {
|
||||
action.onItemClicked = () => {
|
||||
action.invoke(objectPath, view);
|
||||
};
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show popup menu with description of item on hover
|
||||
* @param {number} x x-coordinates for popup
|
||||
|
@ -57,7 +57,7 @@ describe ('The Menu API', () => {
|
||||
name: 'Test Action 1',
|
||||
cssClass: 'icon-clock',
|
||||
description: 'This is a test action',
|
||||
callBack: () => {
|
||||
onItemClicked: () => {
|
||||
result = 'Test Action 1 Invoked';
|
||||
}
|
||||
},
|
||||
@ -66,7 +66,7 @@ describe ('The Menu API', () => {
|
||||
name: 'Test Action 2',
|
||||
cssClass: 'icon-clock',
|
||||
description: 'This is a test action',
|
||||
callBack: () => {
|
||||
onItemClicked: () => {
|
||||
result = 'Test Action 2 Invoked';
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
:key="action.name"
|
||||
:class="[action.cssClass, action.isDisabled ? 'disabled' : '']"
|
||||
:title="action.description"
|
||||
@click="action.callBack"
|
||||
@click="action.onItemClicked"
|
||||
>
|
||||
{{ action.name }}
|
||||
</li>
|
||||
@ -36,7 +36,7 @@
|
||||
:key="action.name"
|
||||
:class="action.cssClass"
|
||||
:title="action.description"
|
||||
@click="action.callBack"
|
||||
@click="action.onItemClicked"
|
||||
>
|
||||
{{ action.name }}
|
||||
</li>
|
||||
|
@ -13,7 +13,7 @@
|
||||
:key="action.name"
|
||||
:class="[action.cssClass, action.isDisabled ? 'disabled' : '']"
|
||||
:title="action.description"
|
||||
@click="action.callBack"
|
||||
@click="action.onItemClicked"
|
||||
@mouseover="toggleItemDescription(action)"
|
||||
@mouseleave="toggleItemDescription()"
|
||||
>
|
||||
@ -42,7 +42,7 @@
|
||||
:key="action.name"
|
||||
:class="action.cssClass"
|
||||
:title="action.description"
|
||||
@click="action.callBack"
|
||||
@click="action.onItemClicked"
|
||||
@mouseover="toggleItemDescription(action)"
|
||||
@mouseleave="toggleItemDescription()"
|
||||
>
|
||||
|
@ -71,12 +71,12 @@ class Menu extends EventEmitter {
|
||||
|
||||
showMenu() {
|
||||
this.component = new Vue({
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
components: {
|
||||
MenuComponent
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
template: '<menu-component />'
|
||||
});
|
||||
|
||||
@ -85,12 +85,12 @@ class Menu extends EventEmitter {
|
||||
|
||||
showSuperMenu() {
|
||||
this.component = new Vue({
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
components: {
|
||||
SuperMenuComponent
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
template: '<super-menu-component />'
|
||||
});
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import LadTableSet from './components/LadTableSet.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
import LadTableSetView from './LadTableSetView';
|
||||
|
||||
export default function LADTableSetViewProvider(openmct) {
|
||||
return {
|
||||
@ -34,32 +34,7 @@ export default function LADTableSetViewProvider(openmct) {
|
||||
return domainObject.type === 'LadTableSet';
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
LadTableSet: LadTableSet
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject
|
||||
};
|
||||
},
|
||||
template: '<lad-table-set :domain-object="domainObject"></lad-table-set>'
|
||||
});
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
return new LadTableSetView(openmct, domainObject, objectPath);
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
|
45
src/plugins/LADTable/LADTableView.js
Normal file
45
src/plugins/LADTable/LADTableView.js
Normal file
@ -0,0 +1,45 @@
|
||||
import LadTable from './components/LADTable.vue';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
export default class LADTableView {
|
||||
constructor(openmct, domainObject, objectPath) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
show(element) {
|
||||
this.component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
LadTable
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
currentView: this
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
domainObject: this.domainObject,
|
||||
objectPath: this.objectPath
|
||||
};
|
||||
},
|
||||
template: '<lad-table ref="ladTable" :domain-object="domainObject" :object-path="objectPath"></lad-table>'
|
||||
});
|
||||
}
|
||||
|
||||
getViewContext() {
|
||||
if (!this.component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.component.$refs.ladTable.getViewContext();
|
||||
}
|
||||
|
||||
destroy(element) {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
}
|
@ -19,50 +19,30 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import LadTable from './components/LADTable.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default function LADTableViewProvider(openmct) {
|
||||
return {
|
||||
key: 'LadTable',
|
||||
name: 'LAD Table',
|
||||
cssClass: 'icon-tabular-lad',
|
||||
canView: function (domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
},
|
||||
canEdit: function (domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
import LADTableView from './LADTableView';
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
LadTableComponent: LadTable
|
||||
},
|
||||
provide: {
|
||||
openmct
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
domainObject,
|
||||
objectPath
|
||||
};
|
||||
},
|
||||
template: '<lad-table-component :domain-object="domainObject" :object-path="objectPath"></lad-table-component>'
|
||||
});
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
export default class LADTableViewProvider {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
this.name = 'LAD Table';
|
||||
this.key = 'LadTable';
|
||||
this.cssClass = 'icon-tabular-lad';
|
||||
}
|
||||
|
||||
canView(domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
}
|
||||
|
||||
canEdit(domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
}
|
||||
|
||||
view(domainObject, objectPath) {
|
||||
return new LADTableView(this.openmct, domainObject, objectPath);
|
||||
}
|
||||
|
||||
priority(domainObject) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
45
src/plugins/LADTable/LadTableSetView.js
Normal file
45
src/plugins/LADTable/LadTableSetView.js
Normal file
@ -0,0 +1,45 @@
|
||||
import LadTableSet from './components/LadTableSet.vue';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
export default class LadTableSetView {
|
||||
constructor(openmct, domainObject, objectPath) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
show(element) {
|
||||
this.component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
LadTableSet
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath,
|
||||
currentView: this
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
domainObject: this.domainObject
|
||||
};
|
||||
},
|
||||
template: '<lad-table-set ref="ladTableSet" :domain-object="domainObject"></lad-table-set>'
|
||||
});
|
||||
}
|
||||
|
||||
getViewContext() {
|
||||
if (!this.component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.component.$refs.ladTableSet.getViewContext();
|
||||
}
|
||||
|
||||
destroy(element) {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@ const CONTEXT_MENU_ACTIONS = [
|
||||
];
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
inject: ['openmct', 'currentView'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
@ -167,25 +167,23 @@ export default {
|
||||
this.resetValues();
|
||||
this.timestampKey = timeSystem.key;
|
||||
},
|
||||
getView() {
|
||||
return {
|
||||
getViewContext: () => {
|
||||
return {
|
||||
viewHistoricalData: true,
|
||||
viewDatumAction: true,
|
||||
getDatum: () => {
|
||||
return this.datum;
|
||||
}
|
||||
};
|
||||
updateViewContext() {
|
||||
this.$emit('rowContextClick', {
|
||||
viewHistoricalData: true,
|
||||
viewDatumAction: true,
|
||||
getDatum: () => {
|
||||
return this.datum;
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
showContextMenu(event) {
|
||||
let actionCollection = this.openmct.actions.get(this.objectPath, this.getView());
|
||||
let allActions = actionCollection.getActionsObject();
|
||||
let applicableActions = CONTEXT_MENU_ACTIONS.map(key => allActions[key]);
|
||||
this.updateViewContext();
|
||||
|
||||
this.openmct.menus.showMenu(event.x, event.y, applicableActions);
|
||||
const actions = CONTEXT_MENU_ACTIONS.map(key => this.openmct.actions.getAction(key));
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(actions, this.objectPath, this.currentView);
|
||||
if (menuItems.length) {
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
}
|
||||
},
|
||||
resetValues() {
|
||||
this.value = '---';
|
||||
|
@ -38,6 +38,7 @@
|
||||
:domain-object="ladRow.domainObject"
|
||||
:path-to-table="objectPath"
|
||||
:has-units="hasUnits"
|
||||
@rowContextClick="updateViewContext"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -51,7 +52,7 @@ export default {
|
||||
components: {
|
||||
LadRow
|
||||
},
|
||||
inject: ['openmct'],
|
||||
inject: ['openmct', 'currentView'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
@ -64,7 +65,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
items: [],
|
||||
viewContext: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -114,6 +116,12 @@ export default {
|
||||
let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
|
||||
|
||||
return metadataWithUnits.length > 0;
|
||||
},
|
||||
updateViewContext(rowContext) {
|
||||
this.viewContext.row = rowContext;
|
||||
},
|
||||
getViewContext() {
|
||||
return this.viewContext;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -48,6 +48,7 @@
|
||||
:domain-object="ladRow.domainObject"
|
||||
:path-to-table="ladTable.objectPath"
|
||||
:has-units="hasUnits"
|
||||
@rowContextClick="updateViewContext"
|
||||
/>
|
||||
</template>
|
||||
</tbody>
|
||||
@ -61,7 +62,7 @@ export default {
|
||||
components: {
|
||||
LadRow
|
||||
},
|
||||
inject: ['openmct', 'objectPath'],
|
||||
inject: ['openmct', 'objectPath', 'currentView'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
@ -72,7 +73,8 @@ export default {
|
||||
return {
|
||||
ladTableObjects: [],
|
||||
ladTelemetryObjects: {},
|
||||
compositions: []
|
||||
compositions: [],
|
||||
viewContext: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -166,6 +168,12 @@ export default {
|
||||
|
||||
this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects);
|
||||
};
|
||||
},
|
||||
updateViewContext(rowContext) {
|
||||
this.viewContext.row = rowContext;
|
||||
},
|
||||
getViewContext() {
|
||||
return this.viewContext;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -215,7 +215,8 @@ export default {
|
||||
},
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
default: false
|
||||
},
|
||||
telemetry: {
|
||||
type: Array,
|
||||
|
@ -20,71 +20,78 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./components/AlphanumericFormatView.vue',
|
||||
'vue'
|
||||
], function (AlphanumericFormatView, Vue) {
|
||||
import AlphanumericFormat from './components/AlphanumericFormat.vue';
|
||||
|
||||
function AlphanumericFormatViewProvider(openmct, options) {
|
||||
function isTelemetryObject(selectionPath) {
|
||||
let selectedObject = selectionPath[0].context.item;
|
||||
let parentObject = selectionPath[1].context.item;
|
||||
let selectedLayoutItem = selectionPath[0].context.layoutItem;
|
||||
import Vue from 'vue';
|
||||
|
||||
return parentObject
|
||||
&& parentObject.type === 'layout'
|
||||
&& selectedObject
|
||||
&& selectedLayoutItem
|
||||
&& selectedLayoutItem.type === 'telemetry-view'
|
||||
&& openmct.telemetry.isTelemetryObject(selectedObject)
|
||||
&& !options.showAsView.includes(selectedObject.type);
|
||||
}
|
||||
|
||||
return {
|
||||
key: 'alphanumeric-format',
|
||||
name: 'Alphanumeric Format',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0 || selection[0].length === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return selection.every(isTelemetryObject);
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
AlphanumericFormatView: AlphanumericFormatView.default
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
objectPath
|
||||
},
|
||||
template: '<alphanumeric-format-view ref="alphanumericFormatView"></alphanumeric-format-view>'
|
||||
});
|
||||
},
|
||||
getViewContext() {
|
||||
if (component) {
|
||||
return component.$refs.alphanumericFormatView.getViewContext();
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
class AlphanumericFormatView {
|
||||
constructor(openmct, domainObject, objectPath) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
return AlphanumericFormatViewProvider;
|
||||
});
|
||||
show(element) {
|
||||
this.component = new Vue({
|
||||
el: element,
|
||||
name: 'AlphanumericFormat',
|
||||
components: {
|
||||
AlphanumericFormat
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath,
|
||||
currentView: this
|
||||
},
|
||||
template: '<alphanumeric-format ref="alphanumericFormat"></alphanumeric-format>'
|
||||
});
|
||||
}
|
||||
|
||||
getViewContext() {
|
||||
if (this.component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.component.$refs.alphanumericFormat.getViewContext();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export default function AlphanumericFormatViewProvider(openmct, options) {
|
||||
function isTelemetryObject(selectionPath) {
|
||||
let selectedObject = selectionPath[0].context.item;
|
||||
let parentObject = selectionPath[1].context.item;
|
||||
let selectedLayoutItem = selectionPath[0].context.layoutItem;
|
||||
|
||||
return parentObject
|
||||
&& parentObject.type === 'layout'
|
||||
&& selectedObject
|
||||
&& selectedLayoutItem
|
||||
&& selectedLayoutItem.type === 'telemetry-view'
|
||||
&& openmct.telemetry.isTelemetryObject(selectedObject)
|
||||
&& !options.showAsView.includes(selectedObject.type);
|
||||
}
|
||||
|
||||
return {
|
||||
key: 'alphanumeric-format',
|
||||
name: 'Alphanumeric Format',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0 || selection[0].length === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return selection.every(isTelemetryObject);
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
return new AlphanumericFormatView(openmct, domainObject, objectPath);
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ export default class CopyToClipboardAction {
|
||||
|
||||
invoke(objectPath, view = {}) {
|
||||
const viewContext = view.getViewContext && view.getViewContext();
|
||||
const formattedValue = viewContext.formattedValueForCopy();
|
||||
const formattedValue = viewContext.row.formattedValueForCopy();
|
||||
|
||||
clipboard.updateClipboard(formattedValue)
|
||||
.then(() => {
|
||||
@ -26,9 +26,13 @@ export default class CopyToClipboardAction {
|
||||
}
|
||||
|
||||
appliesTo(objectPath, view = {}) {
|
||||
let viewContext = view.getViewContext && view.getViewContext();
|
||||
const viewContext = view.getViewContext && view.getViewContext();
|
||||
const row = viewContext && viewContext.row;
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return viewContext && viewContext.formattedValueForCopy
|
||||
&& typeof viewContext.formattedValueForCopy === 'function';
|
||||
return row.formattedValueForCopy
|
||||
&& typeof row.formattedValueForCopy === 'function';
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,8 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
name: 'AlphanumericFormat',
|
||||
inject: ['openmct', 'objectPath'],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing(),
|
@ -56,6 +56,7 @@
|
||||
:index="index"
|
||||
:multi-select="selectedLayoutItems.length > 1"
|
||||
:is-editing="isEditing"
|
||||
@contextClick="updateViewContext"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@endLineResize="endLineResize"
|
||||
@ -140,7 +141,7 @@ function getItemDefinition(itemType, ...options) {
|
||||
|
||||
export default {
|
||||
components: components,
|
||||
inject: ['openmct', 'options', 'objectPath'],
|
||||
inject: ['openmct', 'objectPath', 'options', 'objectUtils', 'currentView'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
@ -155,7 +156,8 @@ export default {
|
||||
return {
|
||||
initSelectIndex: undefined,
|
||||
selection: [],
|
||||
showGrid: true
|
||||
showGrid: true,
|
||||
viewContext: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -819,6 +821,12 @@ export default {
|
||||
},
|
||||
toggleGrid() {
|
||||
this.showGrid = !this.showGrid;
|
||||
},
|
||||
updateViewContext(viewContext) {
|
||||
this.viewContext.row = viewContext;
|
||||
},
|
||||
getViewContext() {
|
||||
return this.viewContext;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ export default {
|
||||
LayoutFrame
|
||||
},
|
||||
mixins: [conditionalStylesMixin],
|
||||
inject: ['openmct', 'objectPath'],
|
||||
inject: ['openmct', 'objectPath', 'currentView'],
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
@ -294,16 +294,6 @@ export default {
|
||||
this.requestHistoricalData(this.domainObject);
|
||||
}
|
||||
},
|
||||
getView() {
|
||||
return {
|
||||
getViewContext: () => {
|
||||
return {
|
||||
viewHistoricalData: true,
|
||||
formattedValueForCopy: this.formattedValueForCopy
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
setObject(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.mutablePromise = undefined;
|
||||
@ -338,30 +328,38 @@ export default {
|
||||
|
||||
this.$emit('formatChanged', this.item, format);
|
||||
},
|
||||
updateViewContext() {
|
||||
this.$emit('contextClick', {
|
||||
viewHistoricalData: true,
|
||||
formattedValueForCopy: this.formattedValueForCopy
|
||||
});
|
||||
},
|
||||
async getContextMenuActions() {
|
||||
const defaultNotebook = getDefaultNotebook();
|
||||
const domainObject = defaultNotebook && await this.openmct.objects.get(defaultNotebook.notebookMeta.identifier);
|
||||
const actionCollection = this.openmct.actions.get(this.currentObjectPath, this.getView());
|
||||
const actionsObject = actionCollection.getActionsObject();
|
||||
|
||||
let copyToNotebookAction = actionsObject.copyToNotebook;
|
||||
|
||||
let defaultNotebookName;
|
||||
if (defaultNotebook) {
|
||||
const defaultPath = domainObject && `${domainObject.name} - ${defaultNotebook.section.name} - ${defaultNotebook.page.name}`;
|
||||
copyToNotebookAction.name = `Copy to Notebook ${defaultPath}`;
|
||||
} else {
|
||||
actionsObject.copyToNotebook = undefined;
|
||||
delete actionsObject.copyToNotebook;
|
||||
defaultNotebookName = `Copy to Notebook ${defaultPath}`;
|
||||
}
|
||||
|
||||
return CONTEXT_MENU_ACTIONS.map(actionKey => {
|
||||
return actionsObject[actionKey];
|
||||
}).filter(action => action !== undefined);
|
||||
return CONTEXT_MENU_ACTIONS
|
||||
.map(actionKey => {
|
||||
const action = this.openmct.actions.getAction(actionKey);
|
||||
if (action.key === 'copyToNotebook') {
|
||||
action.name = defaultNotebookName;
|
||||
}
|
||||
|
||||
return action;
|
||||
})
|
||||
.filter(action => action.name !== undefined);
|
||||
},
|
||||
async showContextMenu(event) {
|
||||
this.updateViewContext();
|
||||
const contextMenuActions = await this.getContextMenuActions();
|
||||
|
||||
this.openmct.menus.showMenu(event.x, event.y, contextMenuActions);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(contextMenuActions, this.currentObjectPath, this.currentView);
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
},
|
||||
setStatus(status) {
|
||||
this.status = status;
|
||||
|
@ -20,13 +20,81 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import Layout from './components/DisplayLayout.vue';
|
||||
import Vue from 'vue';
|
||||
import objectUtils from 'objectUtils';
|
||||
import DisplayLayoutType from './DisplayLayoutType.js';
|
||||
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js';
|
||||
import AlphaNumericFormatViewProvider from './AlphanumericFormatViewProvider.js';
|
||||
import CopyToClipboardAction from './actions/CopyToClipboardAction';
|
||||
import DisplayLayout from './components/DisplayLayout.vue';
|
||||
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js';
|
||||
import DisplayLayoutType from './DisplayLayoutType.js';
|
||||
|
||||
import objectUtils from 'objectUtils';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
class DisplayLayoutView {
|
||||
constructor(openmct, domainObject, objectPath, options) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.options = options;
|
||||
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
show(container, isEditing) {
|
||||
this.component = new Vue({
|
||||
el: container,
|
||||
components: {
|
||||
DisplayLayout
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath,
|
||||
options: this.options,
|
||||
objectUtils,
|
||||
currentView: this
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
domainObject: this.domainObject,
|
||||
isEditing
|
||||
};
|
||||
},
|
||||
template: '<display-layout ref="displayLayout" :domain-object="domainObject" :is-editing="isEditing"></display-layout>'
|
||||
});
|
||||
}
|
||||
|
||||
getViewContext() {
|
||||
if (!this.component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.component.$refs.displayLayout.getViewContext();
|
||||
}
|
||||
|
||||
getSelectionContext() {
|
||||
return {
|
||||
item: this.domainObject,
|
||||
supportsMultiSelect: true,
|
||||
addElement: this.component && this.component.$refs.displayLayout.addElement,
|
||||
removeItem: this.component && this.component.$refs.displayLayout.removeItem,
|
||||
orderItem: this.component && this.component.$refs.displayLayout.orderItem,
|
||||
duplicateItem: this.component && this.component.$refs.displayLayout.duplicateItem,
|
||||
switchViewType: this.component && this.component.$refs.displayLayout.switchViewType,
|
||||
mergeMultipleTelemetryViews: this.component && this.component.$refs.displayLayout.mergeMultipleTelemetryViews,
|
||||
mergeMultipleOverlayPlots: this.component && this.component.$refs.displayLayout.mergeMultipleOverlayPlots,
|
||||
toggleGrid: this.component && this.component.$refs.displayLayout.toggleGrid
|
||||
};
|
||||
}
|
||||
|
||||
onEditModeChange(isEditing) {
|
||||
this.component.isEditing = isEditing;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export default function DisplayLayoutPlugin(options) {
|
||||
return function (openmct) {
|
||||
@ -41,51 +109,7 @@ export default function DisplayLayoutPlugin(options) {
|
||||
return domainObject.type === 'layout';
|
||||
},
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show(container) {
|
||||
component = new Vue({
|
||||
el: container,
|
||||
components: {
|
||||
Layout
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
objectUtils,
|
||||
options,
|
||||
objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject: domainObject,
|
||||
isEditing: openmct.editor.isEditing()
|
||||
};
|
||||
},
|
||||
template: '<layout ref="displayLayout" :domain-object="domainObject" :is-editing="isEditing"></layout>'
|
||||
});
|
||||
},
|
||||
getSelectionContext() {
|
||||
return {
|
||||
item: domainObject,
|
||||
supportsMultiSelect: true,
|
||||
addElement: component && component.$refs.displayLayout.addElement,
|
||||
removeItem: component && component.$refs.displayLayout.removeItem,
|
||||
orderItem: component && component.$refs.displayLayout.orderItem,
|
||||
duplicateItem: component && component.$refs.displayLayout.duplicateItem,
|
||||
switchViewType: component && component.$refs.displayLayout.switchViewType,
|
||||
mergeMultipleTelemetryViews: component && component.$refs.displayLayout.mergeMultipleTelemetryViews,
|
||||
mergeMultipleOverlayPlots: component && component.$refs.displayLayout.mergeMultipleOverlayPlots,
|
||||
toggleGrid: component && component.$refs.displayLayout.toggleGrid
|
||||
};
|
||||
},
|
||||
onEditModeChange: function (isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy() {
|
||||
component.$destroy();
|
||||
}
|
||||
};
|
||||
return new DisplayLayoutView(openmct, domainObject, objectPath, options);
|
||||
},
|
||||
priority() {
|
||||
return 100;
|
||||
|
37
src/plugins/imagery/ImageryView.js
Normal file
37
src/plugins/imagery/ImageryView.js
Normal file
@ -0,0 +1,37 @@
|
||||
import ImageryViewLayout from './components/ImageryViewLayout.vue';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
export default class ImageryView {
|
||||
constructor(openmct, domainObject, objectPath) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
show(element) {
|
||||
this.component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
ImageryViewLayout
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
domainObject: this.domainObject,
|
||||
objectPath: this.objectPath,
|
||||
currentView: this
|
||||
},
|
||||
template: '<imagery-view-layout ref="ImageryLayout"></imagery-view-layout>'
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
_getInstance() {
|
||||
return this.component;
|
||||
}
|
||||
}
|
@ -19,9 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import ImageryViewLayout from './components/ImageryViewLayout.vue';
|
||||
import Vue from 'vue';
|
||||
import ImageryView from './ImageryView';
|
||||
|
||||
export default function ImageryViewProvider(openmct) {
|
||||
const type = 'example.imagery';
|
||||
@ -42,31 +40,8 @@ export default function ImageryViewProvider(openmct) {
|
||||
canView: function (domainObject) {
|
||||
return hasImageTelemetry(domainObject);
|
||||
},
|
||||
view: function (domainObject) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
ImageryViewLayout
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject
|
||||
},
|
||||
template: '<imagery-view-layout ref="ImageryLayout"></imagery-view-layout>'
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
},
|
||||
_getInstance: function () {
|
||||
return component;
|
||||
}
|
||||
};
|
||||
view: function (domainObject, objectPath) {
|
||||
return new ImageryView(openmct, domainObject, objectPath);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -58,6 +58,7 @@
|
||||
<div ref="imageBG"
|
||||
class="c-imagery__main-image__bg"
|
||||
:class="{'paused unnsynced': isPaused,'stale':false }"
|
||||
@click="expand"
|
||||
>
|
||||
<div class="image-wrapper"
|
||||
:style="{
|
||||
@ -170,8 +171,9 @@
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import Compass from './Compass/Compass.vue';
|
||||
|
||||
import RelatedTelemetry from './RelatedTelemetry/RelatedTelemetry';
|
||||
import Compass from './Compass/Compass.vue';
|
||||
|
||||
const DEFAULT_DURATION_FORMATTER = 'duration';
|
||||
const REFRESH_CSS_MS = 500;
|
||||
@ -195,7 +197,7 @@ export default {
|
||||
components: {
|
||||
Compass
|
||||
},
|
||||
inject: ['openmct', 'domainObject'],
|
||||
inject: ['openmct', 'domainObject', 'objectPath', 'currentView'],
|
||||
data() {
|
||||
let timeSystem = this.openmct.time.timeSystem();
|
||||
|
||||
@ -468,6 +470,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
expand() {
|
||||
const actionCollection = this.openmct.actions.getActionsCollection(this.objectPath, this.currentView);
|
||||
const visibleActions = actionCollection.getVisibleActions();
|
||||
const viewLargeAction = visibleActions
|
||||
&& visibleActions.find(action => action.key === 'large.view');
|
||||
|
||||
if (viewLargeAction && viewLargeAction.appliesTo(this.objectPath, this.currentView)) {
|
||||
viewLargeAction.onItemClicked();
|
||||
}
|
||||
},
|
||||
async initializeRelatedTelemetry() {
|
||||
this.relatedTelemetry = new RelatedTelemetry(
|
||||
this.openmct,
|
||||
|
@ -25,16 +25,20 @@ export default class CopyToNotebookAction {
|
||||
});
|
||||
}
|
||||
|
||||
invoke(objectPath, view = {}) {
|
||||
let viewContext = view.getViewContext && view.getViewContext();
|
||||
invoke(objectPath, view) {
|
||||
const formattedValueForCopy = view.getViewContext().row.formattedValueForCopy;
|
||||
|
||||
this.copyToNotebook(viewContext.formattedValueForCopy());
|
||||
this.copyToNotebook(formattedValueForCopy());
|
||||
}
|
||||
|
||||
appliesTo(objectPath, view = {}) {
|
||||
let viewContext = view.getViewContext && view.getViewContext();
|
||||
const viewContext = view.getViewContext && view.getViewContext();
|
||||
const row = viewContext && viewContext.row;
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
return viewContext && viewContext.formattedValueForCopy
|
||||
&& typeof viewContext.formattedValueForCopy === 'function';
|
||||
return row.formattedValueForCopy
|
||||
&& typeof row.formattedValueForCopy === 'function';
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ export default {
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-notebook',
|
||||
name: `Save to Notebook ${defaultPath}`,
|
||||
callBack: () => {
|
||||
onItemClicked: () => {
|
||||
return this.snapshot(NOTEBOOK_DEFAULT);
|
||||
}
|
||||
});
|
||||
@ -89,7 +89,7 @@ export default {
|
||||
notebookTypes.push({
|
||||
cssClass: 'icon-camera',
|
||||
name: 'Save to Notebook Snapshots',
|
||||
callBack: () => {
|
||||
onItemClicked: () => {
|
||||
return this.snapshot(NOTEBOOK_SNAPSHOT);
|
||||
}
|
||||
});
|
||||
|
@ -63,6 +63,7 @@ define([
|
||||
'./defaultRootName/plugin',
|
||||
'./plan/plugin',
|
||||
'./viewDatumAction/plugin',
|
||||
'./viewLargeAction/plugin',
|
||||
'./interceptors/plugin',
|
||||
'./performanceIndicator/plugin',
|
||||
'./CouchDBSearchFolder/plugin',
|
||||
@ -110,6 +111,7 @@ define([
|
||||
DefaultRootName,
|
||||
PlanLayout,
|
||||
ViewDatumAction,
|
||||
ViewLargeAction,
|
||||
ObjectInterceptors,
|
||||
PerformanceIndicator,
|
||||
CouchDBSearchFolder,
|
||||
@ -211,6 +213,7 @@ define([
|
||||
plugins.DefaultRootName = DefaultRootName.default;
|
||||
plugins.PlanLayout = PlanLayout.default;
|
||||
plugins.ViewDatumAction = ViewDatumAction.default;
|
||||
plugins.ViewLargeAction = ViewLargeAction.default;
|
||||
plugins.ObjectInterceptors = ObjectInterceptors.default;
|
||||
plugins.PerformanceIndicator = PerformanceIndicator.default;
|
||||
plugins.CouchDBSearchFolder = CouchDBSearchFolder.default;
|
||||
|
67
src/plugins/telemetryTable/TelemetryTableView.js
Normal file
67
src/plugins/telemetryTable/TelemetryTableView.js
Normal file
@ -0,0 +1,67 @@
|
||||
import TableComponent from './components/table.vue';
|
||||
import TelemetryTable from './TelemetryTable';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default class TelemetryTableView {
|
||||
constructor(openmct, domainObject, objectPath) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = objectPath;
|
||||
this.component = undefined;
|
||||
|
||||
this.table = new TelemetryTable(domainObject, openmct);
|
||||
}
|
||||
|
||||
getViewContext() {
|
||||
if (!this.component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.component.$refs.tableComponent.getViewContext();
|
||||
}
|
||||
|
||||
onEditModeChange(editMode) {
|
||||
this.component.isEditing = editMode;
|
||||
}
|
||||
|
||||
onClearData() {
|
||||
this.table.clearData();
|
||||
}
|
||||
|
||||
getTable() {
|
||||
return this.table;
|
||||
}
|
||||
|
||||
destroy(element) {
|
||||
this.component.$destroy();
|
||||
this.component = undefined;
|
||||
}
|
||||
|
||||
show(element, editMode) {
|
||||
this.component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
TableComponent
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath,
|
||||
table: this.table,
|
||||
currentView: this
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: editMode,
|
||||
marking: {
|
||||
disableMultiSelect: false,
|
||||
enable: true,
|
||||
rowName: '',
|
||||
rowNamePlural: '',
|
||||
useAlternateControlBar: false
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<table-component ref="tableComponent" :is-editing="isEditing" :marking="marking"></table-component>'
|
||||
});
|
||||
}
|
||||
}
|
@ -20,99 +20,35 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./components/table.vue',
|
||||
'./TelemetryTable',
|
||||
'vue'
|
||||
], function (
|
||||
TableComponent,
|
||||
TelemetryTable,
|
||||
Vue
|
||||
) {
|
||||
function TelemetryTableViewProvider(openmct) {
|
||||
function hasTelemetry(domainObject) {
|
||||
if (!Object.prototype.hasOwnProperty.call(domainObject, 'telemetry')) {
|
||||
return false;
|
||||
}
|
||||
import TelemetryTableView from './TelemetryTableView';
|
||||
|
||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||
|
||||
return metadata.values().length > 0;
|
||||
export default function TelemetryTableViewProvider(openmct) {
|
||||
function hasTelemetry(domainObject) {
|
||||
if (!Object.prototype.hasOwnProperty.call(domainObject, 'telemetry')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
key: 'table',
|
||||
name: 'Telemetry Table',
|
||||
cssClass: 'icon-tabular-realtime',
|
||||
canView(domainObject) {
|
||||
return domainObject.type === 'table'
|
||||
|| hasTelemetry(domainObject);
|
||||
},
|
||||
canEdit(domainObject) {
|
||||
return domainObject.type === 'table';
|
||||
},
|
||||
view(domainObject, objectPath) {
|
||||
let table = new TelemetryTable(domainObject, openmct);
|
||||
let component;
|
||||
let markingProp = {
|
||||
enable: true,
|
||||
useAlternateControlBar: false,
|
||||
rowName: '',
|
||||
rowNamePlural: ''
|
||||
};
|
||||
const view = {
|
||||
show: function (element, editMode) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
TableComponent: TableComponent.default
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
table,
|
||||
objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: editMode,
|
||||
markingProp,
|
||||
view
|
||||
};
|
||||
},
|
||||
template: '<table-component ref="tableComponent" :isEditing="isEditing" :marking="markingProp" :view="view"/>'
|
||||
});
|
||||
},
|
||||
onEditModeChange(editMode) {
|
||||
component.isEditing = editMode;
|
||||
},
|
||||
onClearData() {
|
||||
table.clearData();
|
||||
},
|
||||
getViewContext() {
|
||||
if (component) {
|
||||
return component.$refs.tableComponent.getViewContext();
|
||||
} else {
|
||||
return {
|
||||
type: 'telemetry-table'
|
||||
};
|
||||
}
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
},
|
||||
_getTable: function () {
|
||||
return table;
|
||||
}
|
||||
};
|
||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||
|
||||
return view;
|
||||
},
|
||||
priority() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
return metadata.values().length > 0;
|
||||
}
|
||||
|
||||
return TelemetryTableViewProvider;
|
||||
});
|
||||
return {
|
||||
key: 'table',
|
||||
name: 'Telemetry Table',
|
||||
cssClass: 'icon-tabular-realtime',
|
||||
canView(domainObject) {
|
||||
return domainObject.type === 'table'
|
||||
|| hasTelemetry(domainObject);
|
||||
},
|
||||
canEdit(domainObject) {
|
||||
return domainObject.type === 'table';
|
||||
},
|
||||
view(domainObject, objectPath) {
|
||||
return new TelemetryTableView(openmct, domainObject, objectPath);
|
||||
},
|
||||
priority() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -20,83 +20,89 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
let exportCSV = {
|
||||
const exportCSV = {
|
||||
name: 'Export Table Data',
|
||||
key: 'export-csv-all',
|
||||
description: "Export this view's data",
|
||||
cssClass: 'icon-download labeled',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().exportAllDataAsCSV();
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().exportAllDataAsCSV();
|
||||
},
|
||||
group: 'view'
|
||||
};
|
||||
let exportMarkedDataAsCSV = {
|
||||
|
||||
const exportMarkedDataAsCSV = {
|
||||
name: 'Export Marked Rows',
|
||||
key: 'export-csv-marked',
|
||||
description: "Export marked rows as CSV",
|
||||
cssClass: 'icon-download labeled',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().exportMarkedDataAsCSV();
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().exportMarkedDataAsCSV();
|
||||
},
|
||||
group: 'view'
|
||||
};
|
||||
let unmarkAllRows = {
|
||||
|
||||
const unmarkAllRows = {
|
||||
name: 'Unmark All Rows',
|
||||
key: 'unmark-all-rows',
|
||||
description: 'Unmark all rows',
|
||||
cssClass: 'icon-x labeled',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().unmarkAllRows();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
let pause = {
|
||||
name: 'Pause',
|
||||
key: 'pause-data',
|
||||
description: 'Pause real-time data flow',
|
||||
cssClass: 'icon-pause',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().togglePauseByButton();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
let play = {
|
||||
name: 'Play',
|
||||
key: 'play-data',
|
||||
description: 'Continue real-time data flow',
|
||||
cssClass: 'c-button pause-play is-paused',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().togglePauseByButton();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
let expandColumns = {
|
||||
name: 'Expand Columns',
|
||||
key: 'expand-columns',
|
||||
description: "Increase column widths to fit currently available data.",
|
||||
cssClass: 'icon-arrows-right-left labeled',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().expandColumns();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
let autosizeColumns = {
|
||||
name: 'Autosize Columns',
|
||||
key: 'autosize-columns',
|
||||
description: "Automatically size columns to fit the table into the available space.",
|
||||
cssClass: 'icon-expand labeled',
|
||||
invoke: (objectPath, viewProvider) => {
|
||||
viewProvider.getViewContext().autosizeColumns();
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().unmarkAllRows();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
|
||||
let viewActions = [
|
||||
const pause = {
|
||||
name: 'Pause',
|
||||
key: 'pause-data',
|
||||
description: 'Pause real-time data flow',
|
||||
cssClass: 'icon-pause',
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().togglePauseByButton();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
|
||||
const play = {
|
||||
name: 'Play',
|
||||
key: 'play-data',
|
||||
description: 'Continue real-time data flow',
|
||||
cssClass: 'c-button pause-play is-paused',
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().togglePauseByButton();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
|
||||
const expandColumns = {
|
||||
name: 'Expand Columns',
|
||||
key: 'expand-columns',
|
||||
description: "Increase column widths to fit currently available data.",
|
||||
cssClass: 'icon-arrows-right-left labeled',
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().expandColumns();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
|
||||
const autosizeColumns = {
|
||||
name: 'Autosize Columns',
|
||||
key: 'autosize-columns',
|
||||
description: "Automatically size columns to fit the table into the available space.",
|
||||
cssClass: 'icon-expand labeled',
|
||||
invoke: (objectPath, view) => {
|
||||
view.getViewContext().autosizeColumns();
|
||||
},
|
||||
showInStatusBar: true,
|
||||
group: 'view'
|
||||
};
|
||||
|
||||
const viewActions = [
|
||||
exportCSV,
|
||||
exportMarkedDataAsCSV,
|
||||
unmarkAllRows,
|
||||
@ -107,16 +113,13 @@ let viewActions = [
|
||||
];
|
||||
|
||||
viewActions.forEach(action => {
|
||||
action.appliesTo = (objectPath, viewProvider = {}) => {
|
||||
let viewContext = viewProvider.getViewContext && viewProvider.getViewContext();
|
||||
|
||||
if (viewContext) {
|
||||
let type = viewContext.type;
|
||||
|
||||
return type === 'telemetry-table';
|
||||
action.appliesTo = (objectPath, view = {}) => {
|
||||
const viewContext = view.getViewContext && view.getViewContext();
|
||||
if (!viewContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return viewContext.type === 'telemetry-table';
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -49,7 +49,7 @@ export default {
|
||||
components: {
|
||||
TableCell
|
||||
},
|
||||
inject: ['openmct'],
|
||||
inject: ['openmct', 'currentView'],
|
||||
props: {
|
||||
headers: {
|
||||
type: Object,
|
||||
@ -97,16 +97,7 @@ export default {
|
||||
selectable[columnKeys] = this.row.columns[columnKeys].selectable;
|
||||
|
||||
return selectable;
|
||||
}, {}),
|
||||
actionsViewContext: {
|
||||
getViewContext: () => {
|
||||
return {
|
||||
viewHistoricalData: true,
|
||||
viewDatumAction: true,
|
||||
getDatum: this.getDatum
|
||||
};
|
||||
}
|
||||
}
|
||||
}, {})
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -187,19 +178,20 @@ export default {
|
||||
showContextMenu: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.updateViewContext();
|
||||
this.markRow(event);
|
||||
|
||||
this.row.getContextualDomainObject(this.openmct, this.row.objectKeyString).then(domainObject => {
|
||||
let contextualObjectPath = this.objectPath.slice();
|
||||
contextualObjectPath.unshift(domainObject);
|
||||
|
||||
let actionsCollection = this.openmct.actions.get(contextualObjectPath, this.actionsViewContext);
|
||||
let allActions = actionsCollection.getActionsObject();
|
||||
let applicableActions = this.row.getContextMenuActions().map(key => allActions[key]);
|
||||
|
||||
if (applicableActions.length) {
|
||||
this.openmct.menus.showMenu(event.x, event.y, applicableActions);
|
||||
}
|
||||
const actions = this.row.getContextMenuActions().map(key => this.openmct.actions.getAction(key));
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(actions, this.objectPath, this.currentView);
|
||||
if (menuItems.length) {
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
}
|
||||
},
|
||||
updateViewContext() {
|
||||
this.$emit('rowContextClick', {
|
||||
viewHistoricalData: true,
|
||||
viewDatumAction: true,
|
||||
getDatum: this.getDatum
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -233,6 +233,7 @@
|
||||
@mark="markRow"
|
||||
@unmark="unmarkRow"
|
||||
@markMultipleConcurrent="markMultipleConcurrentRows"
|
||||
@rowContextClick="updateViewContext"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -263,6 +264,7 @@
|
||||
:column-widths="configuredColumnWidths"
|
||||
:row="sizingRowData"
|
||||
:object-path="objectPath"
|
||||
@rowContextClick="updateViewContext"
|
||||
/>
|
||||
</table>
|
||||
<table-footer-indicator
|
||||
@ -298,12 +300,25 @@ export default {
|
||||
ToggleSwitch,
|
||||
SizingRow
|
||||
},
|
||||
inject: ['table', 'openmct', 'objectPath'],
|
||||
inject: ['openmct', 'objectPath', 'table', 'currentView'],
|
||||
props: {
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
marking: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {
|
||||
enable: false,
|
||||
disableMultiSelect: false,
|
||||
useAlternateControlBar: false,
|
||||
rowName: '',
|
||||
rowNamePlural: ''
|
||||
};
|
||||
}
|
||||
},
|
||||
allowExport: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
@ -316,28 +331,9 @@ export default {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
marking: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
enable: false,
|
||||
disableMultiSelect: false,
|
||||
useAlternateControlBar: false,
|
||||
rowName: '',
|
||||
rowNamePlural: ""
|
||||
};
|
||||
}
|
||||
},
|
||||
enableLegacyToolbar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
view: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -373,7 +369,8 @@ export default {
|
||||
isShowingMarkedRowsOnly: false,
|
||||
enableRegexSearch: {},
|
||||
hideHeaders: configuration.hideHeaders,
|
||||
totalNumberOfRows: 0
|
||||
totalNumberOfRows: 0,
|
||||
rowContext: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -461,8 +458,10 @@ export default {
|
||||
this.scroll = _.throttle(this.scroll, 100);
|
||||
|
||||
if (!this.marking.useAlternateControlBar && !this.enableLegacyToolbar) {
|
||||
this.viewActionsCollection = this.openmct.actions.get(this.objectPath, this.view);
|
||||
this.initializeViewActions();
|
||||
this.$nextTick(() => {
|
||||
this.viewActionsCollection = this.openmct.actions.getActionsCollection(this.objectPath, this.currentView);
|
||||
this.initializeViewActions();
|
||||
});
|
||||
}
|
||||
|
||||
this.table.on('object-added', this.addObject);
|
||||
@ -996,7 +995,8 @@ export default {
|
||||
unmarkAllRows: this.unmarkAllRows,
|
||||
togglePauseByButton: this.togglePauseByButton,
|
||||
expandColumns: this.recalculateColumnWidths,
|
||||
autosizeColumns: this.autosizeColumns
|
||||
autosizeColumns: this.autosizeColumns,
|
||||
row: this.rowContext
|
||||
};
|
||||
},
|
||||
initializeViewActions() {
|
||||
@ -1027,6 +1027,9 @@ export default {
|
||||
this.setHeight();
|
||||
this.calculateTableSize();
|
||||
this.clearRowsAndRerender();
|
||||
},
|
||||
updateViewContext(rowContext) {
|
||||
this.rowContext = rowContext;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -19,34 +19,26 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import TelemetryTableViewProvider from './TelemetryTableViewProvider';
|
||||
import TableConfigurationViewProvider from './TableConfigurationViewProvider';
|
||||
import TelemetryTableType from './TelemetryTableType';
|
||||
import TelemetryTableViewActions from './ViewActions';
|
||||
|
||||
define([
|
||||
'./TelemetryTableViewProvider',
|
||||
'./TableConfigurationViewProvider',
|
||||
'./TelemetryTableType',
|
||||
'./ViewActions'
|
||||
], function (
|
||||
TelemetryTableViewProvider,
|
||||
TableConfigurationViewProvider,
|
||||
TelemetryTableType,
|
||||
TelemetryTableViewActions
|
||||
) {
|
||||
return function plugin() {
|
||||
return function install(openmct) {
|
||||
openmct.objectViews.addProvider(new TelemetryTableViewProvider(openmct));
|
||||
openmct.inspectorViews.addProvider(new TableConfigurationViewProvider(openmct));
|
||||
openmct.types.addType('table', TelemetryTableType);
|
||||
openmct.composition.addPolicy((parent, child) => {
|
||||
if (parent.type === 'table') {
|
||||
return Object.prototype.hasOwnProperty.call(child, 'telemetry');
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
export default function plugin() {
|
||||
return function install(openmct) {
|
||||
openmct.objectViews.addProvider(new TelemetryTableViewProvider(openmct));
|
||||
openmct.inspectorViews.addProvider(new TableConfigurationViewProvider(openmct));
|
||||
openmct.types.addType('table', TelemetryTableType);
|
||||
openmct.composition.addPolicy((parent, child) => {
|
||||
if (parent.type === 'table') {
|
||||
return Object.prototype.hasOwnProperty.call(child, 'telemetry');
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
TelemetryTableViewActions.default.forEach(action => {
|
||||
openmct.actions.register(action);
|
||||
});
|
||||
};
|
||||
TelemetryTableViewActions.forEach(action => {
|
||||
openmct.actions.register(action);
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ describe("the plugin", () => {
|
||||
tableView = tableViewProvider.view(testTelemetryObject, [testTelemetryObject]);
|
||||
tableView.show(child, true);
|
||||
|
||||
tableInstance = tableView._getTable();
|
||||
tableInstance = tableView.getTable();
|
||||
|
||||
return telemetryPromise.then(() => Vue.nextTick());
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ export default {
|
||||
cssClass: 'icon-history',
|
||||
name,
|
||||
description,
|
||||
callBack: () => this.selectTimespan(timespan)
|
||||
onItemClicked: () => this.selectTimespan(timespan)
|
||||
};
|
||||
});
|
||||
|
||||
@ -160,7 +160,7 @@ export default {
|
||||
description: 'Past timeframes, ordered by latest first',
|
||||
isDisabled: true,
|
||||
name: 'Past timeframes, ordered by latest first',
|
||||
callBack: () => {}
|
||||
onItemClicked: () => {}
|
||||
});
|
||||
|
||||
return history;
|
||||
@ -171,7 +171,7 @@ export default {
|
||||
cssClass: 'icon-clock',
|
||||
name: preset.label,
|
||||
description: preset.label,
|
||||
callBack: () => this.selectPresetBounds(preset.bounds)
|
||||
onItemClicked: () => this.selectPresetBounds(preset.bounds)
|
||||
};
|
||||
});
|
||||
},
|
||||
|
@ -104,7 +104,7 @@ export default {
|
||||
name: 'Fixed Timespan',
|
||||
description: 'Query and explore data that falls between two fixed datetimes.',
|
||||
cssClass: 'icon-tabular',
|
||||
callBack: () => this.setOption(key)
|
||||
onItemClicked: () => this.setOption(key)
|
||||
};
|
||||
} else {
|
||||
const key = clock.key;
|
||||
@ -115,7 +115,7 @@ export default {
|
||||
description: "Monitor streaming data in real-time. The Time "
|
||||
+ "Conductor and displays will automatically advance themselves based on this clock. " + clock.description,
|
||||
cssClass: clock.cssClass || 'icon-clock',
|
||||
callBack: () => this.setOption(key)
|
||||
onItemClicked: () => this.setOption(key)
|
||||
};
|
||||
}
|
||||
},
|
||||
|
@ -70,7 +70,7 @@ export default {
|
||||
.filter(menuOption => menuOption.clock === (clock && clock.key))
|
||||
.map(menuOption => {
|
||||
const timeSystem = JSON.parse(JSON.stringify(this.openmct.time.timeSystems.get(menuOption.timeSystem)));
|
||||
timeSystem.callBack = () => this.setTimeSystemFromView(timeSystem);
|
||||
timeSystem.onItemClicked = () => this.setTimeSystemFromView(timeSystem);
|
||||
|
||||
return timeSystem;
|
||||
});
|
||||
|
@ -34,15 +34,16 @@ export default class ViewDatumAction {
|
||||
}
|
||||
invoke(objectPath, view) {
|
||||
let viewContext = view.getViewContext && view.getViewContext();
|
||||
let attributes = viewContext.getDatum && viewContext.getDatum();
|
||||
const row = viewContext.row;
|
||||
let attributes = row.getDatum && row.getDatum();
|
||||
let component = new Vue ({
|
||||
components: {
|
||||
MetadataListView
|
||||
},
|
||||
provide: {
|
||||
name: this.name,
|
||||
attributes
|
||||
},
|
||||
components: {
|
||||
MetadataListView
|
||||
},
|
||||
template: '<MetadataListView />'
|
||||
});
|
||||
|
||||
@ -57,9 +58,13 @@ export default class ViewDatumAction {
|
||||
}
|
||||
appliesTo(objectPath, view = {}) {
|
||||
let viewContext = (view.getViewContext && view.getViewContext()) || {};
|
||||
let datum = viewContext.getDatum;
|
||||
let enabled = viewContext.viewDatumAction;
|
||||
const row = viewContext.row;
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let datum = row.getDatum;
|
||||
let enabled = row.viewDatumAction;
|
||||
if (enabled && datum) {
|
||||
return true;
|
||||
}
|
||||
|
@ -57,9 +57,11 @@ describe("the plugin", () => {
|
||||
mockView = {
|
||||
getViewContext: () => {
|
||||
return {
|
||||
viewDatumAction: true,
|
||||
getDatum: () => {
|
||||
return mockDatum;
|
||||
row: {
|
||||
viewDatumAction: true,
|
||||
getDatum: () => {
|
||||
return mockDatum;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
29
src/plugins/viewLargeAction/plugin.js
Normal file
29
src/plugins/viewLargeAction/plugin.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import ViewLargeAction from './viewLargeAction.js';
|
||||
|
||||
export default function plugin() {
|
||||
return function install(openmct) {
|
||||
openmct.actions.register(new ViewLargeAction(openmct));
|
||||
};
|
||||
}
|
115
src/plugins/viewLargeAction/viewLargeAction.js
Normal file
115
src/plugins/viewLargeAction/viewLargeAction.js
Normal file
@ -0,0 +1,115 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import PreviewHeader from '@/ui/preview/preview-header.vue';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
export default class ViewLargeAction {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
|
||||
this.cssClass = 'icon-items-expand';
|
||||
this.description = 'View Large';
|
||||
this.group = 'windowing';
|
||||
this.key = 'large.view';
|
||||
this.name = 'Large View';
|
||||
this.priority = 1;
|
||||
this.showInStatusBar = true;
|
||||
}
|
||||
|
||||
invoke(objectPath, view) {
|
||||
const parentElement = view.parentElement;
|
||||
let childElement = parentElement && parentElement.firstChild;
|
||||
if (!childElement) {
|
||||
const message = "ViewLargeAction: missing element";
|
||||
this.openmct.notifications.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
this._expand(objectPath, childElement, view);
|
||||
}
|
||||
|
||||
appliesTo(objectPath, view = {}) {
|
||||
const parentElement = view.parentElement;
|
||||
const element = parentElement && parentElement.firstChild;
|
||||
const viewLargeAction = element && !element.classList.contains('js-main-container')
|
||||
&& !this._isNavigatedObject(objectPath);
|
||||
|
||||
return viewLargeAction;
|
||||
}
|
||||
|
||||
_expand(objectPath, childElement, view) {
|
||||
const parentElement = childElement.parentElement;
|
||||
|
||||
this.overlay = this.openmct.overlays.overlay({
|
||||
element: this._getOverlayElement(objectPath, childElement, view),
|
||||
size: 'large',
|
||||
onDestroy() {
|
||||
parentElement.append(childElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_getOverlayElement(objectPath, childElement, view) {
|
||||
const fragment = new DocumentFragment();
|
||||
const header = this._getPreviewHeader(objectPath, view);
|
||||
fragment.append(header);
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.classList.add('l-preview-window__object-view');
|
||||
wrapper.append(childElement);
|
||||
fragment.append(wrapper);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
_getPreviewHeader(objectPath, view) {
|
||||
const domainObject = objectPath[0];
|
||||
const actionCollection = this.openmct.actions.getActionsCollection(objectPath, view);
|
||||
const preview = new Vue({
|
||||
components: {
|
||||
PreviewHeader
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject,
|
||||
actionCollection
|
||||
};
|
||||
},
|
||||
template: '<PreviewHeader :actionCollection="actionCollection" :domainObject="domainObject" :hideViewSwitcher="true" :showNotebookMenuSwitcher="true"></PreviewHeader>'
|
||||
});
|
||||
|
||||
return preview.$mount().$el;
|
||||
}
|
||||
|
||||
_isNavigatedObject(objectPath) {
|
||||
let targetObject = objectPath[0];
|
||||
let navigatedObject = this.openmct.router.path[0];
|
||||
|
||||
return this.openmct.objects.areIdsEqual(targetObject.identifier, navigatedObject.identifier);
|
||||
}
|
||||
}
|
@ -56,26 +56,19 @@
|
||||
'has-complex-content': complexContent
|
||||
}"
|
||||
>
|
||||
<div class="c-so-view__frame-controls__btns">
|
||||
<div v-if="statusBarItems.length > 0"
|
||||
class="c-so-view__frame-controls__btns"
|
||||
>
|
||||
<button
|
||||
v-for="(item, index) in statusBarItems"
|
||||
:key="index"
|
||||
class="c-icon-button"
|
||||
:class="item.cssClass"
|
||||
:title="item.name"
|
||||
@click="item.callBack"
|
||||
@click="item.onItemClicked"
|
||||
>
|
||||
<span class="c-icon-button__label">{{ item.name }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="c-icon-button icon-items-expand"
|
||||
title="View Large"
|
||||
@click="expand"
|
||||
>
|
||||
<span class="c-icon-button__label">View Large</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<button
|
||||
class="c-icon-button icon-3-dots c-so-view__frame-controls__more"
|
||||
@ -87,7 +80,7 @@
|
||||
|
||||
<object-view
|
||||
ref="objectView"
|
||||
class="c-so-view__object-view"
|
||||
class="c-so-view__object-view js-object-view"
|
||||
:show-edit-view="showEditView"
|
||||
:object-path="objectPath"
|
||||
:layout-font-size="layoutFontSize"
|
||||
@ -99,8 +92,6 @@
|
||||
|
||||
<script>
|
||||
import ObjectView from './ObjectView.vue';
|
||||
import PreviewHeader from '@/ui/preview/preview-header.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
const SIMPLE_CONTENT_TYPES = [
|
||||
'clock',
|
||||
@ -160,7 +151,8 @@ export default {
|
||||
mounted() {
|
||||
this.status = this.openmct.status.get(this.domainObject.identifier);
|
||||
this.removeStatusListener = this.openmct.status.observe(this.domainObject.identifier, this.setStatus);
|
||||
this.$refs.objectView.show(this.domainObject, undefined, false, this.objectPath);
|
||||
const provider = this.openmct.objectViews.get(this.domainObject, this.objectPath)[0];
|
||||
this.$refs.objectView.show(this.domainObject, provider.key, false, this.objectPath);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.removeStatusListener();
|
||||
@ -170,52 +162,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
expand() {
|
||||
let objectView = this.$refs.objectView;
|
||||
let parentElement = objectView.$el;
|
||||
let childElement = parentElement.children[0];
|
||||
|
||||
this.openmct.overlays.overlay({
|
||||
element: this.getOverlayElement(childElement),
|
||||
size: 'large',
|
||||
onDestroy() {
|
||||
parentElement.append(childElement);
|
||||
}
|
||||
});
|
||||
},
|
||||
getOverlayElement(childElement) {
|
||||
const fragment = new DocumentFragment();
|
||||
const header = this.getPreviewHeader();
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.classList.add('l-preview-window__object-view');
|
||||
wrapper.append(childElement);
|
||||
fragment.append(header);
|
||||
fragment.append(wrapper);
|
||||
|
||||
return fragment;
|
||||
},
|
||||
getPreviewHeader() {
|
||||
const domainObject = this.objectPath[0];
|
||||
const actionCollection = this.actionCollection;
|
||||
const preview = new Vue({
|
||||
components: {
|
||||
PreviewHeader
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
objectPath: this.objectPath
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject,
|
||||
actionCollection
|
||||
};
|
||||
},
|
||||
template: '<PreviewHeader :actionCollection="actionCollection" :domainObject="domainObject" :hideViewSwitcher="true" :showNotebookMenuSwitcher="true"></PreviewHeader>'
|
||||
});
|
||||
|
||||
return preview.$mount().$el;
|
||||
},
|
||||
getSelectionContext() {
|
||||
return this.$refs.objectView.getSelectionContext();
|
||||
},
|
||||
@ -233,12 +179,14 @@ export default {
|
||||
delete this.actionCollection;
|
||||
},
|
||||
updateActionItems(actionItems) {
|
||||
this.statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
const statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
this.statusBarItems = this.openmct.menus.actionsToMenuItems(statusBarItems, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.menuActionItems = this.actionCollection.getVisibleActions();
|
||||
},
|
||||
showMenuItems(event) {
|
||||
let sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
this.openmct.menus.showMenu(event.x, event.y, sortedActions);
|
||||
const sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
},
|
||||
setStatus(status) {
|
||||
this.status = status;
|
||||
|
@ -209,7 +209,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
this.getActionCollection();
|
||||
this.currentView.show(this.viewContainer, this.openmct.editor.isEditing());
|
||||
|
||||
if (immediatelySelect) {
|
||||
@ -218,13 +217,17 @@ export default {
|
||||
}
|
||||
|
||||
this.openmct.objectViews.on('clearData', this.clearData);
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.getActionCollection();
|
||||
});
|
||||
},
|
||||
getActionCollection() {
|
||||
if (this.actionCollection) {
|
||||
this.actionCollection.destroy();
|
||||
}
|
||||
|
||||
this.actionCollection = this.openmct.actions._get(this.currentObjectPath || this.objectPath, this.currentView);
|
||||
this.actionCollection = this.openmct.actions.getActionsCollection(this.currentObjectPath || this.objectPath, this.currentView);
|
||||
this.$emit('change-action-collection', this.actionCollection);
|
||||
},
|
||||
show(object, viewKey, immediatelySelect, currentObjectPath) {
|
||||
@ -318,7 +321,6 @@ export default {
|
||||
return viewKey;
|
||||
},
|
||||
getViewProvider() {
|
||||
|
||||
let provider = this.openmct.objectViews.getByProviderKey(this.getViewKey());
|
||||
|
||||
if (!provider) {
|
||||
|
@ -63,7 +63,7 @@ export default {
|
||||
cssClass: font.cssClass || '',
|
||||
name: font.name,
|
||||
description: font.name,
|
||||
callBack: () => this.setFont(font.value)
|
||||
onItemClicked: () => this.setFont(font.value)
|
||||
};
|
||||
});
|
||||
},
|
||||
@ -73,7 +73,7 @@ export default {
|
||||
cssClass: fontSize.cssClass || '',
|
||||
name: fontSize.name,
|
||||
description: fontSize.name,
|
||||
callBack: () => this.setFontSize(fontSize.value)
|
||||
onItemClicked: () => this.setFontSize(fontSize.value)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
</div>
|
||||
|
||||
<div class="l-browse-bar__end">
|
||||
<view-switcher
|
||||
<ViewSwitcher
|
||||
v-if="!isEditing"
|
||||
:current-view="currentView"
|
||||
:views="views"
|
||||
@ -49,7 +49,7 @@
|
||||
:key="index"
|
||||
class="c-button"
|
||||
:class="item.cssClass"
|
||||
@click="item.callBack"
|
||||
@click="item.onItemClicked"
|
||||
>
|
||||
</button>
|
||||
|
||||
@ -172,9 +172,7 @@ export default {
|
||||
key: p.key,
|
||||
cssClass: p.cssClass,
|
||||
name: p.name,
|
||||
callBack: () => {
|
||||
return this.setView({key: p.key});
|
||||
}
|
||||
onItemClicked: () => this.setView({key: p.key})
|
||||
};
|
||||
});
|
||||
},
|
||||
@ -339,12 +337,14 @@ export default {
|
||||
this.openmct.router.navigate(this.parentUrl);
|
||||
},
|
||||
updateActionItems(actionItems) {
|
||||
this.statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
const statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
this.statusBarItems = this.openmct.menus.actionsToMenuItems(statusBarItems, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.menuActionItems = this.actionCollection.getVisibleActions();
|
||||
},
|
||||
showMenuItems(event) {
|
||||
let sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
this.openmct.menus.showMenu(event.x, event.y, sortedActions);
|
||||
const sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
},
|
||||
unlistenToActionCollection() {
|
||||
this.actionCollection.off('update', this.updateActionItems);
|
||||
|
@ -28,7 +28,7 @@ export default {
|
||||
cssClass: menuItem.cssClass,
|
||||
name: menuItem.name,
|
||||
description: menuItem.description,
|
||||
callBack: () => this.create(key)
|
||||
onItemClicked: () => this.create(key)
|
||||
};
|
||||
|
||||
items.push(menuItemTemplate);
|
||||
|
@ -90,7 +90,7 @@
|
||||
/>
|
||||
<object-view
|
||||
ref="browseObject"
|
||||
class="l-shell__main-container"
|
||||
class="l-shell__main-container js-main-container"
|
||||
data-selectable
|
||||
:show-edit-view="true"
|
||||
@change-action-collection="setActionCollection"
|
||||
|
@ -36,7 +36,7 @@ export default {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
let actionsCollection = this.openmct.actions.get(this.objectPath);
|
||||
let actionsCollection = this.openmct.actions.getActionsCollection(this.objectPath);
|
||||
let actions = actionsCollection.getVisibleActions();
|
||||
let sortedActions = this.openmct.actions._groupAndSortActions(actions);
|
||||
|
||||
@ -44,7 +44,8 @@ export default {
|
||||
onDestroy: this.onContextMenuDestroyed
|
||||
};
|
||||
|
||||
this.openmct.menus.showMenu(event.clientX, event.clientY, sortedActions, menuOptions);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, actionsCollection.objectPath, actionsCollection.view);
|
||||
this.openmct.menus.showMenu(event.clientX, event.clientY, menuItems, menuOptions);
|
||||
this.contextClickActive = true;
|
||||
this.$emit('context-click-active', true);
|
||||
},
|
||||
|
@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
<template>
|
||||
<div class="l-preview-window">
|
||||
<div class="l-preview-window js-preview-window">
|
||||
<PreviewHeader
|
||||
:current-view="currentView"
|
||||
:action-collection="actionCollection"
|
||||
@ -116,7 +116,7 @@ export default {
|
||||
this.actionCollection.destroy();
|
||||
}
|
||||
|
||||
this.actionCollection = this.openmct.actions._get(this.objectPath, this.view);
|
||||
this.actionCollection = this.openmct.actions.getActionsCollection(this.objectPath, this.view);
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
|
@ -75,8 +75,13 @@ export default class PreviewAction {
|
||||
PreviewAction.isVisible = true;
|
||||
}
|
||||
|
||||
appliesTo(objectPath) {
|
||||
return !PreviewAction.isVisible && !this._isNavigatedObject(objectPath);
|
||||
appliesTo(objectPath, view = {}) {
|
||||
const parentElement = view.parentElement;
|
||||
const isObjectView = parentElement && parentElement.classList.contains('js-object-view');
|
||||
|
||||
return !PreviewAction.isVisible
|
||||
&& !this._isNavigatedObject(objectPath)
|
||||
&& !isObjectView;
|
||||
}
|
||||
|
||||
_isNavigatedObject(objectPath) {
|
||||
@ -85,6 +90,7 @@ export default class PreviewAction {
|
||||
|
||||
return this._openmct.objects.areIdsEqual(targetObject.identifier, navigatedObject.identifier);
|
||||
}
|
||||
|
||||
_preventPreview(objectPath) {
|
||||
const noPreviewTypes = ['folder'];
|
||||
|
||||
|
@ -36,10 +36,9 @@ export default class ViewHistoricalDataAction extends PreviewAction {
|
||||
appliesTo(objectPath, view = {}) {
|
||||
let viewContext = view.getViewContext && view.getViewContext();
|
||||
|
||||
if (objectPath.length && viewContext && viewContext.viewHistoricalData) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return objectPath.length
|
||||
&& viewContext
|
||||
&& viewContext.row
|
||||
&& viewContext.row.viewHistoricalData;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
:key="index"
|
||||
class="c-button"
|
||||
:class="item.cssClass"
|
||||
@click="item.callBack"
|
||||
@click="item.onItemClicked"
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
@ -42,7 +42,8 @@ import ViewSwitcher from '../../ui/layout/ViewSwitcher.vue';
|
||||
const HIDDEN_ACTIONS = [
|
||||
'remove',
|
||||
'move',
|
||||
'preview'
|
||||
'preview',
|
||||
'large.view'
|
||||
];
|
||||
|
||||
export default {
|
||||
@ -114,6 +115,19 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filterHiddenItems(menuItems) {
|
||||
const items = [];
|
||||
menuItems.forEach(menuItem => {
|
||||
const isGroup = Array.isArray(menuItem);
|
||||
if (isGroup) {
|
||||
items.push(this.filterHiddenItems(menuItem));
|
||||
} else if (!HIDDEN_ACTIONS.includes(menuItem.key)) {
|
||||
items.push(menuItem);
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
},
|
||||
setView(view) {
|
||||
this.$emit('setView', view);
|
||||
},
|
||||
@ -122,12 +136,16 @@ export default {
|
||||
delete this.actionCollection;
|
||||
},
|
||||
updateActionItems() {
|
||||
this.statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
const statusBarItems = this.actionCollection.getStatusBarActions();
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(statusBarItems, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.statusBarItems = this.filterHiddenItems(menuItems);
|
||||
this.menuActionItems = this.actionCollection.getVisibleActions();
|
||||
},
|
||||
showMenuItems(event) {
|
||||
let sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
this.openmct.menus.showMenu(event.x, event.y, sortedActions);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
const visibleMenuItems = this.filterHiddenItems(menuItems);
|
||||
this.openmct.menus.showMenu(event.x, event.y, visibleMenuItems);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -86,6 +86,18 @@ define(['EventEmitter'], function (EventEmitter) {
|
||||
console.warn("Provider already defined for key '%s'. Provider keys must be unique.", key);
|
||||
}
|
||||
|
||||
const wrappedView = provider.view.bind(provider);
|
||||
provider.view = (domainObject, objectPath) => {
|
||||
const viewObject = wrappedView(domainObject, objectPath);
|
||||
const wrappedShow = viewObject.show.bind(viewObject);
|
||||
viewObject.show = (element, isEditing) => {
|
||||
viewObject.parentElement = element.parentElement;
|
||||
wrappedShow(element, isEditing);
|
||||
};
|
||||
|
||||
return viewObject;
|
||||
};
|
||||
|
||||
this.providers[key] = provider;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user