TimeTrex/interface/html5/components/TTMainUI.vue

381 lines
15 KiB
Vue
Raw Permalink Normal View History

2022-12-13 07:10:06 +01:00
<template>
<div v-show="showUI" :class="containerClass" @click="onDocumentClick">
<Toast/>
<TTTopContainer class="hide-in-login"
:topbarMenuActive="topbarMenuActive"
:activeTopbarItem="activeTopbarItem"
@menubutton-click="onMenuButtonClick"
@topbar-menubutton-click="onTopbarMenuButtonClick"
@topbar-item-click="onTopbarItemClick"/>
<TTLeftContainer class="hide-in-login"
:isMenuVisible="isMenuVisible()"
:layoutMode="layoutMode"
@menuitem-click="onMenuItemClick"/>
<div class="layout-content ">
<div class="layout-content-container">
<!-- <router-view></router-view>router-view-->
<router-view :key="$route.fullPath"></router-view> <!-- The router view is setup with this :key to allow the LegacyView component to be re-used instead of cached, ensuring unique component state for each view. -->
</div>
<div v-if="staticMenuMobileActive" class="layout-mask"></div>
</div>
</div>
</template>
<script>
// TODO: Bug: Noticed on a refresh that the main logo in top left flashes with the Apollo logo before showing the company logo.
import TTTopContainer from '@/components/TTTopContainer';
import TTLeftContainer from '@/components/TTLeftContainer';
export default {
created() {
this.event_bus = new TTEventBus( {
component_id: this.component_id
} );
this.event_bus.on( 'global', 'reset_vue_data', this.resetData );
this.event_bus.on( this.component_id, 'get_user_saved_layout_mode', this.getSavedLayoutMode );
this.event_bus.on( this.component_id, 'toggle_ui', this.getSavedLayoutMode );
$( window ).off( 'resize.tt_main' ).on( 'resize.tt_main', Global.debounce( function() {
this.resizeContentLayout();
}, 200 ).bind( this ) );
},
data() {
return {
component_id: 'tt_main_ui',
layoutMode: 'static',
savedLayoutId: '',
showUI: true,
staticMenuDesktopInactive: false,
staticMenuMobileActive: false,
overlayMenuActive: false,
topbarMenuActive: false,
activeTopbarItem: null,
menuActive: false,
};
},
methods: {
resetData() {
Object.assign( this.$data, this.$options.data() );
},
onDocumentClick() {
if ( !this.topbarItemClick ) {
this.activeTopbarItem = null;
this.topbarMenuActive = false;
}
if ( !this.menuClick ) {
if ( this.isHorizontal() || this.isSlim() ) {
this.menuActive = false;
this.event_bus.emit( 'app_menu', 'set_active_index', {
index: null
} );
}
this.hideOverlayMenu();
}
this.topbarItemClick = false;
this.menuClick = false;
},
onMenuClick() {
this.menuClick = true;
},
onMenuButtonClick( event ) {
this.menuClick = true;
this.topbarMenuActive = false;
if ( this.layoutMode === 'overlay' && !this.isMobile() ) {
this.overlayMenuActive = !this.overlayMenuActive;
} else {
if ( this.isDesktop() ) {
// this.staticMenuDesktopInactive = !this.staticMenuDesktopInactive;
//Close open menus when switching menu layout mode.
this.event_bus.emit( 'app_menu', 'set_active_index', {
index: null
} );
if ( this.layoutMode === 'slim' ) {
//In slim mode we offset submenus to prevent the menu from going off screen.
//This needs to be reset when switching from slim so that the changes do not carry over to layout modes.
this.event_bus.emit( 'tt_left_container', 'reset_slim_offsets' );
}
// Override PrimeVue behaviour to use burger button to toggle menu between static, slim and horizontal layouts.
this.layoutMode = this.layoutMode === 'static' ? 'slim' : this.layoutMode === 'slim' ? 'horizontal' : 'static';
this.saveLayoutMode( this.layoutMode )
} else {
this.staticMenuMobileActive = !this.staticMenuMobileActive;
}
}
this.dispatchResizeEvent();
event.preventDefault();
},
onTopbarMenuButtonClick( event ) {
this.topbarItemClick = true;
this.topbarMenuActive = !this.topbarMenuActive;
this.hideOverlayMenu();
event.preventDefault();
},
onTopbarItemClick( event ) {
this.topbarItemClick = true;
if ( this.activeTopbarItem === event.item )
this.activeTopbarItem = null;
else
this.activeTopbarItem = event.item;
event.originalEvent.preventDefault();
},
isDesktop() {
return window.innerWidth > 1024;
},
isMobile() {
return window.innerWidth <= 640;
},
isHorizontal() {
return this.layoutMode === 'horizontal';
},
isSlim() {
return this.layoutMode === 'slim';
},
hideOverlayMenu() {
this.overlayMenuActive = false;
this.staticMenuMobileActive = false;
},
onMenuItemClick( event ) {
if ( !event.item.items ) {
this.event_bus.emit( this.component_id, 'reset-active-index' );
this.hideOverlayMenu();
} else {
this.menuClick = true;
}
if ( !event.item.items && ( this.isHorizontal() || this.isSlim() ) ) {
this.menuActive = false;
}
},
onRootMenuItemClick() {
this.menuActive = !this.menuActive;
},
isMenuVisible() {
if ( this.isDesktop() ) {
if ( this.layoutMode === 'static' ) {
// return !this.staticMenuDesktopInactive;
return true; // Always want to show the contents of the left menu, so that when it slides in/out, the menu doesn't just flash away, but properly slides away with the container.
} else if ( this.layoutMode === 'overlay' )
return this.overlayMenuActive;
else
return true;
} else {
return true;
}
},
toggleConfigurator() {
this.configuratorActive = !this.configuratorActive;
},
hideConfigurator() {
this.configuratorActive = false;
},
onLayoutChange( layoutMode ) {
this.layoutMode = layoutMode;
this.dispatchResizeEvent();
},
resizeContentLayout() {
//Need to resize main content area to account for height changes when horizontal bar stacks on lower widths.
if ( this.isHorizontal() ) {
setTimeout( () => {
let content_container = document.querySelector( '.content-container-after-login' );
if ( !content_container ) {
return;
}
//Horizontal menu is only shown on desktop resolutions (1024px+).
if ( this.isDesktop() ) {
let height = window.innerHeight - document.querySelector( '.layout-menu-container ' ).getBoundingClientRect().bottom;
content_container.style.height = height + 'px';
} else {
let height = window.innerHeight - document.querySelector( '.layout-topbar ' ).getBoundingClientRect().bottom;
content_container.style.height = height + 'px';
}
}, 250 );
}
},
dispatchResizeEvent() {
//Trigger resize events such as dashlet resizing on homeview.
//Delay used to trigger event after layout change to help prevent issues.
setTimeout( () => {
window.dispatchEvent( new Event( 'resize' ) );
}, 250 );
},
saveLayoutMode( layoutMode ) {
let args = {};
args.script = 'global_main_menu';
args.name = 'settings';
args.is_default = false;
args.data = {};
args.data.layout_mode = layoutMode;
if ( this.savedLayoutId ) { //If we have a saved layout id, then the api call is an update and not a create.
args.id = this.savedLayoutId;
}
TTAPI.APIUserGenericData.setUserGenericData( args, {
onResult: function( res ) {
if ( !res.isValid() ) {
Debug.Error( 'Error: Saving user layout mode selectiin failed', 'TTMainUI.vue', 'TTMainUI', 'saveLayoutMode', 10 );
}
}
} );
this.resizeContentLayout();
},
getSavedLayoutMode() {
let $this = this;
let filter_data = {};
filter_data.script = 'global_main_menu';
filter_data.name = 'settings';
filter_data.deleted = false;
TTAPI.APIUserGenericData.getUserGenericData( { filter_data: filter_data }, {
onResult: function( results ) {
var result_data = results.getResult();
if ( result_data && result_data.length > 0 ) {
if ( result_data[0].data.layout_mode ) {
$this.layoutMode = result_data[0].data.layout_mode;
$this.savedLayoutId = result_data[0].id;
}
}
//Do not show main ui until user layout mode selection retrieved. Otherwise page contents would briefly
//shift around going from default width of the static menu to the other layout modes.
$this.toggleUI( true );
$this.resizeContentLayout();
}
} );
},
toggleUI( show ) {
this.showUI = show
},
},
computed: {
containerClass() {
return ['layout-wrapper', {
'layout-horizontal': this.layoutMode === 'horizontal',
'layout-overlay': this.layoutMode === 'overlay',
'layout-static': this.layoutMode === 'static',
'layout-slim': this.layoutMode === 'slim',
'layout-static-inactive': this.staticMenuDesktopInactive,
'layout-mobile-active': this.staticMenuMobileActive,
'layout-overlay-active': this.overlayMenuActive,
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
'p-ripple-disabled': this.$primevue.config.ripple === false
}];
}
},
components: {
TTTopContainer: TTTopContainer,
TTLeftContainer: TTLeftContainer
}
};
</script>
<style>
.login-bg .hide-in-login {
display: none;
}
.layout-wrapper.layout-static .layout-content {
padding-top: 0 !important; /* This is just TEMP to remove the padding for unused breadcrumb. */
}
.bottom-container {
margin-left: 245px; /* TODO this needs to be adjusted. But this footer will likely go into the left menu bottom. */
}
.layout-wrapper .layout-content .layout-content-container {
display: flex; /* To accompany the flex: 1 1 0 coming from PrimeVue styling. This will correctly align the child components. */
padding: 0; /* Remove padding around the main content area. Conflicting with apollo theming. */
}
/* TODO: Possibly temp styles below. Doing this for horizontal menu mode */
.layout-wrapper.layout-horizontal .layout-content {
padding-top: 1px;
}
@media (min-width: 1024px) {
.layout-wrapper.layout-horizontal .layout-menu-container {
position: static;
top: auto;
left: auto;
}
}
.layout-wrapper.layout-horizontal .layout-menu-container .layout-menu>li>a {
height: 40px; /* To override the 50px forced height in PrimeVue, which makes the menu taller than it needs to be. */
}
.layout-wrapper.layout-horizontal .layout-menu-container .layout-menu>li.active-menuitem>ul {
top: 40px; /* To match to the adjusted height above of .layout-content */
z-index: 100; /* To ensure the dropdown menu items are always on top of edit views. */
}
.layout-wrapper.layout-slim .layout-content {
padding-top: 0;
margin-left: 42px; /* Match new slim menu width. */
}
.layout-wrapper.layout-slim .layout-menu-container .layout-menu>li>ul {
left: 42px; /* Match new slim menu width. TODO: Best to update this in the primevue scss source file instead, but dont want to do that until we have to import the whole menu code, as it complicated upgrade steps upon new versions. */
}
.layout-wrapper.layout-static .layout-menu-container {
overflow: visible;
}
/* TODO: temp to move config menu button out of the way */
.layout-config .layout-config-content .layout-config-button {
top: initial;
bottom: 100px;
opacity: 0.8;
}
/* Color overrides. Should eventually go into the SCSS sources */
.layout-wrapper .topbar {
background-color: #32689b
}
#tt_main_ui .layout-wrapper .topbar .menu-button {
margin-left: 0;
margin-right: 0;
width: 42px;
}
/* Hide bottom red border, as everything in here should now have moved to the left menu. Note, this also affects the pagination controls at the bottom. */
/* This may need to be expanded to remove the html grid-bottom-border and bottom-div */
.view .bottom-div,
.edit-view .grid-bottom-border, .view .grid-bottom-border,
.grid-bottom-border {
display: none;
background: none;
height: 0;
}
/* Sub Views need bottom paging div to be visible. */
.view.sub-view .bottom-div {
display: block;
height: auto;
}
/* Styles to hide the topbar during the transition period */
/* Note: The ribbon menu top bar height is 30px */
/*.top-container .ui-tabs .ui-tabs-nav,*/
/*.top-container .right-tab-bg,*/
/*.ribbon-view .right-logo,*/
/*.ribbon-view .left-logo {*/
/* display: none;*/
/*}*/
/*.top-container {*/
/* height: 134px; !* 164px - 30 *!*/
/*}*/
/* Context Menu - Some context menu styles here because overlay menu dropdown attaches to body so needs global styling, and hence want to keep the font sizing all in one place. */
.context-menu-bar span,
.p-menu-overlay span {
font-size: 14px;
}
</style>