Initial Smartproc

This commit is contained in:
Titan Hadiyan
2023-05-27 07:03:08 +07:00
parent b3feeb7809
commit fc7a97585a
90 changed files with 89395 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -0,0 +1,20 @@
<template>
<div class="content-block">
<footer class="footer">
Copyright © 2013-{{new Date().getFullYear()}} {{this.$appInfo.title}}.
<br />By <strong>PLN</strong> Gas & Geothermal
</footer>
</div>
</template>
<style lang="scss">
@import "../themes/generated/variables.base.scss";
.footer {
display: block;
color: rgba($base-text-color, alpha($base-text-color) * 0.7);
border-top: 1px solid rgba(0, 0, 0, 0.1);
padding-top: 20px;
padding-bottom: 24px;
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<header class="header-component">
<dx-toolbar class="header-toolbar" style="background-image: url('images/bg-header.jpg');">
<dx-item
:visible="menuToggleEnabled"
location="before"
css-class="menu-button"
>
<template #default>
<dx-button
icon="menu"
styling-mode="text"
@click="toggleMenuFunc"
/>
</template>
</dx-item>
<dx-item
v-if="title"
location="before"
css-class="header-title dx-toolbar-label"
>
<img src="images/logo_pln.png" style="float: left;"/>
</dx-item>
<dx-item
location="after"
locate-in-menu="auto"
menu-item-template="menuUserItem"
>
<template #default>
<div>
<dx-button
class="user-button authorization"
:width="210"
height="100%"
styling-mode="text"
>
<user-panel :email="email" :menu-items="userMenuItems" menu-mode="context" />
</dx-button>
</div>
</template>
</dx-item>
<template #menuUserItem>
<user-panel
:email="email"
:menu-items="userMenuItems"
menu-mode="list"
/>
</template>
</dx-toolbar>
</header>
</template>
<script>
import DxButton from "devextreme-vue/button";
import DxToolbar, { DxItem } from "devextreme-vue/toolbar";
import auth from "../auth";
import { useRouter, useRoute } from 'vue-router';
import { ref } from 'vue';
import UserPanel from "./user-panel";
export default {
props: {
menuToggleEnabled: Boolean,
title: String,
toggleMenuFunc: Function,
logOutFunc: Function
},
setup() {
const router = useRouter();
const route = useRoute();
const email = ref("");
auth.getUser().then((e) => email.value = e.data.email);
const userMenuItems = [{
text: "Profile",
icon: "user",
onClick: onProfileClick
},
{
text: "Logout",
icon: "runner",
onClick: onLogoutClick
}];
function onLogoutClick() {
auth.logOut();
router.push({
path: "/login-form",
query: { redirect: route.path }
});
}
function onProfileClick() {
router.push({
path: "/profile",
query: { redirect: route.path }
});
}
return {
email,
userMenuItems
};
},
components: {
DxButton,
DxToolbar,
DxItem,
UserPanel
}
};
</script>
<style lang="scss">
@import "../themes/generated/variables.base.scss";
@import "../dx-styles.scss";
.header-component {
flex: 0 0 auto;
z-index: 1;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
.dx-toolbar .dx-toolbar-item.menu-button > .dx-toolbar-item-content .dx-icon {
color: $base-accent;
}
}
.dx-toolbar.header-toolbar .dx-toolbar-items-container .dx-toolbar-after {
padding: 0 40px;
.screen-x-small & {
padding: 0 20px;
}
}
.dx-toolbar .dx-toolbar-item.dx-toolbar-button.menu-button {
width: $side-panel-min-width;
text-align: center;
padding: 0;
}
.header-title .dx-item-content {
padding: 0;
margin: 0;
}
.dx-theme-generic {
.dx-toolbar {
padding: 10px 0;
}
.user-button > .dx-button-content {
padding: 3px;
}
}
</style>

View File

@@ -0,0 +1,224 @@
<template>
<div id="container">
<dxMenu>
<dxItem
icon="home"
>
</dxItem>
<dxItem
text="About"
>
</dxItem>
<dxItem
text="Products"
>
</dxItem>
<dxItem
icon="cart"
>
</dxItem>
</dxMenu>
</div>
<div
class="dx-swatch-additional side-navigation-menu"
@click="forwardClick"
>
<slot />
<div class="menu-container">
<dx-tree-view
ref="treeViewRef"
:items="items"
key-expr="path"
selection-mode="single"
:focus-state-enabled="false"
expand-event="click"
@item-click="handleItemClick"
width="100%"
/>
</div>
</div>
</template>
<script>
import DxTreeView from "devextreme-vue/ui/tree-view";
import { sizes } from '../utils/media-query';
import navigation from '../app-navigation';
import { onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export default {
props: {
compactMode: Boolean
},
setup(props, context) {
const route = useRoute();
const router = useRouter();
const isLargeScreen = sizes()['screen-large'];
const items = navigation.map((item) => {
if(item.path && !(/^\//.test(item.path))){
item.path = `/${item.path}`;
}
return {...item, expanded: isLargeScreen}
});
const treeViewRef = ref(null);
function forwardClick (...args) {
context.emit("click", args);
}
function handleItemClick(e) {
if (!e.itemData.path || props.compactMode) {
return;
}
router.push(e.itemData.path);
const pointerEvent = e.event;
pointerEvent.stopPropagation();
}
function updateSelection () {
if (!treeViewRef.value || !treeViewRef.value.instance) {
return;
}
treeViewRef.value.instance.selectItem(route.path);
treeViewRef.value.instance.expandItem(route.path);
}
onMounted(() => {
updateSelection();
if (props.compactMode) {
treeViewRef.value.instance.collapseAll();
}
});
watch(
() => route.path,
() => {
updateSelection();
}
);
watch(
() => props.compactMode,
() => {
if (props.compactMode) {
treeViewRef.value.instance.collapseAll();
} else {
updateSelection();
}
}
);
return {
treeViewRef,
items,
forwardClick,
handleItemClick,
updateSelection
};
},
components: {
DxTreeView
}
};
</script>
<style lang="scss">
@import "../dx-styles.scss";
@import "../themes/generated/variables.additional.scss";
.side-navigation-menu {
display: flex;
flex-direction: column;
min-height: 100%;
height: 100%;
width: 250px !important;
.menu-container {
min-height: 100%;
display: flex;
flex: 1;
.dx-treeview {
// ## Long text positioning
white-space: nowrap;
// ##
// ## Icon width customization
.dx-treeview-item {
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 {
right: 10px;
left: auto;
}
.dx-rtl .dx-treeview-toggle-item-visibility {
left: 10px;
right: auto;
}
// ##
// ## 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;
}
&.dx-state-selected > .dx-treeview-item * {
color: $base-accent;
}
&:not(.dx-state-focused) > .dx-treeview-item.dx-state-hover {
background-color: lighten($base-bg, 4);
}
}
}
}
.dx-theme-generic .dx-treeview {
.dx-treeview-node-container
.dx-treeview-node.dx-state-selected.dx-state-focused
> .dx-treeview-item
* {
color: inherit;
}
}
// ##
}
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<div
class="dx-swatch-additional side-navigation-menu"
@click="forwardClick"
>
<slot />
<div class="menu-container">
<dx-tree-view
ref="treeViewRef"
:items="items"
key-expr="path"
selection-mode="single"
:focus-state-enabled="false"
expand-event="click"
@item-click="handleItemClick"
width="100%"
/>
</div>
</div>
</template>
<script>
import DxTreeView from "devextreme-vue/ui/tree-view";
import { sizes } from '../utils/media-query';
import navigation from '../app-navigation';
import { onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export default {
props: {
compactMode: Boolean
},
setup(props, context) {
const route = useRoute();
const router = useRouter();
const isLargeScreen = sizes()['screen-large'];
const items = navigation.map((item) => {
if(item.path && !(/^\//.test(item.path))){
item.path = `/${item.path}`;
}
return {...item, expanded: isLargeScreen}
});
const treeViewRef = ref(null);
function forwardClick (...args) {
context.emit("click", args);
}
function handleItemClick(e) {
if (!e.itemData.path || props.compactMode) {
return;
}
router.push(e.itemData.path);
const pointerEvent = e.event;
pointerEvent.stopPropagation();
}
function updateSelection () {
if (!treeViewRef.value || !treeViewRef.value.instance) {
return;
}
treeViewRef.value.instance.selectItem(route.path);
treeViewRef.value.instance.expandItem(route.path);
}
onMounted(() => {
updateSelection();
if (props.compactMode) {
treeViewRef.value.instance.collapseAll();
}
});
watch(
() => route.path,
() => {
updateSelection();
}
);
watch(
() => props.compactMode,
() => {
if (props.compactMode) {
treeViewRef.value.instance.collapseAll();
} else {
updateSelection();
}
}
);
return {
treeViewRef,
items,
forwardClick,
handleItemClick,
updateSelection
};
},
components: {
DxTreeView
}
};
</script>
<style lang="scss">
@import "../dx-styles.scss";
@import "../themes/generated/variables.additional.scss";
.side-navigation-menu {
display: flex;
flex-direction: column;
min-height: 100%;
height: 100%;
width: 250px !important;
.menu-container {
min-height: 100%;
display: flex;
flex: 1;
.dx-treeview {
// ## Long text positioning
white-space: nowrap;
// ##
// ## Icon width customization
.dx-treeview-item {
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 {
right: 10px;
left: auto;
}
.dx-rtl .dx-treeview-toggle-item-visibility {
left: 10px;
right: auto;
}
// ##
// ## 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;
}
&.dx-state-selected > .dx-treeview-item * {
color: $base-accent;
}
&:not(.dx-state-focused) > .dx-treeview-item.dx-state-hover {
background-color: lighten($base-bg, 4);
}
}
}
}
.dx-theme-generic .dx-treeview {
.dx-treeview-node-container
.dx-treeview-node.dx-state-selected.dx-state-focused
> .dx-treeview-item
* {
color: inherit;
}
}
// ##
}
}
</style>

View File

@@ -0,0 +1,114 @@
<template>
<div class="user-panel">
<div class="user-info">
<div class="image-container">
<div class="user-image" />
</div>
<div class="user-name">{{email}}</div>
</div>
<dx-context-menu
v-if="menuMode === 'context'"
target=".user-button"
:items="menuItems"
:width="210"
show-event="dxclick"
css-class="user-menu"
>
<dx-position my="top center" at="bottom center" />
</dx-context-menu>
<dx-list
v-if="menuMode === 'list'"
class="dx-toolbar-menu-action"
:items="menuItems"
/>
</div>
</template>
<script>
import DxContextMenu, { DxPosition } from "devextreme-vue/context-menu";
import DxList from "devextreme-vue/list";
export default {
props: {
menuMode: String,
menuItems: Array,
email: String
},
components: {
DxContextMenu,
DxPosition,
DxList
}
};
</script>
<style lang="scss">
@import "../themes/generated/variables.base.scss";
.user-info {
display: flex;
align-items: center;
.dx-toolbar-menu-section & {
padding: 10px 6px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.image-container {
overflow: hidden;
border-radius: 50%;
height: 30px;
width: 30px;
margin: 0 4px;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
.user-image {
width: 100%;
height: 100%;
background: url("https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png")
no-repeat #fff;
background-size: cover;
}
}
.user-name {
font-size: 14px;
color: $base-text-color;
margin: 0 9px;
}
}
.user-panel {
.dx-list-item .dx-icon {
vertical-align: middle;
color: $base-text-color;
margin-right: 16px;
}
.dx-rtl .dx-list-item .dx-icon {
margin-right: 0;
margin-left: 16px;
}
}
.dx-context-menu.user-menu.dx-menu-base {
&.dx-rtl {
.dx-submenu .dx-menu-items-container .dx-icon {
margin-left: 16px;
}
}
.dx-submenu .dx-menu-items-container .dx-icon {
margin-right: 16px;
}
.dx-menu-item .dx-menu-item-content {
padding: 3px 15px 4px;
}
}
.dx-theme-generic .user-menu .dx-menu-item-content .dx-menu-item-text {
padding-left: 4px;
padding-right: 4px;
}
</style>