openmct/src/plugins/timeConductor/ConductorMode.vue
Charles Hacskaylo 5f9f3cd8e8 Topic themes (#2187)
* Bringing over in-progress changes from topic-core-css

- Adds _espresso-constants.scss;
- Cleanup colors and naming;
- Remove conflict res leftover 'domainObject' in mct-tree.vue;
- Still WIP!

* Various

- Remove pushBack / pullForward functions;
- Fix c-input-inline, remove bg until hover;
- TODO: input bg colors
- Increased margin in main-pane;

* Themeing WIP

- Conductor markup: convert to buttons for accessibility;
- Conductor styles consolidated and changed for better theme support;

* Themeing WIP; significant rewrite of pane headers

- Pane headers restructured for better semantics and clarity;
- Espresso design refined and tightened;
- Grid Vue changes for better themeing support;
- TODO: fix mobile version, collapse icon is whack;

* Restored Number-type input styling for correct positioning of spinner
button;

* Themeing mods for click-icon styles

* Bring Snow theme into style parity with Espresso

- TODO: refine Snow colors;

* Mobile styling fixed

- Mobile menu icon significant fixes;
- Hover only applied to desktop;
- Reorg of mixins;

* Bring Snow theme constants into parity with Espresso

- Refined Snow styles;
- Fixed missing scroll and padding in tree;
- Pane collapse button now uses proper color;
- Item Grid view refinement;
- Cleaned up code;

* Color fixes

- Super-menu description;
- Conductor time buttons hover;
- Datepicker "in-month" items color;
- Espresso colorKeyFilter brightened;
2018-10-10 12:45:46 -07:00

203 lines
7.1 KiB
Vue

/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web 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 Web 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>
<div class="c-ctrl-wrapper c-ctrl-wrapper--menus-up">
<button class="c-button--menu c-mode-button"
@click="toggleMenu($event)">
<span class="c-button__label">{{selectedMode.name}}</span>
</button>
<div class="c-menu c-super-menu c-conductor__mode-menu"
v-if="showMenu">
<div class="c-super-menu__menu">
<ul>
<li v-for="mode in modes"
:key="mode.key"
@click="setOption(mode)"
@mouseover="hoveredMode = mode"
@mouseleave="hoveredMode = {}"
class="menu-item-a"
:class="mode.cssClass">
{{mode.name}}
</li>
</ul>
</div>
<div class="c-super-menu__item-description">
<div :class="['l-item-description__icon', 'bg-' + hoveredMode.cssClass]"></div>
<div class="l-item-description__name">{{hoveredMode.name}}</div>
<div class="l-item-description__description">{{hoveredMode.description}}</div>
</div>
</div>
</div>
</template>
<style lang="scss">
@import "~styles/sass-base";
.c-conductor__mode-menu {
max-height: 80vh;
max-width: 500px;
min-height: 250px;
z-index: 70;
[class*="__icon"] {
filter: $colorKeyFilter;
}
[class*="__item-description"] {
min-width: 200px;
}
}
</style>
<script>
export default {
inject: ['openmct', 'configuration'],
data: function () {
let activeClock = this.openmct.time.clock();
if (activeClock !== undefined) {
//Create copy of active clock so the time API does not get reactified.
activeClock = Object.create(activeClock);
}
return {
selectedMode: this.getModeOptionForClock(activeClock),
selectedTimeSystem: JSON.parse(JSON.stringify(this.openmct.time.timeSystem())),
modes: [],
hoveredMode: {},
showMenu: false
};
},
methods: {
loadClocksFromConfiguration() {
let clocks = this.configuration.menuOptions
.map(menuOption => menuOption.clock)
.filter(isDefinedAndUnique)
.map(this.getClock);
/*
* Populate the modes menu with metadata from the available clocks
* "Fixed Mode" is always first, and has no defined clock
*/
this.modes = [undefined]
.concat(clocks)
.map(this.getModeOptionForClock);
function isDefinedAndUnique(key, index, array) {
return key!== undefined && array.indexOf(key) === index;
}
},
getModeOptionForClock(clock) {
if (clock === undefined) {
return {
key: 'fixed',
name: 'Fixed Timespan Mode',
description: 'Query and explore data that falls between two fixed datetimes.',
cssClass: 'icon-tabular'
}
} else {
return {
key: clock.key,
name: clock.name,
description: "Monitor streaming data in real-time. The Time " +
"Conductor and displays will automatically advance themselves based on this clock. " + clock.description,
cssClass: clock.cssClass || 'icon-clock'
}
}
},
getClock(key) {
return this.openmct.time.getAllClocks().filter(function (clock) {
return clock.key === key;
})[0];
},
setOption(option) {
let clockKey = option.key;
if (clockKey === 'fixed') {
clockKey = undefined;
}
let configuration = this.getMatchingConfig({
clock: clockKey,
timeSystem: this.openmct.time.timeSystem().key
});
if (configuration === undefined) {
configuration = this.getMatchingConfig({
clock: clockKey
});
this.openmct.time.timeSystem(configuration.timeSystem, configuration.bounds);
}
if (clockKey === undefined) {
this.openmct.time.stopClock();
} else {
this.openmct.time.clock(clockKey, configuration.clockOffsets);
}
},
getMatchingConfig(options) {
const matchers = {
clock(config) {
return options.clock === config.clock
},
timeSystem(config) {
return options.timeSystem === config.timeSystem
}
};
function configMatches(config) {
return Object.keys(options).reduce((match, option) => {
return match && matchers[option](config);
}, true);
}
return this.configuration.menuOptions.filter(configMatches)[0];
},
setViewFromClock(clock) {
this.selectedMode = this.getModeOptionForClock(clock);
},
toggleMenu(event) {
this.showMenu = !this.showMenu;
if (this.showMenu) {
document.addEventListener('click', this.toggleMenu, true);
} else {
document.removeEventListener('click', this.toggleMenu, true);
}
},
},
mounted: function () {
this.loadClocksFromConfiguration();
this.openmct.time.on('clock', this.setViewFromClock);
},
destroyed: function () {
this.openmct.time.off('clock', this.setViewFromClock);
}
}
</script>