Compare commits

...

12 Commits

Author SHA1 Message Date
Deep Tailor
f04c274d33 fix lint issues 2020-11-12 16:02:57 -08:00
Deep Tailor
3624236c26 Merge branch 'three-dot-menu-proto' of https://github.com/nasa/openmct into openmct-status-api 2020-11-12 15:05:28 -08:00
Deep Tailor
2c49e62863 merge with latest three-dots 2020-11-12 15:01:37 -08:00
Charles Hacskaylo
c2df3cdd14 CSS and markup refactoring to support addition of 'suspect' telemetry (#3499)
* CSS and markup refactoring to support addition of 'suspect' telemetry

- Significant refactoring of CSS classing: `is-missing` is now
`is-status--missing` and `is-missing__indicator` is now simply
`is-status__indicator`, allowing the wrapping `is-missing--*` class to
control what is displayed;
- New SCSS mixin @isStatus, and changes to mixin @isMissing to support
new `is-status--suspect` class;
- Changed titling for missing objects from 'This item is missing' to
'This item is missing or suspect'. **IMPORTANT NOTE** This is temporary
and should be replaced with a more robust approach to titling that
allows title strings to be defined in configuration and dynamically
applied;
- Refactored computed property `statusClass` across multiple components
to return an empty string when status is undefined - this was
previously erroneously returning `is-undefined` in that circumstance;
- Removed commented code;

* CSS and markup refactoring to support addition of 'suspect' telemetry

- Refinements to broaden capability of `is-status*` mixin;
2020-11-12 14:58:51 -08:00
Deep Tailor
5f03dc45ee fix style application in telemetry vue 2020-10-29 15:44:57 -07:00
Deep Tailor
14ac758760 Merge branch 'three-dot-menu-proto' of https://github.com/nasa/openmct into openmct-status-api 2020-10-29 15:30:48 -07:00
Deep Tailor
eba1a48a44 fix lint errors 2020-10-29 15:19:42 -07:00
Deep Tailor
4a0654dbcb add tests for status API 2020-10-29 15:07:02 -07:00
Deep Tailor
9b6d339d69 add status to tabs view 2020-10-29 13:48:51 -07:00
Deep Tailor
f90afb9277 simplifying class applications 2020-10-29 13:35:19 -07:00
Deep Tailor
018dfb1e28 Merge branch 'master' of https://github.com/nasa/openmct into openmct-status-api 2020-10-29 11:59:03 -07:00
Deep Tailor
c72a02aaa3 wip 2020-10-29 11:07:49 -07:00
26 changed files with 344 additions and 133 deletions

View File

@@ -20,12 +20,12 @@
at runtime from the About dialog for additional information.
-->
<div class="c-object-label"
ng-class="{ 'is-missing': model.status === 'missing' }"
ng-class="{ 'is-status--missing': model.status === 'missing' }"
>
<div class="c-object-label__type-icon {{type.getCssClass()}}"
ng-class="{ 'l-icon-link':location.isLink() }"
>
<span class="is-missing__indicator" title="This item is missing"></span>
<span class="is-status__indicator" title="This item is missing or suspect"></span>
</div>
<div class='c-object-label__name'>{{model.name}}</div>
</div>

View File

@@ -246,6 +246,8 @@ define([
this.actions = new api.ActionsAPI(this);
this.status = new api.StatusAPI(this);
this.router = new ApplicationRouter();
this.branding = BrandingAPI.default;

View File

@@ -21,17 +21,14 @@
*****************************************************************************/
import ActionsAPI from './ActionsAPI';
import ActionsCollection from './ActionCollection';
import { createOpenMct, resetApplicationState } from '../../utils/testing';
describe('The Actions API', () => {
let openmct;
let actionsAPI;
let mockAction;
let invoked;
let mockObjectPath;
let mockViewContext1;
let mockViewContext2;
beforeEach(() => {
openmct = createOpenMct();
@@ -46,6 +43,7 @@ describe('The Actions API', () => {
appliesTo: (objectPath, view = {}) => {
if (view.getViewContext) {
let viewContext = view.getViewContext();
return viewContext.onlyAppliesToTestCase;
} else if (objectPath.length) {
return objectPath[0].type === 'fake-folder';
@@ -54,7 +52,6 @@ describe('The Actions API', () => {
return false;
},
invoke: () => {
invoked = true;
}
};
mockObjectPath = [
@@ -83,13 +80,6 @@ describe('The Actions API', () => {
};
}
};
mockViewContext2 = {
getViewContext:() => {
return {
onlyAppliesToTestCase: true
};
}
};
});
afterEach(() => {
@@ -99,7 +89,7 @@ describe('The Actions API', () => {
describe("register method", () => {
it("adds action to ActionsAPI", () => {
actionsAPI.register(mockAction);
let action = actionsAPI.get(mockObjectPath, mockViewContext1)[mockAction.key];
expect(action.key).toEqual(mockAction.key);

View File

@@ -30,8 +30,8 @@ define([
'./notifications/NotificationAPI',
'./Editor',
'./menu/MenuAPI',
'./actions/ActionsAPI'
'./actions/ActionsAPI',
'./status/StatusAPI'
], function (
TimeAPI,
ObjectAPI,
@@ -42,7 +42,8 @@ define([
NotificationAPI,
EditorAPI,
MenuAPI,
ActionsAPI
ActionsAPI,
StatusAPI
) {
return {
TimeAPI: TimeAPI,
@@ -54,6 +55,7 @@ define([
NotificationAPI: NotificationAPI.default,
EditorAPI: EditorAPI,
MenuAPI: MenuAPI.default,
ActionsAPI: ActionsAPI.default
ActionsAPI: ActionsAPI.default,
StatusAPI: StatusAPI.default
};
});

View File

@@ -0,0 +1,67 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
export default class StatusAPI extends EventEmitter {
constructor(openmct) {
super();
this._openmct = openmct;
this._statusCache = {};
this.get = this.get.bind(this);
this.set = this.set.bind(this);
this.observe = this.observe.bind(this);
}
get(identifier) {
let keyString = this._openmct.objects.makeKeyString(identifier);
return this._statusCache[keyString];
}
set(identifier, value) {
let keyString = this._openmct.objects.makeKeyString(identifier);
this._statusCache[keyString] = value;
this.emit(keyString, value);
}
delete(identifier) {
let keyString = this._openmct.objects.makeKeyString(identifier);
this._statusCache[keyString] = undefined;
this.emit(keyString, undefined);
delete this._statusCache[keyString];
}
observe(identifier, callback) {
let key = this._openmct.objects.makeKeyString(identifier);
this.on(key, callback);
return () => {
this.off(key, callback);
};
}
}

View File

@@ -0,0 +1,85 @@
import StatusAPI from './StatusAPI.js';
import { createOpenMct, resetApplicationState } from '../../utils/testing';
describe("The Status API", () => {
let statusAPI;
let openmct;
let identifier;
let status;
let status2;
let callback;
beforeEach(() => {
openmct = createOpenMct();
statusAPI = new StatusAPI(openmct);
identifier = {
namespace: "test-namespace",
key: "test-key"
};
status = "test-status";
status2 = 'test-status-deux';
callback = jasmine.createSpy('callback', (statusUpdate) => statusUpdate);
});
afterEach(() => {
resetApplicationState(openmct);
});
describe("set function", () => {
it("sets status for identifier", () => {
statusAPI.set(identifier, status);
let resultingStatus = statusAPI.get(identifier);
expect(resultingStatus).toEqual(status);
});
});
describe("get function", () => {
it("returns status for identifier", () => {
statusAPI.set(identifier, status2);
let resultingStatus = statusAPI.get(identifier);
expect(resultingStatus).toEqual(status2);
});
});
describe("delete function", () => {
it("deletes status for identifier", () => {
statusAPI.set(identifier, status);
let resultingStatus = statusAPI.get(identifier);
expect(resultingStatus).toEqual(status);
statusAPI.delete(identifier);
resultingStatus = statusAPI.get(identifier);
expect(resultingStatus).toBeUndefined();
});
});
describe("observe function", () => {
it("allows callbacks to be attached to status set and delete events", () => {
let unsubscribe = statusAPI.observe(identifier, callback);
statusAPI.set(identifier, status);
expect(callback).toHaveBeenCalledWith(status);
statusAPI.delete(identifier);
expect(callback).toHaveBeenCalledWith(undefined);
unsubscribe();
});
it("returns a unsubscribe function", () => {
let unsubscribe = statusAPI.observe(identifier, callback);
unsubscribe();
statusAPI.set(identifier, status);
expect(callback).toHaveBeenCalledTimes(0);
});
});
});

View File

@@ -30,18 +30,15 @@
>
<div
v-if="domainObject"
class="u-style-receiver c-telemetry-view"
:class="{
styleClass,
'is-missing': domainObject.status === 'missing'
}"
class="c-telemetry-view"
:class="[statusClass]"
:style="styleObject"
:data-font-size="item.fontSize"
:data-font="item.font"
@contextmenu.prevent="showContextMenu"
>
<div class="is-missing__indicator"
title="This item is missing"
<div class="is-status__indicator"
title="This item is missing or suspect"
></div>
<div
v-if="showLabel"
@@ -134,10 +131,14 @@ export default {
datum: undefined,
domainObject: undefined,
formats: undefined,
viewKey: `alphanumeric-format-${Math.random()}`
viewKey: `alphanumeric-format-${Math.random()}`,
status: ''
};
},
computed: {
statusClass() {
return (this.status) ? `is-status--${this.status}` : '';
},
showLabel() {
let displayMode = this.item.displayMode;
@@ -215,9 +216,13 @@ export default {
this.openmct.objects.get(this.item.identifier)
.then(this.setObject);
this.openmct.time.on("bounds", this.refreshData);
this.status = this.openmct.status.get(this.item.identifier);
this.removeStatusListener = this.openmct.status.observe(this.item.identifier, this.setStatus);
},
destroyed() {
this.removeSubscription();
this.removeStatusListener();
if (this.removeSelectable) {
this.removeSelectable();
@@ -339,6 +344,9 @@ export default {
async showContextMenu(event) {
const contextMenuActions = await this.getContextMenuActions();
this.openmct.menus.showMenu(event.x, event.y, contextMenuActions);
},
setStatus(status) {
this.status = status;
}
}
};

View File

@@ -29,12 +29,12 @@
@include isMissing($absPos: true);
.is-missing__indicator {
.is-status__indicator {
top: 0;
left: 0;
}
&.is-missing {
&.is-status--missing {
border: $borderMissing;
}
}

View File

@@ -1,11 +1,10 @@
<template>
<a
class="l-grid-view__item c-grid-item"
:class="{
:class="[{
'is-alias': item.isAlias === true,
'is-missing': item.model.status === 'missing',
'c-grid-item--unknown': item.type.cssClass === undefined || item.type.cssClass.indexOf('unknown') !== -1
}"
}, statusClass]"
:href="objectLink"
>
<div
@@ -27,8 +26,8 @@
</div>
</div>
<div class="c-grid-item__controls">
<div class="is-missing__indicator"
title="This item is missing"
<div class="is-status__indicator"
title="This item is missing or suspect"
></div>
<div
class="icon-people"
@@ -46,9 +45,10 @@
<script>
import contextMenuGesture from '../../../ui/mixins/context-menu-gesture';
import objectLink from '../../../ui/mixins/object-link';
import statusListener from './status-listener';
export default {
mixins: [contextMenuGesture, objectLink],
mixins: [contextMenuGesture, objectLink, statusListener],
props: {
item: {
type: Object,

View File

@@ -8,15 +8,15 @@
<a
ref="objectLink"
class="c-object-label"
:class="{ 'is-missing': item.model.status === 'missing' }"
:class="[statusClass]"
:href="objectLink"
>
<div
class="c-object-label__type-icon c-list-item__name__type-icon"
:class="item.type.cssClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<div class="c-object-label__name c-list-item__name__name">{{ item.model.name }}</div>
@@ -39,9 +39,10 @@
import moment from 'moment';
import contextMenuGesture from '../../../ui/mixins/context-menu-gesture';
import objectLink from '../../../ui/mixins/object-link';
import statusListener from './status-listener';
export default {
mixins: [contextMenuGesture, objectLink],
mixins: [contextMenuGesture, objectLink, statusListener],
props: {
item: {
type: Object,

View File

@@ -43,7 +43,7 @@
}
}
&.is-missing {
&.is-status--missing {
@include isMissing();
[class*='__type-icon'],

View File

@@ -0,0 +1,33 @@
export default {
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
}
},
computed: {
statusClass() {
return (this.status) ? `is-status--${this.status}` : '';
}
},
data() {
return {
status: ''
};
},
methods: {
setStatus(status) {
this.status = status;
}
},
mounted() {
let identifier = this.item.model.identifier;
this.status = this.openmct.status.get(identifier);
this.removeStatusListener = this.openmct.status.observe(identifier, this.setStatus);
},
destroyed() {
this.removeStatusListener();
}
};

View File

@@ -111,7 +111,7 @@ import Search from '@/ui/components/search.vue';
import SearchResults from './SearchResults.vue';
import Sidebar from './Sidebar.vue';
import { clearDefaultNotebook, getDefaultNotebook, setDefaultNotebook, setDefaultNotebookSection, setDefaultNotebookPage } from '../utils/notebook-storage';
import { DEFAULT_CLASS, addNotebookEntry, createNewEmbed, getNotebookEntries } from '../utils/notebook-entries';
import { addNotebookEntry, createNewEmbed, getNotebookEntries } from '../utils/notebook-entries';
import objectUtils from 'objectUtils';
import { throttle } from 'lodash';
@@ -416,14 +416,7 @@ export default {
return;
}
const classList = domainObject.classList || [];
const index = classList.indexOf(DEFAULT_CLASS);
if (!classList.length || index < 0) {
return;
}
classList.splice(index, 1);
this.openmct.objects.mutate(domainObject, 'classList', classList);
this.openmct.status.delete(domainObject.identifier);
},
searchItem(input) {
this.search = input;

View File

@@ -50,6 +50,7 @@ export default {
},
mounted() {
this.notebookSnapshot = new Snapshot(this.openmct);
this.setDefaultNotebookStatus();
},
methods: {
showMenu(event) {
@@ -105,6 +106,15 @@ export default {
this.notebookSnapshot.capture(snapshotMeta, notebook.type, element);
});
},
setDefaultNotebookStatus() {
let defaultNotebookObject = getDefaultNotebook();
if (defaultNotebookObject && defaultNotebookObject.notebookMeta) {
let notebookIdentifier = defaultNotebookObject.notebookMeta.identifier;
this.openmct.status.set(notebookIdentifier, 'notebook-default');
}
}
}
};

View File

@@ -1,6 +1,6 @@
import objectLink from '../../../ui/mixins/object-link';
export const DEFAULT_CLASS = 'is-notebook-default';
export const DEFAULT_CLASS = 'notebook-default';
const TIME_BOUNDS = {
START_BOUND: 'tc.startBound',
END_BOUND: 'tc.endBound',
@@ -129,7 +129,7 @@ export function addNotebookEntry(openmct, domainObject, notebookStorage, embed =
embeds
});
addDefaultClass(domainObject);
addDefaultClass(domainObject, openmct);
openmct.objects.mutate(domainObject, 'configuration.entries', entries);
return id;
@@ -199,11 +199,6 @@ export function deleteNotebookEntries(openmct, domainObject, selectedSection, se
openmct.objects.mutate(domainObject, 'configuration.entries', entries);
}
function addDefaultClass(domainObject) {
const classList = domainObject.classList || [];
if (classList.includes(DEFAULT_CLASS)) {
return;
}
classList.push(DEFAULT_CLASS);
function addDefaultClass(domainObject, openmct) {
openmct.status.set(domainObject.identifier, DEFAULT_CLASS);
}

View File

@@ -40,7 +40,7 @@
<div class="c-state-indicator__alert-cursor-lock icon-cursor-lock" title="Cursor is point locked. Click anywhere in the plot to unlock."></div>
<div class="plot-legend-item"
ng-class="{
'is-missing': series.domainObject.status === 'missing'
'is-status--missing': series.domainObject.status === 'missing'
}"
ng-repeat="series in series track by $index"
>
@@ -48,7 +48,7 @@
<span class="plot-series-color-swatch"
ng-style="{ 'background-color': series.get('color').asHexString() }">
</span>
<span class="is-missing__indicator" title="This item is missing"></span>
<span class="is-status__indicator" title="This item is missing or suspect"></span>
<span class="plot-series-name">{{ series.nameWithUnit() }}</span>
</div>
<div class="plot-series-value hover-value-enabled value-to-display-{{ legend.get('valueToShowWhenCollapsed') }} {{ series.closest.mctLimitState.cssClass }}"
@@ -95,14 +95,14 @@
<tr ng-repeat="series in series"
class="plot-legend-item"
ng-class="{
'is-missing': series.domainObject.status === 'missing'
'is-status--missing': series.domainObject.status === 'missing'
}"
>
<td class="plot-series-swatch-and-name">
<span class="plot-series-color-swatch"
ng-style="{ 'background-color': series.get('color').asHexString() }">
</span>
<span class="is-missing__indicator" title="This item is missing"></span>
<span class="is-status__indicator" title="This item is missing or suspect"></span>
<span class="plot-series-name">{{ series.get('name') }}</span>
</td>

View File

@@ -29,13 +29,13 @@
@click="showTab(tab, index)"
>
<div class="c-tabs-view__tab__label c-object-label"
:class="{'is-missing': tab.domainObject.status === 'missing'}"
:class="[tab.status ? `is-${tab.status}` : '']"
>
<div class="c-object-label__type-icon"
:class="tab.type.definition.cssClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<span class="c-button__label c-object-label__name">{{ tab.domainObject.name }}</span>
@@ -192,8 +192,10 @@ export default {
},
addItem(domainObject) {
let type = this.openmct.types.get(domainObject.type) || unknownObjectType;
let status = this.openmct.status.get(domainObject.identifier);
let tabItem = {
domainObject,
status,
type: type,
key: this.openmct.objects.makeKeyString(domainObject.identifier)
};

View File

@@ -59,12 +59,12 @@ mct-plot {
}
/*********************** MISSING ITEM INDICATORS */
.is-missing__indicator {
.is-status__indicator {
display: none;
}
.is-missing {
.is-status--missing {
@include isMissing();
.is-missing__indicator {
.is-status__indicator {
font-size: 0.8em;
}
}

View File

@@ -129,31 +129,44 @@
}
}
@mixin isMissing($absPos: false) {
@mixin isStatus($absPos: false) {
// Supports CSS classing as follows:
// is-status--missing, is-status--suspect, etc.
// Common styles to be applied to tree items, object labels, grid and list item views
//opacity: 0.7;
//pointer-events: none; // Don't think we can do this, as disables title hover on icon element
.is-missing__indicator {
.is-status__indicator {
display: none ;
text-shadow: $colorBodyBg 0 0 2px;
color: $colorAlert;
font-family: symbolsfont;
&:before {
content: $glyph-icon-alert-triangle;
&[class^='is-status'] .is-status__indicator,
[class^='is-status'] .is-status__indicator {
display: block !important;
}
}
@if $absPos {
.is-missing__indicator {
@if $absPos {
position: absolute;
z-index: 3;
}
}
}
&.is-missing .is-missing__indicator,
.is-missing .is-missing__indicator { display: block !important; }
@mixin isMissing($absPos: false) {
@include isStatus($absPos);
.is-status__indicator:before {
color: $colorAlert;
content: $glyph-icon-alert-triangle;
}
}
@mixin isSuspect($absPos: false) {
@include isStatus($absPos);
.is-status__indicator:before {
color: $colorWarningLo;
content: $glyph-icon-alert-rect;
}
}
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {

View File

@@ -35,16 +35,13 @@
class="c-so-view__header"
>
<div class="c-object-label"
:class="{
classList,
'is-missing': domainObject.status === 'missing'
}"
:class="[ statusClass ]"
>
<div class="c-object-label__type-icon"
:class="cssClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<div class="c-object-label__name">
@@ -88,8 +85,8 @@
</div>
</div>
<div class="is-missing__indicator"
title="This item is missing"
<div class="is-status__indicator"
title="This item is missing or suspect"
></div>
<object-view
ref="objectView"
@@ -160,20 +157,22 @@ export default {
cssClass,
complexContent,
viewProvider,
statusBarItems
statusBarItems,
status: ''
};
},
computed: {
classList() {
const classList = this.domainObject.classList;
if (!classList || !classList.length) {
return '';
}
return classList.join(' ');
statusClass() {
return (this.status) ? `is-status--${this.status}` : '';
}
},
mounted() {
this.status = this.openmct.status.get(this.domainObject.identifier);
this.removeStatusListener = this.openmct.status.observe(this.domainObject.identifier, this.setStatus);
},
beforeDestroy() {
this.removeStatusListener();
if (this.actionCollection) {
this.unlistenToActionCollection();
}
@@ -264,6 +263,9 @@ export default {
let sortedActions = this.openmct.actions._groupAndSortActions(actions);
this.openmct.menus.showMenu(event.x, event.y, sortedActions);
},
setStatus(status) {
this.status = status;
}
}
};

View File

@@ -1,10 +1,7 @@
<template>
<a
class="c-tree__item__label c-object-label"
:class="{
classList,
'is-missing': observedObject.status === 'missing'
}"
:class="[statusClass]"
draggable="true"
:href="objectLink"
@dragstart="dragStart"
@@ -14,8 +11,8 @@
class="c-tree__item__type-icon c-object-label__type-icon"
:class="typeClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<div class="c-tree__item__name c-object-label__name">
@@ -49,18 +46,11 @@ export default {
},
data() {
return {
observedObject: this.domainObject
observedObject: this.domainObject,
status: ''
};
},
computed: {
classList() {
const classList = this.observedObject.classList;
if (!classList || !classList.length) {
return '';
}
return classList.join(' ');
},
typeClass() {
let type = this.openmct.types.get(this.observedObject.type);
if (!type) {
@@ -68,6 +58,9 @@ export default {
}
return type.definition.cssClass;
},
statusClass() {
return (this.status) ? `is-status--${this.status}` : '';
}
},
mounted() {
@@ -78,8 +71,13 @@ export default {
this.$once('hook:destroyed', removeListener);
}
this.removeStatusListener = this.openmct.status.observe(this.observedObject.identifier, this.setStatus);
this.status = this.openmct.status.get(this.observedObject.identifier);
this.previewAction = new PreviewAction(this.openmct);
},
destroyed() {
this.removeStatusListener();
},
methods: {
navigateOrPreview(event) {
if (this.openmct.editor.isEditing()) {
@@ -110,6 +108,9 @@ export default {
// (eg. notabook.)
event.dataTransfer.setData("openmct/domain-object-path", serializedPath);
event.dataTransfer.setData(`openmct/domain-object/${keyString}`, this.domainObject);
},
setStatus(status) {
this.status = status;
}
}
};

View File

@@ -110,10 +110,10 @@
}
}
&.is-missing {
&.is-status--missing {
@include isMissing($absPos: true);
.is-missing__indicator {
.is-status__indicator {
top: $interiorMargin;
left: $interiorMargin;
}
@@ -145,7 +145,7 @@
> .c-so-view__view-large { display: block; }
}
&.is-missing {
&.is-status--missing {
border: $borderMissing;
}

View File

@@ -21,7 +21,7 @@
font-size: 1.1em;
}
&.is-missing {
&.is-status--missing {
@include isMissing($absPos: true);
[class*='__type-icon']:before,
@@ -29,7 +29,7 @@
opacity: $opacityMissing;
}
.is-missing__indicator {
.is-status__indicator {
right: -3px;
top: -3px;
transform: scale(0.7);

View File

@@ -2,13 +2,13 @@
<div class="c-inspector__header">
<div v-if="!multiSelect"
class="c-inspector__selected c-object-label"
:class="{'is-missing': isMissing }"
:class="{'is-status--missing': isMissing }"
>
<div class="c-object-label__type-icon"
:class="typeCssClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<span v-if="!singleSelectNonObject"

View File

@@ -9,16 +9,13 @@
></button>
<div
class="l-browse-bar__object-name--w c-object-label"
:class="{
classList,
'is-missing': domainObject.status === 'missing'
}"
:class="[statusClass]"
>
<div class="c-object-label__type-icon"
:class="type.cssClass"
>
<span class="is-missing__indicator"
title="This item is missing"
<span class="is-status__indicator"
title="This item is missing or suspect"
></span>
</div>
<span
@@ -149,17 +146,13 @@ export default {
viewKey: undefined,
isEditing: this.openmct.editor.isEditing(),
notebookEnabled: this.openmct.types.get('notebook'),
statusBarItems: []
statusBarItems: [],
status: ''
};
},
computed: {
classList() {
const classList = this.domainObject.classList;
if (!classList || !classList.length) {
return '';
}
return classList.join(' ');
statusClass() {
return (this.status) ? `is-status--${this.status}` : '';
},
currentView() {
return this.views.filter(v => v.key === this.viewKey)[0] || {};
@@ -225,6 +218,13 @@ export default {
this.mutationObserver = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
this.domainObject = domainObject;
});
if (this.removeStatusListener) {
this.removeStatusListener();
}
this.status = this.openmct.status.get(this.domainObject.identifier, this.setStatus);
this.removeStatusListener = this.openmct.status.observe(this.domainObject.identifier, this.setStatus);
},
viewProvider(viewProvider) {
if (this.actionCollection) {
@@ -259,6 +259,10 @@ export default {
this.unlistenToActionCollection();
}
if (this.removeStatusListener) {
this.removeStatusListener();
}
document.removeEventListener('click', this.closeViewAndSaveMenu);
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
},
@@ -366,6 +370,9 @@ export default {
},
toggleLock(flag) {
this.openmct.objects.mutate(this.domainObject, 'locked', flag);
},
setStatus(status) {
this.status = status;
}
}
};

View File

@@ -380,7 +380,7 @@
margin-left: $interiorMarginLg;
min-width: 0;
.is-missing__indicator {
.is-status__indicator {
right: -5px !important;
top: -4px !important;
}