Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Henry
ca88996d86 Persist table sort options 2019-03-22 17:44:29 -07:00
107 changed files with 2028 additions and 3154 deletions

View File

@@ -54,9 +54,6 @@
openmct.install(openmct.plugins.AutoflowView({
type: "telemetry.panel"
}));
openmct.install(openmct.plugins.DisplayLayout({
showAsView: ['summary-widget', 'example.imagery']
}));
openmct.install(openmct.plugins.Conductor({
menuOptions: [
{

View File

@@ -31,6 +31,7 @@ define([
"./src/navigation/NavigateAction",
"./src/navigation/OrphanNavigationHandler",
"./src/windowing/NewTabAction",
"./src/windowing/WindowTitler",
"./res/templates/browse.html",
"./res/templates/browse-object.html",
"./res/templates/browse/object-header.html",
@@ -51,6 +52,7 @@ define([
NavigateAction,
OrphanNavigationHandler,
NewTabAction,
WindowTitler,
browseTemplate,
browseObjectTemplate,
objectHeaderTemplate,
@@ -224,6 +226,14 @@ define([
}
],
"runs": [
{
"implementation": WindowTitler,
"depends": [
"navigationService",
"$rootScope",
"$document"
]
},
{
"implementation": OrphanNavigationHandler,
"depends": [

View File

@@ -0,0 +1,51 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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.
*****************************************************************************/
define(
[],
function () {
/**
* Updates the title of the current window to reflect the name
* of the currently navigated-to domain object.
* @memberof platform/commonUI/browse
* @constructor
*/
function WindowTitler(navigationService, $rootScope, $document) {
// Look up name of the navigated domain object...
function getNavigatedObjectName() {
var navigatedObject = navigationService.getNavigation();
return navigatedObject && navigatedObject.getModel().name;
}
// Set the window title...
function setTitle(name) {
$document[0].title = name;
}
// Watch the former, and invoke the latter
$rootScope.$watch(getNavigatedObjectName, setTitle);
}
return WindowTitler;
}
);

View File

@@ -0,0 +1,78 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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.
*****************************************************************************/
/**
* WindowTitlerSpec. Created by vwoeltje on 11/6/14.
*/
define(
["../../src/windowing/WindowTitler"],
function (WindowTitler) {
describe("The window titler", function () {
var mockNavigationService,
mockRootScope,
mockDocument,
mockDomainObject,
titler; // eslint-disable-line
beforeEach(function () {
mockNavigationService = jasmine.createSpyObj(
'navigationService',
['getNavigation']
);
mockRootScope = jasmine.createSpyObj(
'$rootScope',
['$watch']
);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getModel']
);
mockDocument = [{}];
mockDomainObject.getModel.and.returnValue({ name: 'Test name' });
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
titler = new WindowTitler(
mockNavigationService,
mockRootScope,
mockDocument
);
});
it("listens for changes to the name of the navigated object", function () {
expect(mockRootScope.$watch).toHaveBeenCalledWith(
jasmine.any(Function),
jasmine.any(Function)
);
expect(mockRootScope.$watch.calls.mostRecent().args[0]())
.toEqual('Test name');
});
it("sets the title to the name of the navigated object", function () {
mockRootScope.$watch.calls.mostRecent().args[1]("Some name");
expect(mockDocument[0].title).toEqual("Some name");
});
});
}
);

View File

@@ -65,8 +65,7 @@ define([
"depends": [
"$document",
"$compile",
"$rootScope",
"$timeout"
"$rootScope"
]
}
],

View File

@@ -44,9 +44,8 @@ define(
* @memberof platform/commonUI/dialog
* @constructor
*/
function OverlayService($document, $compile, $rootScope, $timeout) {
function OverlayService($document, $compile, $rootScope) {
this.$compile = $compile;
this.$timeout = $timeout;
// Don't include $document and $rootScope directly;
// avoids https://docs.angularjs.org/error/ng/cpws
@@ -94,14 +93,12 @@ define(
scope.key = key;
scope.typeClass = typeClass || 't-dialog';
this.$timeout(() => {
// Create the overlay element and add it to the document's body
element = this.$compile(TEMPLATE)(scope);
// Append so that most recent dialog is last in DOM. This means the most recent dialog will be on top when
// multiple overlays with the same z-index are active.
this.findBody().append(element);
});
return {
dismiss: dismiss

View File

@@ -35,20 +35,16 @@ define(
mockTemplate,
mockElement,
mockScope,
mockTimeout,
overlayService;
beforeEach(function () {
mockDocument = jasmine.createSpyObj("$document", ["find"]);
mockCompile = jasmine.createSpy("$compile");
mockRootScope = jasmine.createSpyObj("$rootScope", ["$new"]);
mockBody = jasmine.createSpyObj("body", ["append"]);
mockBody = jasmine.createSpyObj("body", ["prepend"]);
mockTemplate = jasmine.createSpy("template");
mockElement = jasmine.createSpyObj("element", ["remove"]);
mockScope = jasmine.createSpyObj("scope", ["$destroy"]);
mockTimeout = function (callback) {
callback();
}
mockDocument.find.and.returnValue(mockBody);
mockCompile.and.returnValue(mockTemplate);
@@ -58,8 +54,7 @@ define(
overlayService = new OverlayService(
mockDocument,
mockCompile,
mockRootScope,
mockTimeout
mockRootScope
);
});
@@ -72,7 +67,7 @@ define(
it("adds the templated element to the body", function () {
overlayService.createOverlay("test", {});
expect(mockBody.append).toHaveBeenCalledWith(mockElement);
expect(mockBody.prepend).toHaveBeenCalledWith(mockElement);
});
it("places the provided model/key in its template's scope", function () {

View File

@@ -49,7 +49,7 @@ define(
name: "Properties",
rows: this.properties.map(function (property, index) {
// Property definition is same as form row definition
var row = JSON.parse(JSON.stringify(property.getDefinition()));
var row = Object.create(property.getDefinition());
row.key = index;
return row;
}).filter(function (row) {

View File

@@ -162,6 +162,9 @@ function (
function saveAfterClone(clonedObject) {
return this.openmct.editor.save().then(() => {
// Force mutation for search indexing
clonedObject.useCapability('mutation', (model) => {
return model;
});
return clonedObject;
})
}
@@ -170,14 +173,6 @@ function (
return fetchObject(clonedObject.getId())
}
function indexForSearch(savedObject) {
savedObject.useCapability('mutation', (model) => {
return model;
});
return savedObject;
}
function onSuccess(object) {
self.notificationService.info("Save Succeeded");
return object;
@@ -199,7 +194,6 @@ function (
.then(undirtyOriginals)
.then(saveAfterClone)
.then(finishEditing)
.then(indexForSearch)
.then(hideBlockingDialog)
.then(onSuccess)
.catch(onFailure);

View File

@@ -71,12 +71,6 @@ define(
openmct.editor.cancel();
}
function isFirstViewEditable(domainObject) {
let firstView = openmct.objectViews.get(domainObject)[0];
return firstView && firstView.canEdit && firstView.canEdit(domainObject);
}
function navigateAndEdit(object) {
let objectPath = object.getCapability('context').getPath(),
url = '#/browse/' + objectPath
@@ -88,10 +82,8 @@ define(
window.location.href = url;
if (isFirstViewEditable(object.useCapability('adapter'))) {
openmct.editor.edit();
}
}
newModel.type = this.type.getKey();
newModel.location = this.parent.getId();

View File

@@ -66,7 +66,7 @@ define(
name: "Properties",
rows: this.properties.map(function (property, index) {
// Property definition is same as form row definition
var row = JSON.parse(JSON.stringify(property.getDefinition()));
var row = Object.create(property.getDefinition());
// Use index as the key into the formValue;
// this correlates to the indexing provided by

View File

@@ -54,7 +54,6 @@ define(
if (isDestroyed) {
return;
}
var removeSelectable = openmct.selection.selectable(
element[0],
scope.$eval(attrs.mctSelectable),

View File

@@ -37,17 +37,75 @@ define(
}
/**
* Discard failures
* Handle persistence failures by providing the user with a
* dialog summarizing these failures, and giving the option
* to overwrite/cancel as appropriate.
* @param {Array} failures persistence failures, as prepared
* by PersistenceQueueHandler
* @memberof platform/persistence/queue.PersistenceFailureHandler#
*/
PersistenceFailureHandler.prototype.handle = function handleFailures(failures) {
// Prepare dialog for display
var dialogModel = new PersistenceFailureDialog(failures),
revisionErrors = dialogModel.model.revised,
$q = this.$q;
// Refresh revision information for the domain object associated
// with this persistence failure
function refresh(failure) {
// Refresh the domain object to the latest from persistence
return failure.persistence.refresh();
}
// Issue a new persist call for the domain object associated with
// this failure.
function persist(failure) {
// Note that we reissue the persist request here, but don't
// return it, to avoid a circular wait. We trust that the
// PersistenceQueue will behave correctly on the next round
// of flushing.
failure.requeue();
}
// Retry persistence (overwrite) for this set of failed attempts
function retry(failuresToRetry) {
var models = {};
// Cache a copy of the model
function cacheModel(failure) {
// Clone...
models[failure.id] = JSON.parse(JSON.stringify(
failure.domainObject.getModel()
));
}
// Mutate a domain object to restore its model
function remutate(failure) {
var model = models[failure.id];
return failure.domainObject.useCapability(
"mutation",
function () {
return model;
},
model.modified
);
}
// Cache the object models we might want to save
failuresToRetry.forEach(cacheModel);
// Strategy here:
// * Cache all of the models we might want to save (above)
// * Refresh all domain objects (so they are latest versions)
// * Re-insert the cached domain object models
// * Invoke persistence again
return $q.all(failuresToRetry.map(refresh)).then(function () {
return $q.all(failuresToRetry.map(remutate));
}).then(function () {
return $q.all(failuresToRetry.map(persist));
});
}
// Discard changes for a failed refresh
function discard(failure) {
var persistence =
@@ -60,7 +118,19 @@ define(
return $q.all(failuresToDiscard.map(discard));
}
// Handle user input (did they choose to overwrite?)
function handleChoice(key) {
// If so, try again
if (key === PersistenceFailureConstants.OVERWRITE_KEY) {
return retry(revisionErrors);
} else {
return discardAll(revisionErrors);
}
}
// Prompt for user input, the overwrite if they said so.
return this.dialogService.getUserChoice(dialogModel)
.then(handleChoice, handleChoice);
};
return PersistenceFailureHandler;

View File

@@ -74,14 +74,43 @@ define(
handler = new PersistenceFailureHandler(mockQ, mockDialogService);
});
it("discards on handle", function () {
it("shows a dialog to handle failures", function () {
handler.handle(mockFailures);
expect(mockDialogService.getUserChoice).toHaveBeenCalled();
});
it("overwrites on request", function () {
mockQ.all.and.returnValue(asPromise([]));
handler.handle(mockFailures);
// User chooses overwrite
mockPromise.then.calls.mostRecent().args[0](Constants.OVERWRITE_KEY);
// Should refresh, remutate, and requeue all objects
mockFailures.forEach(function (mockFailure, i) {
expect(mockFailure.persistence.refresh).toHaveBeenCalled();
expect(mockFailure.requeue).toHaveBeenCalled();
expect(mockFailure.domainObject.useCapability).toHaveBeenCalledWith(
'mutation',
jasmine.any(Function),
i // timestamp
);
expect(mockFailure.domainObject.useCapability.calls.mostRecent().args[1]())
.toEqual({ id: mockFailure.id, modified: i });
});
});
it("discards on request", function () {
mockQ.all.and.returnValue(asPromise([]));
handler.handle(mockFailures);
// User chooses overwrite
mockPromise.then.calls.mostRecent().args[0](false);
// Should refresh, but not remutate, and requeue all objects
mockFailures.forEach(function (mockFailure) {
expect(mockFailure.persistence.refresh).toHaveBeenCalled();
expect(mockFailure.requeue).not.toHaveBeenCalled();
expect(mockFailure.domainObject.useCapability).not.toHaveBeenCalled();
});
});
});
}
);

View File

@@ -248,6 +248,7 @@ define([
this.legacyRegistry = defaultRegistry;
this.install(this.plugins.Plot());
this.install(this.plugins.TelemetryTable());
this.install(this.plugins.DisplayLayout());
this.install(PreviewPlugin.default());
this.install(LegacyIndicatorsPlugin());
this.install(LicensesPlugin.default());
@@ -256,6 +257,7 @@ define([
if (typeof BUILD_CONSTANTS !== 'undefined') {
this.install(buildInfoPlugin(BUILD_CONSTANTS));
}
}
MCT.prototype = Object.create(EventEmitter.prototype);
@@ -326,12 +328,6 @@ define([
* MCT; if undefined, MCT will be run in the body of the document
*/
MCT.prototype.start = function (domElement) {
if (!this.plugins.DisplayLayout._installed) {
this.install(this.plugins.DisplayLayout({
showAsView: ['summary-widget']
}));
}
if (!domElement) {
domElement = document.body;
}
@@ -356,7 +352,7 @@ define([
legacyRegistry.enable('adapter');
this.router.route(/^\/$/, () => {
this.router.setPath('/browse/');
this.router.setPath('/browse/mine');
});
/**

View File

@@ -33,13 +33,9 @@ export default class LegacyContextMenuAction {
}
invoke(objectPath) {
this.openmct.objects.getRoot().then((root) => {
let pathWithRoot = objectPath.slice();
pathWithRoot.push(root);
let context = {
category: 'contextual',
domainObject: this.openmct.legacyObject(pathWithRoot)
domainObject: this.openmct.legacyObject(objectPath)
}
let legacyAction = new this.LegacyAction(context);
@@ -51,7 +47,6 @@ export default class LegacyContextMenuAction {
}.bind(legacyAction);
}
legacyAction.perform();
});
}
appliesTo(objectPath) {

View File

@@ -137,7 +137,8 @@ define([
function callbackWrapper(series) {
callback(createDatum(domainObject, metadata, series, series.getPointCount() - 1));
}
return capability.subscribe(callbackWrapper, request) || function () {};
return capability.subscribe(callbackWrapper, request);
};
LegacyTelemetryProvider.prototype.supportsLimits = function (domainObject) {

View File

@@ -57,10 +57,8 @@ define([
}.bind(this);
handleLegacyMutation = function (legacyObject) {
var newStyleObject = utils.toNewFormat(legacyObject.getModel(), legacyObject.getId()),
keystring = utils.makeKeyString(newStyleObject.identifier);
this.eventEmitter.emit(keystring + ":*", newStyleObject);
var newStyleObject = utils.toNewFormat(legacyObject.getModel(), legacyObject.getId());
this.eventEmitter.emit(newStyleObject.identifier.key + ":*", newStyleObject);
this.eventEmitter.emit('mutation', newStyleObject);
}.bind(this);

View File

@@ -48,22 +48,12 @@ define([
let scope = $rootScope.$new();
let legacyObject = convertToLegacyObject(domainObject);
let isDestroyed = false;
let unlistenToStatus;
scope.domainObject = legacyObject;
scope.model = legacyObject.getModel();
return {
show: function (container) {
let statusCapability = legacyObject.getCapability('status');
unlistenToStatus = statusCapability.listen((newStatus) => {
container.classList.remove('s-status-timeconductor-unsynced');
if (newStatus.includes('timeconductor-unsynced')) {
container.classList.add('s-status-timeconductor-unsynced');
}
});
// TODO: implement "gestures" support ?
let uses = legacyView.uses || [];
let promises = [];
@@ -104,7 +94,6 @@ define([
},
destroy: function () {
scope.$destroy();
unlistenToStatus();
}
}
},

View File

@@ -25,20 +25,14 @@ define([
cssClass: representation.cssClass,
description: representation.description,
canView: function (selection) {
if (selection.length === 0 || selection[0].length === 0) {
if (!selection[0] || !selection[0].context.item) {
return false;
}
let selectionContext = selection[0][0].context;
if (!selectionContext.item) {
return false;
}
return selectionContext.item.type === typeDefinition.key;
let domainObject = selection[0].context.item;
return domainObject.type === typeDefinition.key;
},
view: function (selection) {
let domainObject = selection[0][0].context.item;
let domainObject = selection[0].context.item;
let $rootScope = openmct.$injector.get('$rootScope');
let templateLinker = openmct.$injector.get('templateLinker');
let scope = $rootScope.$new();

View File

@@ -28,6 +28,11 @@ export default class Editor extends EventEmitter {
super();
this.editing = false;
this.openmct = openmct;
document.addEventListener('drop', (event) => {
if (!this.isEditing()) {
this.edit();
}
}, {capture: true});
}
/**
@@ -74,11 +79,9 @@ export default class Editor extends EventEmitter {
* @private
*/
cancel() {
let cancelPromise = this.getTransactionService().cancel();
this.getTransactionService().cancel();
this.editing = false;
this.emit('isEditing', false);
return cancelPromise;
}
/**

View File

@@ -25,6 +25,7 @@ define([
], function (
_
) {
/**
* A CompositionCollection represents the list of domain objects contained
* by another domain object. It provides methods for loading this
@@ -62,6 +63,7 @@ define([
this.onProviderRemove = this.onProviderRemove.bind(this);
}
/**
* Listen for changes to this composition. Supports 'add', 'remove', and
* 'load' events.
@@ -74,11 +76,7 @@ define([
if (!this.listeners[event]) {
throw new Error('Event not supported by composition: ' + event);
}
if (!this.mutationListener) {
this.mutationListener = this.publicAPI.objects.observe(this.domainObject, '*', (newDomainObject) => {
this.domainObject = newDomainObject;
})
}
if (this.provider.on && this.provider.off) {
if (event === 'add') {
this.provider.on(
@@ -134,10 +132,6 @@ define([
this.listeners[event].splice(index, 1);
if (this.listeners[event].length === 0) {
if (this.mutationListener) {
this.mutationListener();
delete this.mutationListener;
}
// Remove provider listener if this is the last callback to
// be removed.
if (this.provider.off && this.provider.on) {

View File

@@ -21,10 +21,8 @@
*****************************************************************************/
define([
'./object-utils.js',
'lodash'
], function (
utils,
_
) {
var ANY_OBJECT_EVENT = "mutation";
@@ -43,9 +41,7 @@ define([
}
function qualifiedEventName(object, eventName) {
var keystring = utils.makeKeyString(object.identifier);
return [keystring, eventName].join(':');
return [object.identifier.key, eventName].join(':');
}
MutableObject.prototype.stopListening = function () {

View File

@@ -36,7 +36,7 @@
.c-message {
display: flex;
align-items: center;
align-items: flex-start;
> * + * {
margin-left: $interiorMarginLg;
@@ -66,17 +66,6 @@
font-size: 1.2em; // TEMP
}
&--simple {
// Icon and text elements only
&:before {
font-size: 30px !important;
}
[class*='__text'] {
font-size: 1.25em;
}
}
/************************** LEGACY */
&.message-severity-info:before {
@include legacyMessage();

View File

@@ -280,11 +280,7 @@ define([
if (!provider) {
return Promise.reject('No provider found');
}
return provider.request.apply(provider, arguments).catch((rejected) => {
this.openmct.notifications.error('Error requesting telemetry data, see console for details');
console.error(rejected);
return Promise.reject(rejected);
});
return provider.request.apply(provider, arguments);
};
/**

View File

@@ -28,17 +28,11 @@ define([], function () {
key: "layout",
description: "A toolbar for objects inside a display layout.",
forSelection: function (selection) {
if (!selection || selection.length === 0) {
return false;
}
let selectionPath = selection[0];
let selectedObject = selectionPath[0];
let selectedParent = selectionPath[1];
// Apply the layout toolbar if the selected object is inside a layout, or the main layout is selected.
return (selectedParent && selectedParent.context.item && selectedParent.context.item.type === 'layout') ||
(selectedObject.context.item && selectedObject.context.item.type === 'layout');
// Apply the layout toolbar if the selected object
// is inside a layout, or the main layout is selected.
return (selection &&
((selection[1] && selection[1].context.item && selection[1].context.item.type === 'layout') ||
(selection[0].context.item && selection[0].context.item.type === 'layout')));
},
toolbar: function (selection) {
const DIALOG_FORM = {
@@ -79,36 +73,27 @@ define([], function () {
return openmct.$injector.get('dialogService').getUserInput(form, {});
}
function getPath(selectionPath) {
return `configuration.items[${selectionPath[0].context.index}]`;
function getPath() {
return `configuration.items[${selection[0].context.index}]`;
}
function getAllTypes(selection) {
return selection.filter(selectionPath => {
let type = selectionPath[0].context.layoutItem.type;
return type === 'text-view' ||
type === 'telemetry-view' ||
type === 'box-view' ||
type === 'image-view' ||
type === 'line-view' ||
type === 'subobject-view';
});
}
let selectedParent = selection[1] && selection[1].context.item,
selectedObject = selection[0].context.item,
layoutItem = selection[0].context.layoutItem,
toolbar = [];
function getAddButton(selection, selectionPath) {
if (selection.length === 1) {
selectionPath = selectionPath || selection[0];
return {
if (selectedObject && selectedObject.type === 'layout') {
toolbar.push({
control: "menu",
domainObject: selectionPath[0].context.item,
domainObject: selectedObject,
method: function (option) {
let name = option.name.toLowerCase();
let form = DIALOG_FORM[name];
if (form) {
getUserInput(form)
.then(element => selectionPath[0].context.addElement(name, element));
.then(element => selection[0].context.addElement(name, element));
} else {
selectionPath[0].context.addElement(name);
selection[0].context.addElement(name);
}
},
key: "add",
@@ -132,43 +117,23 @@ define([], function () {
"class": "icon-image"
}
]
};
}
});
}
function getToggleFrameButton(selectedParent, selection) {
return {
control: "toggle-button",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath =>
selectionPath[0].context.layoutItem.type === 'subobject-view'
),
property: function (selectionPath) {
return getPath(selectionPath) + ".hasFrame";
},
options: [
{
value: false,
icon: 'icon-frame-show',
title: "Frame visible"
},
{
value: true,
icon: 'icon-frame-hide',
title: "Frame hidden"
}
]
};
if (!layoutItem) {
return toolbar;
}
function getRemoveButton(selectedParent, selectionPath, selection) {
return {
let separator = {
control: "separator"
};
let remove = {
control: "button",
domainObject: selectedParent,
icon: "icon-trash",
title: "Delete the selected object",
method: function () {
let removeItem = selectionPath[1].context.removeItem;
let removeItem = selection[1].context.removeItem;
let prompt = openmct.overlays.dialog({
iconClass: 'alert',
message: `Warning! This action will remove this item from the Display Layout. Do you want to continue?`,
@@ -177,7 +142,7 @@ define([], function () {
label: 'Ok',
emphasis: 'true',
callback: function () {
removeItem(getAllTypes(selection));
removeItem(layoutItem, selection[0].context.index);
prompt.dismiss();
}
},
@@ -191,10 +156,7 @@ define([], function () {
});
}
};
}
function getStackOrder(selectedParent, selectionPath) {
return {
let stackOrder = {
control: "menu",
domainObject: selectedParent,
icon: "icon-layers",
@@ -222,122 +184,138 @@ define([], function () {
}
],
method: function (option) {
selectionPath[1].context.orderItem(option.value, getAllTypes(selection));
selection[1].context.orderItem(option.value, selection[0].context.index);
}
};
let useGrid = {
control: "toggle-button",
domainObject: selectedParent,
property: function () {
return getPath() + ".useGrid";
},
options: [
{
value: false,
icon: "icon-grid-snap-to",
title: "Grid snapping enabled"
},
{
value: true,
icon: "icon-grid-snap-no",
title: "Grid snapping disabled"
}
function getXInput(selectedParent, selection) {
if (selection.length === 1) {
return {
]
};
let x = {
control: "input",
type: "number",
domainObject: selectedParent,
applicableSelectedItems: getAllTypes(selection),
property: function (selectionPath) {
return getPath(selectionPath) + ".x";
property: function () {
return getPath() + ".x";
},
label: "X:",
title: "X position"
};
}
}
function getYInput(selectedParent, selection) {
if (selection.length === 1) {
return {
},
y = {
control: "input",
type: "number",
domainObject: selectedParent,
applicableSelectedItems: getAllTypes(selection),
property: function (selectionPath) {
return getPath(selectionPath) + ".y";
property: function () {
return getPath() + ".y";
},
label: "Y:",
title: "Y position",
};
}
}
function getWidthInput(selectedParent, selection) {
if (selection.length === 1) {
return {
},
width = {
control: 'input',
type: 'number',
domainObject: selectedParent,
applicableSelectedItems: getAllTypes(selection),
property: function (selectionPath) {
return getPath(selectionPath) + ".width";
property: function () {
return getPath() + ".width";
},
label: 'W:',
title: 'Resize object width'
};
}
}
function getHeightInput(selectedParent, selection) {
if (selection.length === 1) {
return {
},
height = {
control: 'input',
type: 'number',
domainObject: selectedParent,
applicableSelectedItems: getAllTypes(selection),
property: function (selectionPath) {
return getPath(selectionPath) + ".height";
property: function () {
return getPath() + ".height";
},
label: 'H:',
title: 'Resize object height'
};
}
if (layoutItem.type === 'subobject-view') {
if (toolbar.length > 0) {
toolbar.push(separator);
}
function getX2Input(selectedParent, selection) {
if (selection.length === 1) {
return {
control: "input",
type: "number",
toolbar.push({
control: "toggle-button",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'line-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".x2";
property: function () {
return getPath() + ".hasFrame";
},
label: "X2:",
title: "X2 position"
};
}
}
function getY2Input(selectedParent, selection) {
if (selection.length === 1) {
return {
control: "input",
type: "number",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'line-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".y2";
options: [
{
value: false,
icon: 'icon-frame-show',
title: "Frame visible"
},
label: "Y2:",
title: "Y2 position",
};
{
value: true,
icon: 'icon-frame-hide',
title: "Frame hidden"
}
}
function getTextSizeMenu(selectedParent, selection) {
]
});
toolbar.push(separator);
toolbar.push(stackOrder);
toolbar.push(x);
toolbar.push(y);
toolbar.push(width);
toolbar.push(height);
toolbar.push(useGrid);
toolbar.push(separator);
toolbar.push(remove);
} else {
const TEXT_SIZE = [8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96, 128];
return {
let fill = {
control: "color-picker",
domainObject: selectedParent,
property: function () {
return getPath() + ".fill";
},
icon: "icon-paint-bucket",
title: "Set fill color"
},
stroke = {
control: "color-picker",
domainObject: selectedParent,
property: function () {
return getPath() + ".stroke";
},
icon: "icon-line-horz",
title: "Set border color"
},
color = {
control: "color-picker",
domainObject: selectedParent,
property: function () {
return getPath() + ".color";
},
icon: "icon-font",
mandatory: true,
title: "Set text color",
preventNone: true
},
size = {
control: "select-menu",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
let type = selectionPath[0].context.layoutItem.type;
return type === 'text-view' || type === 'telemetry-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".size";
property: function () {
return getPath() + ".size";
},
title: "Set text size",
options: TEXT_SIZE.map(size => {
@@ -346,128 +324,13 @@ define([], function () {
};
})
};
}
function getFillMenu(selectedParent, selection) {
return {
control: "color-picker",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
let type = selectionPath[0].context.layoutItem.type;
return type === 'text-view' ||
type === 'telemetry-view' ||
type === 'box-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".fill";
},
icon: "icon-paint-bucket",
title: "Set fill color"
};
}
function getStrokeMenu(selectedParent, selection) {
return {
control: "color-picker",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
let type = selectionPath[0].context.layoutItem.type;
return type === 'text-view' ||
type === 'telemetry-view' ||
type === 'box-view' ||
type === 'image-view' ||
type === 'line-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".stroke";
},
icon: "icon-line-horz",
title: "Set border color"
};
}
function getTextColorMenu(selectedParent, selection) {
return {
control: "color-picker",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
let type = selectionPath[0].context.layoutItem.type;
return type === 'text-view' || type === 'telemetry-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".color";
},
icon: "icon-font",
mandatory: true,
title: "Set text color",
preventNone: true
};
}
function getURLButton(selectedParent, selection) {
return {
control: "button",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'image-view';
}),
property: function (selectionPath) {
return getPath(selectionPath);
},
icon: "icon-image",
title: "Edit image properties",
dialog: DIALOG_FORM['image']
};
}
function getTextButton(selectedParent, selection) {
return {
control: "button",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'text-view';
}),
property: function (selectionPath) {
return getPath(selectionPath);
},
icon: "icon-gear",
title: "Edit text properties",
dialog: DIALOG_FORM['text']
};
}
function getTelemetryValueMenu(selectionPath, selection) {
if (selection.length === 1) {
return {
control: "select-menu",
domainObject: selectionPath[1].context.item,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'telemetry-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".value";
},
title: "Set value",
options: openmct.telemetry.getMetadata(selectionPath[0].context.item).values().map(value => {
return {
name: value.name,
value: value.key
}
})
};
}
}
function getDisplayModeMenu(selectedParent, selection) {
if (selection.length === 1) {
return {
if (layoutItem.type === 'telemetry-view') {
let displayMode = {
control: "select-menu",
domainObject: selectedParent,
applicableSelectedItems: selection.filter(selectionPath => {
return selectionPath[0].context.layoutItem.type === 'telemetry-view';
}),
property: function (selectionPath) {
return getPath(selectionPath) + ".displayMode";
property: function () {
return getPath() + ".displayMode";
},
title: "Set display mode",
options: [
@@ -484,196 +347,146 @@ define([], function () {
value: "value"
}
]
};
}
}
function getSeparator() {
},
value = {
control: "select-menu",
domainObject: selectedParent,
property: function () {
return getPath() + ".value";
},
title: "Set value",
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
return {
control: "separator"
name: value.name,
value: value.key
}
})
};
}
function isMainLayoutSelected(selectionPath) {
let selectedObject = selectionPath[0].context.item;
return selectedObject && selectedObject.type === 'layout' &&
!selectionPath[0].context.layoutItem;
}
if (isMainLayoutSelected(selection[0])) {
return [getAddButton(selection)];
}
let toolbar = {
'add-menu': [],
'toggle-frame': [],
'display-mode': [],
'telemetry-value': [],
'style': [],
'text-style': [],
'position': [],
'text': [],
'url': [],
'remove': [],
};
selection.forEach(selectionPath => {
let selectedParent = selectionPath[1].context.item;
let layoutItem = selectionPath[0].context.layoutItem;
if (layoutItem.type === 'subobject-view') {
if (toolbar['add-menu'].length === 0 && selectionPath[0].context.item.type === 'layout') {
toolbar['add-menu'] = [getAddButton(selection, selectionPath)];
}
if (toolbar['toggle-frame'].length === 0) {
toolbar['toggle-frame'] = [getToggleFrameButton(selectedParent, selection)];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getHeightInput(selectedParent, selection),
getWidthInput(selectedParent, selection)
toolbar = [
displayMode,
separator,
value,
separator,
fill,
stroke,
color,
separator,
size,
separator,
stackOrder,
x,
y,
height,
width,
useGrid,
separator,
remove
];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
} else if (layoutItem.type === 'telemetry-view') {
if (toolbar['display-mode'].length === 0) {
toolbar['display-mode'] = [getDisplayModeMenu(selectedParent, selection)];
}
if (toolbar['telemetry-value'].length === 0) {
toolbar['telemetry-value'] = [getTelemetryValueMenu(selectionPath, selection)];
}
if (toolbar['style'].length < 2) {
toolbar['style'] = [
getFillMenu(selectedParent, selection),
getStrokeMenu(selectedParent, selection)
];
}
if (toolbar['text-style'].length === 0) {
toolbar['text-style'] = [
getTextColorMenu(selectedParent, selection),
getTextSizeMenu(selectedParent, selection)
];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getHeightInput(selectedParent, selection),
getWidthInput(selectedParent, selection)
];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
} else if (layoutItem.type === 'text-view') {
if (toolbar['style'].length < 2) {
toolbar['style'] = [
getFillMenu(selectedParent, selection),
getStrokeMenu(selectedParent, selection)
let text = {
control: "button",
domainObject: selectedParent,
property: function () {
return getPath();
},
icon: "icon-gear",
title: "Edit text properties",
dialog: DIALOG_FORM['text']
};
toolbar = [
fill,
stroke,
separator,
color,
size,
separator,
stackOrder,
x,
y,
height,
width,
useGrid,
separator,
text,
separator,
remove
];
}
if (toolbar['text-style'].length === 0) {
toolbar['text-style'] = [
getTextColorMenu(selectedParent, selection),
getTextSizeMenu(selectedParent, selection)
];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getHeightInput(selectedParent, selection),
getWidthInput(selectedParent, selection)
];
}
if (toolbar['text'].length === 0) {
toolbar['text'] = [getTextButton(selectedParent, selection)];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
} else if (layoutItem.type === 'box-view') {
if (toolbar['style'].length < 2) {
toolbar['style'] = [
getFillMenu(selectedParent, selection),
getStrokeMenu(selectedParent, selection)
toolbar = [
fill,
stroke,
separator,
stackOrder,
x,
y,
height,
width,
useGrid,
separator,
remove
];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getHeightInput(selectedParent, selection),
getWidthInput(selectedParent, selection)
];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
} else if (layoutItem.type === 'image-view') {
if (toolbar['style'].length === 0) {
toolbar['style'] = [
getStrokeMenu(selectedParent, selection)
let url = {
control: "button",
domainObject: selectedParent,
property: function () {
return getPath();
},
icon: "icon-image",
title: "Edit image properties",
dialog: DIALOG_FORM['image']
};
toolbar = [
stroke,
separator,
stackOrder,
x,
y,
height,
width,
useGrid,
separator,
url,
separator,
remove
];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getHeightInput(selectedParent, selection),
getWidthInput(selectedParent, selection)
];
}
if (toolbar['url'].length === 0) {
toolbar['url'] = [getURLButton(selectedParent, selection)];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
} else if (layoutItem.type === 'line-view') {
if (toolbar['style'].length === 0) {
toolbar['style'] = [
getStrokeMenu(selectedParent, selection)
let x2 = {
control: "input",
type: "number",
domainObject: selectedParent,
property: function () {
return getPath() + ".x2";
},
label: "X2:",
title: "X2 position"
},
y2 = {
control: "input",
type: "number",
domainObject: selectedParent,
property: function () {
return getPath() + ".y2";
},
label: "Y2:",
title: "Y2 position",
};
toolbar = [
stroke,
separator,
stackOrder,
x,
y,
x2,
y2,
useGrid,
separator,
remove
];
}
if (toolbar['position'].length === 0) {
toolbar['position'] = [
getStackOrder(selectedParent, selectionPath),
getXInput(selectedParent, selection),
getYInput(selectedParent, selection),
getX2Input(selectedParent, selection),
getY2Input(selectedParent, selection)
];
}
if (toolbar['remove'].length === 0) {
toolbar['remove'] = [getRemoveButton(selectedParent, selectionPath, selection)];
}
}
});
let toolbarArray = Object.values(toolbar);
return _.flatten(toolbarArray.reduce((accumulator, group, index) => {
group = group.filter(control => control !== undefined);
if (group.length > 0) {
accumulator.push(group);
if (index < toolbarArray.length - 1) {
accumulator.push(getSeparator());
}
}
return accumulator;
}, []));
return toolbar;
}
}
}

View File

@@ -95,7 +95,7 @@ define(
* @param {number[]} pixelDelta the offset from the
* original position, in pixels
*/
LayoutDrag.prototype.getAdjustedPositionAndDimensions = function (pixelDelta) {
LayoutDrag.prototype.getAdjustedPosition = function (pixelDelta) {
var gridDelta = toGridDelta(this.gridSize, pixelDelta);
return {
position: max(add(
@@ -109,16 +109,6 @@ define(
};
};
LayoutDrag.prototype.getAdjustedPosition = function (pixelDelta) {
var gridDelta = toGridDelta(this.gridSize, pixelDelta);
return {
position: max(add(
this.rawPosition.position,
multiply(gridDelta, this.posFactor)
), [0, 0])
};
};
return LayoutDrag;
}

View File

@@ -23,8 +23,7 @@
<template>
<layout-frame :item="item"
:grid-size="gridSize"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')">
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
<div class="c-box-view"
:style="style">
</div>
@@ -55,7 +54,8 @@
x: 1,
y: 1,
width: 10,
height: 5
height: 5,
useGrid: true
};
},
inject: ['openmct'],

View File

@@ -23,11 +23,8 @@
<template>
<div class="l-layout"
@dragover="handleDragOver"
@click.capture="bypassSelection"
@drop="handleDrop"
:class="{
'is-multi-selected': selectedLayoutItems.length > 1
}">
@click="bypassSelection"
@drop="handleDrop">
<!-- Background grid -->
<div class="l-layout__grid-holder c-grid">
<div class="c-grid__x l-grid l-grid-x"
@@ -42,38 +39,18 @@
:is="item.type"
:item="item"
:key="item.id"
:gridSize="gridSize"
:gridSize="item.useGrid ? gridSize : [1, 1]"
:initSelect="initSelectIndex === index"
:index="index"
:multiSelect="selectedLayoutItems.length > 1"
@move="move"
@endMove="endMove"
@endLineResize='endLineResize'>
@endDrag="endDrag"
>
</component>
<edit-marquee v-if='showMarquee'
:gridSize="gridSize"
:selectedLayoutItems="selectedLayoutItems"
@endResize="endResize">
</edit-marquee>
</div>
</template>
<style lang="scss">
@import "~styles/sass-base";
@mixin displayMarquee($c) {
> .c-frame-edit {
// All other frames
//@include test($c, 0.4);
display: block;
}
> .c-frame > .c-frame-edit {
// Line object frame
//@include test($c, 0.4);
display: block;
}
}
.l-layout {
@include abs();
display: flex;
@@ -93,7 +70,7 @@
.l-shell__main-container {
&[s-selected],
&[s-selected-parent] {
// Display grid and allow edit marquee to display in main layout holder when editing
// Display grid in main layout holder when editing
> .l-layout {
background: $editUIGridColorBg;
@@ -107,7 +84,7 @@
.l-layout__frame {
&[s-selected],
&[s-selected-parent] {
// Display grid and allow edit marquee to display in nested layouts when editing
// Display grid in nested layouts when editing
> * > * > .l-layout {
background: $editUIGridColorBg;
box-shadow: inset $editUIGridColorFg 0 0 2px 1px;
@@ -118,21 +95,10 @@
}
}
}
/*********************** EDIT MARQUEE CONTROL */
*[s-selected-parent] {
> .l-layout {
// When main shell layout is the parent
@include displayMarquee(deeppink);
}
> * > * > * {
// When a sub-layout is the parent
@include displayMarquee(blue);
}
}
}
</style>
<script>
import uuid from 'uuid';
@@ -142,7 +108,6 @@
import TextView from './TextView.vue'
import LineView from './LineView.vue'
import ImageView from './ImageView.vue'
import EditMarquee from './EditMarquee.vue'
const ITEM_TYPE_VIEW_MAP = {
'subobject-view': SubobjectView,
@@ -158,10 +123,8 @@
down: -1,
bottom: Number.NEGATIVE_INFINITY
};
const DRAG_OBJECT_TRANSFER_PREFIX = 'openmct/domain-object/';
let components = ITEM_TYPE_VIEW_MAP;
components['edit-marquee'] = EditMarquee;
const DRAG_OBJECT_TRANSFER_PREFIX = 'openmct/domain-object/';
function getItemDefinition(itemType, ...options) {
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
@@ -178,8 +141,7 @@
let domainObject = JSON.parse(JSON.stringify(this.domainObject));
return {
internalDomainObject: domainObject,
initSelectIndex: undefined,
selection: []
initSelectIndex: undefined
};
},
computed: {
@@ -188,115 +150,82 @@
},
layoutItems() {
return this.internalDomainObject.configuration.items;
},
selectedLayoutItems() {
return this.layoutItems.filter(item => {
return this.itemIsInCurrentSelection(item);
});
},
showMarquee() {
let selectionPath = this.selection[0];
let singleSelectedLine = this.selection.length === 1 &&
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.type === 'line-view';
return selectionPath && selectionPath.length > 1 && !singleSelectedLine;
}
},
inject: ['openmct', 'options'],
inject: ['openmct'],
props: ['domainObject'],
components: components,
components: ITEM_TYPE_VIEW_MAP,
methods: {
addElement(itemType, element) {
this.addItem(itemType + '-view', element);
},
setSelection(selection) {
this.selection = selection;
if (selection.length === 0) {
return;
}
if (this.removeSelectionListener) {
this.removeSelectionListener();
}
let itemIndex = selection[0].context.index;
if (itemIndex !== undefined) {
this.attachSelectionListener(itemIndex);
}
},
itemIsInCurrentSelection(item) {
return this.selection.some(selectionPath =>
selectionPath[0].context.layoutItem && selectionPath[0].context.layoutItem.id === item.id);
attachSelectionListener(index) {
let path = `configuration.items[${index}].useGrid`;
this.removeSelectionListener = this.openmct.objects.observe(this.internalDomainObject, path, function (value) {
let item = this.layoutItems[index];
if (value) {
item.x = Math.round(item.x / this.gridSize[0]);
item.y = Math.round(item.y / this.gridSize[1]);
item.width = Math.round(item.width / this.gridSize[0]);
item.height = Math.round(item.height / this.gridSize[1]);
if (item.x2) {
item.x2 = Math.round(item.x2 / this.gridSize[0]);
}
if (item.y2) {
item.y2 = Math.round(item.y2 / this.gridSize[1]);
}
} else {
item.x = this.gridSize[0] * item.x;
item.y = this.gridSize[1] * item.y;
item.width = this.gridSize[0] * item.width;
item.height = this.gridSize[1] * item.height;
if (item.x2) {
item.x2 = this.gridSize[0] * item.x2;
}
if (item.y2) {
item.y2 = this.gridSize[1] * item.y2;
}
}
item.useGrid = value;
this.mutate(`configuration.items[${index}]`, item);
}.bind(this));
},
bypassSelection($event) {
if (this.dragInProgress) {
if ($event) {
$event.stopImmediatePropagation();
}
this.dragInProgress = false;
return;
}
},
endLineResize(item, updates) {
endDrag(item, updates) {
this.dragInProgress = true;
setTimeout(function () {
this.dragInProgress = false;
}.bind(this), 0);
let index = this.layoutItems.indexOf(item);
Object.assign(item, updates);
this.mutate(`configuration.items[${index}]`, item);
},
endResize(scaleWidth, scaleHeight, marqueeStart, marqueeOffset) {
this.dragInProgress = true;
this.layoutItems.forEach(item => {
if (this.itemIsInCurrentSelection(item)) {
let itemXInMarqueeSpace = item.x - marqueeStart.x;
let itemXInMarqueeSpaceAfterScale = Math.round(itemXInMarqueeSpace * scaleWidth);
item.x = itemXInMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
let itemYInMarqueeSpace = item.y - marqueeStart.y;
let itemYInMarqueeSpaceAfterScale = Math.round(itemYInMarqueeSpace * scaleHeight);
item.y = itemYInMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
if (item.x2) {
let itemX2InMarqueeSpace = item.x2 - marqueeStart.x;
let itemX2InMarqueeSpaceAfterScale = Math.round(itemX2InMarqueeSpace * scaleWidth);
item.x2 = itemX2InMarqueeSpaceAfterScale + marqueeOffset.x + marqueeStart.x;
} else {
item.width = Math.round(item.width * scaleWidth);
}
if (item.y2) {
let itemY2InMarqueeSpace = item.y2 - marqueeStart.y;
let itemY2InMarqueeSpaceAfterScale = Math.round(itemY2InMarqueeSpace * scaleHeight);
item.y2 = itemY2InMarqueeSpaceAfterScale + marqueeOffset.y + marqueeStart.y;
} else {
item.height = Math.round(item.height * scaleHeight);
}
}
});
this.mutate("configuration.items", this.layoutItems);
},
move(gridDelta) {
this.dragInProgress = true;
if (!this.initialPositions) {
this.initialPositions = {};
_.cloneDeep(this.selectedLayoutItems).forEach(selectedItem => {
if (selectedItem.type === 'line-view') {
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y, selectedItem.x2, selectedItem.y2];
} else {
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y];
}
});
}
let layoutItems = this.layoutItems.map(item => {
if (this.initialPositions[item.id]) {
let startingPosition = this.initialPositions[item.id];
let [startingX, startingY, startingX2, startingY2] = startingPosition;
item.x = startingX + gridDelta[0];
item.y = startingY + gridDelta[1];
if (item.x2) {
item.x2 = startingX2 + gridDelta[0];
}
if (item.y2) {
item.y2 = startingY2 + gridDelta[1];
}
}
return item;
});
},
endMove() {
this.mutate('configuration.items', this.layoutItems);
this.initialPositions = undefined;
},
mutate(path, value) {
this.openmct.objects.mutate(this.internalDomainObject, path, value);
},
@@ -354,8 +283,9 @@
}
},
isTelemetry(domainObject) {
if (this.openmct.telemetry.isTelemetryObject(domainObject) &&
!this.options.showAsView.includes(domainObject.type)) {
if (this.openmct.telemetry.isTelemetryObject(domainObject)
&& domainObject.type !== 'summary-widget'
&& domainObject.type !== 'example.imagery') {
return true;
} else {
return false;
@@ -384,15 +314,11 @@
this.objectViewMap[keyString] = true;
}
},
removeItem(selectedItems) {
let indices = [];
removeItem(item, index) {
this.initSelectIndex = -1;
selectedItems.forEach(selectedItem => {
indices.push(selectedItem[0].context.index);
this.untrackItem(selectedItem[0].context.layoutItem);
});
_.pullAt(this.layoutItems, indices);
this.layoutItems.splice(index, 1);
this.mutate("configuration.items", this.layoutItems);
this.untrackItem(item);
this.$el.click();
},
untrackItem(item) {
@@ -458,74 +384,20 @@
this.mutate("configuration.items", layoutItems);
this.$el.click();
},
orderItem(position, selectedItems) {
orderItem(position, index) {
let delta = ORDERS[position];
let indices = [];
let newIndex = -1;
let items = [];
Object.assign(items, this.layoutItems);
this.selectedLayoutItems.forEach(selectedItem => {
indices.push(this.layoutItems.indexOf(selectedItem));
});
indices.sort((a, b) => a - b);
if (position === 'top' || position === 'up') {
indices.reverse();
}
if (position === 'top' || position === 'bottom') {
this.moveToTopOrBottom(position, indices, items, delta);
} else {
this.moveUpOrDown(position, indices, items, delta);
}
let newIndex = Math.max(Math.min(index + delta, this.layoutItems.length - 1), 0);
let item = this.layoutItems[index];
if (newIndex !== index) {
this.layoutItems.splice(index, 1);
this.layoutItems.splice(newIndex, 0, item);
this.mutate('configuration.items', this.layoutItems);
},
moveUpOrDown(position, indices, items, delta) {
let previousItemIndex = -1;
let newIndex = -1;
indices.forEach((itemIndex, index) => {
let isAdjacentItemSelected = position === 'up' ?
itemIndex + 1 === previousItemIndex :
itemIndex - 1 === previousItemIndex;
if (index > 0 && isAdjacentItemSelected) {
if (position === 'up') {
newIndex -= 1;
} else {
newIndex += 1;
if (this.removeSelectionListener) {
this.removeSelectionListener();
this.attachSelectionListener(newIndex);
}
} else {
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
}
previousItemIndex = itemIndex;
this.updateItemOrder(newIndex, itemIndex, items);
});
},
moveToTopOrBottom(position, indices, items, delta) {
let newIndex = -1;
indices.forEach((itemIndex, index) => {
if (index === 0) {
newIndex = Math.max(Math.min(itemIndex + delta, this.layoutItems.length - 1), 0);
} else {
if (position === 'top') {
newIndex -= 1;
} else {
newIndex += 1;
}
}
this.updateItemOrder(newIndex, itemIndex, items);
});
},
updateItemOrder(newIndex, itemIndex, items) {
if (newIndex !== itemIndex) {
this.layoutItems.splice(itemIndex, 1);
this.layoutItems.splice(newIndex, 0, items[itemIndex]);
}
}
},
@@ -541,10 +413,14 @@
this.composition.load();
},
destroyed: function () {
this.openmct.selection.off('change', this.setSelection);
this.openmct.off('change', this.setSelection);
this.composition.off('add', this.addChild);
this.composition.off('remove', this.removeChild);
this.unlisten();
if (this.removeSelectionListener) {
this.removeSelectionListener();
}
}
}
</script>

View File

@@ -1,233 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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.
*****************************************************************************/
<template>
<!-- Resize handles -->
<div class="c-frame-edit" :style="style">
<div class="c-frame-edit__handle c-frame-edit__handle--nw"
@mousedown="startResize([1,1], [-1,-1], $event)"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--ne"
@mousedown="startResize([0,1], [1,-1], $event)"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--sw"
@mousedown="startResize([1,0], [-1,1], $event)"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--se"
@mousedown="startResize([0,0], [1,1], $event)"></div>
</div>
</template>
<style lang="scss">
@import "~styles/sass-base";
.c-frame-edit {
// In Layouts, this is the editing rect and handles
display: none; // Set to display: block in DisplayLayout.vue
pointer-events: none;
@include abs();
border: $editMarqueeBorder;
&__handle {
$d: 6px;
$o: floor($d * -0.5);
background: $editFrameColorHandleFg;
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
pointer-events: all;
position: absolute;
width: $d; height: $d;
top: auto; right: auto; bottom: auto; left: auto;
&:before {
// Extended hit area
@include abs(-10px);
content: '';
display: block;
z-index: 0;
}
&:hover {
background: $editUIColor;
}
&--nwse {
cursor: nwse-resize;
}
&--nw {
cursor: nw-resize;
left: $o; top: $o;
}
&--ne {
cursor: ne-resize;
right: $o; top: $o;
}
&--se {
cursor: se-resize;
right: $o; bottom: $o;
}
&--sw {
cursor: sw-resize;
left: $o; bottom: $o;
}
}
}
</style>
<script>
import LayoutDrag from './../LayoutDrag'
export default {
inject: ['openmct'],
props: {
selectedLayoutItems: Array,
gridSize: Array
},
data() {
return {
dragPosition: undefined
}
},
computed: {
style() {
let x = Number.POSITIVE_INFINITY;
let y = Number.POSITIVE_INFINITY;
let width = Number.NEGATIVE_INFINITY;
let height = Number.NEGATIVE_INFINITY;
this.selectedLayoutItems.forEach(item => {
if (item.x2) {
let lineWidth = Math.abs(item.x - item.x2);
let lineMinX = Math.min(item.x, item.x2);
x = Math.min(lineMinX, x);
width = Math.max(lineWidth + lineMinX, width);
} else {
x = Math.min(item.x, x);
width = Math.max(item.width + item.x, width);
}
if (item.y2) {
let lineHeight = Math.abs(item.y - item.y2);
let lineMinY = Math.min(item.y, item.y2);
y = Math.min(lineMinY, y);
height = Math.max(lineHeight + lineMinY, height);
} else {
y = Math.min(item.y, y);
height = Math.max(item.height + item.y, height);
}
});
if (this.dragPosition) {
[x, y] = this.dragPosition.position;
[width, height] = this.dragPosition.dimensions;
} else {
width = width - x;
height = height - y;
}
this.marqueePosition = {
x: x,
y: y,
width: width,
height: height
}
return this.getMarqueeStyle(x, y, width, height);
}
},
methods: {
getMarqueeStyle(x, y, width, height) {
return {
left: (this.gridSize[0] * x) + 'px',
top: (this.gridSize[1] * y) + 'px',
width: (this.gridSize[0] * width) + 'px',
height: (this.gridSize[1] * height) + 'px'
};
},
updatePosition(event) {
let currentPosition = [event.pageX, event.pageY];
this.initialPosition = this.initialPosition || currentPosition;
this.delta = currentPosition.map(function (value, index) {
return value - this.initialPosition[index];
}.bind(this));
},
startResize(posFactor, dimFactor, event) {
document.body.addEventListener('mousemove', this.continueResize);
document.body.addEventListener('mouseup', this.endResize);
this.marqueeStartPosition = {
position: [this.marqueePosition.x, this.marqueePosition.y],
dimensions: [this.marqueePosition.width, this.marqueePosition.height]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(this.marqueeStartPosition, posFactor, dimFactor, this.gridSize);
event.preventDefault();
},
continueResize(event) {
event.preventDefault();
this.updatePosition(event);
this.dragPosition = this.activeDrag.getAdjustedPositionAndDimensions(this.delta);
},
endResize(event) {
document.body.removeEventListener('mousemove', this.continueResize);
document.body.removeEventListener('mouseup', this.endResize);
this.continueResize(event);
let marqueeStartWidth = this.marqueeStartPosition.dimensions[0];
let marqueeStartHeight = this.marqueeStartPosition.dimensions[1];
let marqueeStartX = this.marqueeStartPosition.position[0];
let marqueeStartY = this.marqueeStartPosition.position[1];
let marqueeEndX = this.dragPosition.position[0];
let marqueeEndY = this.dragPosition.position[1];
let marqueeEndWidth = this.dragPosition.dimensions[0];
let marqueeEndHeight = this.dragPosition.dimensions[1];
let scaleWidth = marqueeEndWidth / marqueeStartWidth;
let scaleHeight = marqueeEndHeight / marqueeStartHeight;
let marqueeStart = {
x: marqueeStartX,
y: marqueeStartY,
height: marqueeStartWidth,
width: marqueeStartHeight
};
let marqueeEnd = {
x: marqueeEndX,
y: marqueeEndY,
width: marqueeEndWidth,
height: marqueeEndHeight
};
let marqueeOffset = {
x: marqueeEnd.x - marqueeStart.x,
y: marqueeEnd.y - marqueeStart.y
};
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
this.dragPosition = undefined;
this.initialPosition = undefined;
this.marqueeStartPosition = undefined;
this.delta = undefined;
event.preventDefault();
}
}
}
</script>

View File

@@ -23,8 +23,7 @@
<template>
<layout-frame :item="item"
:grid-size="gridSize"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')">
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
<div class="c-image-view"
:style="style">
</div>
@@ -57,7 +56,8 @@
y: 1,
width: 10,
height: 5,
url: element.url
url: element.url,
useGrid: true
};
},
inject: ['openmct'],

View File

@@ -24,14 +24,25 @@
<div class="l-layout__frame c-frame"
:class="{
'no-frame': !item.hasFrame,
'u-inspectable': inspectable
'u-inspectable': inspectable,
'is-resizing': isResizing
}"
:style="style">
<slot></slot>
<!-- Drag handles -->
<div class="c-frame-edit">
<div class="c-frame-edit__move"
@mousedown="startMove([1,1], [0,0], $event)">
@mousedown="startDrag([1,1], [0,0], $event, 'move')"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--nw"
@mousedown="startDrag([1,1], [-1,-1], $event, 'resize')"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--ne"
@mousedown="startDrag([0,1], [1,-1], $event, 'resize')"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--sw"
@mousedown="startDrag([1,0], [-1,1], $event, 'resize')"></div>
<div class="c-frame-edit__handle c-frame-edit__handle--se"
@mousedown="startDrag([0,0], [1,1], $event, 'resize')"></div>
</div>
</div>
</template>
@@ -39,7 +50,7 @@
<style lang="scss">
@import "~styles/sass-base";
/******************* FRAME */
/******************************* FRAME */
.c-frame {
display: flex;
flex-direction: column;
@@ -48,74 +59,83 @@
> *:first-child {
flex: 1 1 auto;
}
&:not(.no-frame) {
background: $colorBodyBg;
border: $browseFrameBorder;
padding: $interiorMargin;
}
.c-frame-edit__move {
}
.c-frame-edit {
// In Layouts, this is the editing rect and handles
// In Fixed Position, this is a wrapper element
@include abs();
display: none;
}
.is-editing {
/******************* STYLES FOR C-FRAME WHILE EDITING */
.c-frame {
&:not([s-selected]) {
&:hover {
border: $editFrameBorderHov;
}
}
&[s-selected] {
// All frames selected while editing
border: $editFrameSelectedBorder;
box-shadow: $editFrameSelectedShdw;
.c-frame-edit__move {
&__move {
@include abs();
cursor: move;
}
}
}
/******************* DEFAULT STYLES FOR -EDIT__MOVE */
// All object types
.c-frame-edit__move {
@include abs();
&__handle {
$d: 6px;
$o: floor($d * -0.5);
background: $editFrameColorHandleFg;
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
display: none; // Set to block via s-selected selector
position: absolute;
width: $d; height: $d;
top: auto; right: auto; bottom: auto; left: auto;
&:before {
// Extended hit area
@include abs(-10px);
content: '';
display: block;
z-index: 0;
}
// Has-complex-content objects
.c-so-view.has-complex-content {
transition: $transOut;
transition-delay: $moveBarOutDelay;
> .c-so-view__local-controls {
transition: transform 250ms ease-in-out;
transition-delay: $moveBarOutDelay;
&:hover {
background: $editUIColor;
}
+ .c-frame-edit__move {
display: none;
&--nwse {
cursor: nwse-resize;
}
&--nw {
cursor: nw-resize;
left: $o; top: $o;
}
.l-layout {
/******************* 0 - 1 ITEM SELECTED */
&:not(.is-multi-selected) {
> .l-layout__frame[s-selected] {
> .c-so-view.has-complex-content {
> .c-so-view__local-controls {
transition: transform $transOutTime ease-in-out;
transition-delay: $moveBarOutDelay;
&--ne {
cursor: ne-resize;
right: $o; top: $o;
}
+ .c-frame-edit__move {
transition: $transOut;
transition-delay: $moveBarOutDelay;
&--se {
cursor: se-resize;
right: $o; bottom: $o;
}
&--sw {
cursor: sw-resize;
left: $o; bottom: $o;
}
}
}
.c-so-view.has-complex-content + .c-frame-edit {
// Target frames that hold domain objects that include header elements, as opposed to drawing and alpha objects
// Make the __move element a more affordable drag UI element
.c-frame-edit__move {
@include userSelectNone();
background: $editFrameMovebarColorBg;
box-shadow: rgba(black, 0.2) 0 1px;
bottom: auto;
display: block;
height: 0; // Height is set on hover below
height: 0; // Height is set on hover on s-selected.c-frame
opacity: 0.8;
max-height: 100%;
overflow: hidden;
@@ -130,48 +150,75 @@
content: '';
display: block;
position: absolute;
top: $tbOffset;
right: $lrOffset;
bottom: $tbOffset;
left: $lrOffset;
}
}
top: $tbOffset; right: $lrOffset; bottom: $tbOffset; left: $lrOffset;
}
&:hover {
> .c-so-view.has-complex-content {
transition: $transIn;
transition-delay: 0s;
padding-top: $editFrameMovebarH + $interiorMarginSm;
> .c-so-view__local-controls {
transform: translateY($editFrameMovebarH);
transition: transform $transInTime ease-in-out;
transition-delay: 0s;
}
+ .c-frame-edit__move {
transition: $transIn;
transition-delay: 0s;
height: $editFrameMovebarH;
}
}
background: $editFrameHovMovebarColorBg;
&:before { @include grippy($editFrameHovMovebarColorFg); }
}
}
}
/******************* > 1 ITEMS SELECTED */
&.is-multi-selected {
.l-layout__frame[s-selected] {
> .c-so-view.has-complex-content + .c-frame-edit__move {
.is-editing {
.c-frame {
$moveBarOutDelay: 500ms;
&.no-frame {
border: $editFrameBorder; // Base border style for a frame element while editing.
}
&-edit {
display: contents;
}
&-edit__move,
.c-so-view {
transition: $transOut;
transition-delay: $moveBarOutDelay;
}
&:not([s-selected]) {
&:hover {
border: $editFrameBorderHov;
}
}
&[s-selected] {
// All frames selected while editing
border: $editFrameSelectedBorder;
box-shadow: $editFrameSelectedShdw;
> .c-frame-edit {
[class*='__handle'] {
display: block;
}
}
}
}
.l-layout__frame:not(.is-resizing) {
// Show and animate the __move bar for sub-object views with complex content
&:hover > .c-so-view.has-complex-content {
// Move content down so the __move bar doesn't cover it.
padding-top: $editFrameMovebarH;
transition: $transIn;
&.c-so-view--no-frame {
// Move content down with a bit more space
padding-top: $editFrameMovebarH + $interiorMarginSm;
}
// Show the move bar
+ .c-frame-edit .c-frame-edit__move {
height: $editFrameMovebarH;
transition: $transIn;
}
}
}
}
</style>
<script>
import LayoutDrag from './../LayoutDrag'
@@ -181,9 +228,21 @@
item: Object,
gridSize: Array
},
data() {
return {
dragPosition: undefined,
isResizing: undefined
}
},
computed: {
style() {
let {x, y, width, height} = this.item;
if (this.dragPosition) {
[x, y] = this.dragPosition.position;
[width, height] = this.dragPosition.dimensions;
}
return {
left: (this.gridSize[0] * x) + 'px',
top: (this.gridSize[1] * y) + 'px',
@@ -205,40 +264,36 @@
return value - this.initialPosition[index];
}.bind(this));
},
startMove(posFactor, dimFactor, event) {
document.body.addEventListener('mousemove', this.continueMove);
document.body.addEventListener('mouseup', this.endMove);
startDrag(posFactor, dimFactor, event, type) {
document.body.addEventListener('mousemove', this.continueDrag);
document.body.addEventListener('mouseup', this.endDrag);
this.dragPosition = {
position: [this.item.x, this.item.y]
position: [this.item.x, this.item.y],
dimensions: [this.item.width, this.item.height]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
this.isResizing = type === 'resize';
event.preventDefault();
},
continueMove(event) {
continueDrag(event) {
event.preventDefault();
this.updatePosition(event);
let newPosition = this.activeDrag.getAdjustedPosition(this.delta);
if (!_.isEqual(newPosition, this.dragPosition)) {
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(this.delta));
}
this.dragPosition = this.activeDrag.getAdjustedPosition(this.delta);
},
endMove(event) {
document.body.removeEventListener('mousemove', this.continueMove);
document.body.removeEventListener('mouseup', this.endMove);
this.continueMove(event);
this.$emit('endMove');
endDrag(event) {
document.body.removeEventListener('mousemove', this.continueDrag);
document.body.removeEventListener('mouseup', this.endDrag);
this.continueDrag(event);
let [x, y] = this.dragPosition.position;
let [width, height] = this.dragPosition.dimensions;
this.$emit('endDrag', this.item, {x, y, width, height});
this.dragPosition = undefined;
this.initialPosition = undefined;
this.delta = undefined;
this.isResizing = undefined;
event.preventDefault();
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
}
}
}

View File

@@ -30,9 +30,9 @@
</line>
</svg>
<div class="c-frame-edit">
<div class="c-frame-edit__move"
@mousedown="startDrag($event)"></div>
<div class="c-frame-edit" v-if="showFrameEdit">
<div class="c-frame-edit__handle"
:class="startHandleClass"
@mousedown="startDrag($event, 'start')"></div>
@@ -66,7 +66,8 @@
y: 10,
x2: 10,
y2: 5,
stroke: '#717171'
stroke: '#717171',
useGrid: true
};
},
inject: ['openmct'],
@@ -75,31 +76,24 @@
gridSize: Array,
initSelect: Boolean,
index: Number,
multiSelect: Boolean
},
data() {
return {
dragPosition: undefined,
dragging: undefined,
selection: []
dragPosition: undefined
};
},
computed: {
showFrameEdit() {
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
},
position() {
let {x, y, x2, y2} = this.item;
if (this.dragging && this.dragPosition) {
if (this.dragPosition) {
({x, y, x2, y2} = this.dragPosition);
}
return {x, y, x2, y2};
},
style() {
let {x, y, x2, y2} = this.position;
let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
let width = this.gridSize[0] * Math.abs(x - x2);
let height = this.gridSize[1] * Math.abs(y - y2);
let left = this.gridSize[0] * Math.min(x, x2);
let top = this.gridSize[1] * Math.min(y, y2);
return {
@@ -181,27 +175,13 @@
event.preventDefault();
let pxDeltaX = this.startPosition[0] - event.pageX;
let pxDeltaY = this.startPosition[1] - event.pageY;
let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
if (!this.dragging) {
if (!_.isEqual(newPosition, this.dragPosition)) {
let gridDelta = [event.pageX - this.startPosition[0], event.pageY - this.startPosition[1]];
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(gridDelta));
}
} else {
this.dragPosition = newPosition;
}
this.dragPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
},
endDrag(event) {
document.body.removeEventListener('mousemove', this.continueDrag);
document.body.removeEventListener('mouseup', this.endDrag);
let {x, y, x2, y2} = this.dragPosition;
if (!this.dragging) {
this.$emit('endMove');
} else {
this.$emit('endLineResize', this.item, {x, y, x2, y2});
}
this.$emit('endDrag', this.item, {x, y, x2, y2});
this.dragPosition = undefined;
this.dragging = undefined;
event.preventDefault();
@@ -211,7 +191,6 @@
let gridDeltaY = Math.round(pxDeltaY / this.gridSize[0]); // TODO: should this be gridSize[1]?
let {x, y, x2, y2} = this.item;
let dragPosition = {x, y, x2, y2};
if (this.dragging === 'start') {
dragPosition.x -= gridDeltaX;
dragPosition.y -= gridDeltaY;
@@ -226,14 +205,6 @@
dragPosition.y2 -= gridDeltaY;
}
return dragPosition;
},
setSelection(selection) {
this.selection = selection;
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
}
},
watch: {
@@ -246,7 +217,6 @@
}
},
mounted() {
this.openmct.selection.on('change', this.setSelection);
this.context = {
layoutItem: this.item,
index: this.index
@@ -258,7 +228,6 @@
if (this.removeSelectable) {
this.removeSelectable();
}
this.openmct.selection.off('change', this.setSelection);
}
}
</script>

View File

@@ -22,9 +22,7 @@
<template>
<layout-frame :item="item"
:grid-size="gridSize"
:title="domainObject && domainObject.name"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')">
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
<object-frame v-if="domainObject"
:domain-object="domainObject"
:object-path="objectPath"
@@ -68,7 +66,8 @@
x: position[0],
y: position[1],
identifier: domainObject.identifier,
hasFrame: hasFrameByDefault(domainObject.type)
hasFrame: hasFrameByDefault(domainObject.type),
useGrid: true
};
},
inject: ['openmct'],

View File

@@ -23,8 +23,7 @@
<template>
<layout-frame :item="item"
:grid-size="gridSize"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')">
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
<div class="c-telemetry-view"
:style="styleObject"
v-if="domainObject">
@@ -97,9 +96,10 @@
displayMode: 'all',
value: metadata.getDefaultDisplayValue(),
stroke: "transparent",
fill: "transparent",
fill: "",
color: "",
size: "13px"
size: "13px",
useGrid: true
};
},
inject: ['openmct'],
@@ -176,8 +176,7 @@
let options = {
start: bounds.start,
end: bounds.end,
size: 1,
strategy: 'latest'
size: 1
};
this.openmct.telemetry.request(this.domainObject, options)
.then(data => {

View File

@@ -23,8 +23,7 @@
<template>
<layout-frame :item="item"
:grid-size="gridSize"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')">
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
<div class="c-text-view"
:style="style">
{{ item.text }}
@@ -60,7 +59,8 @@
y: 1,
width: 10,
height: 5,
text: element.text
text: element.text,
useGrid: true
};
},
inject: ['openmct'],

View File

@@ -25,7 +25,8 @@ import Vue from 'vue'
import objectUtils from '../../api/objects/object-utils.js'
import DisplayLayoutType from './DisplayLayoutType.js'
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js'
export default function DisplayLayoutPlugin(options) {
export default function () {
return function (openmct) {
openmct.objectViews.addProvider({
key: 'layout.view',
@@ -46,8 +47,7 @@ export default function DisplayLayoutPlugin(options) {
template: '<layout ref="displayLayout" :domain-object="domainObject"></layout>',
provide: {
openmct,
objectUtils,
options
objectUtils
},
el: container,
data () {
@@ -60,7 +60,6 @@ export default function DisplayLayoutPlugin(options) {
getSelectionContext() {
return {
item: domainObject,
supportsMultiSelect: true,
addElement: component && component.$refs.displayLayout.addElement,
removeItem: component && component.$refs.displayLayout.removeItem,
orderItem: component && component.$refs.displayLayout.orderItem
@@ -84,6 +83,5 @@ export default function DisplayLayoutPlugin(options) {
return true;
}
});
DisplayLayoutPlugin._installed = true;
}
}

View File

@@ -42,10 +42,7 @@
<!-- Checkbox list, NOT editing -->
<template v-if="filter.possibleValues && !isEditing">
<span
v-if="persistedFilters[filter.comparator]">
{{persistedFilters[filter.comparator].join(', ')}}
</span>
<span>{{persistedFilters[filter.comparator].join(', ')}}</span>
</template>
</div>
</li>

View File

@@ -5,11 +5,11 @@
<span class="c-disclosure-triangle is-enabled flex-elem"
:class="{'c-disclosure-triangle--expanded': expanded}"></span>
<div class="c-tree__item__label">
<div class="c-object-label">
<div class="c-object-label__type-icon"
<div class="t-object-label l-flex-row flex-elem grows">
<div class="t-item-icon flex-elem"
:class="objectCssClass">
</div>
<div class="c-object-label__name flex-elem grows">{{ filterObject.name }}</div>
<div class="t-title-label flex-elem grows">{{ filterObject.name }}</div>
</div>
</div>
</div>
@@ -69,17 +69,16 @@ export default {
}
} else {
if (!this.updatedFilters[key]) {
this.$set(this.updatedFilters, key, {});
this.updatedFilters[key] = {};
}
this.$set(this.updatedFilters[key], comparator, [value ? valueName : undefined]);
this.updatedFilters[key][comparator] = [value ? valueName : undefined];
}
this.$emit('updateFilters', this.keyString, this.updatedFilters);
},
updateTextFilter(key, comparator, value) {
if (!this.updatedFilters[key]) {
this.$set(this.updatedFilters, key, {});
this.$set(this.updatedFilters[key], comparator, '');
this.updatedFilters[key] = {};
}
this.updatedFilters[key][comparator] = value;
this.$emit('updateFilters', this.keyString, this.updatedFilters);

View File

@@ -23,18 +23,17 @@ export default {
FilterObject
},
inject: [
'openmct'
'openmct',
'providedObject'
],
data() {
let providedObject = this.openmct.selection.get()[0][0].context.item;
let persistedFilters = {};
if (providedObject.configuration && providedObject.configuration.filters) {
persistedFilters = providedObject.configuration.filters;
if (this.providedObject.configuration && this.providedObject.configuration.filters) {
persistedFilters = this.providedObject.configuration.filters;
}
return {
providedObject,
persistedFilters,
children: {}
}
@@ -74,14 +73,13 @@ export default {
this.composition.on('add', this.addChildren);
this.composition.on('remove', this.removeChildren);
this.composition.load();
this.unobserve = this.openmct.objects.observe(this.providedObject, 'configuration.filters', this.updatePersistedFilters);
this.unobserveAllMutation = this.openmct.objects.observe(this.providedObject, '*', (mutatedObject) => this.providedObject = mutatedObject);
},
beforeDestroy() {
this.composition.off('add', this.addChildren);
this.composition.off('remove', this.removeChildren);
this.unobserve();
this.unobserveAllMutation();
}
}
</script>

View File

@@ -33,20 +33,23 @@ define([
key: 'filters-inspector',
name: 'Filters Inspector View',
canView: function (selection) {
if (selection.length === 0 || selection[0].length === 0) {
if (selection.length === 0) {
return false;
}
let object = selection[0][0].context.item;
let object = selection[0].context.item;
return object && supportedObjectTypesArray.some(type => object.type === type);
},
view: function (selection) {
let component;
let providedObject = selection[0].context.item;
return {
show: function (element) {
component = new Vue({
provide: {
openmct
openmct,
providedObject
},
components: {
FiltersView: FiltersView.default
@@ -56,12 +59,10 @@ define([
});
},
destroy: function () {
if (component) {
component.$destroy();
component = undefined;
}
}
}
},
priority: function () {
return 1;

View File

@@ -106,6 +106,9 @@
.c-fl {
@include abs();
display: flex;
flex-direction: column; // TEMP: only needed to support temp-toolbar element
> * + * { margin-top: $interiorMargin; }
.temp-toolbar {
flex: 0 0 auto;
@@ -113,8 +116,7 @@
&__container-holder {
display: flex;
flex: 1 1 100%; // Must be 100% to work
overflow: auto;
flex: 1 1 100%; // Must needs to be 100% to work
// Columns by default
flex-direction: row;
@@ -290,6 +292,11 @@
margin-bottom: $interiorMargin;
}
&__object-view {
flex: 1 1 auto;
overflow: auto;
}
&__size-indicator {
$size: 35px;
@@ -415,7 +422,6 @@ import Container from '../utils/container';
import Frame from '../utils/frame';
import ResizeHandle from './resizeHandle.vue';
import DropHint from './dropHint.vue';
import RemoveAction from '../../remove/RemoveAction.js';
const MIN_CONTAINER_SIZE = 5;
@@ -507,7 +513,7 @@ export default {
remove associated domainObjects from composition
*/
container.frames.forEach(f => {
this.removeFromComposition(f.domainObjectIdentifier);
this.composition.remove({identifier: f.domainObjectIdentifier});
});
this.containers.splice(containerIndex, 1);
@@ -522,7 +528,6 @@ export default {
}
sizeToFill(this.containers);
this.setSelectionToParent();
this.persist();
},
moveFrame(toContainerIndex, toFrameIndex, frameId, fromContainerIndex) {
@@ -556,23 +561,20 @@ export default {
deleteFrame(frameId) {
let container = this.containers
.filter(c => c.frames.some(f => f.id === frameId))[0];
let containerIndex = this.containers.indexOf(container);
let frame = container
.frames
.filter((f => f.id === frameId))[0];
let frameIndex = container.frames.indexOf(frame);
this.removeFromComposition(frame.domainObjectIdentifier)
.then(() => {
sizeToFill(container.frames)
this.setSelectionToParent();
});
},
removeFromComposition(identifier) {
return this.openmct.objects.get(identifier).then((childDomainObject) => {
this.RemoveAction.removeFromComposition(this.domainObject, childDomainObject);
});
},
setSelectionToParent() {
this.$el.click();
/*
remove associated domainObject from composition
*/
this.composition.remove({identifier: frame.domainObjectIdentifier});
container.frames.splice(frameIndex, 1);
sizeToFill(container.frames);
this.persist(containerIndex);
},
allowContainerDrop(event, index) {
if (!event.dataTransfer.types.includes('containerid')) {
@@ -663,8 +665,6 @@ export default {
this.composition.on('remove', this.removeChildObject);
this.composition.on('add', this.addFrame);
this.RemoveAction = new RemoveAction(this.openmct);
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
},
beforeDestroy() {

View File

@@ -79,14 +79,12 @@ export default {
},
setSelection() {
this.$nextTick(function () {
if (this.$refs && this.$refs.objectFrame) {
let childContext = this.$refs.objectFrame.getSelectionContext();
childContext.item = this.domainObject;
childContext.type = 'frame';
childContext.frameId = this.frame.id;
this.unsubscribeSelection = this.openmct.selection.selectable(
this.$refs.frame, childContext, false);
}
});
},
initDrag(event) {

View File

@@ -79,12 +79,10 @@ export default {
mounted() {
document.addEventListener('dragstart', this.setDragging);
document.addEventListener('dragend', this.unsetDragging);
document.addEventListener('drop', this.unsetDragging);
},
destroyed() {
document.removeEventListener('dragstart', this.setDragging);
document.removeEventListener('dragend', this.unsetDragging);
document.removeEventListener('drop', this.unsetDragging);
}
}
</script>

View File

@@ -27,22 +27,28 @@ function ToolbarProvider(openmct) {
key: "flex-layout",
description: "A toolbar for objects inside a Flexible Layout.",
forSelection: function (selection) {
let context = selection[0][0].context;
let context = selection[0].context;
return (context && context.type &&
(context.type === 'flexible-layout' || context.type === 'container' || context.type === 'frame'));
},
toolbar: function (selection) {
let selectionPath = selection[0],
primary = selectionPath[0],
secondary = selectionPath[1],
tertiary = selectionPath[2],
let primary = selection[0],
secondary = selection[1],
tertiary = selection[2],
deleteFrame,
toggleContainer,
deleteContainer,
addContainer,
toggleFrame;
toggleFrame,
separator;
separator = {
control: "separator",
domainObject: selection[0].context.item,
key: "separator"
};
toggleContainer = {
control: 'toggle-button',
@@ -63,12 +69,6 @@ function ToolbarProvider(openmct) {
]
};
function getSeparator() {
return {
control: "separator"
};
}
if (primary.context.type === 'frame') {
let frameId = primary.context.frameId;
let layoutObject = tertiary.context.item;
@@ -77,11 +77,11 @@ function ToolbarProvider(openmct) {
.containers;
let container = containers
.filter(c => c.frames.some(f => f.id === frameId))[0];
let containerIndex = containers.indexOf(container);
let frame = container && container
let frame = container
.frames
.filter((f => f.id === frameId))[0];
let frameIndex = container && container.frames.indexOf(frame);
let containerIndex = containers.indexOf(container);
let frameIndex = container.frames.indexOf(frame);
deleteFrame = {
control: "button",
@@ -202,9 +202,9 @@ function ToolbarProvider(openmct) {
let toolbar = [
toggleContainer,
addContainer,
toggleFrame ? getSeparator() : undefined,
toggleFrame ? separator: undefined,
toggleFrame,
deleteFrame || deleteContainer ? getSeparator() : undefined,
deleteFrame || deleteContainer ? separator : undefined,
deleteFrame,
deleteContainer
];

View File

@@ -14,7 +14,6 @@ export default {
},
mounted() {
this.composition = this.openmct.composition.get(this.domainObject);
this.keystring = this.openmct.objects.makeKeyString(this.domainObject.identifier);
if (!this.composition) {
return;
}
@@ -35,7 +34,7 @@ export default {
this.items.push({
model: child,
type: type.definition,
isAlias: this.keystring !== child.location,
isAlias: this.domainObject.identifier.key !== child.location,
objectPath: [child].concat(this.openmct.router.path),
objectKeyString: this.openmct.objects.makeKeyString(child.identifier)
});

View File

@@ -25,26 +25,6 @@ define([
], function (
uuid
) {
return function Migrations(openmct) {
function getColumnNameKeyMap(domainObject) {
let composition = openmct.composition.get(domainObject);
if (composition) {
return composition.load().then(composees => {
return composees.reduce((nameKeyMap, composee) => {
let metadata = openmct.telemetry.getMetadata(composee);
if (metadata !== undefined) {
metadata.values().forEach(value => {
nameKeyMap[value.name] = value.key;
});
}
return nameKeyMap;
}, {});
});
} else {
return Promise.resolve([]);
}
}
function isTelemetry(domainObject) {
if (openmct.telemetry.isTelemetryObject(domainObject)
&& domainObject.type !== 'summary-widget'
@@ -71,6 +51,7 @@ define([
height: panel.dimensions[1],
x: panel.position[0],
y: panel.position[1],
useGrid: true,
identifier: domainObject.identifier,
id: uuid(),
type: 'telemetry-view',
@@ -87,6 +68,7 @@ define([
height: panel.dimensions[1],
x: panel.position[0],
y: panel.position[1],
useGrid: true,
identifier: domainObject.identifier,
id: uuid(),
type: 'subobject-view',
@@ -102,7 +84,7 @@ define([
return migratedObject;
}
function migrateFixedPositionConfiguration(elements, telemetryObjects, gridSize) {
function migrateFixedPositionConfiguration(elements, telemetryObjects) {
const DEFAULT_STROKE = "transparent";
const DEFAULT_SIZE = "13px";
const DEFAULT_COLOR = "";
@@ -115,16 +97,10 @@ define([
y: element.y,
width: element.width,
height: element.height,
useGrid: element.useGrid,
id: uuid()
};
if (!element.useGrid) {
item.x = Math.round(item.x / gridSize[0]);
item.y = Math.round(item.y / gridSize[1]);
item.width = Math.round(item.width / gridSize[0]);
item.height = Math.round(item.height / gridSize[1]);
}
if (element.type === "fixed.telemetry") {
item.type = "telemetry-view";
item.stroke = element.stroke || DEFAULT_STROKE;
@@ -182,7 +158,7 @@ define([
.then(function () {
return migrateDisplayLayout(domainObject, childObjects);
});
}
},
},
{
check(domainObject) {
@@ -196,11 +172,10 @@ define([
name: domainObject.name,
type: "layout"
};
let gridSize = domainObject.layoutGrid || DEFAULT_GRID_SIZE;
let layoutType = openmct.types.get('layout');
layoutType.definition.initialize(newLayoutObject);
newLayoutObject.composition = domainObject.composition;
newLayoutObject.configuration.layoutGrid = gridSize;
newLayoutObject.configuration.layoutGrid = domainObject.layoutGrid || DEFAULT_GRID_SIZE;
let elements = domainObject.configuration['fixed-display'].elements;
let telemetryObjects = {};
@@ -216,34 +191,10 @@ define([
return Promise.all(promises)
.then(function () {
newLayoutObject.configuration.items =
migrateFixedPositionConfiguration(elements, telemetryObjects, gridSize);
migrateFixedPositionConfiguration(elements, telemetryObjects);
return newLayoutObject;
});
}
},
{
check(domainObject) {
return domainObject.type === 'table' &&
domainObject.configuration.table;
},
migrate(domainObject) {
let currentTableConfiguration = domainObject.configuration.table || {};
let currentColumnConfiguration = currentTableConfiguration.columns || {};
return getColumnNameKeyMap(domainObject).then(nameKeyMap => {
let hiddenColumns = Object.keys(currentColumnConfiguration).filter(columnName => {
return currentColumnConfiguration[columnName] === false;
}).reduce((hiddenColumnsMap, hiddenColumnName) => {
let key = nameKeyMap[hiddenColumnName];
hiddenColumnsMap[key] = true;
return hiddenColumnsMap;
}, {});
domainObject.configuration.hiddenColumns = hiddenColumns;
delete domainObject.configuration.table;
return domainObject;
});
}
}
];
}
});

View File

@@ -20,12 +20,9 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import Migrations from './Migrations.js'
import migrations from './Migrations.js'
export default function () {
return function (openmct) {
let migrations = Migrations(openmct);
function needsMigration(domainObject) {
return migrations.some(m => m.check(domainObject));
}
@@ -35,6 +32,7 @@ export default function () {
.migrate(domainObject);
}
return function (openmct) {
let wrappedFunction = openmct.objects.get;
openmct.objects.get = function migrate(identifier) {
return wrappedFunction.apply(openmct.objects, [identifier])
@@ -50,4 +48,4 @@ export default function () {
});
}
};
}
}

View File

@@ -43,16 +43,12 @@
<div class="l-view-section">
<div class="c-loading--overlay loading"
ng-show="!!currentRequest.pending"></div>
<div class="gl-plot child-frame u-inspectable"
<div class="gl-plot child-frame"
ng-repeat="telemetryObject in telemetryObjects"
ng-class="{
's-status-timeconductor-unsynced': telemetryObject
.getCapability('status')
.get('timeconductor-unsynced')
}"
mct-selectable="{
item: telemetryObject.useCapability('adapter'),
oldItem: telemetryObject
}">
<mct-overlay-plot domain-object="telemetryObject"></mct-overlay-plot>
</div>

View File

@@ -70,15 +70,13 @@ define([
this.listenTo(this.$scope, '$destroy', this.destroy, this);
this.listenTo(config.series, 'add', this.addSeries, this);
this.listenTo(config.series, 'remove', this.resetAllSeries, this);
config.series.forEach(this.addSeries, this);
};
PlotOptionsController.prototype.addSeries = function (series, index) {
this.$timeout(function () {
this.$scope.plotSeries[index] = series;
series.locateOldObject(this.$scope.domainObject);
}.bind(this));
};
PlotOptionsController.prototype.resetAllSeries = function (series, index) {

View File

@@ -315,7 +315,6 @@ define([
};
MCTPlotController.prototype.wheelZoom = function (event) {
const ZOOM_AMT = 0.1;
event.preventDefault();
if (!this.positionOverPlot) {
@@ -350,24 +349,24 @@ define([
if (event.wheelDelta < 0) {
this.$scope.xAxis.set('displayRange', {
min: xDisplayRange.min + ((xAxisDist * ZOOM_AMT) * xAxisMinDist),
max: xDisplayRange.max - ((xAxisDist * ZOOM_AMT) * xAxisMaxDist)
min: xDisplayRange.min + ((xAxisDist * 0.01) * xAxisMinDist),
max: xDisplayRange.max - ((xAxisDist * 0.01) * xAxisMaxDist)
});
this.$scope.yAxis.set('displayRange', {
min: yDisplayRange.min + ((yAxisDist * ZOOM_AMT) * yAxisMinDist),
max: yDisplayRange.max - ((yAxisDist * ZOOM_AMT) * yAxisMaxDist)
min: yDisplayRange.min + ((yAxisDist * 0.01) * yAxisMinDist),
max: yDisplayRange.max - ((yAxisDist * 0.01) * yAxisMaxDist)
});
} else if (event.wheelDelta >= 0) {
this.$scope.xAxis.set('displayRange', {
min: xDisplayRange.min - ((xAxisDist * ZOOM_AMT) * xAxisMinDist),
max: xDisplayRange.max + ((xAxisDist * ZOOM_AMT) * xAxisMaxDist)
min: xDisplayRange.min - ((xAxisDist * 0.01) * xAxisMinDist),
max: xDisplayRange.max + ((xAxisDist * 0.01) * xAxisMaxDist)
});
this.$scope.yAxis.set('displayRange', {
min: yDisplayRange.min - ((yAxisDist * ZOOM_AMT) * yAxisMinDist),
max: yDisplayRange.max + ((yAxisDist * ZOOM_AMT) * yAxisMaxDist)
min: yDisplayRange.min - ((yAxisDist * 0.01) * yAxisMinDist),
max: yDisplayRange.max + ((yAxisDist * 0.01) * yAxisMaxDist)
});
}

View File

@@ -219,7 +219,6 @@ define([
PlotController.prototype.stopLoading = function () {
this.$scope.pending -= 1;
this.$scope.$digest();
};
/**

View File

@@ -79,15 +79,6 @@ define([
$scope.$broadcast('plot:tickWidth', _.max(tickWidthMap));
}
}
function compositionReorder(reorderPlan) {
let oldComposition = telemetryObjects.slice();
reorderPlan.forEach((reorder) => {
telemetryObjects[reorder.newIndex] = oldComposition[reorder.oldIndex];
});
}
thisRequest.pending += 1;
openmct.objects.get(domainObject.getId())
.then(function (obj) {
@@ -98,12 +89,10 @@ define([
composition = openmct.composition.get(obj);
composition.on('add', addChild);
composition.on('remove', removeChild);
composition.on('reorder', compositionReorder);
composition.load();
unlisten = function () {
composition.off('add', addChild);
composition.off('remove', removeChild);
composition.off('reorder', compositionReorder);
};
});
}

View File

@@ -85,17 +85,16 @@ export default class RemoveAction {
);
this.openmct.objects.mutate(parent, 'composition', composition);
if (this.inNavigationPath(child) && this.openmct.editor.isEditing()) {
this.openmct.editor.save();
}
}
appliesTo(objectPath) {
let object = objectPath[0];
let objectType = object && this.openmct.types.get(object.type);
let parent = objectPath[1];
let parentType = parent && this.openmct.types.get(parent.type);
return parentType &&
return objectType.definition.creatable &&
parentType &&
parentType.definition.creatable &&
Array.isArray(parent.composition);
}

View File

@@ -4,7 +4,7 @@
<span class="t-configuration"> </span>
<span class="t-value-inputs"> </span>
</span>
<span class="flex-elem c-local-controls--show-on-hover l-condition-action-buttons-wrapper">
<span class="flex-elem local-control local-controls-hidden l-condition-action-buttons-wrapper">
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
<a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
</span>

View File

@@ -1,5 +1,5 @@
<div class="c-sw-rule">
<div class="c-sw-rule__ui l-compact-form l-widget-rule s-widget-rule has-local-controls">
<div class="c-sw-rule__ui l-compact-form has-local-controls l-widget-rule s-widget-rule">
<div class="c-sw-rule__ui__header widget-rule-header">
<div class="c-sw-rule__grippy-wrapper">
<div class="c-sw-rule__grippy t-grippy local-control local-controls-hidden"></div>
@@ -11,7 +11,7 @@
</div>
<div class="flex-elem rule-title">Default Title</div>
<div class="flex-elem rule-description grows">Rule description goes here</div>
<div class="flex-elem c-local-controls--show-on-hover l-rule-action-buttons-wrapper">
<div class="flex-elem local-control local-controls-hidden l-rule-action-buttons-wrapper">
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
<a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
</div>

View File

@@ -7,7 +7,7 @@
<span class="equal-to hidden"> equal to </span>
<span class="t-value-inputs"></span>
</span>
<span class="flex-elem c-local-controls--show-on-hover l-widget-test-data-item-action-buttons-wrapper">
<span class="flex-elem local-control local-controls-hidden l-widget-test-data-item-action-buttons-wrapper">
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this test value"></a>
<a class="s-icon-button icon-trash t-delete" title="Delete this test value"></a>
</span>

View File

@@ -3,11 +3,13 @@
<div id="widgetIcon" class="c-sw__icon js-sw__icon"></div>
<div id="widgetLabel" class="label widget-label c-sw__label js-sw__label">Default Static Name</div>
</a>
<div class="js-summary-widget__message c-summary-widget__message c-message c-message--simple message-severity-alert">
<div class="c-summary-widget__text">
<div class="c-summary-widget__message holder flex-elem t-message-inline c-message message-severity-alert t-message-widget-no-data">
<div class="w-message-contents l-message-body-only">
<div class="message-body">
You must add at least one telemetry object to edit this widget.
</div>
</div>
</div>
<div class="c-sw-edit__ui holder l-flex-accordion flex-elem grows widget-edit-holder expanded-widget-test-data expanded-widget-rules">
<div class="c-sw-edit__ui__header">
<span class="c-disclosure-triangle c-disclosure-triangle--expanded is-enabled t-view-control-test-data"></span>

View File

@@ -237,7 +237,6 @@ define ([
});
delete this.compositionObjs[objectId];
this.subscriptions[objectId](); //unsubscribe from telemetry source
delete this.subscriptions[objectId];
this.eventEmitter.emit('remove', identifier);
if (_.isEmpty(this.compositionObjs)) {

View File

@@ -43,7 +43,7 @@ define([
return evaluator.requestLatest(options)
.then(function (latestDatum) {
this.pool.release(evaluator);
return latestDatum ? [latestDatum] : [];
return [latestDatum];
}.bind(this));
};

View File

@@ -52,10 +52,7 @@ define([
strategy: 'latest',
size: 1
}).then(function (results) {
if (this.destroyed ||
this.hasUpdated ||
this.renderTracker !== renderTracker ||
results.length === 0) {
if (this.destroyed || this.hasUpdated || this.renderTracker !== renderTracker) {
return;
}
this.updateState(results[results.length - 1]);

View File

@@ -1,18 +1,17 @@
<template>
<div class="c-tabs-view">
<div class="c-tabs-view__tabs-holder c-tabs"
<div class="c-tabs-view__tabs-holder c-compact-button-holder"
:class="{
'is-dragging': isDragging,
'is-mouse-over': allowDrop
}">
<div class="c-drop-hint"
@drop="onDrop"
@dragenter="dragenter"
@dragleave="dragleave">
ref="dropHint">
</div>
<div class="c-tabs-view__empty-message"
v-if="!tabsList.length > 0">Drag objects here to add them to this view.</div>
<button class="c-tabs-view__tab c-tab"
<button class="c-tabs-view__tab c-compact-button"
v-for="(tab,index) in tabsList"
:key="index"
:class="[
@@ -26,9 +25,8 @@
<div class="c-tabs-view__object-holder"
v-for="(tab, index) in tabsList"
:key="index"
:class="{'c-tabs-view__object-holder--hidden': !isCurrent(tab)}">
<div v-if="currentTab"
class="c-tabs-view__object-name l-browse-bar__object-name--w"
:class="{'invisible': !isCurrent(tab)}">
<div class="c-tabs-view__object-name l-browse-bar__object-name--w"
:class="currentTab.type.definition.cssClass">
<div class="l-browse-bar__object-name">
{{currentTab.domainObject.name}}
@@ -55,28 +53,15 @@
}
&__tabs-holder {
@include userSelectNone();
flex: 0 0 auto;
min-height: $h;
}
&__tab {
&:before {
margin-right: $interiorMarginSm;
opacity: 0.7;
}
}
&__object-holder {
flex: 1 1 auto;
display: flex;
flex-direction: column;
&--hidden {
height: 1000px;
width: 1000px;
position: absolute;
left: -9999px;
top: -9999px;
}
}
&__object-name {
@@ -87,14 +72,10 @@
}
&__object {
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
height: 0; // Chrome 73 oveflow bug fix
}
&__empty-message {
background: rgba($colorBodyFg, 0.1);
color: rgba($colorBodyFg, 0.7);
font-style: italic;
text-align: center;
@@ -159,13 +140,6 @@ export default {
this.showTab(this.tabsList[this.tabsList.length - 1]);
}
},
onReorder(reorderPlan) {
let oldTabs = this.tabsList.slice();
reorderPlan.forEach(reorderEvent => {
this.$set(this.tabsList, reorderEvent.newIndex, oldTabs[reorderEvent.oldIndex]);
});
},
onDrop(e) {
this.setCurrentTab = true;
},
@@ -192,20 +166,31 @@ export default {
if (this.composition) {
this.composition.on('add', this.addItem);
this.composition.on('remove', this.removeItem);
this.composition.on('reorder', this.onReorder);
this.composition.load();
}
document.addEventListener('dragstart', this.dragstart);
document.addEventListener('dragend', this.dragend);
let dropHint = this.$refs.dropHint;
if (dropHint) {
dropHint.addEventListener('dragenter', this.dragenter);
dropHint.addEventListener('dragleave', this.dragleave);
}
},
destroyed() {
this.composition.off('add', this.addItem);
this.composition.off('remove', this.removeItem);
this.composition.off('reorder', this.onReorder);
document.removeEventListener('dragstart', this.dragstart);
document.removeEventListener('dragend', this.dragend);
},
beforeDestroy() {
let dropHint = this.$refs.dropHint;
dropHint.removeEventListener('dragenter', this.dragenter);
dropHint.removeEventListener('dragleave', this.dragleave);
}
}
</script>

View File

@@ -31,7 +31,6 @@ define([
openmct.types.addType('tabs', {
name: "Tabs View",
description: 'Add multiple objects of any type to this view, and quickly navigate between them with tabs',
creatable: true,
cssClass: 'icon-tabs-view',
initialize(domainObject) {

View File

@@ -37,15 +37,15 @@ define([
key: 'table-configuration',
name: 'Telemetry Table Configuration',
canView: function (selection) {
if (selection.length === 0 || selection[0].length === 0) {
if (selection.length === 0) {
return false;
}
let object = selection[0][0].context.item;
let object = selection[0].context.item;
return object && object.type === 'table';
},
view: function (selection) {
let component;
let domainObject = selection[0][0].context.item;
let domainObject = selection[0].context.item;
let tableConfiguration = new TelemetryTableConfiguration(domainObject, openmct);
return {
show: function (element) {
@@ -62,11 +62,8 @@ define([
});
},
destroy: function () {
if (component) {
component.$destroy();
component = undefined;
}
tableConfiguration = undefined;
}
}

View File

@@ -137,17 +137,12 @@ define([
let requestOptions = this.buildOptionsFromConfiguration(telemetryObject);
return this.openmct.telemetry.request(telemetryObject, requestOptions)
.then(telemetryData => {
//Check that telemetry object has not been removed since telemetry was requested.
if (!this.telemetryObjects.includes(telemetryObject)) {
return;
}
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
let columnMap = this.getColumnMapForObject(keyString);
let limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
let telemetryRows = telemetryData.map(datum => new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
this.boundedRows.add(telemetryRows);
}).finally(() => {
this.decrementOutstandingRequests();
});
}
@@ -198,10 +193,6 @@ define([
let limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
this.subscriptions[keyString] = this.openmct.telemetry.subscribe(telemetryObject, (datum) => {
//Check that telemetry object has not been removed since telemetry was requested.
if (!this.telemetryObjects.includes(telemetryObject)) {
return;
}
this.boundedRows.add(new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
}, subscribeOptions);
}

View File

@@ -32,20 +32,12 @@ define([
Vue
) {
function TelemetryTableViewProvider(openmct) {
function hasTelemetry(domainObject) {
if (!domainObject.hasOwnProperty('telemetry')) {
return false;
}
let metadata = openmct.telemetry.getMetadata(domainObject);
return metadata.values().length > 0;
}
return {
key: 'table',
name: 'Telemetry Table',
cssClass: 'icon-tabular-realtime',
canView(domainObject) {
return domainObject.type === 'table' ||
hasTelemetry(domainObject)
return domainObject.type === 'table' || domainObject.hasOwnProperty('telemetry');
},
canEdit(domainObject) {
return domainObject.type === 'table';

View File

@@ -34,13 +34,39 @@
isSortable ? 'is-sortable' : '',
isSortable && sortOptions.key === headerKey ? 'is-sorting' : '',
isSortable && sortOptions.direction].join(' ')">
<div class="c-telemetry-table__resize-hitarea"
<div v-if="isEditing" class="c-telemetry-table__resize-hotzone c-telemetry-table__resize-hotzone--right"
@mousedown="resizeColumnStart"
></div>
<slot></slot>
</div>
</th>
</template>
<style lang="scss">
@import "~styles/sass-base";
@import "~styles/table";
$hotzone-size: 6px;
.c-telemetry-table__headers__content {
width: 100%;
}
.c-table.c-telemetry-table {
.c-telemetry-table__resize-hotzone {
display: block;
position: absolute;
height: 100%;
padding: 0;
margin: 0;
width: $hotzone-size;
min-width: $hotzone-size;
cursor: col-resize;
border: none;
right: 0px;
margin-right: -$tabularTdPadLR - 1 - $hotzone-size / 2;
}
}
</style>
<script>
import _ from 'lodash';
const MOVE_COLUMN_DT_TYPE = 'movecolumnfromindex';

View File

@@ -34,7 +34,7 @@
<div class="c-telemetry-table__headers-w js-table__headers-w" ref="headersTable" :style="{ 'max-width': widthWithScroll}">
<table class="c-table__headers c-telemetry-table__headers">
<thead>
<tr class="c-telemetry-table__headers__labels">
<tr class="c-telemetry-table__headers__name">
<table-column-header
v-for="(title, key, headerIndex) in headers"
:key="key"
@@ -49,8 +49,7 @@
:columnWidth="columnWidths[key]"
:sortOptions="sortOptions"
:isEditing="isEditing"
><span class="c-telemetry-table__headers__label">{{title}}</span>
</table-column-header>
>{{title}}</table-column-header>
</tr>
<tr class="c-telemetry-table__headers__filter">
<table-column-header
@@ -160,32 +159,6 @@
thead {
display: block;
}
&__labels {
// Top row, has labels
.c-telemetry-table__headers__content {
// Holds __label, sort indicator and resize-hitarea
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
}
}
&__headers__label {
overflow: hidden;
flex: 0 1 auto;
}
&__resize-hitarea {
// In table-column-header.vue
@include abs();
display: none; // Set to display: block in .is-editing section below
left: auto; right: -1 * $tabularTdPadLR;
width: $tableResizeColHitareaD;
cursor: col-resize;
transform: translateX(50%); // Move so this element sits over border between columns
}
/******************************* ELEMENTS */
@@ -200,7 +173,6 @@
&__body-w {
// Wraps __body table provides scrolling
flex: 1 1 100%;
height: 0; // Fixes Chrome 73 overflow bug
overflow-x: auto;
overflow-y: scroll;
}
@@ -248,7 +220,7 @@
/******************************* EDITING */
.is-editing {
.c-telemetry-table__headers__labels {
.c-telemetry-table__headers__name {
th[draggable],
th[draggable] > * {
cursor: move;
@@ -260,10 +232,6 @@
> * { background: $b; }
}
}
.c-telemetry-table__resize-hitarea {
display: block;
}
}
/******************************* LEGACY */
@@ -588,18 +556,13 @@ export default {
let el = this.$el;
let width = el.clientWidth;
let height = el.clientHeight;
let scrollTop = this.scrollable.scrollTop;
this.resizePollHandle = setInterval(() => {
if ((el.clientWidth !== width || el.clientHeight !== height) && this.isAutosizeEnabled) {
this.calculateTableSize();
// On some resize events scrollTop is reset to 0. Possibly due to a transition we're using?
// Need to preserve scroll position in this case.
this.scrollable.scrollTop = scrollTop;
width = el.clientWidth;
height = el.clientHeight;
}
scrollTop = this.scrollable.scrollTop;
}, RESIZE_POLL_INTERVAL);
},

View File

@@ -23,7 +23,6 @@
<div class="c-conductor"
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']">
<form class="u-contents" ref="conductorForm" @submit.prevent="updateTimeFromConductor">
<div class="c-conductor__time-bounds">
<button class="c-input--submit" type="submit" ref="submitButton"></button>
<ConductorModeIcon class="c-conductor__mode-icon"></ConductorModeIcon>
@@ -91,8 +90,6 @@
class="c-conductor__ticks"
:bounds="rawBounds"
@panAxis="setViewFromBounds"></conductor-axis>
</div>
<div class="c-conductor__controls">
<!-- Mode, time system menu buttons and duration slider -->
<ConductorMode class="c-conductor__mode-select"></ConductorMode>
@@ -116,17 +113,17 @@
/*********************************************** CONDUCTOR LAYOUT */
.c-conductor {
&__time-bounds {
display: grid;
grid-column-gap: $interiorMargin;
grid-row-gap: $interiorMargin;
align-items: center;
// Default: fixed mode, desktop
grid-template-rows: 1fr;
grid-template-rows: 1fr 1fr;
grid-template-columns: 20px auto 1fr auto;
grid-template-areas: "tc-mode-icon tc-start tc-ticks tc-end";
}
grid-template-areas:
"tc-mode-icon tc-start tc-ticks tc-end"
"tc-controls tc-controls tc-controls tc-controls";
&__mode-icon {
grid-area: tc-mode-icon;
@@ -166,10 +163,10 @@
}
&.is-realtime-mode {
.c-conductor__time-bounds {
grid-template-columns: 20px auto 1fr auto auto;
grid-template-areas: "tc-mode-icon tc-start tc-ticks tc-updated tc-end";
}
grid-template-areas:
"tc-mode-icon tc-start tc-ticks tc-updated tc-end"
"tc-controls tc-controls tc-controls tc-controls tc-controls";
.c-conductor__end-fixed {
grid-area: tc-updated;
@@ -177,15 +174,9 @@
}
body.phone.portrait & {
.c-conductor__time-bounds {
grid-row-gap: $interiorMargin;
grid-template-rows: auto auto;
grid-template-rows: auto auto auto;
grid-template-columns: 20px auto auto;
}
.c-conductor__controls {
padding-left: 25px; // Line up visually with other controls
}
&__mode-icon {
grid-row: 1;
@@ -209,19 +200,17 @@
justify-content: flex-start;
}
.c-conductor__time-bounds {
grid-template-areas:
"tc-mode-icon tc-start tc-start"
"tc-mode-icon tc-end tc-end"
}
"tc-mode-icon tc-controls tc-controls";
}
&.is-realtime-mode {
.c-conductor__time-bounds {
grid-template-areas:
"tc-mode-icon tc-start tc-updated"
"tc-mode-icon tc-end tc-end";
}
"tc-mode-icon tc-end tc-end"
"tc-mode-icon tc-controls tc-controls";
.c-conductor__end-fixed {
justify-content: flex-end;

View File

@@ -20,15 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[
'EventEmitter',
'lodash'
],
function (
EventEmitter,
_
) {
define(['EventEmitter'], function (EventEmitter) {
/**
* Manages selection state for Open MCT
@@ -55,87 +47,21 @@ define(
* Selects the selectable object and emits the 'change' event.
*
* @param {object} selectable an object with element and context properties
* @param {Boolean} isMultiSelectEvent flag indication shift key is pressed or not
* @private
*/
Selection.prototype.select = function (selectable, isMultiSelectEvent) {
Selection.prototype.select = function (selectable) {
if (!Array.isArray(selectable)) {
selectable = [selectable];
}
let multiSelect = isMultiSelectEvent &&
this.parentSupportsMultiSelect(selectable) &&
this.isPeer(selectable) &&
!this.selectionContainsParent(selectable);
if (multiSelect) {
this.handleMultiSelect(selectable);
} else {
this.setSelectionStyles(selectable);
this.selected = [selectable];
if (this.selected[0] && this.selected[0].element) {
this.selected[0].element.removeAttribute('s-selected');
}
this.emit('change', this.selected);
};
/**
* @private
*/
Selection.prototype.handleMultiSelect = function (selectable) {
if (this.elementSelected(selectable)) {
this.remove(selectable);
} else {
this.addSelectionAttributes(selectable);
this.selected.push(selectable);
}
};
/**
* @private
*/
Selection.prototype.elementSelected = function (selectable) {
return this.selected.some(selectionPath => _.isEqual(selectionPath, selectable));
};
/**
* @private
*/
Selection.prototype.remove = function (selectable) {
this.selected = this.selected.filter(selectionPath => !_.isEqual(selectionPath, selectable));
if (this.selected.length === 0) {
this.removeSelectionAttributes(selectable);
selectable[1].element.click(); // Select the parent if there is no selection.
} else {
this.removeSelectionAttributes(selectable, true);
}
};
/**
* @private
*/
Selection.prototype.setSelectionStyles = function (selectable) {
this.selected.map(selectionPath => {
this.removeSelectionAttributes(selectionPath);
});
this.addSelectionAttributes(selectable);
};
Selection.prototype.removeSelectionAttributes = function (selectionPath, keepParentStyle) {
if (selectionPath[0] && selectionPath[0].element) {
selectionPath[0].element.removeAttribute('s-selected');
if (this.selected[1] && this.selected[1].element) {
this.selected[1].element.removeAttribute('s-selected-parent');
}
if (selectionPath[1] && selectionPath[1].element && !keepParentStyle) {
selectionPath[1].element.removeAttribute('s-selected-parent');
}
};
/*
* Adds selection attributes to the selected element and its parent.
* @private
*/
Selection.prototype.addSelectionAttributes = function (selectable) {
if (selectable[0] && selectable[0].element) {
selectable[0].element.setAttribute('s-selected', "");
}
@@ -143,36 +69,16 @@ define(
if (selectable[1] && selectable[1].element) {
selectable[1].element.setAttribute('s-selected-parent', "");
}
};
/**
* @private
*/
Selection.prototype.parentSupportsMultiSelect = function (selectable) {
return selectable[1] && selectable[1].context.supportsMultiSelect;
};
/**
* @private
*/
Selection.prototype.selectionContainsParent = function (selectable) {
return this.selected.some(selectionPath => _.isEqual(selectionPath[0], selectable[1]));
};
/**
* @private
*/
Selection.prototype.isPeer = function (selectable) {
return this.selected.some(selectionPath => _.isEqual(selectionPath[1], selectable[1]));
this.selected = selectable;
this.emit('change', this.selected);
};
/**
* @private
*/
Selection.prototype.capture = function (selectable) {
let capturingContainsSelectable = this.capturing && this.capturing.includes(selectable);
if (!this.capturing || capturingContainsSelectable) {
if (!this.capturing) {
this.capturing = [];
}
@@ -182,14 +88,13 @@ define(
/**
* @private
*/
Selection.prototype.selectCapture = function (selectable, event) {
Selection.prototype.selectCapture = function (selectable) {
if (!this.capturing) {
return;
}
let reversedCapturing = this.capturing.reverse();
this.select(this.capturing.reverse());
delete this.capturing;
this.select(reversedCapturing, event.shiftKey);
};
/**
@@ -207,7 +112,7 @@ define(
* @public
*/
Selection.prototype.selectable = function (element, context, select) {
let selectable = {
var selectable = {
context: context,
element: element
};

View File

@@ -79,13 +79,10 @@ $colorKeyHov: #26d8ff;
$colorKeyFilter: invert(36%) sepia(76%) saturate(2514%) hue-rotate(170deg) brightness(99%) contrast(101%);
$colorKeyFilterHov: invert(63%) sepia(88%) saturate(3029%) hue-rotate(154deg) brightness(101%) contrast(100%);
$colorKeySelectedBg: $colorKey;
$uiColor: #0093ff; // Resize bars, splitter bars, etc.
$uiColor: #00b2ff; // Resize bars, splitter bars, etc.
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
$colorA: #ccc;
$colorAHov: #fff;
$filterHov: brightness(1.3); // Tree, location items
$colorSelectedBg: pushBack($colorKey, 10%);
$colorSelectedFg: pullForward($colorBodyFg, 20%);
// Layout
$shellMainPad: 4px 0;
@@ -101,20 +98,6 @@ $colorStatusAlertFilter: invert(78%) sepia(26%) saturate(1160%) hue-rotate(324de
$colorStatusError: #da0004;
$colorStatusErrorFilter: invert(10%) sepia(96%) saturate(4360%) hue-rotate(351deg) brightness(111%) contrast(115%);
$colorStatusBtnBg: #666; // Where is this used?
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// States
$colorPausedBg: #ff9900;
@@ -143,8 +126,6 @@ $browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
/************************************************** EDITING */
$editUIColor: $uiColor; // Base color
$editUIColorBg: $editUIColor;
$editUIColorFg: #fff;
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
$editUIBaseColor: #344b8d; // Base color, toolbar bg
$editUIBaseColorHov: pullForward($editUIBaseColor, 20%);
@@ -161,8 +142,8 @@ $editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
$editFrameColorSelected: #ccc; // Border of selected frames
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
$editFrameSelectedShdw: rgba(black, 0.4) 0 1px 5px 1px;
$editFrameSelectedBorder: 1px solid $editFrameColorHov; // Selected frame element
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
$editFrameHovMovebarColorBg: pullForward($editFrameMovebarColorBg, 10%); // Hover style
@@ -170,7 +151,6 @@ $editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
$editFrameMovebarH: 10px; // Height of move bar in layout frame
$editMarqueeBorder: 1px dashed $editFrameColorSelected;
// Icons
$colorIconAlias: #4af6f3;
@@ -193,10 +173,6 @@ $colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
$colorBtnCautionBg: #f16f6f;
$colorBtnCautionBgHov: #f1504e;
$colorBtnCautionFg: $colorBtnFg;
$colorBtnActiveBg: $colorOk;
$colorBtnActiveFg: $colorOkFg;
$colorBtnSelectedBg: $colorSelectedBg;
$colorBtnSelectedFg: $colorSelectedFg;
$colorClickIconButton: $colorKey;
$colorClickIconButtonBgHov: rgba($colorKey, 0.6);
$colorClickIconButtonFgHov: $colorKeyHov;
@@ -227,8 +203,6 @@ $menuItemPad: $interiorMargin, floor($interiorMargin * 1.25);
$paletteItemBorderOuterColorSelected: black;
$paletteItemBorderInnerColorSelected: white;
$paletteItemBorderInnerColor: rgba($paletteItemBorderOuterColorSelected, 0.3);
$mixedSettingBg: (transparent rgba($editUIBaseColorHov, 0.7)); // Used in .c-click-icon--mixed
$mixedSettingBgSize: 5px;
// Forms
$colorCheck: $colorKey;
@@ -291,9 +265,26 @@ $colorLimitRedBg: #940000;
$colorLimitRedFg: #ffa489;
$colorLimitRedIc: #ff4222;
// Status
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// Bubble colors
$colorInfoBubbleBg: #dddddd;
$colorInfoBubbleFg: #666;
$colorInfoBubbleFg: #666;
$colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
@@ -315,9 +306,6 @@ $colorTabHeaderFg: $colorBodyFg;
$colorTabHeaderBorder: $colorBodyBg;
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
$colorTabGroupHeaderFg: pushBack($colorTabHeaderFg, 10%);
$colorSummaryBg: #2c2c2c;
$colorSummaryFg: rgba($colorBodyFg, 0.7);
$colorSummaryFgEm: $colorBodyFg;
// Plot
$colorPlotBg: rgba(black, 0.05);
@@ -336,7 +324,7 @@ $colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
$colorItemTreeIcon: $colorKey; // Used
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
$colorItemTreeFg: $colorBodyFg;
$colorItemTreeSelectedBg: $colorSelectedBg;
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
$colorItemTreeSelectedFg: $colorItemTreeHoverFg;
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
@@ -390,10 +378,8 @@ $colorLoadingFg: #776ba2;
$colorLoadingBg: rgba($colorLoadingFg, 0.1);
// Transitions
$transInTime: 50ms;
$transOutTime: 250ms;
$transIn: all $transInTime ease-in-out;
$transOut: all $transOutTime ease-in-out;
$transIn: all 50ms ease-in-out;
$transOut: all 250ms ease-in-out;
$transInBounce: all 200ms cubic-bezier(.47,.01,.25,1.5);
$transInBounceBig: all 300ms cubic-bezier(.2,1.6,.6,3);

View File

@@ -87,9 +87,6 @@ $uiColor: #00b2ff; // Resize bars, splitter bars, etc.
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
$colorA: #ccc;
$colorAHov: #fff;
$filterHov: brightness(1.3); // Tree, location items
$colorSelectedBg: pushBack($colorKey, 10%);
$colorSelectedFg: pullForward($colorBodyFg, 20%);
// Layout
$shellMainPad: 4px 0;
@@ -105,20 +102,6 @@ $colorStatusAlertFilter: invert(78%) sepia(26%) saturate(1160%) hue-rotate(324de
$colorStatusError: #da0004;
$colorStatusErrorFilter: invert(10%) sepia(96%) saturate(4360%) hue-rotate(351deg) brightness(111%) contrast(115%);
$colorStatusBtnBg: #666; // Where is this used?
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// States
$colorPausedBg: #ff9900;
@@ -147,8 +130,6 @@ $browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
/************************************************** EDITING */
$editUIColor: $uiColor; // Base color
$editUIColorBg: $editUIColor;
$editUIColorFg: #fff;
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
$editUIBaseColor: #344b8d; // Base color, toolbar bg
$editUIBaseColorHov: pullForward($editUIBaseColor, 20%);
@@ -165,8 +146,8 @@ $editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
$editFrameColorSelected: #ccc; // Border of selected frames
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
$editFrameSelectedShdw: rgba(black, 0.4) 0 1px 5px 1px;
$editFrameSelectedBorder: 1px solid $editFrameColorHov; // Selected frame element
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
$editFrameHovMovebarColorBg: pullForward($editFrameMovebarColorBg, 10%); // Hover style
@@ -174,7 +155,6 @@ $editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
$editFrameMovebarH: 10px; // Height of move bar in layout frame
$editMarqueeBorder: 1px dashed $editFrameColorSelected;
// Icons
$colorIconAlias: #4af6f3;
@@ -197,10 +177,6 @@ $colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
$colorBtnCautionBg: #f16f6f;
$colorBtnCautionBgHov: #f1504e;
$colorBtnCautionFg: $colorBtnFg;
$colorBtnActiveBg: $colorOk;
$colorBtnActiveFg: $colorOkFg;
$colorBtnSelectedBg: $colorSelectedBg;
$colorBtnSelectedFg: $colorSelectedFg;
$colorClickIconButton: $colorKey;
$colorClickIconButtonBgHov: rgba($colorKey, 0.6);
$colorClickIconButtonFgHov: $colorKeyHov;
@@ -231,8 +207,6 @@ $menuItemPad: $interiorMargin, floor($interiorMargin * 1.25);
$paletteItemBorderOuterColorSelected: black;
$paletteItemBorderInnerColorSelected: white;
$paletteItemBorderInnerColor: rgba($paletteItemBorderOuterColorSelected, 0.3);
$mixedSettingBg: (transparent rgba($editUIBaseColorHov, 0.7)); // Used in .c-click-icon--mixed
$mixedSettingBgSize: 5px;
// Forms
$colorCheck: $colorKey;
@@ -295,9 +269,26 @@ $colorLimitRedBg: #940000;
$colorLimitRedFg: #ffa489;
$colorLimitRedIc: #ff4222;
// Status
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// Bubble colors
$colorInfoBubbleBg: #dddddd;
$colorInfoBubbleFg: #666;
$colorInfoBubbleFg: #666;
$colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
@@ -319,9 +310,6 @@ $colorTabHeaderFg: $colorBodyFg;
$colorTabHeaderBorder: $colorBodyBg;
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
$colorTabGroupHeaderFg: pushBack($colorTabHeaderFg, 10%);
$colorSummaryBg: #2c2c2c;
$colorSummaryFg: rgba($colorBodyFg, 0.7);
$colorSummaryFgEm: $colorBodyFg;
// Plot
$colorPlotBg: rgba(black, 0.05);
@@ -340,7 +328,7 @@ $colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
$colorItemTreeIcon: $colorKey; // Used
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
$colorItemTreeFg: $colorBodyFg;
$colorItemTreeSelectedBg: $colorSelectedBg;
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
$colorItemTreeSelectedFg: $colorItemTreeHoverFg;
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
@@ -387,17 +375,15 @@ $colorMobilePaneLeftTreeItemFg: $colorItemTreeFg;
$colorMobileSelectListTreeItemBg: rgba(#000, 0.05);
// About Screen
$colorAboutLink: #9bb5ff;
$colorAboutLink: $colorKeySubtle;
// Loading
$colorLoadingFg: #776ba2;
$colorLoadingBg: rgba($colorLoadingFg, 0.1);
// Transitions
$transInTime: 50ms;
$transOutTime: 250ms;
$transIn: all $transInTime ease-in-out;
$transOut: all $transOutTime ease-in-out;
$transIn: all 50ms ease-in-out;
$transOut: all 250ms ease-in-out;
$transInBounce: all 200ms cubic-bezier(.47,.01,.25,1.5);
$transInBounceBig: all 300ms cubic-bezier(.2,1.6,.6,3);

View File

@@ -83,9 +83,6 @@ $uiColor: #289fec; // Resize bars, splitter bars, etc.
$colorInteriorBorder: rgba($colorBodyFg, 0.2);
$colorA: #999;
$colorAHov: $colorKey;
$filterHov: brightness(1.3); // Tree, location items
$colorSelectedBg: pushBack($colorKey, 40%);
$colorSelectedFg: pullForward($colorBodyFg, 10%);
// Layout
$shellMainPad: 4px 0;
@@ -101,20 +98,6 @@ $colorStatusAlertFilter: invert(89%) sepia(26%) saturate(5035%) hue-rotate(316de
$colorStatusError: #da0004;
$colorStatusErrorFilter: invert(8%) sepia(96%) saturate(4511%) hue-rotate(352deg) brightness(136%) contrast(114%);
$colorStatusBtnBg: #666; // Where is this used?
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// States
$colorPausedBg: #ff9900;
@@ -143,8 +126,6 @@ $browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
/************************************************** EDITING */
$editUIColor: $uiColor; // Base color
$editUIColorBg: $editUIColor;
$editUIColorFg: #fff;
$editUIColorHov: pullForward(saturate($uiColor, 10%), 20%); // Hover color when $editUIColor is applied as a base color
$editUIBaseColor: #cae1ff; // Base color, toolbar bg
$editUIBaseColorHov: pushBack($editUIBaseColor, 20%);
@@ -161,7 +142,7 @@ $editFrameBorderHov: 1px solid $editFrameColorHov; // Hover on selectable frames
$editFrameColorSelected: #333; // Border of selected frames
$editFrameColorHandleBg: $colorBodyBg; // Resize handle 'offset' color to make handle standout
$editFrameColorHandleFg: $editFrameColorSelected; // Resize handle main color
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 5px 2px;
$editFrameSelectedShdw: rgba(black, 0.5) 0 1px 10px 1px;
$editFrameSelectedBorder: 1px dashed $editFrameColorSelected; // Selected frame element
$editFrameMovebarColorBg: $editFrameColor; // Movebar bg color
$editFrameMovebarColorFg: pullForward($editFrameMovebarColorBg, 20%); // Grippy lines, container size text
@@ -170,7 +151,6 @@ $editFrameHovMovebarColorFg: pullForward($editFrameMovebarColorFg, 10%);
$editFrameSelectedMovebarColorBg: pullForward($editFrameMovebarColorBg, 15%); // Selected style
$editFrameSelectedMovebarColorFg: pullForward($editFrameMovebarColorFg, 15%);
$editFrameMovebarH: 10px; // Height of move bar in layout frame
$editMarqueeBorder: 1px dashed $editFrameColorSelected;
// Icons
$colorIconAlias: #4af6f3;
@@ -193,10 +173,6 @@ $colorBtnMajorFgHov: pushBack($colorBtnMajorFg, 10%);
$colorBtnCautionBg: #f16f6f;
$colorBtnCautionBgHov: #f1504e;
$colorBtnCautionFg: $colorBtnFg;
$colorBtnActiveBg: $colorOk;
$colorBtnActiveFg: $colorOkFg;
$colorBtnSelectedBg: $colorBtnMajorBg;
$colorBtnSelectedFg: $colorBtnMajorFg;
$colorClickIconButton: $colorKey;
$colorClickIconButtonBgHov: rgba($colorKey, 0.2);
$colorClickIconButtonFgHov: $colorKeyHov;
@@ -209,7 +185,7 @@ $colorDisclosureCtrlHov: rgba($colorBodyFg, 0.7);
$btnStdH: 24px;
$colorCursorGuide: rgba(black, 0.6);
$shdwCursorGuide: rgba(white, 0.4) 0 0 2px;
$colorLocalControlOvrBg: rgba($colorBodyFg, 0.8);
$colorLocalControlOvrBg: rgba($colorBodyBg, 0.8);
// Menus
$colorMenuBg: pushBack($colorBodyBg, 10%);
@@ -227,8 +203,6 @@ $menuItemPad: $interiorMargin, floor($interiorMargin * 1.25);
$paletteItemBorderOuterColorSelected: black;
$paletteItemBorderInnerColorSelected: white;
$paletteItemBorderInnerColor: rgba($paletteItemBorderOuterColorSelected, 0.3);
$mixedSettingBg: (transparent rgba($editUIBaseColorHov, 0.9)); // Used in .c-click-icon--mixed
$mixedSettingBgSize: 10px;
// Forms
$colorCheck: $colorKey;
@@ -247,8 +221,8 @@ $colorInputPlaceholder: pushBack($colorBodyFg, 20%);
$colorFormText: pushBack($colorBodyFg, 10%);
$colorInputIcon: pushBack($colorBodyFg, 25%);
$colorFieldHint: pullForward($colorBodyFg, 40%);
$shdwInput: inset rgba(black, 0.5) 0 0 2px;
$shdwInputHov: inset rgba(black, 0.8) 0 0 2px;
$shdwInput: inset rgba(black, 0.7) 0 0 1px;
$shdwInputHov: inset rgba(black, 0.7) 0 0 2px;
$shdwInputFoc: inset rgba(black, 0.8) 0 0.25px 3px;
$formTBPad: $interiorMargin;
$formLRPad: $interiorMargin;
@@ -291,6 +265,22 @@ $colorLimitRedBg: #ff0000;
$colorLimitRedFg: #fff;
$colorLimitRedIc: #ffa99a;
// Status
$colorAlert: #ff3c00;
$colorAlertFg: #fff;
$colorWarningHi: #990000;
$colorWarningHiFg: #FF9594;
$colorWarningLo: #ff9900;
$colorWarningLoFg: #523400;
$colorDiagnostic: #a4b442;
$colorDiagnosticFg: #39461A;
$colorCommand: #3693bd;
$colorCommandFg: #fff;
$colorInfo: #2294a2;
$colorInfoFg: #fff;
$colorOk: #33cc33;
$colorOkFg: #fff;
// Bubble colors
$colorInfoBubbleBg: $colorMenuBg;
$colorInfoBubbleFg: #666;
@@ -315,9 +305,6 @@ $colorTabHeaderFg: pullForward($colorBodyFg, 20%);
$colorTabHeaderBorder: $colorBodyBg;
$colorTabGroupHeaderBg: pullForward($colorBodyBg, 5%);
$colorTabGroupHeaderFg: pullForward($colorTabGroupHeaderBg, 40%);
$colorSummaryBg: #999;
$colorSummaryFg: rgba($colorBodyBg, 0.7);
$colorSummaryFgEm: white;
// Plot
$colorPlotBg: rgba(black, 0.05);
@@ -336,8 +323,8 @@ $colorItemTreeHoverFg: pullForward($colorBodyFg, 10%);
$colorItemTreeIcon: $colorKey; // Used
$colorItemTreeIconHover: $colorItemTreeIcon; // Used
$colorItemTreeFg: $colorBodyFg;
$colorItemTreeSelectedBg: $colorSelectedBg;
$colorItemTreeSelectedFg: $colorItemTreeHoverFg;
$colorItemTreeSelectedBg: pushBack($colorKey, 15%);
$colorItemTreeSelectedFg: $colorBodyBg;
$colorItemTreeSelectedIcon: $colorItemTreeSelectedFg;
$colorItemTreeEditingBg: pushBack($editUIColor, 20%);
$colorItemTreeEditingFg: $editUIColor;
@@ -360,7 +347,6 @@ $scrollbarThumbColorMenuHov: darken($scrollbarThumbColorMenu, 2%);
// Splitter
$splitterHandleD: 2px;
$splitterD: $splitterHandleD;
$splitterHandleHitMargin: 4px;
$colorSplitterBaseBg: $colorBodyBg;
$colorSplitterBg: pullForward($colorSplitterBaseBg, 20%);
@@ -390,10 +376,8 @@ $colorLoadingFg: #776ba2;
$colorLoadingBg: rgba($colorLoadingFg, 0.1);
// Transitions
$transInTime: 50ms;
$transOutTime: 250ms;
$transIn: all $transInTime ease-in-out;
$transOut: all $transOutTime ease-in-out;
$transIn: all 50ms ease-in-out;
$transOut: all 250ms ease-in-out;
$transInBounce: all 200ms cubic-bezier(.47,.01,.25,1.5);
$transInBounceBig: all 300ms cubic-bezier(.2,1.6,.6,3);

View File

@@ -28,7 +28,6 @@ $dirImgs: 'images/';
$controlFadeMs: 100ms;
$browseToEditAnimMs: 400ms;
$editBorderPulseMs: 500ms;
$moveBarOutDelay: 500ms;
/************************** SPATIAL */
$interiorMarginSm: 3px;
@@ -81,12 +80,10 @@ $formLabelW: 30%;
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;
$waitSpinnerBorderW: 5px;
$waitSpinnerTreeBorderW: 3px;
$waitSpinnerTreeBorderW: 4px;
/*************** Messages */
$messageIconD: 80px;
$messageListIconD: 32px;
/*************** Tables */
$tableResizeColHitareaD: 6px;
/************************** MOBILE */
$mobileMenuIconD: 24px; // Used

View File

@@ -48,16 +48,10 @@ button {
height: $d; width: $d;
}
}
}
&.is-active {
background: $colorBtnActiveBg;
color: $colorBtnActiveFg;
}
&.is-selected {
background: $colorBtnSelectedBg;
color: $colorBtnSelectedFg;
}
.c-compact-button {
@include cCompactButtons($bg: $colorBtnBg, $fg: $colorBtnFg, $bgHov: $colorBtnBgHov);
}
/********* Icon Buttons */
@@ -85,15 +79,6 @@ button {
margin-left: $interiorMargin;
}
$c1: nth($mixedSettingBg, 1);
$c2: nth($mixedSettingBg, 2);
$mixedBgD: $mixedSettingBgSize $mixedSettingBgSize;
&--mixed {
// E.g. click-icons in toolbar that apply to multiple selected items with different settings
@include bgStripes2Color($c1, $c2, $bgSize: $mixedBgD);
}
&--swatched {
// Color control, show swatch element
display: flex;
@@ -102,9 +87,9 @@ button {
justify-content: center;
> [class*='swatch'] {
box-shadow: inset rgba($editUIBaseColorFg, 0.2) 0 0 0 1px;
box-shadow: inset rgba(black, 0.2) 0 0 1px;
flex: 0 0 auto;
height: 5px;
height: 4px;
width: 100%;
margin-top: 1px;
}
@@ -114,13 +99,6 @@ button {
flex: 1 1 auto;
font-size: 1.1em;
}
&--mixed {
// Styling for swatched buttons when settings are mixed
> [class*='swatch'] {
@include bgStripes2Color($c1, $c2, $bgSize: $mixedBgD);
}
}
}
}
@@ -164,6 +142,8 @@ button {
display: block;
font-family: symbolsfont;
font-size: 1rem * $s;
transform-origin: center;
transition: transform 100ms ease-in-out;
}
}
@@ -290,63 +270,6 @@ select {
}
}
/******************************************************** TABS */
.c-tabs {
// Single horizontal strip of tabs, with a bottom divider line
@include userSelectNone();
display: flex;
flex: 0 0 auto;
flex-wrap: wrap;
position: relative; // Required in case this is applied to a <ul>
&:before {
// Separator line at bottom of tabs
content: '';
display: block;
height: 1px;
width: 100%;
background: $colorBtnReverseBg;
position: absolute;
bottom: 0px;
z-index: 1;
}
}
.c-tab {
// Used in Tab View, generic tabs
background: $colorBtnBg;
color: $colorBtnFg;
cursor: pointer;
display: flex;
align-items: center;
flex: 1 1 auto;
margin: 1px 1px 0 0;
padding: $interiorMargin $interiorMarginLg;
white-space: nowrap;
--notchSize: 7px;
clip-path:
polygon(
0% 0%,
calc(100% - var(--notchSize)) 0%,
100% var(--notchSize),
100% calc(100% - var(--notchSize)),
100% 100%,
0% 100%
);
@include hover() {
background: $colorBtnBgHov;
}
&.is-current {
background: $colorBtnReverseBg;
color: $colorBtnReverseFg;
pointer-events: none;
}
}
/******************************************************** HYPERLINKS AND HYPERLINK BUTTONS */
.c-hyperlink {
&--link {
@@ -585,10 +508,6 @@ select {
margin-left: 2px;
}
&__button {
}
&__separator {
@include cToolbarSeparator();
}
@@ -739,7 +658,7 @@ input[type="range"] {
}
}
/******************************************************** LOCAL CONTROLS */
/***************************************************** LOCAL CONTROLS */
.h-local-controls {
// Holder for local controls
&--horz {

View File

@@ -101,6 +101,7 @@
min-width: 120px;
order: 1;
position: relative;
white-space: nowrap;
width: $formLabelW;
}
@@ -120,36 +121,27 @@
margin-right: 5px;
}
}
.l-input-lg { // LEGACY FORM SUPPORT
input[type=text],
input[type=search],
input[type=number] {
width: 100%;
}
}
select {
.select {
margin-right: $interiorMargin;
}
}
.hint, .field-hints { color: $colorFieldHint; }
}
}
.selector-list {
// Displays tree view in dialogs
.selector-list {
// Used in create overlay to display tree view
@include nice-input();
padding: $interiorMargin;
position: relative;
min-height: 0; // Chrome 73 overflow bug fix
min-height: 150px;
height: 100%;
>.wrapper {
$p: $interiorMargin;
box-sizing: border-box;
overflow: auto;
}
}
}
}
.l-controls-first .form .form-row,

View File

@@ -19,7 +19,8 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/******************************************************** RESETS */
/******************************* RESETS */
*,
:before,
:after {
@@ -30,7 +31,7 @@ div {
position: relative;
}
/******************************************************** UTILITIES */
/******************************* UTILITIES */
.u-contents {
display: contents;
}
@@ -44,7 +45,7 @@ div {
}
}
/******************************************************** BROWSER ELEMENTS */
/******************************* BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {
box-sizing: border-box;
@@ -74,7 +75,7 @@ body.desktop {
}
}
/******************************************************** HTML ENTITIES */
/************************** HTML ENTITIES */
a {
color: $colorA;
cursor: pointer;
@@ -166,6 +167,7 @@ body.desktop .has-local-controls {
/******************************************************** SELECTION AND EDITING */
// Provides supporting styles for Display Layouts and augmented legacy Fixed Position view
.c-grid,
.c-grid__x,
.c-grid__y {
@@ -202,88 +204,169 @@ body.desktop .has-local-controls {
}
}
/******************************************************** STATES */
@mixin spinner($b: 5px, $c: $colorKey) {
animation-name: rotation-centered;
animation-duration: 0.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
border-radius: 100%;
box-sizing: border-box;
border-color: rgba($c, 0.25);
border-top-color: rgba($c, 1.0);
border-style: solid;
border-width: $b;
/************************** LEGACY */
mct-container {
display: block;
}
.abs {
position: absolute;
left: 50%; top: 50%;
transform-origin: center;
transform: translate(-50%, -50%);
top: 0;
right: 0;
bottom: 0;
left: 0;
height: auto;
width: auto;
}
.wait-spinner {
@include spinner($waitSpinnerBorderW, $colorKey);
pointer-events: none;
z-index: 2;
&.inline {
display: inline-block !important;
margin-right: $interiorMargin;
position: relative !important;
vertical-align: middle;
}
.code {
font-family: "Lucida Console", monospace;
font-size: 0.7em;
line-height: 150%;
white-space: pre;
}
.loading {
// Can be applied to any block element with height and width
pointer-events: none;
&:before,
&:after {
content: '';
}
&:before {
@include spinner($waitSpinnerBorderW, $colorLoadingFg);
height: $waitSpinnerD; width: $waitSpinnerD;
z-index: 10;
}
&:after {
@include abs();
background: $colorLoadingBg;
display: block;
z-index: 9;
}
&.c-tree__item {
$d: $waitSpinnerTreeD;
$spinnerL: 19px + $d/2;
display: flex;
align-items: center;
padding-left: $spinnerL + $d/2 + $interiorMargin;
background: $colorLoadingBg;
min-height: 5px + $d;
.c-tree__item__label {
font-style: italic;
opacity: 0.6;
}
&:before {
height: $d;
width: $d;
border-width: 4px;
left: $spinnerL;
}
&:after {
display: none;
}
}
&.c-loading--overlay {
@include abs();
}
.codehilite {
@extend .code;
background-color: rgba($colorBodyFg, 0.1);
padding: 1em;
}
*[disabled],
.disabled {
.disabled,
a.disabled {
opacity: $controlDisabledOpacity;
pointer-events: none !important;
cursor: default !important;
}
.s-status-missing {
// Labels. Expects .s-status-missing to be applied to mct-representation that contains
.t-object-label .t-item-icon:before {
content: $glyph-icon-object-unknown;
}
// Item, grid item. Expects .s-status-missing to be applied to mct-representation that contains .item.grid-item
.item .t-item-icon-glyph:before {
content: $glyph-icon-object-unknown;
}
// Object header. Expects .s-status-missing to be applied to mct-representation.object-header
&.object-header {
.type-icon:before {
content: $glyph-icon-object-unknown;
}
}
// Tree item. Expects .s-status-missing to be applied to .tree-item,
// and mct-representation.search-item
&.tree-item,
&.search-item {
> .rep-object-label .t-item-icon:before {
content: $glyph-icon-object-unknown;
}
}
}
.align-right {
text-align: right;
}
.centered {
text-align: center;
}
.no-selection {
// aka selection = "None". Used in palettes and their menu buttons.
$c: red;
$s: 48%;
$e: 52%;
background-image: linear-gradient(-45deg,
transparent $s - 5%,
$c $s,
$c $e,
transparent $e + 5%
);
box-shadow:inset rgba(black, 0.3) 0 0 0 1px;
background-repeat: no-repeat;
background-size: contain;
}
.scrolling,
.scroll {
overflow: auto;
}
.vscroll {
overflow-x: hidden;
overflow-y: auto;
&.scroll-pad {
padding-right: $interiorMargin;
}
}
.vscroll--persist {
overflow-x: hidden;
overflow-y: scroll;
}
.slidable {
cursor: move; // Fallback
cursor: grab;
cursor: -moz-grab;
cursor: -webkit-grab;
&.horz {
cursor: col-resize;
}
&.vert {
cursor: row-resize;
}
}
.no-margin {
margin: 0;
}
.ds {
box-shadow: rgba(#000, 0.7) 0 4px 10px 2px;
}
.capitalize {
text-transform: capitalize;
}
.hide,
.hidden,
.t-main-view .hide-in-t-main-view {
display: none !important;
}
.hide-nice {
opacity: 0;
pointer-events: none;
}
.invisible {
display: block;
visibility: hidden;
height: 0;
padding: 0;
border: 0;
margin: 0 !important;
transform: scale(0);
pointer-events: none;
position: absolute;
}
.sep {
color: rgba(#fff, 0.2);
}
.comma-list span {
&:not(:first-child) {
&:before {
content: ', ';
}
}
}

View File

@@ -51,22 +51,6 @@ mct-plot {
}
}
.is-editing {
.gl-plot.child-frame {
&:hover {
background: rgba($editUIColorBg, 0.1);
box-shadow: inset rgba($editUIColorBg, 0.8) 0 0 0 1px;
}
&[s-selected] {
border: 1px solid $editUIColorFg !important;
color: $editUIColorFg !important;
box-shadow: $editFrameSelectedShdw;
z-index: 2;
}
}
}
.gl-plot {
color: $colorPlotFg;
display: flex;
@@ -564,10 +548,3 @@ mct-plot {
top: 0; bottom: 0;
}
}
.s-status-timeconductor-unsynced {
.t-object-alert.t-alert-unsynced {
@extend .icon-alert-triangle;
color: $colorPausedBg;
}
}

View File

@@ -461,7 +461,7 @@ body.mobile.phone {
width: $ruleLabelW;
}
.js-summary-widget__message {
.t-message-widget-no-data {
display: none;
}
@@ -482,8 +482,6 @@ body.mobile.phone {
.widget-edit-holder {
display: flex; // Overrides `display: none` during Browse mode
flex: 1 1 auto;
.flex-accordion-holder {
// Needed because otherwise accordion elements "creep" when contents expand and contract
display: block !important;
@@ -499,12 +497,18 @@ body.mobile.phone {
// Test data is expanded and rules are collapsed
// Make text data take up all the vertical space
.flex-accordion-holder { display: flex; }
.widget-test-data {
flex-grow: 999999;
}
.w-widget-test-data-items {
max-height: inherit;
}
}
}
&.expanded-widget-rules {
.widget-rules-wrapper {
min-height: 50px;
height: 100%; // Fix for Chrome 73 scrolling bug
height: auto;
opacity: 1;
pointer-events: inherit;
}
@@ -516,7 +520,7 @@ body.mobile.phone {
opacity: 0.3;
pointer-events: none;
}
.js-summary-widget__message {
.t-message-widget-no-data {
display: flex;
}
}
@@ -800,9 +804,7 @@ mct-indicators mct-include {
}
.label {
// Hover bubbles that appear when hovering on an Indicator
display: inline-block;
a,
button,
s-button,
@@ -849,6 +851,8 @@ mct-indicators mct-include {
}
&:not(.no-collapse) {
z-index: 0;
&:before {
margin-right: 0 !important;
}
@@ -866,8 +870,6 @@ mct-indicators mct-include {
transform-origin: 10px 100%;
transform: scale(0.0);
white-space: nowrap;
z-index: 50;
&:before {
// Infobubble-style arrow element
content: '';
@@ -878,9 +880,9 @@ mct-indicators mct-include {
}
}
@include hover() {
&:hover {
background: $bg;
z-index: 1;
.label {
opacity: 1;
transform: scale(1.0);
@@ -1173,6 +1175,79 @@ body.desktop {
}
}
/******************************************************************* WAIT SPINNERS */
@mixin spinner($b: 5px, $c: $colorKey) {
animation-name: rotation-centered;
animation-duration: 0.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
border-radius: 100%;
box-sizing: border-box;
border-color: rgba($c, 0.25);
border-top-color: rgba($c, 1.0);
border-style: solid;
border-width: $b;
display: block;
position: absolute;
left: 50%; top: 50%;
transform-origin: center;
transform: translate(-50%, -50%);
}
.wait-spinner {
@include spinner($waitSpinnerBorderW, $colorKey);
pointer-events: none;
z-index: 2;
&.inline {
display: inline-block !important;
margin-right: $interiorMargin;
position: relative !important;
vertical-align: middle;
}
}
.loading {
// Can be applied to any block element with height and width
pointer-events: none;
&:before,
&:after {
content: '';
}
&:before {
@include spinner($waitSpinnerBorderW, $colorLoadingFg);
height: $waitSpinnerD; width: $waitSpinnerD;
z-index: 10;
}
&:after {
@include abs();
background: $colorLoadingBg;
display: block;
z-index: 9;
}
&.tree-item.t-wait-node {
$d: $waitSpinnerTreeD;
$spinnerL: $interiorMargin + 19px + $d/2;
padding-left: $spinnerL + $d/2 + $interiorMargin;
.t-title-label {
font-style: italic;
opacity: 0.6;
}
&:before {
height: $d;
width: $d;
border-width: 4px;
left: $spinnerL;
}
&:after {
display: none;
}
}
&.c-loading--overlay {
@include abs();
}
}
/******************************************************************* FLEX STYLES */
.l-flex-row,
.l-flex-col {
@@ -1239,7 +1314,7 @@ body.desktop {
.grid-properties {
display: grid;
grid-row-gap: 0;
grid-template-columns: 1fr 2fr;
grid-template-columns: 1fr 1fr;
}
.grid-span-all,
@@ -1437,10 +1512,6 @@ body.desktop {
display: contents;
}
mct-container {
display: block;
}
.overlay {
.outer-holder {
background: $colorMenuBg;
@@ -1506,157 +1577,3 @@ mct-container {
}
}
}
.abs {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: auto;
width: auto;
}
.code {
font-family: "Lucida Console", monospace;
font-size: 0.7em;
line-height: 150%;
white-space: pre;
}
.codehilite {
@extend .code;
background-color: rgba($colorBodyFg, 0.1);
padding: 1em;
}
.s-status-missing {
// Labels. Expects .s-status-missing to be applied to mct-representation that contains
.t-object-label .t-item-icon:before {
content: $glyph-icon-object-unknown;
}
// Item, grid item. Expects .s-status-missing to be applied to mct-representation that contains .item.grid-item
.item .t-item-icon-glyph:before {
content: $glyph-icon-object-unknown;
}
// Object header. Expects .s-status-missing to be applied to mct-representation.object-header
&.object-header {
.type-icon:before {
content: $glyph-icon-object-unknown;
}
}
// Tree item. Expects .s-status-missing to be applied to .tree-item,
// and mct-representation.search-item
&.tree-item,
&.search-item {
> .rep-object-label .t-item-icon:before {
content: $glyph-icon-object-unknown;
}
}
}
.align-right {
text-align: right;
}
.centered {
text-align: center;
}
.no-selection {
// aka selection = "None". Used in palettes and their menu buttons.
$c: red;
$s: 48%;
$e: 52%;
background-image: linear-gradient(-45deg,
transparent $s - 5%,
$c $s,
$c $e,
transparent $e + 5%
);
box-shadow:inset rgba(black, 0.3) 0 0 0 1px;
background-repeat: no-repeat;
background-size: contain;
}
.scrolling,
.scroll {
overflow: auto;
}
.vscroll {
overflow-x: hidden;
overflow-y: auto;
&.scroll-pad {
padding-right: $interiorMargin;
}
}
.vscroll--persist {
overflow-x: hidden;
overflow-y: scroll;
}
.slidable {
cursor: move; // Fallback
cursor: grab;
cursor: -moz-grab;
cursor: -webkit-grab;
&.horz {
cursor: col-resize;
}
&.vert {
cursor: row-resize;
}
}
.no-margin {
margin: 0;
}
.ds {
box-shadow: rgba(#000, 0.7) 0 4px 10px 2px;
}
.capitalize {
text-transform: capitalize;
}
.hide,
.hidden,
.t-main-view .hide-in-t-main-view {
display: none !important;
}
.hide-nice {
opacity: 0;
pointer-events: none;
}
.invisible {
display: block;
visibility: hidden;
height: 0;
padding: 0;
border: 0;
margin: 0 !important;
transform: scale(0);
pointer-events: none;
position: absolute;
}
.sep {
color: rgba(#fff, 0.2);
}
.comma-list span {
&:not(:first-child) {
&:before {
content: ', ';
}
}
}

View File

@@ -108,7 +108,7 @@
}
@mixin bgStripes($c: yellow, $a: 0.1, $bgsize: 5px, $angle: 90deg) {
background: linear-gradient($angle,
background-image: linear-gradient($angle,
rgba($c, $a) 25%, transparent 25%,
transparent 50%, rgba($c, $a) 50%,
rgba($c, $a) 75%, transparent 75%,
@@ -117,16 +117,6 @@
background-size: $bgsize $bgsize;
}
@mixin bgStripes2Color($c1, $c2, $bgSize, $angle: -45deg) {
background: linear-gradient(-45deg,
$c1 0%, $c1 25%,
$c2 25%, $c2 50%,
$c1 50%, $c1 75%,
$c2 75%, $c2 100%
) repeat;
background-size: $bgSize;
}
@mixin disabled() {
opacity: $controlDisabledOpacity;
pointer-events: none !important;
@@ -425,13 +415,12 @@
// Background is displayed on hover
// Padding is included to facilitate a bigger hit area
// Make the icon bigger relative to its container
$pLR: 4px;
$pTB: 4px;
@include cControl();
background: none;
box-shadow: none;
cursor: pointer;
$pLR: 4px;
$pTB: 4px;
transition: $transOut;
border-radius: $controlCr;
padding: $pTB $pLR;
@@ -478,6 +467,50 @@
}
}
@mixin cCompactButtons($bg, $fg, $bgHov) {
// Used in Tab view
// To be used in indicators popups?
$m: 1px;
$btnM: $m;
&-holder {
background: $colorTabsHolderBg;
border-radius: $controlCr;
padding: $m ($m - $btnM) ($m - $btnM) $m;
display: flex;
flex-flow: row wrap;
justify-content: stretch;
> * {
margin: 0 $btnM $btnM 0;
}
}
background: $colorBtnBg;
color: $colorBtnFg;
flex: 1 1 auto;
padding: $interiorMargin;
&:before {
opacity: 0.5;
}
> * {
margin-left: $interiorMarginSm;
}
@include hover() {
background: $bgHov;
}
&.is-current {
background: $colorBtnReverseBg;
color: $colorBtnReverseFg;
pointer-events: none;
}
}
@mixin cSelect($bg, $fg, $arwClr, $shdw) {
$svgArwClr: str-slice(inspect($arwClr), 2, str-length(inspect($arwClr))); // Remove initial # in color value
background: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10'%3e%3cpath fill='%23#{$svgArwClr}' d='M5 5l5-5H0z'/%3e%3c/svg%3e"), $bg;
@@ -575,6 +608,7 @@
@mixin test($c: deeppink, $a: 0.3) {
background: rgba($c, $a) !important;
background-color: rgba($c, $a) !important;
box-shadow: deeppink 0 0 10px 1px !important;
}

View File

@@ -20,36 +20,17 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*************************************************** MIXINS */
@mixin statusStyle($bg, $fg, $imp: false) {
$impStr: null;
@if $imp {
$impStr: !important;
}
background: $bg $impStr;
background-color: $bg $impStr;
color: $fg $impStr;
}
@mixin statusIcon($ic, $glyph: null, $imp: false) {
$impStr: null;
@if $imp {
$impStr: !important;
}
@mixin statusStyle($bg, $fg, $ic) {
background: $bg !important;
background-color: $bg !important;
color: $fg !important;
&:before {
color: $ic;
display: inline-block;
font-family: symbolsfont;
font-size: 0.8em;
font-size: 0.7em;
margin-right: $interiorMargin;
@if $glyph != null {
content: $glyph $impStr;
}
}
}
@mixin statusStyleCombined($bg, $fg, $ic) {
@include statusStyle($bg, $fg, $imp: true);
@include statusIcon($ic);
}
@mixin elementStatusColors($c) {
@@ -66,45 +47,16 @@
}
}
@mixin andUprLwr {
&.is-limit--upr:before { content: $glyph-icon-arrow-up !important; }
&.is-limit--lwr:before { content: $glyph-icon-arrow-down !important; }
.is-limit--yellow {
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg, $colorLimitYellowIc);
&.is-limit--upr:before { content: $glyph-icon-arrow-up; }
&.is-limit--lwr:before { content: $glyph-icon-arrow-down; }
}
/*************************************************** STYLES */
*:not(tr) {
&.is-limit--yellow {
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg, true);
@include statusIcon($colorLimitYellowIc, $glyph-icon-alert-rect);
@include andUprLwr();
}
&.is-limit--red {
@include statusStyle($colorLimitRedBg, $colorLimitRedFg, true);
@include statusIcon($colorLimitRedIc, $glyph-icon-alert-triangle);
@include andUprLwr();
}
}
tr {
&.is-limit--yellow {
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg);
td:first-child {
@include statusIcon($colorLimitYellowIc, $glyph-icon-alert-rect);
}
td { color: $colorLimitYellowFg; }
}
&.is-limit--red {
@include statusStyle($colorLimitRedBg, $colorLimitRedFg);
td:first-child {
@include statusIcon($colorLimitRedIc, $glyph-icon-alert-triangle);
}
td { color: $colorLimitRedFg; }
}
&.is-limit--upr { td:first-child:before { content: $glyph-icon-arrow-up !important; } }
&.is-limit--lwr { td:first-child:before { content: $glyph-icon-arrow-down !important; } }
.is-limit--red {
@include statusStyle($colorLimitRedBg, $colorLimitRedFg, $colorLimitRedIc);
&.is-limit--upr:before { content: $glyph-icon-arrow-double-up; }
&.is-limit--lwr:before { content: $glyph-icon-arrow-double-down; }
}
/*************************************************** STATUS */

View File

@@ -19,20 +19,18 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/******************************************************** TABLE */
table {
$minW: 50px;
width: 100%;
thead {
th {
background: $colorTabHeaderBg;
+ th {
th + th {
border-left: 1px solid $colorTabHeaderBorder;
}
}
}
tbody {
tr + tr {
@@ -49,37 +47,14 @@ table {
td {
vertical-align: top;
}
a { color: $colorBtnMajorBg; }
}
.is-editing {
td.is-selectable {
&:hover {
background: rgba($editUIColorBg, 0.1);
box-shadow: inset rgba($editUIColorBg, 0.8) 0 0 0 1px;
}
&[s-selected] {
background: $editUIColorBg !important;
border: 1px solid $editUIColorFg !important;
color: $editUIColorFg !important;
box-shadow: $editFrameSelectedShdw;
z-index: 2;
}
}
}
/******************************************************** C-TABLE */
div.c-table {
// When c-table is used as a wrapper element in more complex table views
height: 100%;
}
.c-table {
// Can be used by any type of table, scrolling, LAD, etc.
$min-w: 50px;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: 100%;
&__control-bar,
@@ -94,7 +69,7 @@ div.c-table {
}
thead tr,
&.c-table__headers {
[class*="__header"] {
background: $colorTabHeaderBg;
th {
@@ -143,35 +118,3 @@ div.c-table {
width: 33%; // Needed to prevent size jumping as values dynamically update
}
}
/************************************** TABLE AND SUMMARY VIEWS */
// Displays summary values above a table.
.c-table-and-summary {
height: 100%;
width: 100%;
overflow: auto;
display: flex;
flex-direction: column;
> * + * { margin-top: $interiorMargin; }
&__summary {
display: flex;
justify-items: stretch;
> * + * { margin-left: 1px; }
}
&__summary-item {
background: $colorSummaryBg;
color: $colorSummaryFg;
flex: 1 1 auto;
padding: $interiorMargin $interiorMarginLg;
em {
font-weight: bold;
color: $colorSummaryFgEm;
}
}
}

View File

@@ -25,8 +25,8 @@
// Do not include anything that renders to CSS!
@import "constants";
@import "constants-mobile.scss";
//@import "constants-espresso"; // TEMP
@import "constants-snow"; // TEMP
@import "constants-espresso"; // TEMP
//@import "constants-snow"; // TEMP
//@import "constants-maelstrom";
@import "mixins";
@import "animations";

View File

@@ -26,19 +26,21 @@
'has-complex-content': complexContent
}">
<div class="c-so-view__header">
<div class="c-so-view__header__icon" :class="cssClass"></div>
<div class="c-so-view__header__name">
<div class="c-so-view__header__start">
<div class="c-so-view__header__name"
:class="cssClass">
{{ domainObject && domainObject.name }}
</div>
<context-menu-drop-down
:object-path="objectPath">
</context-menu-drop-down>
</div>
<div class="c-so-view__local-controls c-so-view__view-large h-local-controls c-local-controls--show-on-hover">
<button class="c-button icon-expand"
<div class="c-so-view__header__end">
<div class="c-button icon-expand local-controls--hidden"
title="View Large"
@click="expand">
</button>
</div>
</div>
</div>
<object-view
class="c-so-view__object-view"
@@ -63,53 +65,45 @@
align-items: center;
margin-bottom: $interiorMargin;
&__icon {
flex: 0 0 auto;
margin-right: $interiorMarginSm;
opacity: 0.5;
&__start,
&__end {
display: flex;
flex: 1 1 auto;
}
&__end {
justify-content: flex-end;
}
&__name {
@include headerFont(1em);
display: flex;
&:before {
margin-right: $interiorMarginSm;
}
}
}
&--no-frame > .c-so-view__header {
display: none;
}
&__name {
@include ellipsize();
@include headerFont(1.2em);
flex: 0 1 auto;
}
}
&:not(.c-so-view--no-frame) {
background: $colorBodyBg;
border: $browseFrameBorder;
padding: $interiorMargin;
&:before {
// Object type icon
flex: 0 0 auto;
margin-right: $interiorMarginSm;
opacity: 0.5;
}
&--no-frame {
> .c-so-view__header {
display: none;
}
> .c-so-view__local-controls {
top: $interiorMarginSm; right: $interiorMarginSm;
}
}
&__local-controls {
position: absolute;
top: $interiorMargin; right: $interiorMargin;
z-index: 2;
}
&__view-large {
display: none;
}
&.has-complex-content {
> .c-so-view__view-large { display: block; }
}
/*************************** OBJECT VIEW */
&__object-view {
flex: 1 1 auto;
height: 0; // Chrome 73 overflow bug fix
overflow: auto;
.c-object-view {
@@ -134,9 +128,7 @@
const SIMPLE_CONTENT_TYPES = [
'clock',
'timer',
'summary-widget',
'hyperlink'
'summary-widget'
];
export default {

View File

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

View File

@@ -34,10 +34,7 @@ export default {
this.currentObject = this.object;
this.updateView();
this.$el.addEventListener('dragover', this.onDragOver);
this.$el.addEventListener('drop', this.addObjectToParent);
this.$el.addEventListener('drop', this.editIfEditable, {
capture: true
});
this.$el.addEventListener('drop', this.onDrop);
},
methods: {
clear() {
@@ -73,10 +70,15 @@ export default {
this.viewContainer = document.createElement('div');
this.viewContainer.classList.add('c-object-view','u-contents');
this.$el.append(this.viewContainer);
let provider = this.getViewProvider();
let provider = this.openmct.objectViews.getByProviderKey(this.viewKey);
if (!provider) {
provider = this.openmct.objectViews.get(this.currentObject)[0];
if (!provider) {
return;
}
}
if (provider.edit && this.showEditView) {
if (this.openmct.editor.isEditing()) {
@@ -84,7 +86,6 @@ export default {
} 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 {
@@ -132,7 +133,7 @@ export default {
event.preventDefault();
}
},
addObjectToParent(event) {
onDrop(event) {
if (this.hasComposableDomainObject(event)) {
let composableDomainObject = this.getComposableDomainObject(event);
this.currentObject.composition.push(composableDomainObject.identifier);
@@ -141,25 +142,6 @@ export default {
event.stopPropagation();
}
},
getViewProvider() {
let provider = this.openmct.objectViews.getByProviderKey(this.viewKey);
if (!provider) {
provider = this.openmct.objectViews.get(this.currentObject)[0];
if (!provider) {
return;
}
}
return provider;
},
editIfEditable(event) {
let provider = this.getViewProvider();
if (provider &&
provider.canEdit(this.currentObject) &&
!this.openmct.editor.isEditing()) {
this.openmct.editor.edit();
}
},
hasComposableDomainObject(event) {
return event.dataTransfer.types.includes('openmct/composable-domain-object')
},

View File

@@ -5,18 +5,15 @@
@input="applySearch"
@clear="applySearch">
</Search>
<div class="c-elements-pool__elements"
:class="{'is-dragging': isDragging}">
<div class="c-elements-pool__elements">
<ul class="c-tree c-elements-pool__tree" id="inspector-elements-tree"
v-if="elements.length > 0">
<li :key="element.identifier.key" v-for="(element, index) in elements"
@drop="moveTo(index)"
@dragover="allowDrop">
<div class="c-tree__item c-elements-pool__item"
<li :key="element.identifier.key" v-for="(element, index) in elements" @drop="moveTo(index)" @dragover="allowDrop">
<div class="c-tree__item c-elements-pool__item">
<span class="c-elements-pool__grippy"
v-if="elements.length > 1 && isEditing"
draggable="true"
@dragstart="moveFrom(index)">
<span class="c-elements-pool__grippy"
v-if="elements.length > 1 && isEditing">
</span>
<object-label :domainObject="element" :objectPath="[element, parentObject]"></object-label>
</div>
@@ -47,27 +44,22 @@
&__elements {
flex: 1 1 auto;
overflow: auto;
&.is-dragging {
li { opacity: 0.2; }
}
}
&__grippy {
$d: 8px;
@include grippy($c: $colorItemTreeVC, $dir: 'y');
flex: 0 0 auto;
margin-right: $interiorMarginSm;
transform: translateY(-2px);
width: $d; height: $d;
}
}
.js-last-place {
.js-last-place{
height: 10px;
}
</style>
<script>
import _ from 'lodash';
import Search from '../components/search.vue';
import ObjectLabel from '../components/ObjectLabel.vue';
@@ -82,9 +74,7 @@ export default {
elements: [],
isEditing: this.openmct.editor.isEditing(),
parentObject: undefined,
currentSearch: '',
isDragging: false,
selection: []
currentSearch: ''
}
},
mounted() {
@@ -101,15 +91,10 @@ export default {
this.showSelection(this.openmct.selection.get());
},
showSelection(selection) {
if (_.isEqual(this.selection, selection)) {
return;
}
this.selection = selection;
this.elements = [];
this.elementsCache = {};
this.listeners = [];
this.parentObject = selection && selection[0] && selection[0][0].context.item;
this.parentObject = selection[0].context.item;
if (this.mutationUnobserver) {
this.mutationUnobserver();
}
@@ -149,7 +134,7 @@ export default {
this.applySearch(this.currentSearch);
},
removeElement(identifier) {
let keyString = this.openmct.objects.makeKeyString(identifier);
let keyString = this.openmct.objects.makeKeyString(element.identifier);
delete this.elementsCache[keyString];
this.applySearch(this.currentSearch);
},
@@ -169,19 +154,12 @@ export default {
this.composition.reorder(this.moveFromIndex, moveToIndex);
},
moveFrom(index){
this.isDragging = true;
this.moveFromIndex = index;
document.addEventListener('dragend', this.hideDragStyling);
},
hideDragStyling() {
this.isDragging = false;
document.removeEventListener('dragend', this.hideDragStyling);
}
},
destroyed() {
this.openmct.editor.off('isEditing', this.setEditState);
this.openmct.selection.off('change', this.showSelection);
if (this.mutationUnobserver) {
this.mutationUnobserver();
}

View File

@@ -22,6 +22,7 @@
min-height: 50px;
+ [class*="__"] {
// Margin between elements
margin-top: $interiorMargin;
}
@@ -36,7 +37,9 @@
}
&__elements {
height: 200px; // Initial height
// LEGACY TODO: Refactor when markup is updated, fix scrolling
// so that only tree holder handles overflow
height: 200px;
.tree-item {
.t-object-label {
@@ -61,6 +64,48 @@
}
/************************************************************** LEGACY */
// TODO: refactor when legacy properties markup can be converted
.inspector-location {
display: inline-block;
.location-item {
$h: 1.2em;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
line-height: $h;
position: relative;
padding: 2px 4px;
.t-object-label {
.t-item-icon {
height: $h;
margin-right: $interiorMarginSm;
}
}
&:hover {
background: $colorItemTreeHoverBg;
color: $colorItemTreeHoverFg;
.icon {
color: $colorItemTreeIconHover;
}
}
}
&:not(.last) .t-object-label .t-title-label:after {
color: pushBack($colorInspectorFg, 15%);
content: '\e904';
display: inline-block;
font-family: symbolsfont;
font-size: 8px;
font-style: normal !important;
line-height: inherit;
margin-left: $interiorMarginSm;
width: 4px;
}
}
.l-inspector-part {
display: contents;
}
@@ -71,8 +116,8 @@
grid-column: 1 / 3;
}
.c-tree .grid-properties {
margin-left: $treeItemIndent;
.tree .grid-properties {
margin-left: $treeItemIndent + $interiorMarginLg;
}
}
@@ -98,6 +143,7 @@
}
+ .c-properties {
// Margin between components
margin-top: $interiorMarginLg;
}
@@ -199,8 +245,8 @@
},
methods: {
refreshComposition(selection) {
if (selection.length > 0 && selection[0].length > 0) {
let parentObject = selection[0][0].context.item;
if (selection[0]) {
let parentObject = selection[0].context.item;
this.hasComposition = !!(parentObject && this.openmct.composition.get(parentObject));
}

View File

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

View File

@@ -1,68 +1,26 @@
<template>
<div class="c-properties c-properties--location">
<div class="c-properties__header" title="The location of this linked object.">Original Location</div>
<ul class="c-properties__section" v-if="!multiSelect">
<div class="c-properties__header" title="The location of this linked object.">Location</div>
<ul class="c-properties__section">
<li class="c-properties__row" v-if="originalPath.length">
<ul class="c-properties__value c-location">
<div class="c-properties__label">Original</div>
<ul class="c-properties__value">
<li v-for="pathObject in orderedOriginalPath"
class="c-location__item"
:key="pathObject.key">
<object-label
:domainObject="pathObject.domainObject"
:objectPath="pathObject.objectPath">
</object-label>
<span class="c-disclosure-triangle"></span>
</li>
</ul>
</li>
</ul>
<div class="c-properties__row--span-all" v-if="multiSelect">No location to display for multiple items</div>
</div>
</template>
<style lang="scss">
@import "~styles/sass-base";
.c-location {
display: flex;
flex-wrap: wrap;
&__item {
$m: $interiorMarginSm;
cursor: pointer;
display: flex;
align-items: center;
margin: 0 $m $m 0;
&:not(:last-child) {
&:after {
color: $colorInspectorPropName;
content: $glyph-icon-arrow-right;
font-family: symbolsfont;
font-size: 0.7em;
margin-left: $m;
opacity: 0.8;
}
}
.c-object-label {
padding: 0;
transition: $transOut;
&__type-icon {
width: auto;
font-size: 1em;
}
&:hover {
transition: $transIn;
filter: $filterHov;
}
}
}
}
</style>
<script>
import ObjectLabel from '../components/ObjectLabel.vue';
export default {
@@ -73,7 +31,6 @@ export default {
data() {
return {
domainObject: {},
multiSelect: false,
originalPath: [],
keyString: ''
}
@@ -86,14 +43,8 @@ export default {
this.openmct.selection.off('change', this.updateSelection);
},
methods: {
setOriginalPath(path, skipSlice) {
let originalPath = path;
if (!skipSlice) {
originalPath = path.slice(1,-1);
}
this.originalPath = originalPath.map((domainObject, index, pathArray) => {
setOriginalPath(path) {
this.originalPath = path.slice(1,-1).map((domainObject, index, pathArray) => {
let key = this.openmct.objects.makeKeyString(domainObject.identifier);
return {
domainObject,
@@ -102,36 +53,18 @@ export default {
}
});
},
clearData() {
this.domainObject = {};
this.originalPath = [];
this.keyString = '';
},
updateSelection(selection) {
if (!selection.length || !selection[0].length) {
this.clearData();
if (selection.length === 0) {
this.domainObject = {};
this.originalLocation = [];
return;
}
if (selection.length > 1) {
this.multiSelect = true;
return;
} else {
this.multiSelect = false;
}
this.domainObject = selection[0][0].context.item;
let parentObject = selection[0][1];
if (!this.domainObject && parentObject && parentObject.context.item) {
this.setOriginalPath([parentObject.context.item], true);
this.keyString = '';
return;
}
this.domainObject = selection[0].context.item;
let keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
if (keyString && this.keyString !== keyString) {
if (this.keyString !== keyString) {
this.keyString = keyString;
this.originalPath = [];

View File

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

View File

@@ -1,9 +1,9 @@
<template>
<div class="c-about c-about--splash">
<div v-if="!branding.aboutHtml" class="c-about__image c-splash-image"></div>
<div v-if="branding.aboutHtml" class="s-text l-content" v-html="branding.aboutHtml"></div>
<div v-else class="c-about__image c-splash-image"></div>
<div class="c-about__text s-text">
<div v-if="branding.aboutHtml" class="s-text l-content" v-html="branding.aboutHtml"></div>
<h1 class="l-title s-title">Open MCT</h1>
<div class="l-description s-description">
<p>Open MCT, Copyright &copy; 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>

View File

@@ -43,8 +43,7 @@
</div>
<!-- Action buttons -->
<div class="l-browse-bar__actions">
<button v-if="notebookEnabled"
class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
<button class="l-browse-bar__actions__notebook-entry c-button icon-notebook"
title="New Notebook entry"
@click="snapshot()">
</button>
@@ -113,16 +112,13 @@ const PLACEHOLDER_OBJECT = {};
promptUserandCancelEditing() {
let dialog = this.openmct.overlays.dialog({
iconClass: 'alert',
message: 'Any unsaved changes will be lost. Are you sure you want to continue?',
message: 'Are you sure you want to continue? All unsaved changes will be lost!',
buttons: [
{
label: 'Ok',
emphasis: true,
callback: () => {
this.openmct.editor.cancel().then(() => {
//refresh object view
this.openmct.layout.$refs.browseObject.show(this.domainObject, this.viewKey, true);
});
this.openmct.editor.cancel();
dialog.dismiss();
}
},
@@ -171,8 +167,7 @@ const PLACEHOLDER_OBJECT = {};
showSaveMenu: false,
domainObject: PLACEHOLDER_OBJECT,
viewKey: undefined,
isEditing: this.openmct.editor.isEditing(),
notebookEnabled: false
isEditing: this.openmct.editor.isEditing()
}
},
computed: {
@@ -218,11 +213,7 @@ const PLACEHOLDER_OBJECT = {};
}
},
mounted: function () {
if (this.openmct.types.get('notebook')) {
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
this.notebookEnabled = true;
}
document.addEventListener('click', this.closeViewAndSaveMenu);
window.addEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
@@ -231,20 +222,7 @@ const PLACEHOLDER_OBJECT = {};
this.isEditing = isEditing;
});
},
watch: {
domainObject() {
if (this.mutationObserver) {
this.mutationObserver();
}
this.mutationObserver = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
this.domainObject = domainObject;
});
}
},
beforeDestroy: function () {
if (this.mutationObserver) {
this.mutationObserver();
}
document.removeEventListener('click', this.closeViewAndSaveMenu);
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
}
@@ -289,14 +267,10 @@ const PLACEHOLDER_OBJECT = {};
&__nav-to-parent-button {
// This is an icon-button
$p: $interiorMargin;
$p: $interiorMarginLg;
margin-right: $interiorMargin;
padding-left: $p;
padding-right: $p;
.is-editing & {
display: none;
}
}
&__object-name--w {

View File

@@ -8,7 +8,7 @@
v-if="opened">
<div class="c-super-menu__menu">
<ul>
<li v-for="(item, index) in sortedItems"
<li v-for="(item, index) in items"
:key="index"
:class="item.class"
:title="item.title"
@@ -145,19 +145,6 @@
selectedMenuItem: {},
opened: false
}
},
computed: {
sortedItems () {
return this.items.sort((a,b) => {
if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
});
}
}
}
</script>

View File

@@ -64,6 +64,7 @@
&__status {
background: $colorStatusBarBg;
color: $colorStatusBarFg;
height: 24px;
padding: $interiorMarginSm;
}
@@ -74,7 +75,6 @@
// For mobile, collapse button becomes menu icon
body.mobile & {
@include cClickIconButton();
color: $colorKey !important;
position: absolute;
right: -2 * nth($shellPanePad, 2); // Needs to be -1 * when pane is collapsed
top: 0;
@@ -95,7 +95,6 @@
.l-pane__contents {
display: flex;
flex-flow: column nowrap;
overflow-x: hidden;
> * {
flex: 0 0 auto;
@@ -186,8 +185,8 @@
&__main-container {
// Wrapper for main views
flex: 1 1 auto !important;
height: 0; // Chrome 73 overflow bug fix
overflow: auto;
//font-size: 16px; // TEMP FOR LEGACY STYLING
}
&__tree {
@@ -210,8 +209,6 @@
&__main {
// Top and bottom padding in container that holds tree, __pane-main and Inspector
padding: $shellMainPad;
min-height: 0;
> .l-pane {
padding-top: 0;
padding-bottom: 0;
@@ -243,10 +240,7 @@
.is-editing {
.l-shell__main-container {
$m: 3px;
box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdw;
margin-left: $m;
margin-right: $m;
&[s-selected] {
// Provide a clearer selection context articulation for the main edit area
@@ -349,7 +343,7 @@
toggleHasToolbar(selection) {
let structure = undefined;
if (!selection || !selection[0]) {
if (!selection[0]) {
structure = [];
} else {
structure = this.openmct.toolbars.get(selection);

View File

@@ -7,17 +7,10 @@
@clear="searchTree">
</search>
</div>
<!-- loading -->
<div class="c-tree-and-search__loading loading"
v-if="isLoading"></div>
<!-- end loading -->
<div class="c-tree-and-search__no-results" v-if="treeItems.length === 0">
No results found
</div>
<ul class="c-tree-and-search__tree c-tree"
v-if="!isLoading">
<ul class="c-tree-and-search__tree c-tree">
<tree-item v-for="treeItem in treeItems"
:key="treeItem.id"
:node="treeItem">
@@ -41,10 +34,6 @@
flex: 0 0 auto;
}
&__loading {
flex: 1 1 auto;
}
&__no-results {
font-style: italic;
opacity: 0.6;
@@ -52,7 +41,7 @@
&__tree {
flex: 1 1 auto;
height: 0; // Chrome 73 overflow bug fix
height: 100%;
}
}
@@ -62,11 +51,6 @@
overflow-y: auto;
padding-right: $interiorMargin;
li {
position: relative;
&.c-tree__item-h { display: block; }
}
.c-tree {
margin-left: 15px;
}
@@ -184,8 +168,7 @@
return {
searchValue: '',
allTreeItems: [],
filteredTreeItems: [],
isLoading: false
filteredTreeItems: []
}
},
computed: {
@@ -199,19 +182,14 @@
},
methods: {
getAllChildren() {
this.isLoading = true;
this.openmct.objects.get('ROOT')
.then(root => {
return this.openmct.composition.get(root).load()
})
.then(root => this.openmct.composition.get(root).load())
.then(children => {
this.isLoading = false;
this.allTreeItems = children.map(c => {
return {
id: this.openmct.objects.makeKeyString(c.identifier),
object: c,
objectPath: [c],
navigateToParent: '/browse'
objectPath: [c]
};
});
});
@@ -222,23 +200,18 @@
let context = child.object.getCapability('context'),
object = child.object.useCapability('adapter'),
objectPath = [],
navigateToParent;
objectPath = [];
if (context) {
objectPath = context.getPath().slice(1)
.map(oldObject => oldObject.useCapability('adapter'))
.reverse();
navigateToParent = '/browse/' + objectPath.slice(1)
.map((parent) => this.openmct.objects.makeKeyString(parent.identifier))
.join('/');
}
return {
id: this.openmct.objects.makeKeyString(object.identifier),
object,
objectPath,
navigateToParent
objectPath
}
});
});

View File

@@ -128,6 +128,7 @@
background: $colorSplitterBg;
display: block;
position: absolute;
z-index: 10;
transition: $transOut;
&:before {
@@ -194,8 +195,8 @@
/********************************* STYLES FOR DESKTOP COLLAPSED PANES, ALL ORIENTATIONS */
$d: nth($splitterBtnD, 1);
flex-basis: $d;
min-width: $d;
min-height: $d;
min-width: $d !important;
min-height: $d !important;
> .l-pane__handle {
display: none;

View File

@@ -7,20 +7,14 @@
v-model="expanded">
</view-control>
<object-label :domainObject="node.object"
:objectPath="node.objectPath"
:navigateToPath="navigateToPath">
:objectPath="node.objectPath">
</object-label>
</div>
<ul v-if="expanded" class="c-tree">
<li class="c-tree__item-h"
v-if="isLoading && !loaded">
<div class="c-tree__item loading">
<span class="c-tree__item__label">Loading...</span>
</div>
</li>
<tree-item v-for="child in children"
:key="child.id"
:node="child">
:node="child"
>
</tree-item>
</ul>
</li>
@@ -37,12 +31,13 @@
node: Object
},
data() {
this.navigateToPath = this.buildPathString(this.node.navigateToParent)
this.pathToObject = this.buildPathString(this.node.objectPath);
return {
hasChildren: false,
isLoading: false,
loaded: false,
isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path,
isNavigated: this.pathToObject === this.openmct.router.currentLocation.path,
children: [],
expanded: false
}
@@ -55,7 +50,7 @@
}
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
return parentKeyString !== this.node.object.location;
}
},
},
mounted() {
// TODO: should update on mutation.
@@ -93,8 +88,7 @@
this.composition = this.openmct.composition.get(this.domainObject);
this.composition.on('add', this.addChild);
this.composition.on('remove', this.removeChild);
this.composition.load().then(this.finishLoading);
this.isLoading = true;
this.composition.load().then(this.finishLoading());
}
}
},
@@ -103,8 +97,7 @@
this.children.push({
id: this.openmct.objects.makeKeyString(child.identifier),
object: child,
objectPath: [child].concat(this.node.objectPath),
navigateToParent: this.navigateToPath
objectPath: [child].concat(this.node.objectPath)
});
},
removeChild(identifier) {
@@ -116,13 +109,15 @@
this.isLoading = false;
this.loaded = true;
},
buildPathString(parentPath) {
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
buildPathString(path) {
return '/browse/' + path.map(o => o && this.openmct.objects.makeKeyString(o.identifier))
.reverse()
.join('/');
},
highlightIfNavigated(newPath, oldPath){
if (newPath === this.navigateToPath) {
if (newPath === this.pathToObject) {
this.isNavigated = true;
} else if (oldPath === this.navigateToPath) {
} else if (oldPath === this.pathToObject) {
this.isNavigated = false;
}
}

View File

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

View File

@@ -33,8 +33,7 @@
</div>
<div class="l-browse-bar__end">
<div class="l-browse-bar__actions">
<button v-if="notebookEnabled"
class="l-browse-bar__actions__edit c-button icon-notebook"
<button class="l-browse-bar__actions__edit c-button icon-notebook"
title="New Notebook entry"
@click="snapshot">
</button>
@@ -64,11 +63,7 @@
}
&__object-view {
background: $colorBodyBg;
border: 1px solid $colorInteriorBorder;
flex: 1 1 auto;
overflow: auto;
padding: $interiorMargin;
> div:not([class]) {
// Target an immediate child div without a class and make it display: contents
@@ -102,19 +97,14 @@
return {
domainObject: domainObject,
type: type,
notebookEnabled: false
type: type
};
},
mounted() {
let viewProvider = this.openmct.objectViews.get(this.domainObject)[0];
this.view = viewProvider.view(this.domainObject);
this.view.show(this.$refs.objectView, false);
if (this.openmct.types.get('notebook')) {
this.notebookSnapshot = new NotebookSnapshot(this.openmct);
this.notebookEnabled = true;
}
},
destroy() {
this.view.destroy();

Some files were not shown because too many files have changed in this diff Show More