feat(app): tests
This commit is contained in:
parent
eefc7ba4ac
commit
2b37e59afc
@ -26,6 +26,7 @@
|
||||
<link rel="stylesheet" href="/css/components/media.css">
|
||||
<link rel="stylesheet" href="/css/components/menu.css">
|
||||
<link rel="stylesheet" href="/css/_flatpickr.css">
|
||||
<link rel="stylesheet" href="/css/animation.css">
|
||||
<title>LiveMonitor</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
92
live_monitor_vue/public/css/animation.css
Normal file
92
live_monitor_vue/public/css/animation.css
Normal file
@ -0,0 +1,92 @@
|
||||
/* Определение анимации */
|
||||
@keyframes slide-left {
|
||||
from {
|
||||
transform: translateX(-100vw); /* Старт с -100% по оси X, чтобы меню было скрыто */
|
||||
opacity: 0; /* Начальная прозрачность для плавного появления */
|
||||
}
|
||||
to {
|
||||
transform: translateX(0vw); /* Конечное положение: на месте */
|
||||
opacity: 1; /* Полная видимость */
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes appear-opacity {
|
||||
from {
|
||||
opacity: 0; /* Начальная прозрачность для плавного появления */
|
||||
}
|
||||
to {
|
||||
opacity: 1; /* Полная видимость */
|
||||
}
|
||||
}
|
||||
|
||||
.appear-opacity-100 {
|
||||
animation: appear-opacity 0.1s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-200 {
|
||||
animation: appear-opacity 0.2s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-300 {
|
||||
animation: appear-opacity 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-400 {
|
||||
animation: appear-opacity 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-500 {
|
||||
animation: appear-opacity 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-600 {
|
||||
animation: appear-opacity 0.6s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-700 {
|
||||
animation: appear-opacity 0.7s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-800 {
|
||||
animation: appear-opacity 0.8s ease-out forwards;
|
||||
}
|
||||
|
||||
.appear-opacity-900 {
|
||||
animation: appear-opacity 0.9s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-100 {
|
||||
animation: slide-left 0.1s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-200 {
|
||||
animation: slide-left 0.2s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-300 {
|
||||
animation: slide-left 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-400 {
|
||||
animation: slide-left 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-500 {
|
||||
animation: slide-left 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-600 {
|
||||
animation: slide-left 0.6s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-700 {
|
||||
animation: slide-left 0.7s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-800 {
|
||||
animation: slide-left 0.8s ease-out forwards;
|
||||
}
|
||||
|
||||
.slide-left-900 {
|
||||
animation: slide-left 0.9s ease-out forwards;
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
<script>
|
||||
import MenuList from './MenuList.vue'
|
||||
import MobileMenu from './MobileMenu.vue'
|
||||
import MenuList from './MenuList/MenuList.vue'
|
||||
import MobileMenu from './AppContainerMobileMenu.vue'
|
||||
import LeftPanel from './AppContainerLeftPanel.vue'
|
||||
import Breadcrumbs from './AppContainerBreadcrumbs.vue'
|
||||
import RightPanel from './RightPanel.vue'
|
||||
import RightPanel from './AppContainerRightPanel.vue'
|
||||
import AppContainerHeader from './AppContainerHeader.vue'
|
||||
import {mapGetters} from 'vuex'
|
||||
import ServiceOfLayout from '@services/ServiceOfLayout'
|
||||
|
||||
export default {
|
||||
name: 'AppContainer',
|
||||
@ -18,41 +19,91 @@ export default {
|
||||
AppContainerHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
serviceOfLayout: null,
|
||||
isOpenedMobileMenu: false,
|
||||
routeName: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('layout', ["show_menu", 'is_enabled_menu']),
|
||||
...mapGetters('auth', ['menuList']),
|
||||
...mapGetters('layout', ["isShowMenu", 'isEnabledMenu']),
|
||||
...mapGetters('auth', ['menuList', 'currentUser']),
|
||||
menuListWithIndex() {
|
||||
return this.menuList.map((el, index) => ({...el, index}))
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
$route (to){
|
||||
this.routeName = to.name;
|
||||
this.closeMobileMenu()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const store = this.$store
|
||||
this.serviceOfLayout = new ServiceOfLayout(store)
|
||||
},
|
||||
methods: {
|
||||
closeMobileMenu() {
|
||||
this.isOpenedMobileMenu = false
|
||||
},
|
||||
openMobileMenu() {
|
||||
this.isOpenedMobileMenu = true
|
||||
},
|
||||
setIsMobileMenuOpened(isOpened) {
|
||||
if (this.serviceOfLayout) {
|
||||
this.serviceOfLayout.setIsMobileMenuOpened(isOpened)
|
||||
}
|
||||
},
|
||||
toggleMenu() {
|
||||
if (this.serviceOfLayout) {
|
||||
this.serviceOfLayout.toggleMenu()
|
||||
}
|
||||
},
|
||||
toggleMobileMenu() {
|
||||
if (this.isOpenedMobileMenu) {
|
||||
this.closeMobileMenu()
|
||||
} else {
|
||||
this.openMobileMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main w-full">
|
||||
<div
|
||||
v-if="serviceOfLayout"
|
||||
class="main w-full"
|
||||
>
|
||||
<!-- BEGIN: TOP BAR -->
|
||||
<div
|
||||
id="menu"
|
||||
class="top-bar-boxed w-full h-[59px] mt-[4px] z-[51] relative justify-center border-b border-white/[0.2] -mx-3 px-3 sm:pl-8 md:pt-0 mb-[4px]"
|
||||
>
|
||||
<MobileMenu
|
||||
v-if="false"
|
||||
current_menu_item=""
|
||||
current_user=""
|
||||
:menu_list="menuList"
|
||||
v-if="isOpenedMobileMenu"
|
||||
:menuListWithIndex="menuListWithIndex"
|
||||
currentMenuItem="routeName"
|
||||
:currentUser="currentUser"
|
||||
setIsMobileMenuOpened="setIsMobileMenuOpened"
|
||||
:toggleMobileMenu="toggleMobileMenu"
|
||||
/>
|
||||
<AppContainerHeader>
|
||||
<div class="flex justify-between items-center">
|
||||
<LeftPanel />
|
||||
<LeftPanel
|
||||
:toggleMobileMenu="toggleMobileMenu"
|
||||
/>
|
||||
<Breadcrumbs
|
||||
v-if="false"
|
||||
:breadcrumbs="[]"
|
||||
/>
|
||||
<RightPanel
|
||||
:current_user="''"
|
||||
:page_title="''"
|
||||
:pageTitle="''"
|
||||
:toggleMenu="toggleMenu"
|
||||
:notifications="[{from: 'Бот из LM', datetime: '10:00', message: 'Проведен редизайн приложения', readed: false}]"
|
||||
:currentUser="currentUser"
|
||||
/>
|
||||
</div>
|
||||
<div class="sm:hidden flex items-center justify-between" />
|
||||
@ -61,9 +112,11 @@ export default {
|
||||
<!-- END: TOP BAR -->
|
||||
<div class="wrapper">
|
||||
<div class="wrapper-box">
|
||||
<div v-if="show_menu && is_enabled_menu">
|
||||
<div v-if="isShowMenu && isEnabledMenu">
|
||||
<MenuList
|
||||
:menu_list="menuList"
|
||||
:isShowMenu="isShowMenu"
|
||||
:menuListWithIndex="menuListWithIndex"
|
||||
:routeName="routeName"
|
||||
/>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
@ -9,8 +9,6 @@ export default {
|
||||
default: null
|
||||
},
|
||||
},
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
<script>
|
||||
import { h } from 'vue'
|
||||
import {createIcons, icons} from "lucide";
|
||||
|
||||
export default {
|
||||
name: 'AppContainerLeftPanel',
|
||||
components: {},
|
||||
components: {
|
||||
MobileMenuButton: h('div')
|
||||
},
|
||||
props: {
|
||||
toggleMobileMenu: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mobile_menu_opened: false
|
||||
@ -10,25 +20,34 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
mounted() {
|
||||
this.icons()
|
||||
},
|
||||
updated() {
|
||||
this.icons()
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
icons() {
|
||||
createIcons({ icons, nameAttr: "icon" })
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center border-white/[0.2] border-r">
|
||||
<div
|
||||
class="flex p-4 cursor-pointer flex md:hidden"
|
||||
@click="mobile_menu_opened = !mobile_menu_opened"
|
||||
<mobile-menu-button
|
||||
class="flex p-4 cursor-pointer md:hidden"
|
||||
@click="toggleMobileMenu()"
|
||||
>
|
||||
<i
|
||||
icon="bar-chart-2"
|
||||
class="w-6 h-6 text-white transform rotate-90"
|
||||
/>
|
||||
</div>
|
||||
</mobile-menu-button>
|
||||
<router-link
|
||||
class="items-center relative -intro-x flex cursor-pointer p-4 hidden md:flex"
|
||||
class="hidden md:flex items-center relative -intro-x cursor-pointer p-4 "
|
||||
to="/?page=machines&mode=cards"
|
||||
>
|
||||
<div
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
<script>
|
||||
import MenuListItem from './MenuList/MenuListItem.vue'
|
||||
|
||||
export default {
|
||||
name: 'AppContainerMobileMenu',
|
||||
components: {
|
||||
MenuListItem
|
||||
},
|
||||
props: {
|
||||
currentMenuItem: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
menuListWithIndex: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
toggleMobileMenu: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
randomkey() {
|
||||
return Math.random().toString(36).slice(4)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="mobile-menu--active appear-opacity-200 mobile-menu md:hidden">
|
||||
<span
|
||||
class="absolute top-[30px] right-0 z-40"
|
||||
@click="toggleMobileMenu()"
|
||||
>
|
||||
<i
|
||||
icon="x-circle"
|
||||
class="w-8 h-8 text-white transform -rotate-90"
|
||||
/>
|
||||
</span>
|
||||
<div class="scrollable slide-left-400">
|
||||
<ul class=" scrollable__content py-2">
|
||||
<MenuListItem
|
||||
v-for="{index, ...menuItem} in menuListWithIndex"
|
||||
:key="randomkey(index)"
|
||||
baseClass="menu"
|
||||
:type="menuItem.type"
|
||||
:menuItem="menuItem"
|
||||
:currentMenuItem="currentMenuItem"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -1,24 +1,30 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import {mapGetters, mapMutations} from 'vuex'
|
||||
import {mapGetters} from 'vuex'
|
||||
import { createIcons, icons } from "lucide";
|
||||
|
||||
export default {
|
||||
name: 'RightPanel',
|
||||
components: {},
|
||||
props: {
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
page_title: {
|
||||
pageTitle: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
toggleMenu: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
},
|
||||
notifications: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
currentUser: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('auth', ['current_user'])
|
||||
return { }
|
||||
},
|
||||
mounted() {
|
||||
this.icons()
|
||||
@ -27,11 +33,12 @@ export default {
|
||||
this.icons()
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('layout', ["toggle_menu"]),
|
||||
icons() {
|
||||
createIcons({ icons, "stroke-width": 1.5, nameAttr: "icon" })
|
||||
createIcons({
|
||||
icons, "stroke-width": 1.5, nameAttr: "icon"
|
||||
})
|
||||
},
|
||||
rkey() {
|
||||
randomkey() {
|
||||
return Math.random().toString(36).slice(4)
|
||||
},
|
||||
closeDropDown() {
|
||||
@ -46,9 +53,9 @@ export default {
|
||||
|
||||
|
||||
<template>
|
||||
<div class="flex items-center justify-end grow gapy-2 px-4 border-hide-600">
|
||||
<div class="flex items-center justify-end grow px-4 border-hide-600">
|
||||
<div class="">
|
||||
{{ page_title }}
|
||||
{{ pageTitle }}
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="relative">
|
||||
@ -66,7 +73,7 @@ export default {
|
||||
/>
|
||||
<div
|
||||
style="font-size: 7px; font-weight: 900; top: 10px; left: 30px"
|
||||
class="h-[13px] w-[13px] bg-white rounded-full mr-8 transition absolute flex itens-center justify-center"
|
||||
class="h-[13px] w-[13px] bg-white rounded-full mr-8 transition absolute flex items-center justify-center"
|
||||
>
|
||||
<span
|
||||
style="line-height: 13px; font-weight: 900; font-size: 7px"
|
||||
@ -81,14 +88,17 @@ export default {
|
||||
</div>
|
||||
<div
|
||||
v-for="{from, datetime, message, readed} in notifications"
|
||||
:key="rkey(message)"
|
||||
:key="randomkey(message)"
|
||||
class="cursor-pointer relative flex items-center "
|
||||
>
|
||||
<div :class="{'bg-gray-400 w-3 h-3 absolute right-0 bottom-0 rounded-full border-2 border-white dark:border-darkmode-600|, else: ~s|bg-success w-3 h-3 absolute right-0 bottom-0 rounded-full border-2 border-white dark:border-darkmode-600': readed}" />
|
||||
<div
|
||||
:class="{'bg-gray-400 w-3 h-3 absolute right-0 bottom-0 rounded-full border-2 border-white dark:border-darkmode-600': readed,
|
||||
'bg-success w-3 h-3 absolute right-0 bottom-0 rounded-full border-2 border-white dark:border-darkmode-600': !readed}"
|
||||
/>
|
||||
<div class="ml-2 overflow-hidden">
|
||||
<div class="flex items-center">
|
||||
<a
|
||||
href="javascript:;"
|
||||
href="javascript:"
|
||||
class="font-medium truncate mr-5"
|
||||
>{{ from }}</a>
|
||||
<div class="text-xs text-slate-400 ml-auto whitespace-nowrap">
|
||||
@ -120,7 +130,7 @@ export default {
|
||||
</div>
|
||||
<div
|
||||
class="cursor-pointer hidden md:flex border-white/[0.2] border-r p-4"
|
||||
@click="toggle_menu"
|
||||
@click="toggleMenu"
|
||||
>
|
||||
<i
|
||||
id="menu_library"
|
||||
@ -146,13 +156,13 @@ export default {
|
||||
<ul class="dropdown-content before:block before:absolute before:bg-black before:inset-0 before:rounded-md before:z-[-1]">
|
||||
<li class="p-2">
|
||||
<div class="font-bold">
|
||||
{{ current_user?.first_name || "" }} {{ current_user?.last_name || "" }}
|
||||
{{ currentUser?.first_name || "" }} {{ currentUser?.last_name || "" }}
|
||||
</div>
|
||||
<div
|
||||
class="text-xs text-black/60 dark:text-slate-500"
|
||||
style="margin-top: -0.25rem;"
|
||||
>
|
||||
{{ current_user?.position || "позиция не указана" }}
|
||||
{{ currentUser?.position || "позиция не указана" }}
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
@ -1,119 +0,0 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import { cond, equals, T, always } from 'ramda'
|
||||
import { createIcons, icons } from "lucide";
|
||||
import MenuItemGroup from './MenuItemGroup.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
components: {MenuItemGroup},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
menu_item: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
link: "/"
|
||||
})
|
||||
},
|
||||
base_class: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
routeName: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
_base_class() {
|
||||
return `${this.base_class}`
|
||||
},
|
||||
activeClass () {
|
||||
return 'side-menu side-menu--active'
|
||||
},
|
||||
menuRouterName() {
|
||||
return this.menu_item.router || ""
|
||||
},
|
||||
currentRouterName() {
|
||||
return this.$router.currentRoute._value.name || ""
|
||||
},
|
||||
linkClass() {
|
||||
const menuRouterName = this.menu_item.router || ""
|
||||
if (menuRouterName === this.routeName)
|
||||
return `${this._base_class} ${this._base_class}--active`
|
||||
return this._base_class
|
||||
},
|
||||
_type() {
|
||||
return cond([
|
||||
[equals("simple_link"), (x) => x],
|
||||
[equals("line"), (x) => x],
|
||||
[equals("group"), (x) => x],
|
||||
[T, () => "other"],
|
||||
])(this.type)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.icons()
|
||||
},
|
||||
updated() {
|
||||
console.log(123)
|
||||
|
||||
this.icons()
|
||||
},
|
||||
methods: {
|
||||
icons() {
|
||||
createIcons({ icons, "stroke-width": 1.5, nameAttr: "icon" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<li v-if="_type == 'simple_link'">
|
||||
<router-link
|
||||
phx-hook="MenuLink"
|
||||
:class="linkClass"
|
||||
:to="menu_item.link"
|
||||
>
|
||||
<div :class="`${_base_class}__icon`">
|
||||
<i :icon="menu_item?.icon" />
|
||||
</div>
|
||||
<div :class="`${_base_class}__title`">
|
||||
{{ menu_item.show }}
|
||||
</div>
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="_type == 'line'">
|
||||
<hr class="m-4">
|
||||
</li>
|
||||
<MenuItemGroup
|
||||
v-if="_type == 'group'"
|
||||
:type="_type"
|
||||
:base_class="base_class"
|
||||
:menu_item="menu_item"
|
||||
/>
|
||||
<div v-if="_type == 'other'">
|
||||
""
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- <router-link
|
||||
v-if="type === 'link'"
|
||||
class="flex p-2 rounded-md hover:bg-gray-100 flex items-center"
|
||||
:class="{'bg-gray-200': pageName === name}"
|
||||
:to="link"
|
||||
>
|
||||
<i :class="`ri-${icon} text-slate-600 mr-2 `" />
|
||||
<span
|
||||
v-if="isOpenMenu"
|
||||
class="text-slate-700"
|
||||
>{{ title }}</span>
|
||||
</router-link> -->
|
||||
@ -1,93 +0,0 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import { cond, equals, T } from 'ramda'
|
||||
import { createIcons, icons } from "lucide";
|
||||
|
||||
export default {
|
||||
name: 'MenuItemCopy',
|
||||
components: {},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
menu_item: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
link: "/"
|
||||
})
|
||||
},
|
||||
base_class: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
_base_class() {
|
||||
return `${this.base_class}`
|
||||
},
|
||||
activeClass () {
|
||||
return 'side-menu side-menu--active'
|
||||
},
|
||||
menuRouterName() {
|
||||
return this.menu_item.router || ""
|
||||
},
|
||||
currentRouterName() {
|
||||
return this.$router.currentRoute._value.name || ""
|
||||
},
|
||||
linkClass() {
|
||||
const menuRouterName = this.menu_item.router || ""
|
||||
const currentRouterName = this.$router.currentRoute._value.name || Math.random()
|
||||
if (menuRouterName === currentRouterName)
|
||||
return `${this._base_class} ${this._base_class}--active`
|
||||
return this._base_class
|
||||
},
|
||||
_type() {
|
||||
return cond([
|
||||
[equals("simple_link"), (x) => x],
|
||||
[equals("line"), (x) => x],
|
||||
[equals("group"), (x) => x],
|
||||
[T, () => "other"],
|
||||
])(this.type)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.icons()
|
||||
},
|
||||
updated() {
|
||||
this.icons()
|
||||
},
|
||||
methods: {
|
||||
icons() {
|
||||
createIcons({ icons, "stroke-width": 1.5, nameAttr: "icon" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<li v-if="_type == 'simple_link'">
|
||||
<router-link
|
||||
phx-hook="MenuLink"
|
||||
:class="linkClass"
|
||||
:to="menu_item.link"
|
||||
>
|
||||
<div :class="`${_base_class}__icon`">
|
||||
<i :icon="menu_item?.icon" />
|
||||
</div>
|
||||
<div :class="`${_base_class}__title`">
|
||||
{{ menu_item.show }}
|
||||
</div>
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="_type == 'line'">
|
||||
<hr class="m-4">
|
||||
</li>
|
||||
<div v-if="_type == 'other'">
|
||||
""
|
||||
</div>
|
||||
</template>
|
||||
@ -1,80 +0,0 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import MenuItem from './MenuItemCopy.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuItemGroup',
|
||||
components: {
|
||||
MenuItem
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
base_class: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
menu_item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
open: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
const menuRouterName = this.menu_item.router || ""
|
||||
const currentRouterName = this.$router.currentRoute._value.name || Math.random()
|
||||
if (menuRouterName === currentRouterName) return `${this.base_class} ${this.base_class}--active`
|
||||
return `${this.base_class}`
|
||||
},
|
||||
itemClass() {
|
||||
if (this.open) return `${this.base_class}__sub-icon transform rotate-180`
|
||||
return `${this.base_class}__sub-icon`
|
||||
},
|
||||
listClass() {
|
||||
if (this.open) return `${this.base_class}__sub-open`
|
||||
return ""
|
||||
},
|
||||
menu_list_with_index() {
|
||||
return this.menu_item.children.map((el, index) => ({...el, index}))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.open = !this.open
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<li>
|
||||
<span
|
||||
:class="containerClass"
|
||||
@click="toggle"
|
||||
>
|
||||
<div :class="`${base_class}__icon`"> <i :icon="menu_item.icon" /> </div>
|
||||
<div :class="`${base_class}__title`">
|
||||
{{ menu_item.show }}
|
||||
<div :class="itemClass"> <i icon="chevron-down" /> </div>
|
||||
</div>
|
||||
</span>
|
||||
<ul :class="listClass">
|
||||
<MenuItem
|
||||
v-for="item in menu_item.children"
|
||||
:key="JSON.stringify(item)"
|
||||
:base_class="base_class"
|
||||
:type="item.type"
|
||||
:menu_item="item"
|
||||
/>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
@ -1,63 +0,0 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import MenuItem from './MenuItem.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuList',
|
||||
components: {MenuItem},
|
||||
props: {
|
||||
current_menu_item: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
menu_list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
routeName: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('', ['mobile_menu_opened', 'show_menu']),
|
||||
menu_list_with_index() {
|
||||
return this.menu_list.map((el, index) => ({...el, index}))
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
$route (to){
|
||||
this.routeName = to.name;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rkey() {
|
||||
return Math.random().toString(36).slice(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<nav
|
||||
x-show="show_menu"
|
||||
class="side-nav"
|
||||
>
|
||||
<ul>
|
||||
<MenuItem
|
||||
v-for="{index, ...menu_item} in menu_list_with_index"
|
||||
:id="`main_menu_item_component_${index}`"
|
||||
:key="rkey(index)"
|
||||
base_class="side-menu"
|
||||
:type="menu_item.type"
|
||||
:menu_item="menu_item"
|
||||
:current_menu_item="current_menu_item"
|
||||
:routeName="routeName"
|
||||
/>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
@ -0,0 +1,54 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import MenuListItem from './MenuListItem.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuList',
|
||||
components: {MenuListItem},
|
||||
props: {
|
||||
menuListWithIndex: {
|
||||
type: [{
|
||||
type: String,
|
||||
default: null
|
||||
}],
|
||||
default: () => []
|
||||
},
|
||||
isShowMenu: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
routeName: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
randomkey() {
|
||||
return Math.random().toString(36).slice(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<nav class="side-nav">
|
||||
<ul>
|
||||
<MenuListItem
|
||||
v-for="{index, ...menuItem} in menuListWithIndex"
|
||||
:id="`main_menu_item_component_${index}`"
|
||||
:key="randomkey(index)"
|
||||
baseClass="side-menu"
|
||||
:type="menuItem.type"
|
||||
:menuItem="menuItem"
|
||||
:routeName="routeName"
|
||||
/>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import MenuListItemImplementation from './MenuListItemImplementation.vue'
|
||||
import MenuListItemGroup from "@frames/AppContainer/MenuList/MenuListItemGroup.vue";
|
||||
|
||||
export default {
|
||||
name: 'MenuListItem',
|
||||
components: {MenuListItemGroup, MenuListItemImplementation},
|
||||
//eslint-disable-next-line
|
||||
props: ['type', 'menuItem', 'baseClass', 'routeName'],
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<MenuListItemImplementation
|
||||
:type="type"
|
||||
:menuItem="menuItem"
|
||||
:baseClass="baseClass"
|
||||
:routeName="routeName"
|
||||
>
|
||||
<MenuListItemGroup
|
||||
v-if="type === 'group'"
|
||||
:type="type"
|
||||
:baseClass="baseClass"
|
||||
:menuItem="menuItem"
|
||||
:routeName="routeName"
|
||||
/>
|
||||
</MenuListItemImplementation>
|
||||
</template>
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
<script>
|
||||
import MenuListItemImplementation from './MenuListItemImplementation.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuListItemCopy',
|
||||
components: {MenuListItemImplementation},
|
||||
//eslint-disable-next-line
|
||||
props: ['type', 'menuItem', 'baseClass', 'routeName'],
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<MenuListItemImplementation
|
||||
:type="type"
|
||||
:menuItem="menuItem"
|
||||
:baseClass="baseClass"
|
||||
:routeName="routeName"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
<!-- eslint-disable vue/prop-name-casing -->
|
||||
<script>
|
||||
import MenuItem from './MenuListItemCopy.vue'
|
||||
|
||||
export default {
|
||||
name: 'MenuItemGroup',
|
||||
components: {
|
||||
MenuItem
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
baseClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
menuItem: {
|
||||
type: {
|
||||
show: String,
|
||||
children: Array,
|
||||
router: String
|
||||
},
|
||||
default: () => ({})
|
||||
},
|
||||
routeName: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
open: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
const routeName = this.routeName
|
||||
const menuRouterName = this.menuItem.router || ""
|
||||
if (menuRouterName === routeName) return `${this.baseClass} ${this.baseClass}--active`
|
||||
return `${this.baseClass}`
|
||||
},
|
||||
itemClass() {
|
||||
if (this.open) return `${this.baseClass}__sub-icon transform rotate-180`
|
||||
return `${this.baseClass}__sub-icon`
|
||||
},
|
||||
listClass() {
|
||||
if (this.open) return `${this.baseClass}__sub-open`
|
||||
return ""
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.open = !this.open
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<li>
|
||||
<span
|
||||
:class="containerClass"
|
||||
@click="toggle"
|
||||
>
|
||||
<div :class="`${baseClass}__icon`"> <i :icon="menuItem.icon" /> </div>
|
||||
<div :class="`${baseClass}__title`">
|
||||
{{ menuItem.show }}
|
||||
<div :class="itemClass"> <i icon="chevron-down" /> </div>
|
||||
</div>
|
||||
</span>
|
||||
<ul :class="listClass">
|
||||
<MenuItem
|
||||
v-for="item in menuItem.children"
|
||||
:key="JSON.stringify(item)"
|
||||
:baseClass="baseClass"
|
||||
:type="item.type"
|
||||
:menuItem="item"
|
||||
/>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
@ -0,0 +1,89 @@
|
||||
<script>
|
||||
import { cond, equals, T } from 'ramda'
|
||||
import { createIcons, icons } from "lucide";
|
||||
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
menuItem: {
|
||||
type: {
|
||||
line: String,
|
||||
icon: String,
|
||||
|
||||
},
|
||||
default: () => ({
|
||||
link: "/"
|
||||
})
|
||||
},
|
||||
baseClass: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
routeName: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
linkClass() {
|
||||
const menuRouterName = this.menuItem.router || ""
|
||||
if (menuRouterName === this.routeName)
|
||||
return `${this.baseClass} ${this.baseClass}--active`
|
||||
return this.baseClass
|
||||
},
|
||||
_type() {
|
||||
return cond([
|
||||
[equals("simple_link"), (x) => x],
|
||||
[equals("line"), (x) => x],
|
||||
[equals("group"), (x) => x],
|
||||
[T, () => "other"],
|
||||
])(this.type)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.icons()
|
||||
},
|
||||
updated() {
|
||||
this.icons()
|
||||
},
|
||||
methods: {
|
||||
icons() {
|
||||
createIcons({ icons, nameAttr: "icon" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<li v-if="_type === 'simple_link'">
|
||||
<router-link
|
||||
phx-hook="MenuLink"
|
||||
:class="linkClass"
|
||||
:to="menuItem.link"
|
||||
>
|
||||
<div :class="`${baseClass}__icon`">
|
||||
<i :icon="menuItem?.icon" />
|
||||
</div>
|
||||
<div :class="`${baseClass}__title`">
|
||||
{{ menuItem.show }}
|
||||
</div>
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="_type === 'line'">
|
||||
<hr class="m-4">
|
||||
</li>
|
||||
<slot />
|
||||
<div v-if="_type === 'other'">
|
||||
""
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
<script>
|
||||
import MenuItem from './MenuItem.vue'
|
||||
|
||||
export default {
|
||||
name: 'MobileMenu',
|
||||
components: {
|
||||
MenuItem
|
||||
},
|
||||
props: {
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
current_menu_item: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
menu_list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
menu_list_with_index() {
|
||||
return this.menu_list.map((el, index) => ({...el, index}))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rkey() {
|
||||
return Math.random().toString(36).slice(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div x-bind:class="mobile_menu_opened ? 'mobile-menu--active mobile-menu md:hidden' : 'mobile-menu md:hidden'">
|
||||
<div class="scrollable">
|
||||
<span
|
||||
class="mobile-menu-toggler"
|
||||
@click="mobile_menu_opened = !mobile_menu_opened"
|
||||
>
|
||||
<i
|
||||
icon="x-circle"
|
||||
class="w-8 h-8 text-white transform -rotate-90"
|
||||
/>
|
||||
</span>
|
||||
<ul class="scrollable__content py-2">
|
||||
<MenuItem
|
||||
v-for="{index, ...menu_item} in menu_list_with_index"
|
||||
:id="`main_menu_item_component_${index}`"
|
||||
:key="rkey(index)"
|
||||
base_class="menu"
|
||||
:type="menu_item.type"
|
||||
:menu_item="menu_item"
|
||||
:current_menu_item="current_menu_item"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "PacksContainer",
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "PacksContainerBody"
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
ComponentTemplate
|
||||
</div>
|
||||
</template>
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "PacksContainerControl",
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<form
|
||||
phx-submit="fetch_pack"
|
||||
class="rounded-md bg-light px-4 pt-4 pb-6 gap-2 shadow lg:col-span-4 xl:col-span-3 2xl:col-span-2 col-span-12"
|
||||
autocomplete="off"
|
||||
>
|
||||
<slot />
|
||||
</form>
|
||||
</template>
|
||||
@ -1,3 +1,64 @@
|
||||
<script>
|
||||
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
|
||||
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
|
||||
import {mapGetters, mapMutations, mapActions} from 'vuex'
|
||||
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
|
||||
import Spinner from "@molecules/VSpinner/VSpinner.vue"
|
||||
import MachinesModal from "@molecules/MachinesModal/MachinesModal.vue"
|
||||
|
||||
export default {
|
||||
name: 'LastPacks',
|
||||
components: {
|
||||
Datepicker,
|
||||
ButtonModal,
|
||||
Tabulator,
|
||||
Spinner,
|
||||
MachinesModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
packNum: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('last_packs', ['dtStart', 'dtFinish', 'imei', 'pageState', 'packsData']),
|
||||
tabulatorOtps() {
|
||||
return {
|
||||
dataSource: this.packsData,
|
||||
columns: [
|
||||
{
|
||||
title: "Нормер пакета",
|
||||
field: "pack_number",
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: "Количество записей",
|
||||
field: "count",
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: "Последняя дата пакета",
|
||||
field: "pack_dt",
|
||||
width: 150,
|
||||
render: "{{ dt_format (dt_shift pack_dt 3 'hour') }}"
|
||||
}
|
||||
],
|
||||
height: "550px"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('last_packs', [
|
||||
"setDtStart",
|
||||
"setDtFinish",
|
||||
"setImei"
|
||||
]),
|
||||
...mapActions('last_packs', ['uploadData'])
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
|
||||
<form
|
||||
@ -99,64 +160,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
|
||||
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
|
||||
import {mapGetters, mapMutations, mapActions} from 'vuex'
|
||||
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
|
||||
import Spinner from "@molecules/VSpinner/VSpinner.vue"
|
||||
import MachinesModal from "@molecules/MachinesModal/MachinesModal.vue"
|
||||
|
||||
export default {
|
||||
name: 'LastPacks',
|
||||
components: {
|
||||
Datepicker,
|
||||
ButtonModal,
|
||||
Tabulator,
|
||||
Spinner,
|
||||
MachinesModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
packNum: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('last_packs', ['dtStart', 'dtFinish', 'imei', 'pageState', 'packsData']),
|
||||
tabulatorOtps() {
|
||||
return {
|
||||
dataSource: this.packsData,
|
||||
columns: [
|
||||
{
|
||||
title: "Нормер пакета",
|
||||
field: "pack_number",
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: "Количество записей",
|
||||
field: "count",
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: "Последняя дата пакета",
|
||||
field: "pack_dt",
|
||||
width: 150,
|
||||
render: "{{ dt_format (dt_shift pack_dt 3 'hour') }}"
|
||||
}
|
||||
],
|
||||
height: "550px"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('last_packs', [
|
||||
"setDtStart",
|
||||
"setDtFinish",
|
||||
"setImei"
|
||||
]),
|
||||
...mapActions('last_packs', ['uploadData'])
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
43
live_monitor_vue/src/services/ServiceOfLayout.js
Normal file
43
live_monitor_vue/src/services/ServiceOfLayout.js
Normal file
@ -0,0 +1,43 @@
|
||||
class ServiceOfLayout {
|
||||
constructor(store) {
|
||||
this.store = store
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
return this.store.getters['layout/height']
|
||||
}
|
||||
getWidth() {
|
||||
return this.store.getters['layout/width']
|
||||
}
|
||||
getIsOpenMenu() {
|
||||
return this.store.getters['layout/isOpenMenu']
|
||||
}
|
||||
getIsShowMenu() {
|
||||
return this.store.getters['layout/isShowMenu']
|
||||
}
|
||||
getIsEnabledMenu() {
|
||||
return this.store.getters['layout/isEnabledMenu']
|
||||
}
|
||||
|
||||
setIsShowMenu(upd) {
|
||||
this.store.dispatch('layout/setIsShowMenu', upd)
|
||||
}
|
||||
|
||||
setIsMobileMenuOpened(upd) {
|
||||
this.store.dispatch('layout/setIsMobileMenuOpened', upd)
|
||||
}
|
||||
|
||||
setIsOpenMenu(upd) {
|
||||
this.store.dispatch('layout/setIsOpenMenu', upd)
|
||||
}
|
||||
|
||||
setIsEnabledMenu(upd) {
|
||||
this.store.dispatch('layout/setIsEnabledMenu', upd)
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.store.dispatch('layout/toggleMenu')
|
||||
}
|
||||
}
|
||||
|
||||
export default ServiceOfLayout
|
||||
@ -6,7 +6,7 @@ import axios from 'axios';
|
||||
import {orisMenu} from './menuList'
|
||||
|
||||
const initState = {
|
||||
current_user: null,
|
||||
currentUser: null,
|
||||
errorMsg: null,
|
||||
token: null,
|
||||
inited: false,
|
||||
@ -17,7 +17,7 @@ const state = {
|
||||
...initState
|
||||
};
|
||||
|
||||
const current_user = (token) => ({
|
||||
const setCurrentUser = (token) => ({
|
||||
position: "",
|
||||
first_name: "Сергей",
|
||||
last_name: "Шлыков",
|
||||
@ -31,17 +31,17 @@ const getters = {
|
||||
login: (state) => state.login,
|
||||
password: (state) => state.password,
|
||||
my_comp: (state) => state.my_comp,
|
||||
current_user: (state) => state.current_user,
|
||||
currentUser: (state) => state.currentUser,
|
||||
menuList: () => orisMenu,
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
initAuth: (state, token) => {
|
||||
state.current_user = current_user(token)
|
||||
state.currentUser = setCurrentUser(token)
|
||||
state.token = token;
|
||||
state.inited = true
|
||||
},
|
||||
set_my_comp: (state, upd) => state.my_comp,
|
||||
set_my_comp: (state) => state.my_comp,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
|
||||
|
||||
const orisMenu = [
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "home",
|
||||
show: "Главная",
|
||||
link: "/",
|
||||
router: "main"
|
||||
router: "machines"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
|
||||
@ -1,58 +1,94 @@
|
||||
import {initScreenListener, disableScreenListener} from "./stateHelpers.js";
|
||||
|
||||
const initState = {
|
||||
height: 0,
|
||||
width: 0,
|
||||
isOpenMenu: false,
|
||||
isOpenedMobileMenu: false,
|
||||
isEnabledMenu: true,
|
||||
isShowMenu: true,
|
||||
initedScreenListener: false,
|
||||
};
|
||||
|
||||
|
||||
const state = {
|
||||
height: 0,
|
||||
width: 0,
|
||||
inited: false,
|
||||
isOpenMenu: false,
|
||||
mobile_menu_opened: false,
|
||||
show_menu: true,
|
||||
is_enabled_menu: true
|
||||
...initState
|
||||
};
|
||||
|
||||
const getters = {
|
||||
height: (state) => state.height,
|
||||
width: (state) => state.width,
|
||||
isOpenMenu: (state) => state.isOpenMenu,
|
||||
menuWidth: (state) => null,
|
||||
show_menu: (state) => state.show_menu,
|
||||
is_enabled_menu: (state) => state.is_enabled_menu,
|
||||
isShowMenu: (state) => state.isShowMenu,
|
||||
isOpenedMobileMenu: (state) => state.isOpenedMobileMenu,
|
||||
isEnabledMenu: (state) => state.isEnabledMenu,
|
||||
initedScreenListener: (state) => state.initedScreenListener,
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
enableScreenListener: (state) => {
|
||||
state.height = window.innerHeight
|
||||
state.width = window.innerWidth
|
||||
const acc = !!state.inited
|
||||
if (!acc) {
|
||||
window.addEventListener("resize", (e) => {
|
||||
state.height= e.target.innerHeight
|
||||
state.width = e.target.innerWidth
|
||||
});
|
||||
state.inited = true
|
||||
const inited = state.initedScreenListener
|
||||
if (!inited) {
|
||||
initScreenListener(state)
|
||||
state.initedScreenListener = true
|
||||
}
|
||||
},
|
||||
toggle_menu: (state) => {
|
||||
state.show_menu = !state.show_menu
|
||||
disableScreenListener: (state) => {
|
||||
disableScreenListener(state)
|
||||
},
|
||||
set_mobile_menu_opened: (state, upd) => {
|
||||
state.mobile_menu_opened = upd
|
||||
toggleMenu: (state) => {
|
||||
state.isShowMenu = !state.isShowMenu
|
||||
},
|
||||
set_show_menu: (state, upd) => {
|
||||
state.show_menu = upd
|
||||
saveIsMobileMenuOpened: (state, upd) => {
|
||||
state.isOpenedMobileMenu = upd
|
||||
},
|
||||
saveIsShowMenu: (state, upd) => {
|
||||
state.isShowMenu = upd
|
||||
},
|
||||
resetStore: (state) => {
|
||||
for (let key in state) {
|
||||
state[key] = initState[key]
|
||||
}
|
||||
},
|
||||
saveIsEnabledMenu: (state, upd) => {
|
||||
state.isEnabledMenu = upd
|
||||
},
|
||||
saveIsOpenMenu: (state, upd) => {
|
||||
state.isOpenMenu = upd
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
initScreenSizeRecalc: ({commit}) => {
|
||||
initScreenSizeListener: ({commit}) => {
|
||||
commit("enableScreenListener")
|
||||
},
|
||||
|
||||
disableScreenListener: ({commit}) => {
|
||||
commit("disableScreenListener")
|
||||
},
|
||||
resetStore: ({commit}) => {
|
||||
commit("resetStore")
|
||||
},
|
||||
toggleMenu: ({commit}) => {
|
||||
commit("toggleMenu")
|
||||
},
|
||||
setIsShowMenu: ({commit}, upd) => {
|
||||
commit("saveIsShowMenu", upd)
|
||||
},
|
||||
setIsMobileMenuOpened: ({commit}, upd) => {
|
||||
commit("saveIsMobileMenuOpened", upd)
|
||||
},
|
||||
setIsEnabledMenu: ({commit}, upd) => {
|
||||
commit("saveIsEnabledMenu", upd)
|
||||
},
|
||||
setIsOpenMenu: ({commit}, upd) => {
|
||||
commit("saveIsOpenMenu", upd)
|
||||
},
|
||||
};
|
||||
|
||||
export const store = {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
actions,
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
actions,
|
||||
};
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
const orisMenu = [
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "home",
|
||||
show: "Главная",
|
||||
link: "/",
|
||||
router: "main"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "book-marked",
|
||||
show: "Последние пакеты",
|
||||
link: "/html/last_packs",
|
||||
router: "last_packs"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "box",
|
||||
show: "Коммуникационный",
|
||||
link: "/html/controll_com_service",
|
||||
router: "comm"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "book-key",
|
||||
show: "Последние пакеты(по номеру)",
|
||||
link: "/html/last_packs_by_pack",
|
||||
router: "last_pack_number"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "beaker",
|
||||
show: "Топливо",
|
||||
link: "/html/live_fuel",
|
||||
router: "fuel"
|
||||
},
|
||||
{type: "simple_link", icon: "timer", show: "Крон", link: "/html/cron", router: "cron"},
|
||||
{
|
||||
type: "group",
|
||||
show: "Справочники",
|
||||
icon: "book",
|
||||
children: [
|
||||
{type: "simple_link", icon: "book-open", show: "ICCID", link: "/html/fetch_iccid"},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "book-open",
|
||||
show: "Устройства",
|
||||
link: "/html/fetch_askr_devices"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "group",
|
||||
show: "Пакеты",
|
||||
icon: "cast",
|
||||
children:
|
||||
[
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "curly-braces",
|
||||
show: "Свободный поиск",
|
||||
link: "/html/free_packs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{type: "line"},
|
||||
{
|
||||
type: "group",
|
||||
show: "Логи",
|
||||
icon: "fingerprint",
|
||||
children: [
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "code",
|
||||
show: "Файлы логов",
|
||||
link: "/html/file_viewer/logs"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "code",
|
||||
show: "Файлы машин",
|
||||
link: "/html/file_viewer/machine_data"
|
||||
}
|
||||
]
|
||||
},
|
||||
{type: "line"},
|
||||
{
|
||||
type: "group",
|
||||
show: "Работоспособность сервсисов",
|
||||
icon: "cloud-cog",
|
||||
children: [
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "cpu",
|
||||
show: "ДИАП",
|
||||
link: "/admin_panel/services/diap"
|
||||
},
|
||||
{type: "simple_link", icon: "table", show: "Сервисы", link: "/html/communications"},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "group",
|
||||
show: "Админка",
|
||||
icon: "hand-metal",
|
||||
children: [
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "haze",
|
||||
show: "Сервис управления",
|
||||
link: "/admin_panel/auth_service"
|
||||
},
|
||||
{
|
||||
type: "simple_link",
|
||||
icon: "line-chart",
|
||||
show: "Анализ топлива",
|
||||
link: "/admin_panel/fuel_analyzer"
|
||||
},
|
||||
{type: "simple_link", icon: "newspaper", show: "Обновления", link: "/html/updates"},
|
||||
{type: "simple_link", icon: "boxes", show: "Пакеты", link: "/admin_panel/packs"}
|
||||
]
|
||||
},
|
||||
{type: "line"},
|
||||
{type: "simple_link", icon: "newspaper", show: "Обновления", link: "/html/updates", router: "news"},
|
||||
]
|
||||
|
||||
export {orisMenu}
|
||||
19
live_monitor_vue/src/store/modules/layout/stateHelpers.js
Normal file
19
live_monitor_vue/src/store/modules/layout/stateHelpers.js
Normal file
@ -0,0 +1,19 @@
|
||||
const initScreenListener = (state) => {
|
||||
state.height = window.innerHeight
|
||||
state.width = window.innerWidth
|
||||
window.addEventListener("resize", (e) => {
|
||||
state.height= e.target.innerHeight
|
||||
state.width = e.target.innerWidth
|
||||
});
|
||||
return "ok"
|
||||
}
|
||||
|
||||
const disableScreenListener = (state) => {
|
||||
window.removeEventListener("resize", () => {
|
||||
state.height = null
|
||||
state.width = null
|
||||
});
|
||||
return "ok"
|
||||
}
|
||||
|
||||
export { initScreenListener, disableScreenListener }
|
||||
@ -7,7 +7,7 @@
|
||||
&.mobile-menu--active {
|
||||
&:before {
|
||||
content: "";
|
||||
@apply visible opacity-100;
|
||||
@apply visible opacity-100 h-[110vh];
|
||||
}
|
||||
.scrollable {
|
||||
@apply ml-0 overflow-y-auto;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import {test, describe, expect} from 'vitest'
|
||||
import { mount} from '@vue/test-utils'
|
||||
import Button from '@atoms/VButton.vue';
|
||||
import VButton from '@atoms/VButton.vue';
|
||||
|
||||
describe('Accordion', () => {
|
||||
test('Accordion mounted', () => {
|
||||
const wrapper = mount(Button)
|
||||
describe('VButton', () => {
|
||||
test('VButton mounted', () => {
|
||||
const wrapper = mount(VButton)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,27 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainer from '@frames/AppContainer/AppContainer.vue';
|
||||
import {createStore} from "vuex";
|
||||
import { store as layout } from '@/store/modules/layout';
|
||||
import { store as auth } from '@/store/modules/auth';
|
||||
|
||||
describe('AppContainer', () => {
|
||||
const store = createStore({
|
||||
modules: {
|
||||
layout,
|
||||
auth
|
||||
},
|
||||
})
|
||||
|
||||
test('AppContainer mounted', () => {
|
||||
const wrapper = shallowMount(AppContainer,
|
||||
{
|
||||
global: {
|
||||
mocks: {
|
||||
$store: store,
|
||||
},
|
||||
}}
|
||||
)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainerBreadcrumbs from '@frames/AppContainer/AppContainerBreadcrumbs.vue';
|
||||
|
||||
describe('AppContainerBreadcrumbs', () => {
|
||||
test('AppContainerBreadcrumbs mounted', () => {
|
||||
const wrapper = shallowMount(AppContainerBreadcrumbs)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainerHeader from '@frames/AppContainer/AppContainerHeader.vue';
|
||||
|
||||
describe('AppContainerHeader', () => {
|
||||
test('AppContainerHeader mounted', () => {
|
||||
const wrapper = shallowMount(AppContainerHeader)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,16 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainerLeftPanel from '@frames/AppContainer/AppContainerLeftPanel.vue';
|
||||
import Router from "@router"
|
||||
|
||||
describe('AppContainerLeftPanel', () => {
|
||||
test('AppContainerLeftPanel mounted', () => {
|
||||
const wrapper = shallowMount(AppContainerLeftPanel,
|
||||
{
|
||||
global: {
|
||||
plugins: [Router]
|
||||
}
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,15 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainerMobileMenu from '@frames/AppContainer/AppContainerMobileMenu.vue';
|
||||
|
||||
describe('AppContainerMobileMenu', () => {
|
||||
test('AppContainerMobileMenu mounted', () => {
|
||||
const wrapper = shallowMount(AppContainerMobileMenu, {
|
||||
props: {
|
||||
isOpenedMobileMenu: false,
|
||||
setIsMobileMenuOpened: () => {},
|
||||
}
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,20 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import AppContainerRightPanel from '@frames/AppContainer/AppContainerRightPanel.vue';
|
||||
import Router from "@router"
|
||||
|
||||
describe('AppContainerRightPanel', () => {
|
||||
test('AppContainerRightPanel mounted', () => {
|
||||
const wrapper = shallowMount(AppContainerRightPanel, {
|
||||
props: {
|
||||
currentUser: {
|
||||
id: 1,
|
||||
}
|
||||
},
|
||||
global: {
|
||||
plugins: [Router]
|
||||
}
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,15 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import MenuList from '@frames/AppContainer/MenuList/MenuList.vue';
|
||||
|
||||
describe('MenuList', () => {
|
||||
|
||||
test('MenuList mounted', () => {
|
||||
const wrapper = shallowMount(MenuList, {
|
||||
props: {
|
||||
routeName: ""
|
||||
}
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,11 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import MenuListItem from '@frames/AppContainer/MenuList/MenuListItem.vue';
|
||||
|
||||
describe('MenuListItem', () => {
|
||||
|
||||
test('MenuListItem mounted', () => {
|
||||
const wrapper = shallowMount(MenuListItem)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import MenuListItemCopy from '@frames/AppContainer/MenuList/MenuListItemCopy.vue';
|
||||
|
||||
describe('MenuListItemCopy', () => {
|
||||
test('MenuListItemCopy mounted', () => {
|
||||
const wrapper = shallowMount(MenuListItemCopy)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import MenuListItemGroup from '@frames/AppContainer/MenuList/MenuListItemGroup.vue';
|
||||
|
||||
describe('MenuListItemGroup', () => {
|
||||
test('MenuListItemGroup mounted', () => {
|
||||
const wrapper = shallowMount(MenuListItemGroup)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,17 @@
|
||||
import {test, describe, expect, } from 'vitest'
|
||||
import { shallowMount} from '@vue/test-utils'
|
||||
import MenuListItemImplementation from '@frames/AppContainer/MenuList/MenuListItemImplementation.vue';
|
||||
import Router from "@router"
|
||||
|
||||
describe('MenuListItemImplementation', () => {
|
||||
|
||||
test('MenuListItemImplementation mounted', () => {
|
||||
const wrapper = shallowMount(MenuListItemImplementation,
|
||||
{
|
||||
global: {
|
||||
plugins: [Router]
|
||||
}
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect} from 'vitest'
|
||||
import { mount} from '@vue/test-utils'
|
||||
import PacksContainer from '@frames/PacksContainer/PacksContainer.vue';
|
||||
|
||||
describe('PacksContainer', () => {
|
||||
test('PacksContainer mounted', () => {
|
||||
const wrapper = mount(PacksContainer)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect} from 'vitest'
|
||||
import { mount} from '@vue/test-utils'
|
||||
import PacksContainerBody from '@frames/PacksContainer/PacksContainerBody.vue';
|
||||
|
||||
describe('PacksContainerBody', () => {
|
||||
test('PacksContainerBody mounted', () => {
|
||||
const wrapper = mount(PacksContainerBody)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,10 @@
|
||||
import {test, describe, expect} from 'vitest'
|
||||
import { mount} from '@vue/test-utils'
|
||||
import PacksContainerControl from '@frames/PacksContainer//PacksContainerControl.vue';
|
||||
|
||||
describe('PacksContainerControl', () => {
|
||||
test('PacksContainerControl mounted', () => {
|
||||
const wrapper = mount(PacksContainerControl)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
51
live_monitor_vue/tests/services/ServiceOfLayout.test.js
Normal file
51
live_monitor_vue/tests/services/ServiceOfLayout.test.js
Normal file
@ -0,0 +1,51 @@
|
||||
import {expect, describe, test, beforeEach} from 'vitest'
|
||||
import ServiceOfLayout from "@services/ServiceOfLayout.js"
|
||||
import { createStore } from "vuex"
|
||||
import { store as layout } from '@/store/modules/layout';
|
||||
|
||||
describe('test ServiceOfLayout', () => {
|
||||
const store = createStore({
|
||||
modules: {
|
||||
layout
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
store.dispatch('layout/resetStore')
|
||||
})
|
||||
|
||||
const serviceOfLayout = new ServiceOfLayout(store)
|
||||
|
||||
test('test ServiceOfLayout exist', async () => {
|
||||
expect(serviceOfLayout).toBeTruthy()
|
||||
expect(serviceOfLayout.getHeight()).toBe(0)
|
||||
expect(serviceOfLayout.getWidth()).toBe(0)
|
||||
expect(serviceOfLayout.getIsOpenMenu()).toBe(false)
|
||||
expect(serviceOfLayout.getIsEnabledMenu()).toBe(true)
|
||||
expect(serviceOfLayout.getIsShowMenu()).toBe(true)
|
||||
})
|
||||
|
||||
test('test toggleMenu', async () => {
|
||||
serviceOfLayout.toggleMenu()
|
||||
const result = store.getters['layout/isShowMenu']
|
||||
expect(result).toBe(false)
|
||||
})
|
||||
|
||||
test('setIsShowMenu', async () => {
|
||||
serviceOfLayout.setIsShowMenu(false)
|
||||
const result = serviceOfLayout.getIsShowMenu()
|
||||
expect(result).toBe(false)
|
||||
})
|
||||
|
||||
test('setIsOpenMenu', async () => {
|
||||
serviceOfLayout.setIsOpenMenu(true)
|
||||
const result = serviceOfLayout.getIsOpenMenu()
|
||||
expect(result).toBe(true)
|
||||
})
|
||||
|
||||
test('setIsEnabledMenu', async () => {
|
||||
serviceOfLayout.setIsEnabledMenu(false)
|
||||
const result = serviceOfLayout.getIsEnabledMenu()
|
||||
expect(result).toBe(false)
|
||||
})
|
||||
})
|
||||
53
live_monitor_vue/tests/store/layout.test.js
Normal file
53
live_monitor_vue/tests/store/layout.test.js
Normal file
@ -0,0 +1,53 @@
|
||||
import {expect, describe, test, beforeEach} from 'vitest'
|
||||
import { createStore } from "vuex"
|
||||
import { store as layout } from '@/store/modules/layout';
|
||||
|
||||
describe('test of layout store', () => {
|
||||
const store = createStore({
|
||||
modules: {
|
||||
layout
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
store.dispatch('layout/resetStore')
|
||||
})
|
||||
|
||||
test('test layout store exist', async () => {
|
||||
expect(store).toBeTruthy()
|
||||
expect(store.getters['layout/isOpenedMobileMenu']).toBe(false)
|
||||
expect(store.getters['layout/isEnabledMenu']).toBe(true)
|
||||
})
|
||||
|
||||
test('test toggleMenu', () => {
|
||||
store.dispatch('layout/toggleMenu')
|
||||
const result = store.getters['layout/isShowMenu']
|
||||
expect(result).toBe(false)
|
||||
})
|
||||
|
||||
test('test setIsShowMenu', () => {
|
||||
store.dispatch('layout/setIsShowMenu', false)
|
||||
const result = store.getters['layout/isShowMenu']
|
||||
expect(result).toBe(false)
|
||||
})
|
||||
|
||||
test('test setIsMobileMenuOpened', () => {
|
||||
store.dispatch('layout/setIsMobileMenuOpened', true)
|
||||
const result = store.getters['layout/isOpenedMobileMenu']
|
||||
expect(result).toBe(true)
|
||||
})
|
||||
|
||||
test('test resetStore', () => {
|
||||
store.dispatch('layout/resetStore')
|
||||
const result = store.getters['layout/isShowMenu']
|
||||
expect(result).toBe(true)
|
||||
})
|
||||
|
||||
test('test initScreenSizeListener', () => {
|
||||
store.dispatch('layout/initScreenSizeListener')
|
||||
const result = store.getters['layout/initedScreenListener']
|
||||
expect(result).toBe(true)
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user