Compare commits

..

8 Commits

Author SHA1 Message Date
Andrew Henry
a8ebf3d00c Some experimentation resulting in slightly lower CPU usage, but broken scrolling 2019-03-29 12:57:32 -07:00
Andrew Henry
bc5e300ba9 Optionally provide list of object types to show as views rather than telemetry in Display Layouts (#2339)
* Optionally provide list of object types to show as views rather than alpha numerics to display layouts

* Only make table view available for objects that have telemetry to show
2019-03-28 22:21:27 -07:00
Andrew Henry
57efef3160 Digest after telemetry returned. (#2343) 2019-03-28 22:19:22 -07:00
Deep Tailor
dfc5a9f040 Tabs view fixes plus elements pool (#2340)
* use reorder api

* fix regression where elements pool doesnt update on remove

* fix issue where tabs was not updating when changes are discarded
2019-03-28 17:45:07 -07:00
Charles Hacskaylo
57443d227d Misc UI 6 (#2338)
* Sanding and shimming on loading CSS

- Wait spinners in the tree;
- Move spinner and loading CSS from legacy to global.scss;

* Misc UI 6
- Better approach to Time Conductor overflow;
- Fixed main page left/right clipping issue;
- Fixed table header bg styling that had issues in legacy tables;
- Fixed Time Conductor datetime picker clipping issue;
- New .c-message--simple for use in Summary Widgets;
- Better styling for header in empty Tabs view;
- Fixed Chrome 73 scrolling bug in Summary Widgets;
- Fixed problem in Inspector <li> elements from new wait spinner;
- Fixed color of <a> tags in tables to be more visible;
styling;

* Misc UI 6

- Fix VISTA session selector not scrolling (Chrome 73 overflow bug);

* Misc UI 6

- Fix VISTA session selector not scrolling (Chrome 73 overflow bug);
2019-03-28 16:29:39 -07:00
Deep Tailor
d36441db73 Persistence dialog fix (#2337)
* discard persistence error dialog

* update tests
2019-03-28 13:55:39 -07:00
Deep Tailor
327782835e save object before triggering mutate (#2336) 2019-03-28 13:54:27 -07:00
Andrew Henry
994f6be535 do not return null unsubscribe function (#2335) 2019-03-27 18:09:13 -07:00
25 changed files with 339 additions and 381 deletions

View File

@@ -54,6 +54,9 @@
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

@@ -162,9 +162,6 @@ function (
function saveAfterClone(clonedObject) {
return this.openmct.editor.save().then(() => {
// Force mutation for search indexing
clonedObject.useCapability('mutation', (model) => {
return model;
});
return clonedObject;
})
}
@@ -173,6 +170,14 @@ 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;
@@ -194,6 +199,7 @@ function (
.then(undirtyOriginals)
.then(saveAfterClone)
.then(finishEditing)
.then(indexForSearch)
.then(hideBlockingDialog)
.then(onSuccess)
.catch(onFailure);

View File

@@ -37,75 +37,17 @@ define(
}
/**
* Handle persistence failures by providing the user with a
* dialog summarizing these failures, and giving the option
* to overwrite/cancel as appropriate.
* Discard failures
* @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 =
@@ -118,19 +60,7 @@ 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 discardAll(revisionErrors);
};
return PersistenceFailureHandler;

View File

@@ -74,43 +74,14 @@ define(
handler = new PersistenceFailureHandler(mockQ, mockDialogService);
});
it("shows a dialog to handle failures", function () {
it("discards on handle", 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,7 +248,6 @@ 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());
@@ -257,7 +256,6 @@ define([
if (typeof BUILD_CONSTANTS !== 'undefined') {
this.install(buildInfoPlugin(BUILD_CONSTANTS));
}
}
MCT.prototype = Object.create(EventEmitter.prototype);
@@ -328,6 +326,12 @@ 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;
}

View File

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

View File

@@ -36,7 +36,7 @@
.c-message {
display: flex;
align-items: flex-start;
align-items: center;
> * + * {
margin-left: $interiorMarginLg;
@@ -66,6 +66,17 @@
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

@@ -152,7 +152,7 @@
return this.internalDomainObject.configuration.items;
}
},
inject: ['openmct'],
inject: ['openmct', 'options'],
props: ['domainObject'],
components: ITEM_TYPE_VIEW_MAP,
methods: {
@@ -283,9 +283,8 @@
}
},
isTelemetry(domainObject) {
if (this.openmct.telemetry.isTelemetryObject(domainObject)
&& domainObject.type !== 'summary-widget'
&& domainObject.type !== 'example.imagery') {
if (this.openmct.telemetry.isTelemetryObject(domainObject) &&
!this.options.showAsView.includes(domainObject.type)) {
return true;
} else {
return false;

View File

@@ -25,8 +25,7 @@ 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 () {
export default function DisplayLayoutPlugin(options) {
return function (openmct) {
openmct.objectViews.addProvider({
key: 'layout.view',
@@ -47,7 +46,8 @@ export default function () {
template: '<layout ref="displayLayout" :domain-object="domainObject"></layout>',
provide: {
openmct,
objectUtils
objectUtils,
options
},
el: container,
data () {
@@ -83,5 +83,6 @@ export default function () {
return true;
}
});
DisplayLayoutPlugin._installed = true;
}
}

View File

@@ -76,7 +76,6 @@ define([
PlotOptionsController.prototype.addSeries = function (series, index) {
this.$scope.plotSeries[index] = series;
series.locateOldObject(this.$scope.domainObject);
};
PlotOptionsController.prototype.resetAllSeries = function (series, index) {

View File

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

View File

@@ -3,11 +3,9 @@
<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="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 class="js-summary-widget__message c-summary-widget__message c-message c-message--simple message-severity-alert">
<div class="c-summary-widget__text">
You must add at least one telemetry object to edit this widget.
</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">

View File

@@ -26,7 +26,8 @@
v-for="(tab, index) in tabsList"
:key="index"
:class="{'invisible': !isCurrent(tab)}">
<div class="c-tabs-view__object-name l-browse-bar__object-name--w"
<div v-if="currentTab"
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}}
@@ -81,6 +82,7 @@
}
&__empty-message {
background: rgba($colorBodyFg, 0.1);
color: rgba($colorBodyFg, 0.7);
font-style: italic;
text-align: center;
@@ -145,6 +147,13 @@ 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;
},
@@ -171,6 +180,7 @@ 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();
}
@@ -187,6 +197,7 @@ export default {
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);

View File

@@ -32,12 +32,20 @@ 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' || domainObject.hasOwnProperty('telemetry');
return domainObject.type === 'table' ||
hasTelemetry(domainObject)
},
canEdit(domainObject) {
return domainObject.type === 'table';

View File

@@ -432,9 +432,9 @@ export default {
shouldSnapToBottom() {
return this.scrollable.scrollTop >= (this.scrollable.scrollHeight - this.scrollable.offsetHeight - AUTO_SCROLL_TRIGGER_HEIGHT);
},
scrollToBottom() {
scrollToBottom: _.throttle(function() {
this.scrollable.scrollTop = this.scrollable.scrollHeight;
},
}, 100),
synchronizeScrollX() {
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
},

View File

@@ -126,7 +126,6 @@
grid-template-rows: 1fr;
grid-template-columns: 20px auto 1fr auto;
grid-template-areas: "tc-mode-icon tc-start tc-ticks tc-end";
overflow: hidden;
}
&__mode-icon {

View File

@@ -80,7 +80,7 @@ $formLabelW: 30%;
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;
$waitSpinnerBorderW: 5px;
$waitSpinnerTreeBorderW: 4px;
$waitSpinnerTreeBorderW: 3px;
/*************** Messages */
$messageIconD: 80px;
$messageListIconD: 32px;

View File

@@ -143,7 +143,7 @@
@include nice-input();
padding: $interiorMargin;
position: relative;
min-height: 150px;
min-height: 0; // Chrome 73 overflow bug fix
height: 100%;
>.wrapper {
$p: $interiorMargin;

View File

@@ -19,8 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/******************************* RESETS */
/******************************************************** RESETS */
*,
:before,
:after {
@@ -31,7 +30,7 @@ div {
position: relative;
}
/******************************* UTILITIES */
/******************************************************** UTILITIES */
.u-contents {
display: contents;
}
@@ -45,7 +44,7 @@ div {
}
}
/******************************* BROWSER ELEMENTS */
/******************************************************** BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {
box-sizing: border-box;
@@ -75,7 +74,7 @@ body.desktop {
}
}
/************************** HTML ENTITIES */
/******************************************************** HTML ENTITIES */
a {
color: $colorA;
cursor: pointer;
@@ -167,7 +166,6 @@ 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 {
@@ -204,169 +202,88 @@ body.desktop .has-local-controls {
}
}
/************************** LEGACY */
mct-container {
/******************************************************** 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;
display: block;
}
.abs {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: auto;
width: auto;
left: 50%; top: 50%;
transform-origin: center;
transform: translate(-50%, -50%);
}
.code {
font-family: "Lucida Console", monospace;
font-size: 0.7em;
line-height: 150%;
white-space: pre;
.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;
}
}
.codehilite {
@extend .code;
background-color: rgba($colorBodyFg, 0.1);
padding: 1em;
.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();
}
}
*[disabled],
.disabled,
a.disabled {
.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

@@ -461,7 +461,7 @@ body.mobile.phone {
width: $ruleLabelW;
}
.t-message-widget-no-data {
.js-summary-widget__message {
display: none;
}
@@ -508,7 +508,7 @@ body.mobile.phone {
&.expanded-widget-rules {
.widget-rules-wrapper {
min-height: 50px;
height: auto;
height: 100%; // Fix for Chrome 73 scrolling bug
opacity: 1;
pointer-events: inherit;
}
@@ -520,7 +520,7 @@ body.mobile.phone {
opacity: 0.3;
pointer-events: none;
}
.t-message-widget-no-data {
.js-summary-widget__message {
display: flex;
}
}
@@ -1177,79 +1177,6 @@ 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 {
@@ -1514,6 +1441,10 @@ body.desktop {
display: contents;
}
mct-container {
display: block;
}
.overlay {
.outer-holder {
background: $colorMenuBg;
@@ -1579,3 +1510,157 @@ body.desktop {
}
}
}
.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

@@ -25,9 +25,12 @@ table {
width: 100%;
thead {
background: $colorTabHeaderBg;
th + th {
border-left: 1px solid $colorTabHeaderBorder;
th {
background: $colorTabHeaderBg;
+ th {
border-left: 1px solid $colorTabHeaderBorder;
}
}
}
@@ -46,6 +49,8 @@ table {
td {
vertical-align: top;
}
a { color: $colorBtnMajorBg; }
}
div.c-table {

View File

@@ -142,7 +142,7 @@ export default {
this.applySearch(this.currentSearch);
},
removeElement(identifier) {
let keyString = this.openmct.objects.makeKeyString(element.identifier);
let keyString = this.openmct.objects.makeKeyString(identifier);
delete this.elementsCache[keyString];
this.applySearch(this.currentSearch);
},

View File

@@ -95,7 +95,7 @@
.l-pane__contents {
display: flex;
flex-flow: column nowrap;
overflow: auto;
overflow-x: hidden;
> * {
flex: 0 0 auto;
@@ -242,7 +242,10 @@
.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

View File

@@ -9,15 +9,15 @@
</div>
<!-- loading -->
<span v-if="isLoading"
class="loading">
</span>
<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">
<ul class="c-tree-and-search__tree c-tree"
v-if="!isLoading">
<tree-item v-for="treeItem in treeItems"
:key="treeItem.id"
:node="treeItem">
@@ -41,6 +41,10 @@
flex: 0 0 auto;
}
&__loading {
flex: 1 1 auto;
}
&__no-results {
font-style: italic;
opacity: 0.6;
@@ -54,10 +58,16 @@
.c-tree {
@include userSelectNone();
height: 100%; // Chrome 73 overflow bug fix
overflow-x: hidden;
overflow-y: auto;
padding-right: $interiorMargin;
li {
position: relative;
&.c-tree__item-h { display: block; }
}
.c-tree {
margin-left: 15px;
}

View File

@@ -11,14 +11,12 @@
</object-label>
</div>
<ul v-if="expanded" class="c-tree">
<!-- loading -->
<li
class="loading"
<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>
<!-- end loading -->
<tree-item v-for="child in children"
:key="child.id"
:node="child">