mirror of
https://github.com/nasa/openmct.git
synced 2025-01-11 15:32:56 +00:00
Overlay Service re-written in Vue (#2186)
* working overlayService * wire to snapshot, and add onDestroy Callback * increment overlayId * New branch from topic-core-refactor to use as central point for common CSS work - Manually migrated changes from vue-toolbar, expect conflicts there and in vue-layout; * Manually update constants-snow from vue-toolbar branch * Update markup to use latest button classnames - c-menu-button > c-button--menu; - c-icon-button > c-click-icon; * Various from vue-conductor-style - Mods to input styling; - Input[] styles moved to _controls; - New/revised constants vals; * Resolve bizarre merge conflict when applying stash * Code cleanup * remove duplicate div * Alias and type-icon fixes - More robust approach to alias indicators; - Added alias indication to tree-item.vue; - TODO: wire up alias indication tree-item.vue; * Accessibility mods, convert elements to <button> - Better reset styles for htmlInputReset mixin to allow use of <button> without browser default styling; - Create button; - BrowseBar action buttons; - c-click-icons; - Removed Preview button from BrowseBar.vue; * Overlay styling WIP - Base markup pretty solid; - Stubbed in temp values for overlayTypeCssClass in overlayService.js; - TODO: styling for contents area; * add options object, scope variables to show function, add destroy callback to active Overlay Object (for easier retrieval
This commit is contained in:
parent
e7cdb334de
commit
f40c9fa6f9
@ -40,6 +40,7 @@ define([
|
|||||||
'./styles-new/core.scss',
|
'./styles-new/core.scss',
|
||||||
'./styles-new/notebook.scss',
|
'./styles-new/notebook.scss',
|
||||||
'./ui/components/layout/Layout.vue',
|
'./ui/components/layout/Layout.vue',
|
||||||
|
'./ui/overlayService/overlayService',
|
||||||
'vue'
|
'vue'
|
||||||
], function (
|
], function (
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
@ -61,6 +62,7 @@ define([
|
|||||||
coreStyles,
|
coreStyles,
|
||||||
NotebookStyles,
|
NotebookStyles,
|
||||||
Layout,
|
Layout,
|
||||||
|
OverlayService,
|
||||||
Vue
|
Vue
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
@ -225,6 +227,8 @@ define([
|
|||||||
|
|
||||||
this.editor = new api.EditorAPI.default(this);
|
this.editor = new api.EditorAPI.default(this);
|
||||||
|
|
||||||
|
this.OverlayService = new OverlayService();
|
||||||
|
|
||||||
this.legacyRegistry = defaultRegistry;
|
this.legacyRegistry = defaultRegistry;
|
||||||
this.install(this.plugins.Plot());
|
this.install(this.plugins.Plot());
|
||||||
this.install(this.plugins.TelemetryTable());
|
this.install(this.plugins.TelemetryTable());
|
||||||
|
29
src/plugins/notebook/res/templates/snapshotTemplate.html
Normal file
29
src/plugins/notebook/res/templates/snapshotTemplate.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<div class="u-contents">
|
||||||
|
|
||||||
|
<div class="t-snapshot abs l-view-header">
|
||||||
|
<div class="abs object-browse-bar l-flex-row">
|
||||||
|
<div class="left flex-elem l-flex-row grows">
|
||||||
|
<div class="object-header flex-elem l-flex-row grows">
|
||||||
|
<div class="type-icon flex-elem embed-icon holder" v-bind:class="embed.cssClass"></div>
|
||||||
|
<div class="title-label flex-elem holder flex-can-shrink">{{embed.name}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||||
|
<div class="flex-elem holder flex-can-shrink s-snapshot-datetime">
|
||||||
|
SNAPSHOT {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
|
||||||
|
</div>
|
||||||
|
<a class="s-button icon-pencil" title="Annotate">
|
||||||
|
<span class="title-label">Annotate</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="abs object-holder t-image-holder s-image-holder">
|
||||||
|
<div
|
||||||
|
class="image-main s-image-main"
|
||||||
|
v-bind:style="{ backgroundImage: 'url(' + embed.snapshot.src + ')' }">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -24,11 +24,15 @@ define([
|
|||||||
'moment',
|
'moment',
|
||||||
'zepto',
|
'zepto',
|
||||||
'../utils/SnapshotOverlay',
|
'../utils/SnapshotOverlay',
|
||||||
|
'../../res/templates/snapshotTemplate.html',
|
||||||
|
'vue'
|
||||||
],
|
],
|
||||||
function (
|
function (
|
||||||
Moment,
|
Moment,
|
||||||
$,
|
$,
|
||||||
SnapshotOverlay
|
SnapshotOverlay,
|
||||||
|
SnapshotTemplate,
|
||||||
|
Vue
|
||||||
) {
|
) {
|
||||||
function EmbedController (openmct, domainObject) {
|
function EmbedController (openmct, domainObject) {
|
||||||
this.openmct = openmct;
|
this.openmct = openmct;
|
||||||
@ -53,11 +57,24 @@ function (
|
|||||||
};
|
};
|
||||||
|
|
||||||
EmbedController.prototype.openSnapshot = function () {
|
EmbedController.prototype.openSnapshot = function () {
|
||||||
if (!this.snapshotOverlay) {
|
var self = this,
|
||||||
this.snapShotOverlay = new SnapshotOverlay(this.embed, this.formatTime);
|
snapshot = new Vue({
|
||||||
} else {
|
template: SnapshotTemplate,
|
||||||
this.snapShotOverlay = undefined;
|
data: function () {
|
||||||
|
return {
|
||||||
|
embed: self.embed
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatTime: self.formatTime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function onDestroyCallback() {
|
||||||
|
snapshot.$destroy(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.openmct.OverlayService.show(snapshot.$mount().$el, {onDestroy: onDestroyCallback, cssClass: 'l-large-view'});
|
||||||
};
|
};
|
||||||
|
|
||||||
EmbedController.prototype.formatTime = function (unixTime, timeFormat) {
|
EmbedController.prototype.formatTime = function (unixTime, timeFormat) {
|
||||||
|
@ -60,6 +60,7 @@ function (
|
|||||||
this.container = container;
|
this.container = container;
|
||||||
|
|
||||||
var notebookEmbed = {
|
var notebookEmbed = {
|
||||||
|
inject:['openmct'],
|
||||||
props:['embed', 'entry'],
|
props:['embed', 'entry'],
|
||||||
template: EmbedTemplate,
|
template: EmbedTemplate,
|
||||||
data: embedController.exposedData,
|
data: embedController.exposedData,
|
||||||
@ -80,6 +81,7 @@ function (
|
|||||||
|
|
||||||
var notebookVue = Vue.extend({
|
var notebookVue = Vue.extend({
|
||||||
template: NotebookTemplate,
|
template: NotebookTemplate,
|
||||||
|
provide: {openmct: self.openmct},
|
||||||
components: {
|
components: {
|
||||||
'notebook-entry': entryComponent,
|
'notebook-entry': entryComponent,
|
||||||
'search': search.default
|
'search': search.default
|
||||||
|
@ -224,9 +224,9 @@ $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
|
|||||||
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
|
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
|
||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
$colorOvrBlocker: rgba(black, 0.7);//
|
$colorOvrBlocker: rgba(black, 0.7); // Used
|
||||||
$colorOvrBg: $colorBodyBg;
|
$colorOvrBg: $colorBodyBg; // Used
|
||||||
$colorOvrFg: $colorBodyFg;
|
$colorOvrFg: $colorBodyFg; // Used
|
||||||
$colorOvrBtnBg: pullForward($colorOvrBg, 40%);
|
$colorOvrBtnBg: pullForward($colorOvrBg, 40%);
|
||||||
$colorOvrBtnFg: #fff;
|
$colorOvrBtnFg: #fff;
|
||||||
$colorFieldHintOverlay: pullForward($colorOvrBg, 40%);
|
$colorFieldHintOverlay: pullForward($colorOvrBg, 40%);
|
||||||
|
@ -40,6 +40,8 @@ $inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
|
|||||||
$menuLineH: 1.5rem;
|
$menuLineH: 1.5rem;
|
||||||
$treeItemIndent: 16px;
|
$treeItemIndent: 16px;
|
||||||
$treeTypeIconW: 18px;
|
$treeTypeIconW: 18px;
|
||||||
|
$overlayOuterMargin: 5%;
|
||||||
|
$overlayInnerMargin: 25px;
|
||||||
|
|
||||||
/*************** Items */
|
/*************** Items */
|
||||||
$itemPadLR: 5px;
|
$itemPadLR: 5px;
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// VERSION MANUALLY MIGRATED FROM VUE-TOOLBAR
|
||||||
|
|
||||||
/************************** VISUALS */
|
/************************** VISUALS */
|
||||||
@mixin ancillaryIcon($d, $c) {
|
@mixin ancillaryIcon($d, $c) {
|
||||||
// Used for small icons used in combination with larger icons,
|
// Used for small icons used in combination with larger icons,
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
import viewControl from '../controls/viewControl.vue'
|
import viewControl from '../controls/viewControl.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'tree-item',
|
name: 'tree-item',
|
||||||
inject: ['openmct'],
|
inject: ['openmct', 'domainObject'],
|
||||||
props: {
|
props: {
|
||||||
node: Object
|
node: Object
|
||||||
},
|
},
|
||||||
|
91
src/ui/overlayService/overlay.vue
Normal file
91
src/ui/overlayService/overlay.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div class="c-overlay">
|
||||||
|
<div class="c-overlay__blocker"
|
||||||
|
v-on:click="destroy">
|
||||||
|
</div>
|
||||||
|
<div class="c-overlay__outer">
|
||||||
|
<button class="c-click-icon c-overlay__close-button icon-x-in-circle"
|
||||||
|
v-on:click="destroy">
|
||||||
|
</button>
|
||||||
|
<div class="c-overlay__contents" ref="element"></div>
|
||||||
|
<div class="c-overlay__button-bar">
|
||||||
|
<button class="c-button c-button--major"
|
||||||
|
v-on:click="destroy">Done</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "~styles/sass-base";
|
||||||
|
|
||||||
|
.l-overlay-wrapper {
|
||||||
|
// Created by overlayService.js, contains this template.
|
||||||
|
// Acts as an anchor for one or more overlays.
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-overlay {
|
||||||
|
@include abs();
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
&__blocker {
|
||||||
|
display: none; // Mobile-first
|
||||||
|
}
|
||||||
|
|
||||||
|
&__outer {
|
||||||
|
@include abs();
|
||||||
|
background: $colorOvrBg;
|
||||||
|
color: $colorOvrFg;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: $overlayInnerMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__close-button {
|
||||||
|
$p: $interiorMarginSm;
|
||||||
|
border-radius: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: $p; right: $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__contents {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button-bar {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: $interiorMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.desktop & {
|
||||||
|
&__blocker {
|
||||||
|
@include abs();
|
||||||
|
background: $colorOvrBlocker;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__outer {
|
||||||
|
$m: $overlayOuterMargin;
|
||||||
|
top: $m; right: $m; bottom: $m; left: $m;
|
||||||
|
border-radius: $overlayCr;
|
||||||
|
box-shadow: rgba(black, 0.5) 0 2px 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
inject: ['destroy', 'element'],
|
||||||
|
mounted() {
|
||||||
|
this.$refs.element.appendChild(this.element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
87
src/ui/overlayService/overlayService.js
Normal file
87
src/ui/overlayService/overlayService.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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([
|
||||||
|
'./overlay.vue',
|
||||||
|
'vue'
|
||||||
|
], function (
|
||||||
|
OverlayComponent,
|
||||||
|
Vue
|
||||||
|
) {
|
||||||
|
|
||||||
|
function OverlayService() {
|
||||||
|
this.activeOverlays = [];
|
||||||
|
this.overlayId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayService.prototype.show = function (element, options) {
|
||||||
|
if(this.activeOverlays.length) {
|
||||||
|
this.activeOverlays[this.activeOverlays.length - 1].overlay.classList.add('invisible');
|
||||||
|
}
|
||||||
|
|
||||||
|
let overlayTypeCssClass = options.cssClass, // Values could be l-large-view, l-dialog, l-message
|
||||||
|
overlay = document.createElement('div'),
|
||||||
|
component = new Vue({
|
||||||
|
provide: {
|
||||||
|
destroy: this.destroy.bind(this),
|
||||||
|
element: element
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
OverlayComponent: OverlayComponent.default
|
||||||
|
},
|
||||||
|
template: '<overlay-component></overlay-component>'
|
||||||
|
});
|
||||||
|
|
||||||
|
overlay.classList.add('l-overlay-wrapper', overlayTypeCssClass);
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
overlay.appendChild(component.$mount().$el);
|
||||||
|
|
||||||
|
this.activeOverlays.push({
|
||||||
|
overlay: overlay,
|
||||||
|
component: component,
|
||||||
|
onDestroy: options.onDestroy,
|
||||||
|
id: this.overlayId
|
||||||
|
});
|
||||||
|
|
||||||
|
this.overlayId++;
|
||||||
|
};
|
||||||
|
|
||||||
|
OverlayService.prototype.destroy = function () {
|
||||||
|
var lastActiveOverlayObject = this.activeOverlays.pop(),
|
||||||
|
lastActiveOverlay = lastActiveOverlayObject.overlay,
|
||||||
|
lastActiveComponent = lastActiveOverlayObject.component;
|
||||||
|
|
||||||
|
if (lastActiveOverlayObject.onDestroy && typeof lastActiveOverlayObject.onDestroy === 'function') {
|
||||||
|
lastActiveOverlayObject.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
lastActiveComponent.$destroy(true);
|
||||||
|
document.body.removeChild(lastActiveOverlay);
|
||||||
|
|
||||||
|
if (this.activeOverlays.length) {
|
||||||
|
this.activeOverlays[this.activeOverlays.length - 1].overlay.classList.remove('invisible');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return OverlayService;
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user