mirror of
https://github.com/nasa/openmct.git
synced 2025-06-24 18:25:19 +00:00
Compare commits
5 Commits
omm-r5.3.1
...
edit-views
Author | SHA1 | Date | |
---|---|---|---|
e2fcaecffc | |||
e7569b6349 | |||
98beafca14 | |||
24d45b1456 | |||
12651069c0 |
@ -39,6 +39,7 @@ export default class Editor extends EventEmitter {
|
||||
* Initiate an editing session. This will start a transaction during
|
||||
* which any persist operations will be deferred until either save()
|
||||
* or finish() are called.
|
||||
* @private
|
||||
*/
|
||||
edit() {
|
||||
if (this.editing === true) {
|
||||
@ -59,6 +60,8 @@ export default class Editor extends EventEmitter {
|
||||
/**
|
||||
* Save any unsaved changes from this editing session. This will
|
||||
* end the current transaction.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
save() {
|
||||
return this.getTransactionService().commit().then((result)=>{
|
||||
@ -72,6 +75,8 @@ export default class Editor extends EventEmitter {
|
||||
|
||||
/**
|
||||
* End the currently active transaction and discard unsaved changes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cancel() {
|
||||
this.getTransactionService().cancel();
|
||||
|
@ -47,7 +47,8 @@
|
||||
:key="frame.id"
|
||||
:frame="frame"
|
||||
:index="i"
|
||||
:containerIndex="index">
|
||||
:containerIndex="index"
|
||||
:isEditing="isEditing">
|
||||
</frame-component>
|
||||
|
||||
<drop-hint
|
||||
@ -65,7 +66,8 @@
|
||||
:orientation="rowsLayout ? 'horizontal' : 'vertical'"
|
||||
@init-move="startFrameResizing"
|
||||
@move="frameResizing"
|
||||
@end-move="endFrameResizing">
|
||||
@end-move="endFrameResizing"
|
||||
:isEditing="isEditing">
|
||||
</resize-handle>
|
||||
</template>
|
||||
</div>
|
||||
@ -77,14 +79,12 @@ import FrameComponent from './frame.vue';
|
||||
import Frame from '../utils/frame';
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import DropHint from './dropHint.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
const MIN_FRAME_SIZE = 5;
|
||||
|
||||
export default {
|
||||
inject:['openmct'],
|
||||
props: ['container', 'index', 'rowsLayout'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['container', 'index', 'rowsLayout', 'isEditing'],
|
||||
components: {
|
||||
FrameComponent,
|
||||
ResizeHandle,
|
||||
|
@ -49,6 +49,7 @@
|
||||
:index="index"
|
||||
:container="container"
|
||||
:rowsLayout="rowsLayout"
|
||||
:isEditing="isEditing"
|
||||
@move-frame="moveFrame"
|
||||
@create-frame="createFrame"
|
||||
@persist="persist">
|
||||
@ -59,6 +60,7 @@
|
||||
:key="index"
|
||||
:index="index"
|
||||
:orientation="rowsLayout ? 'vertical' : 'horizontal'"
|
||||
:isEditing="isEditing"
|
||||
@init-move="startContainerResizing"
|
||||
@move="containerResizing"
|
||||
@end-move="endContainerResizing">
|
||||
@ -398,7 +400,6 @@ import Container from '../utils/container';
|
||||
import Frame from '../utils/frame';
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import DropHint from './dropHint.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
const MIN_CONTAINER_SIZE = 5;
|
||||
|
||||
@ -443,7 +444,6 @@ function sizeToFill(items) {
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'layoutObject'],
|
||||
mixins: [isEditingMixin],
|
||||
components: {
|
||||
ContainerComponent,
|
||||
ResizeHandle,
|
||||
@ -454,6 +454,9 @@ export default {
|
||||
domainObject: this.layoutObject
|
||||
}
|
||||
},
|
||||
props: {
|
||||
isEditing: Boolean
|
||||
},
|
||||
computed: {
|
||||
layoutDirectionStr() {
|
||||
if (this.rowsLayout) {
|
||||
|
@ -50,12 +50,10 @@
|
||||
<script>
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import ObjectFrame from '../../../ui/components/ObjectFrame.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
props: ['frame', 'index', 'containerIndex'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['frame', 'index', 'containerIndex', 'isEditing'],
|
||||
data() {
|
||||
return {
|
||||
domainObject: undefined,
|
||||
|
@ -29,11 +29,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
props: ['orientation', 'index'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['orientation', 'index', 'isEditing'],
|
||||
data() {
|
||||
return {
|
||||
initialPos: 0,
|
||||
|
@ -42,8 +42,13 @@ define([
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
show: function (element, isEditing) {
|
||||
component = new Vue({
|
||||
data() {
|
||||
return {
|
||||
isEditing: isEditing
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FlexibleLayoutComponent: FlexibleLayoutComponent.default
|
||||
},
|
||||
@ -52,9 +57,12 @@ define([
|
||||
layoutObject: domainObject
|
||||
},
|
||||
el: element,
|
||||
template: '<flexible-layout-component ref="flexibleLayout"></flexible-layout-component>'
|
||||
template: '<flexible-layout-component :isEditing="isEditing"></flexible-layout-component>'
|
||||
});
|
||||
},
|
||||
onEditModeChange(isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
getSelectionContext: function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
|
@ -1,19 +0,0 @@
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.editor.on('isEditing', this.toggleEditing);
|
||||
},
|
||||
destroyed() {
|
||||
this.openmct.editor.off('isEditing', this.toggleEditing);
|
||||
},
|
||||
methods: {
|
||||
toggleEditing(value) {
|
||||
this.isEditing = value;
|
||||
}
|
||||
}
|
||||
};
|
@ -5,7 +5,7 @@
|
||||
<span class="grippy-holder">
|
||||
<span class="t-grippy grippy local-control local-controls-hidden"></span>
|
||||
</span>
|
||||
<span class="view-control expanded"></span>
|
||||
<span class="js-disclosure-control c-disclosure-triangle is-enabled"></span>
|
||||
<span class="t-widget-thumb widget-thumb">
|
||||
<span class="widget-label">DEF</span>
|
||||
</span>
|
||||
|
@ -54,7 +54,7 @@ define([
|
||||
this.title = $('.rule-title', this.domElement);
|
||||
this.description = $('.rule-description', this.domElement);
|
||||
this.trigger = $('.t-trigger', this.domElement);
|
||||
this.toggleConfigButton = $('.view-control', this.domElement);
|
||||
this.toggleConfigButton = $('.js-disclosure-control', this.domElement);
|
||||
this.configArea = $('.widget-rule-content', this.domElement);
|
||||
this.grippy = $('.t-grippy', this.domElement);
|
||||
this.conditionArea = $('.t-widget-rule-config', this.domElement);
|
||||
@ -168,7 +168,7 @@ define([
|
||||
*/
|
||||
function toggleConfig() {
|
||||
self.configArea.toggleClass('expanded');
|
||||
self.toggleConfigButton.toggleClass('expanded');
|
||||
self.toggleConfigButton.toggleClass('c-disclosure-triangle--expanded');
|
||||
self.config.expanded = !self.config.expanded;
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,7 @@ define([
|
||||
this.toggleRulesControl = $('.t-view-control-rules', this.domElement);
|
||||
this.toggleTestDataControl = $('.t-view-control-test-data', this.domElement);
|
||||
this.widgetButton = this.domElement.children('#widget');
|
||||
this.editing = false;
|
||||
this.container = '';
|
||||
this.editListenerUnsubscribe = $.noop;
|
||||
|
||||
this.outerWrapper = $('.widget-edit-holder', this.domElement);
|
||||
this.ruleArea = $('#ruleArea', this.domElement);
|
||||
@ -74,7 +72,6 @@ define([
|
||||
this.show = this.show.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.addRule = this.addRule.bind(this);
|
||||
this.onEdit = this.onEdit.bind(this);
|
||||
|
||||
this.addHyperlink(domainObject.url, domainObject.openNewTab);
|
||||
this.watchForChanges(openmct, domainObject);
|
||||
@ -103,19 +100,6 @@ define([
|
||||
self.toggleRulesControl.toggleClass('expanded');
|
||||
}
|
||||
this.listenTo(this.toggleRulesControl, 'click', toggleRules);
|
||||
|
||||
openmct.$injector.get('objectService')
|
||||
.getObjects([id])
|
||||
.then(function (objs) {
|
||||
oldDomainObject = objs[id];
|
||||
statusCapability = oldDomainObject.getCapability('status');
|
||||
self.editListenerUnsubscribe = statusCapability.listen(self.onEdit);
|
||||
if (statusCapability.get('editing')) {
|
||||
self.onEdit(['editing']);
|
||||
} else {
|
||||
self.onEdit([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +156,10 @@ define([
|
||||
});
|
||||
this.refreshRules();
|
||||
this.updateWidget();
|
||||
this.updateView();
|
||||
|
||||
this.ruleArea.show();
|
||||
this.testDataArea.show();
|
||||
this.addRuleButton.show();
|
||||
|
||||
this.listenTo(this.addRuleButton, 'click', this.addRule);
|
||||
this.conditionManager.on('receiveTelemetry', this.executeRules, this);
|
||||
@ -184,7 +171,6 @@ define([
|
||||
* and clean up event handlers
|
||||
*/
|
||||
SummaryWidget.prototype.destroy = function (container) {
|
||||
this.editListenerUnsubscribe();
|
||||
this.conditionManager.destroy();
|
||||
this.testDataManager.destroy();
|
||||
this.widgetDnD.destroy();
|
||||
@ -196,37 +182,6 @@ define([
|
||||
this.stopListening();
|
||||
};
|
||||
|
||||
/**
|
||||
* A callback function for the Open MCT status capability listener. If the
|
||||
* view representing the domain object is in edit mode, update the internal
|
||||
* state and widget view accordingly.
|
||||
* @param {string[]} status an array containing the domain object's current status
|
||||
*/
|
||||
SummaryWidget.prototype.onEdit = function (status) {
|
||||
if (status && status.includes('editing')) {
|
||||
this.editing = true;
|
||||
} else {
|
||||
this.editing = false;
|
||||
}
|
||||
this.updateView();
|
||||
};
|
||||
|
||||
/**
|
||||
* If this view is currently in edit mode, show all rule configuration interfaces.
|
||||
* Otherwise, hide them.
|
||||
*/
|
||||
SummaryWidget.prototype.updateView = function () {
|
||||
if (this.editing) {
|
||||
this.ruleArea.show();
|
||||
this.testDataArea.show();
|
||||
this.addRuleButton.show();
|
||||
} else {
|
||||
this.ruleArea.hide();
|
||||
this.testDataArea.hide();
|
||||
this.addRuleButton.hide();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the view from the current rule configuration and order
|
||||
*/
|
||||
|
@ -24,16 +24,10 @@ define([
|
||||
return domainObject.type === 'summary-widget';
|
||||
},
|
||||
view: function (domainObject) {
|
||||
var statusService = openmct.$injector.get('statusService');
|
||||
var objectId = objectUtils.makeKeyString(domainObject.identifier);
|
||||
var statuses = statusService.listStatuses(objectId);
|
||||
var isEditing = statuses.indexOf('editing') !== -1;
|
||||
|
||||
if (isEditing) {
|
||||
return new SummaryWidgetEditView(domainObject, openmct);
|
||||
} else {
|
||||
return new SummaryWidgetView(domainObject, openmct);
|
||||
}
|
||||
return new SummaryWidgetView(domainObject, openmct);
|
||||
},
|
||||
edit: function (domainObject) {
|
||||
return new SummaryWidgetEditView(domainObject, openmct);
|
||||
},
|
||||
priority: function (domainObject) {
|
||||
if (domainObject.type === 'summary-widget') {
|
||||
|
@ -47,8 +47,13 @@ define([
|
||||
let table = new TelemetryTable(domainObject, openmct);
|
||||
let component;
|
||||
return {
|
||||
show: function (element) {
|
||||
show: function (element, isEditing) {
|
||||
component = new Vue({
|
||||
data() {
|
||||
return {
|
||||
isEditing: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TableComponent: TableComponent.default,
|
||||
},
|
||||
@ -58,9 +63,12 @@ define([
|
||||
table
|
||||
},
|
||||
el: element,
|
||||
template: '<table-component></table-component>'
|
||||
template: '<table-component :isEditing="isEditing"></table-component>'
|
||||
});
|
||||
},
|
||||
onEditModeChange(isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
@ -73,18 +73,14 @@ const MOVE_COLUMN_DT_TYPE = 'movecolumnfromindex';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
}
|
||||
},
|
||||
props: {
|
||||
headerKey: String,
|
||||
headerIndex: Number,
|
||||
isHeaderTitle: Boolean,
|
||||
sortOptions: Object,
|
||||
columnWidth: Number,
|
||||
hotzone: Boolean
|
||||
hotzone: Boolean,
|
||||
isEditing: Boolean
|
||||
},
|
||||
computed: {
|
||||
isSortable() {
|
||||
@ -167,16 +163,7 @@ export default {
|
||||
},
|
||||
sort() {
|
||||
this.$emit("sort");
|
||||
},
|
||||
toggleEditMode(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.openmct.editor.on('isEditing', this.toggleEditMode);
|
||||
},
|
||||
destroyed() {
|
||||
this.openmct.editor.off('isEditing', this.toggleEditMode);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -48,6 +48,7 @@
|
||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||
:columnWidth="columnWidths[key]"
|
||||
:sortOptions="sortOptions"
|
||||
:isEditing="isEditing"
|
||||
>{{title}}</table-column-header>
|
||||
</tr>
|
||||
<tr class="c-telemetry-table__headers__filter">
|
||||
@ -61,7 +62,9 @@
|
||||
@dropTargetActive="dropTargetActive"
|
||||
@reorderColumn="reorderColumn"
|
||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||
:columnWidth="columnWidths[key]">
|
||||
:columnWidth="columnWidths[key]"
|
||||
:isEditing="isEditing"
|
||||
>
|
||||
<search class="c-table__search"
|
||||
v-model="filters[key]"
|
||||
v-on:input="filterChanged(key)"
|
||||
@ -260,6 +263,12 @@ export default {
|
||||
search
|
||||
},
|
||||
inject: ['table', 'openmct', 'csvExporter'],
|
||||
props: {
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
let configuration = this.table.configuration.getConfiguration();
|
||||
|
||||
|
@ -123,7 +123,7 @@
|
||||
}
|
||||
|
||||
/********************************************************** EDITING A WIDGET */
|
||||
.s-status-editing > mct-view > .w-summary-widget {
|
||||
.is-editing .w-summary-widget {
|
||||
// Classes for editor layout while editing a widget
|
||||
// This selector is ugly and brittle, but needed to prevent interface from showing when widget is in a layout
|
||||
// being edited.
|
||||
|
@ -12,6 +12,7 @@ export default {
|
||||
},
|
||||
destroyed() {
|
||||
this.clear();
|
||||
this.openmct.editor.off('isEditing', this.setEditMode);
|
||||
},
|
||||
watch: {
|
||||
view(newView, oldView) {
|
||||
@ -37,10 +38,22 @@ export default {
|
||||
if (this.currentView) {
|
||||
this.currentView.destroy();
|
||||
this.$el.innerHTML = '';
|
||||
|
||||
if (this.releaseEditModeHandler) {
|
||||
this.releaseEditModeHandler();
|
||||
delete this.releaseEditModeHandler;
|
||||
}
|
||||
}
|
||||
delete this.viewContainer;
|
||||
delete this.currentView;
|
||||
},
|
||||
invokeEditModeHandler(editMode) {
|
||||
this.currentView.onEditModeChange(editMode);
|
||||
},
|
||||
toggleEditView(editMode) {
|
||||
this.clear();
|
||||
this.updateView(true);
|
||||
},
|
||||
updateView(immediatelySelect) {
|
||||
this.clear();
|
||||
if (!this.currentObject) {
|
||||
@ -50,14 +63,32 @@ export default {
|
||||
this.viewContainer.classList.add('c-object-view','u-contents');
|
||||
this.$el.append(this.viewContainer);
|
||||
let provider = this.openmct.objectViews.getByProviderKey(this.viewKey);
|
||||
|
||||
if (!provider) {
|
||||
provider = this.openmct.objectViews.get(this.currentObject)[0];
|
||||
if (!provider) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.currentView = provider.view(this.currentObject);
|
||||
this.currentView.show(this.viewContainer);
|
||||
|
||||
|
||||
if (provider.edit) {
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
this.currentView = provider.edit(this.currentObject);
|
||||
} else {
|
||||
this.currentView = provider.view(this.currentObject, false);
|
||||
}
|
||||
this.openmct.editor.on('isEditing', this.toggleEditView);
|
||||
this.releaseEditModeHandler = () => this.openmct.editor.off('isEditing', this.toggleEditView);
|
||||
} else {
|
||||
this.currentView = provider.view(this.currentObject, this.openmct.editor.isEditing());
|
||||
|
||||
if (this.currentView.onEditModeChange) {
|
||||
this.openmct.editor.on('isEditing', this.invokeEditModeHandler);
|
||||
this.releaseEditModeHandler = () => this.openmct.editor.off('isEditing', this.invokeEditModeHandler);
|
||||
}
|
||||
}
|
||||
this.currentView.show(this.viewContainer, this.openmct.editor.isEditing());
|
||||
|
||||
if (immediatelySelect) {
|
||||
this.removeSelectable = openmct.selection.selectable(
|
||||
|
@ -84,7 +84,7 @@
|
||||
mounted() {
|
||||
let viewProvider = this.openmct.objectViews.get(this.domainObject)[0];
|
||||
this.view = viewProvider.view(this.domainObject);
|
||||
this.view.show(this.$refs.objectView);
|
||||
this.view.show(this.$refs.objectView, false);
|
||||
},
|
||||
destroy() {
|
||||
this.view.destroy();
|
||||
|
@ -120,6 +120,19 @@ define([], function () {
|
||||
* @memberof module:openmct.View#
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates whether or not the application is in edit mode. This supports
|
||||
* views that have distinct visual and behavioral elements when the
|
||||
* navigated object is being edited.
|
||||
*
|
||||
* For cases where a completely separate view is desired for editing purposes,
|
||||
* see {@link openmct.ViewProvider#edit}
|
||||
*
|
||||
* @param {boolean} isEditing
|
||||
* @method show
|
||||
* @memberof module:openmct.View#
|
||||
*/
|
||||
|
||||
/**
|
||||
* Release any resources associated with this view.
|
||||
*
|
||||
@ -172,7 +185,15 @@ define([], function () {
|
||||
|
||||
/**
|
||||
* An optional function that defines whether or not this view can be used to edit a given object.
|
||||
* If not provided, will default to `false` and the view will not support editing.
|
||||
* If not provided, will default to `false` and the view will not support editing. To support editing,
|
||||
* return true from this function and then -
|
||||
* * Return a {@link openmct.View} from the `view` function, using the `onEditModeChange` callback to
|
||||
* add and remove editing elements from the view
|
||||
* OR
|
||||
* * Return a {@link openmct.View} from the `view` function defining a read-only view.
|
||||
* AND
|
||||
* * Define an {@link openmct.ViewProvider#Edit} function on the view provider that returns an
|
||||
* editing-specific view.
|
||||
*
|
||||
* @method canEdit
|
||||
* @memberof module:openmct.ViewProvider#
|
||||
@ -211,6 +232,19 @@ define([], function () {
|
||||
* @returns {module:openmct.View} a view of this domain object
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide an edit-mode specific view of this object.
|
||||
*
|
||||
* If optionally specified, this function will be called when the application
|
||||
* enters edit mode. This will cause the active non-edit mode view and its
|
||||
* dom element to be destroyed.
|
||||
*
|
||||
* @method edit
|
||||
* @memberof module:openmct.ViewProvider#
|
||||
* @param {*} object the object to be edit
|
||||
* @returns {module:openmct.View} an editable view of this domain object
|
||||
*/
|
||||
|
||||
return ViewRegistry;
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user