Merge branch 'feat/sidebar-v2' into wip2

This commit is contained in:
Mulia Nasution 2023-06-07 12:43:07 +07:00
commit e3ee71abd0
11 changed files with 157 additions and 114 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 779 B

View File

@ -2,7 +2,7 @@
<header class="header-component"> <header class="header-component">
<dx-toolbar class="header-toolbar" style="background-image: url('images/bg-header.jpg');"> <dx-toolbar class="header-toolbar" style="background-image: url('images/bg-header.jpg');">
<dx-item <dx-item
:visible="menuToggleEnabled" :visible="false"
location="before" location="before"
css-class="menu-button" css-class="menu-button"
> >
@ -142,7 +142,7 @@ export default {
} }
.header-title .dx-item-content { .header-title .dx-item-content {
padding: 0; padding: 0 24px;
margin: 0; margin: 0;
} }

View File

@ -1,26 +1,31 @@
<template> <template>
<div <div
class="dx-swatch-additional side-navigation-menu" class="side-navigation-menu"
@click="forwardClick" @click="forwardClick"
> >
<slot /> <slot />
<div class="menu-container"> <div v-for="item in menus" :key="item.id" class="relative-view">
<dx-tree-view <img :src="item.icon" alt="icon" @click="handleIconClick(item.text)" :class="selectedMenus === item.text ? 'active-icons' : 'icons'">
ref="treeViewRef"
:items="menus" <div ref="expandRef" v-if="item.text === selectedMenus" class="absolute-view">
key-expr="path" <div class="expand-title">
selection-mode="single" <p>{{item.text}}</p>
:focus-state-enabled="false" </div>
expand-event="click"
@item-click="handleItemClick" <dx-scroll-view ref="scrollViewRef" :class="checkLength(item.items) ? 'expand-menu-height' : 'expand-menu'">
width="100%" <div v-for="it in item.items" :key="it.id" class="no-wrap">
/> <p :class="route.path === it.path ? 'pointer-active' : 'pointer'" @click="handleItemClick(item.text,it.path)">
{{it.text}}
</p>
</div>
</dx-scroll-view>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import DxTreeView from "devextreme-vue/ui/tree-view"; import DxScrollView from "devextreme-vue/scroll-view";
import { sizes } from '../utils/media-query'; import { sizes } from '../utils/media-query';
import navigation from '../app-navigation'; import navigation from '../app-navigation';
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
@ -36,7 +41,12 @@ export default {
const router = useRouter(); const router = useRouter();
const menus = ref(""); const menus = ref("");
auth.getUser().then((e) => menus.value = e.data.menus); const selectedMenus = ref("")
auth.getUser().then((e) => {
const listMenu = e.data.menus.filter((it) => it.text !== "Home")
menus.value = listMenu
});
//console.log(navigation); //console.log(navigation);
console.log(menus); console.log(menus);
@ -48,29 +58,39 @@ export default {
return {...item, expanded: isLargeScreen} return {...item, expanded: isLargeScreen}
}); });
const expandRef = ref(null)
const treeViewRef = ref(null); const treeViewRef = ref(null);
const scrollViewRef = ref(null);
function forwardClick (...args) { function forwardClick (...args) {
context.emit("click", args); context.emit("click", args);
} }
function handleItemClick(e) { function handleItemClick(text, path) {
if (!e.itemData.path || props.compactMode) { if (!path) {
return; return;
} }
router.push(e.itemData.path); router.push(path);
selectedMenus.value = text
}
const pointerEvent = e.event; function handleIconClick(text) {
pointerEvent.stopPropagation(); if(text === selectedMenus.value) {
selectedMenus.value = ""
return
}
selectedMenus.value = text
} }
function updateSelection () { function updateSelection () {
if (!treeViewRef.value || !treeViewRef.value.instance) { if(route.path === "/home") {
return; selectedMenus.value = "Home"
selectedMenus.value = ""
}
} }
treeViewRef.value.instance.selectItem(route.path); function checkLength(it) {
treeViewRef.value.instance.expandItem(route.path); return it.length > 4
} }
onMounted(() => { onMounted(() => {
@ -105,11 +125,16 @@ export default {
forwardClick, forwardClick,
handleItemClick, handleItemClick,
updateSelection, updateSelection,
menus menus,
route,
selectedMenus,
handleIconClick,
scrollViewRef,
checkLength,
expandRef
}; };
}, },components: {
components: { DxScrollView
DxTreeView
} }
}; };
</script> </script>
@ -117,95 +142,95 @@ export default {
<style lang="scss"> <style lang="scss">
@import "../dx-styles.scss"; @import "../dx-styles.scss";
@import "../themes/generated/variables.additional.scss"; @import "../themes/generated/variables.additional.scss";
@import "../themes/generated/variables.base.scss";
.side-navigation-menu { .side-navigation-menu {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 100%; min-height: 100%;
height: 100%; height: 100%;
width: 250px !important; width: $side-bar-width !important;
box-shadow: $base-shadow-color 4px 100px 10px 0px !important;
padding-top: 25px !important;
background-color: white;
padding-left: 9px;
.menu-container { .relative-view {
min-height: 100%; position: relative;
display: flex;
flex: 1;
.dx-treeview { .icons {
// ## Long text positioning border-radius: 4px !important;
white-space: nowrap; width: $side-bar-icon-size !important;
// ## height: $side-bar-icon-size !important;
border: 1px solid $base-border-color !important;
// ## Icon width customization margin-bottom: 24px;
.dx-treeview-item { cursor: pointer;
padding-left: 0;
padding-right: 0;
.dx-icon {
width: $side-panel-min-width !important;
margin: 0 !important;
}
}
// ##
// ## Arrow customization
.dx-treeview-node {
padding: 0 0 !important;
} }
.dx-treeview-toggle-item-visibility { .active-icons {
right: 10px; border-radius: 4px !important;
left: auto; width: $side-bar-icon-size !important;
height: $side-bar-icon-size !important;
border: 1px solid $datagrid-columnchooser-item-color !important;
margin-bottom: 24px;
cursor: pointer;
} }
.dx-rtl .dx-treeview-toggle-item-visibility { .absolute-view {
left: 10px; position: absolute;
right: auto; top: 0;
} z-index: 1;
// ##
// ## Item levels customization
.dx-treeview-node {
&[aria-level="1"] {
font-weight: bold;
border-bottom: 1px solid $base-border-color;
}
&[aria-level="2"] .dx-treeview-item-content {
font-weight: normal;
padding: 0 $side-panel-min-width;
}
}
// ##
}
// ## Selected & Focuced items customization
.dx-treeview {
.dx-treeview-node-container {
.dx-treeview-node {
&.dx-state-selected:not(.dx-state-focused) > .dx-treeview-item {
background: transparent; background: transparent;
left: $side-bar-expand-left;
width: $side-bar-expand-width;
.pointer {
cursor: pointer;
width: 100%;
background: white;
padding: 4px 38px;
color: $base-text-color;
} }
&.dx-state-selected > .dx-treeview-item * { .pointer-active {
color: $base-accent; cursor: pointer;
width: 100%;
background: white;
padding: 4px 38px;
color: $datagrid-columnchooser-item-color;
} }
&:not(.dx-state-focused) > .dx-treeview-item.dx-state-hover { .expand-title {
background-color: lighten($base-bg, 4); border-radius: 0px 8px 0px 0px !important;
background: $datagrid-columnchooser-item-color;
margin: 0 !important;
color: white;
padding: 1px 22px;
font-size: 18px;
font-weight: 600;
} }
.expand-menu {
background: white;
margin-top: 0px !important;
padding: 8px 0px;
border-radius: 0px 0px 8px 0px !important;
}
.expand-menu-height {
background: white;
margin-top: 0px !important;
padding: 8px 0px;
border-radius: 0px 0px 8px 0px !important;
height: 200px;
}
.no-wrap {
white-space: nowrap;
} }
} }
} }
.dx-theme-generic .dx-treeview {
.dx-treeview-node-container
.dx-treeview-node.dx-state-selected.dx-state-focused
> .dx-treeview-item
* {
color: inherit;
}
}
// ##
}
} }
</style> </style>

View File

@ -67,3 +67,8 @@
} }
$side-panel-min-width: 60px; $side-panel-min-width: 60px;
$side-bar-width: 76px;
$side-bar-expand-left: 70px;
$side-bar-icon-size: 56px;
$side-bar-expand-width: 239px;
$base-shadow-color: #3333331A;

View File

@ -9,7 +9,6 @@
<dx-drawer <dx-drawer
class="layout-body" class="layout-body"
position="before" position="before"
template="menuTemplate"
v-model:opened="menuOpened" v-model:opened="menuOpened"
:opened-state-mode="drawerOptions.menuMode" :opened-state-mode="drawerOptions.menuMode"
:reveal-mode="drawerOptions.menuRevealMode" :reveal-mode="drawerOptions.menuRevealMode"
@ -18,16 +17,18 @@
:shading="drawerOptions.shaderEnabled" :shading="drawerOptions.shaderEnabled"
:close-on-outside-click="drawerOptions.closeOnOutsideClick" :close-on-outside-click="drawerOptions.closeOnOutsideClick"
> >
<dx-scroll-view ref="scrollViewRef" class="with-footer"> <div class="flex">
<slot /> <div class="sidebar">
<slot name="footer" />
</dx-scroll-view>
<template #menuTemplate>
<side-nav-menu <side-nav-menu
:compact-mode="!menuOpened" :compact-mode="!menuOpened"
@click="handleSideBarClick" @click="handleSideBarClick"
/> />
</template> </div>
<dx-scroll-view ref="scrollViewRef" class="with-footer">
<slot />
<slot name="footer" />
</dx-scroll-view>
</div>
</dx-drawer> </dx-drawer>
</div> </div>
</template> </template>
@ -122,6 +123,8 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import "../dx-styles.scss";
.side-nav-outer-toolbar { .side-nav-outer-toolbar {
flex-direction: column; flex-direction: column;
display: flex; display: flex;
@ -132,4 +135,14 @@ export default {
.layout-header { .layout-header {
z-index: 1501; z-index: 1501;
} }
.flex {
display: flex;
height: 100%;
width: 100%;
}
.sidebar {
width: $side-bar-width;
}
</style> </style>