feat(app && tests): refactor

This commit is contained in:
vbuglov 2024-03-28 10:31:29 +03:00
parent 49626cb681
commit 6e6e5311b0
96 changed files with 946 additions and 928 deletions

View File

@ -5,6 +5,9 @@ module.exports = {
],
rules: {
"no-multiple-empty-lines": ["error", {max: 2, "maxBOF": 0}],
"vue/component-tags-order": ["error", {
"order": [ "script", "template", "style"]
}],
"vue/order-in-components": "error",
"indent": ["error", 2],
"no-mixed-spaces-and-tabs": "error",

View File

@ -22,6 +22,18 @@ prehook:
@chmod +x $(HOOK_PATH)
@echo "Pre-push hook set successfully."
add:
ifeq ($(pack),)
$(error mn is not set)
endif
yarn add "../repo/${pack}/"
packs_list:
cd .. && make packs_list
list_packs:
make packs_list
push:
ifeq ($(commit),)
$(error mn is not set)

View File

@ -15,7 +15,9 @@
"lint_fix": "eslint --ext .js, **/*.vue --fix"
},
"dependencies": {
"0-tools-eslint": "../repo/0-tools-eslint/",
"1-toolkits-helpers": "../repo/1-toolkits-helpers/",
"3-class-complex-assistants": "../repo/3-class-complex-assistants/",
"D": "^1.0.0",
"axios": "^1.6.2",
"echarts": "^5.4.3",

View File

@ -1,11 +1,11 @@
<script>
import {mapGetters, mapMutations} from 'vuex'
import MenuContainer from "@frames/Menu/MenuContainer.vue"
import AppContainer from "@frames/AppContainer/AppContainer.vue"
export default {
name: 'App',
components: {
MenuContainer
AppContainer
},
data() {
return {}
@ -40,9 +40,9 @@ export default {
v-if="innerPage"
class="flex min-h-[100vh]"
>
<MenuContainer>
<AppContainer>
<router-view />
</MenuContainer>
</AppContainer>
</div>
<div
v-if="outerPage"

View File

@ -1,53 +0,0 @@
<!-- eslint-disable -->
<script>
import Modal from '@molecules/Modal/index.vue'
export default {
name: 'Accordion',
components: {
Modal,
},
props: {
isOpen: {
type: Boolean,
default: false
},
id: {
type: String,
default: ""
},
},
setup(props, {slots}) {
const hasHeader = slots.header != undefined
const hasBody = slots.body != undefined
return {
hasHeader,
hasBody
}
},
computed: {
},
methods: {
}
}
</script>
<!-- eslint-disable -->
<template>
<div class="relative w-full">
<input type="checkbox" :id="id" value="" :checked="isOpen" class="hidden peer" required="">
<label :for="id" class="inline-flex items-center justify-between w-full px-5 h-[50px] text-gray-600 bg-white border border-gray-200 rounded-lg cursor-pointer dark:hover:text-gray-300 dark:border-gray-700 peer-checked:border-slate-300 peer-checked:rounded-b-none peer-checked:border-slate-200 hover:text-gray-600 dark:peer-checked:text-gray-300 peer-checked:text-gray-600 hover:bg-gray-50 dark:text-gray-400 dark:bg-gray-800 transition-all">
<div v-if="hasHeader"><slot name="header" /></div>
</label>
<i class="ri-arrow-down-s-line absolute right-[10px] top-[15px] peer-checked:rotate-180 transition-all pointer-events-none"></i>
<div v-if="hasBody" class="hidden peer-checked:block transition-all w-full px-5 py-4 text-gray-600 bg-white border border-gray-200 rounded-b-lg cursor-default">
<slot name="body" />
</div>
</div>
</template>
<style scoped>
</style>

View File

@ -1,3 +1,20 @@
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>
<template>
<fwb-button
color="dark"
@ -40,20 +57,3 @@
</svg>
</fwb-button>
</template>
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>

View File

@ -1,3 +1,20 @@
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>
<template>
<fwb-button
color="dark"
@ -22,20 +39,3 @@
</svg>
</fwb-button>
</template>
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>

View File

@ -1,3 +1,20 @@
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>
<template>
<fwb-button
color="dark"
@ -23,20 +40,3 @@
</svg>
</fwb-button>
</template>
<script>
import {FwbButton} from "flowbite-vue";
export default {
components: {
FwbButton
},
props: {
onClick: {
type: Function,
default: () => {
},
}
}
}
</script>

View File

@ -1,13 +1,9 @@
<!-- eslint-disable -->
<script>
// import Button from "@/components/1_atoms/Button.vue";
export default {
name: 'DoubleSwitch',
components: {
// Button,
},
props: {
machine: {
type: Object,
@ -30,32 +26,18 @@ export default {
default: ''
},
},
data() {
return {
// isChecked: false
}
},
computed: {
},
mounted () {
},
inject: ['isChecked'],
// watch: {
// isChecked: {
// handler(newValue, oldValue) {
// this.$emit('switched', newValue)
// },
// deep: true
// },
// },
emits: ['switched'],
methods: {
buttonClass: function(value) {
return `border border-slate-400 flex items-center justify-center cursor-pointer rounded transition-all text-xs text-center py-[5px] px-2 ${value}`
},
setChecked(e) {
// this.isChecked = e.target.checked
this.$emit('switched', e.target.checked)
}
}
@ -63,7 +45,6 @@ export default {
</script>
<!-- eslint-disable -->
<template>
@ -76,7 +57,9 @@ export default {
@change="setChecked"
/>
<div :class="`w-11 h-6 rounded-full peer peer-focus:ring-4 peer-focus:ring-${secondColor}-300 dark:peer-focus:ring-${secondColor}-800 dark:bg-${firstColor}-700 peer-checked/checkbox:after:translate-x-full peer-checked/checkbox:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-${firstColor}-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-${firstColor}-600`" :style="{background: !isChecked ? firstColor : secondColor}"></div>
<div
:class="`w-11 h-6 rounded-full peer peer-focus:ring-4 peer-focus:ring-${secondColor}-300 dark:peer-focus:ring-${secondColor}-800 dark:bg-${firstColor}-700 peer-checked/checkbox:after:translate-x-full peer-checked/checkbox:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-${firstColor}-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-${firstColor}-600`"
:style="{background: !isChecked ? firstColor : secondColor}"></div>
<span class="block peer-checked/checkbox:hidden ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> {{ firstTitle }}</span>
<span class="hidden peer-checked/checkbox:block ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> {{ secondTitle }} </span>
</label>

View File

@ -0,0 +1,58 @@
<script>
export default {
name: 'VAccordion',
props: {
isOpen: {
type: Boolean,
default: false
},
id: {
type: String,
default: ""
},
},
setup(props, {slots}) {
const hasHeader = slots.header !== undefined
const hasBody = slots.body !== undefined
return {
hasHeader,
hasBody
}
},
computed: {
},
methods: {
}
}
</script>
<template>
<div class="relative w-full">
<input
:id="id"
type="checkbox"
value=""
:checked="isOpen"
class="hidden peer"
required=""
>
<label
:for="id"
class="inline-flex items-center justify-between w-full px-5 h-[50px] text-gray-600 bg-white border border-gray-200 rounded-lg cursor-pointer dark:hover:text-gray-300 dark:border-gray-700 peer-checked:rounded-b-none peer-checked:border-slate-200 hover:text-gray-600 dark:peer-checked:text-gray-300 peer-checked:text-gray-600 hover:bg-gray-50 dark:text-gray-400 dark:bg-gray-800 transition-all"
>
<div v-if="hasHeader"><slot name="header" /></div>
</label>
<i class="ri-arrow-down-s-line absolute right-[10px] top-[15px] peer-checked:rotate-180 transition-all pointer-events-none" />
<div
v-if="hasBody"
class="hidden peer-checked:block transition-all w-full px-5 py-4 text-gray-600 bg-white border border-gray-200 rounded-b-lg cursor-default"
>
<slot name="body" />
</div>
</div>
</template>
<style scoped>
</style>

View File

@ -1,18 +1,7 @@
<!-- eslint-disable -->
<template>
<button @click="setSelected()" :type="type" :class="classBtn" class="w-full relative col-span-4 md:col-span-2 items-center justify-center text-center border-solid border-blue-1 z-10 cursor-pointer">
<i v-if="classIcon" :class="classIcon" class="text-blue-1"></i>
{{ title }}
</button>
</template>
<script>
export default {
components: {
},
name: "VButton",
props: {
onClick: {
type: Function,
@ -51,3 +40,19 @@ export default {
}
}
</script>
<template>
<button
:type="type"
:class="classBtn"
class="w-full relative col-span-4 md:col-span-2 items-center justify-center text-center border-solid border-blue-1 z-10 cursor-pointer"
@click="setSelected()"
>
<i
v-if="classIcon"
:class="classIcon"
class="text-blue-1"
/>
{{ title }}
</button>
</template>

View File

@ -1,6 +1,5 @@
<!-- eslint-disable vue/prop-name-casing -->
<script>
import Modal from '../Modal/index.vue'
import Modal from '../VModal/VModal.vue'
export default {
name: 'ButtonModal',

View File

@ -1,112 +0,0 @@
<!-- eslint-disable -->
<script>
import { toRefs } from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import Button from "@/components/1_atoms/Button.vue";
import ECharts from '@store/hooks/Echarts';
export default {
name: 'Chart',
components: {
Button,
},
props: {
data: {
type: Object,
default: () => {}
},
sizes: {
type: Object,
default: () => {}
},
id: {
type: String,
required: true,
default: ''
},
type: {
type: String,
required: true,
default: ''
},
height: {
type: String,
default: ''
},
maxWidth: {
type: String,
default: ''
},
maxHeight: {
type: String,
default: ''
},
},
data() {
return {
chartStyles: {
maxWidth: `${this.maxWidth}`,
maxHeight: `${this.maxHeight}`,
top: '15px;',
padding: '10px',
margin: '10px',
boxShadow: 'rgb(0 0 0 / 12%) 2px 3px 7px',
border: '1px solid rgba(0, 0, 0, 0.15)',
}
}
},
setup(props) {
},
watch: {
},
computed: {
// ...mapGetters('main', ['activeChartData', 'prevGroupByData', 'activeMenuChartData']),
},
mounted () {
this.$nextTick(function () {
const chart = new ECharts(this.id, this.sizes)
this.setTypeFunc(this.type, chart, this.data)
chart.onClickedBarCharts(this.updateCharts)
})
},
updated () {
this.$nextTick(function () {
const chart = new ECharts(this.id, this.sizes)
this.setTypeFunc(this.type, chart, this.data)
chart.onClickedBarCharts(this.updateCharts)
})
},
methods: {
...mapActions('machines', ['updateCharts']),
buttonClass: function(value) {
return `border border-slate-400 flex items-center justify-center cursor-pointer rounded transition-all text-xs text-center py-[5px] px-2 ${value}`
},
setTypeFunc: function(type, chart, data) {
switch(type) {
case 'pie': return chart.makePieCharts({...data, type: type})
case 'mount': return chart.makeBarMountCharts({...data, type: type, height: this.height})
case 'mainMl': return chart.makeBarCharts({...data, type: type})
case 'default': return chart.makeBarTypesCharts({...data, type: type})
case 'types': return chart.makeBarTypesCharts({...data, type: type})
case 'without_first_layout': return chart.makeBarTypesCharts({...data, type: type})
case 'ml': return chart.makeBarTypesCharts({...data, type: type})
case 'packLines': return chart.makeLinesPackCharts({...data, type: type})
}
}
}
}
</script>
<!-- eslint-disable -->
<template>
<div :id="id" class="flex grow justify-center relative overflow-hidden bg-white" :style="chartStyles">
</div>
<div id="button_close" class="flex absolute h-max top-[50px] right-[45px]">
</div>
</template>
<style scoped>
</style>

View File

@ -10,12 +10,13 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Tabulator from "@molecules/Tabulator/index.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
export default {
name: 'MachinesModal',
components: {ButtonModal, Tabulator},
data() {
return {}
},
computed: {
tabulatorOptions() {

View File

@ -1,7 +1,5 @@
<!-- eslint-disable -->
<script>
import Modal from '@molecules/Modal/index.vue'
import Modal from '@molecules/VModal/VModal.vue'
import {CoordsMap} from './helpers'
export default {
@ -55,8 +53,6 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<Modal
v-if="open"
@ -64,7 +60,6 @@ export default {
:isOpen="true"
:containerClass="containerClass"
>
<div :class="headerClass">
<slot name="header" />
</div>

View File

@ -2,23 +2,20 @@ import Map from 'ol/Map.js';
import OSM from 'ol/source/OSM.js';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import { transform, fromLonLat, toLonLat } from "ol/proj";
import { fromLonLat } from "ol/proj";
import Point from "ol/geom/Point";
import {Fill, Stroke, Style, Text, Icon} from 'ol/style.js';
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import Feature from "ol/Feature";
import Overlay from "ol/Overlay";
import {toStringHDMS} from 'ol/coordinate.js';
const svg = (color = "black", course) => {
const svg = () => {
const screen_width = document.documentElement.clientWidth;
let svg_width = 25;
let svg_height = 45;
let text_size = "30px";
if (
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
@ -50,9 +47,9 @@ const createMap = (elId, zoom, coordinates = [37.619829, 55.752603]) => {
)
}
const mapFeature = (coord) => {
const mapFeature = (coordinate) => {
return new Feature({
geometry: new Point(coord).transform("EPSG:4326", "EPSG:900913"),
geometry: new Point(coordinate).transform("EPSG:4326", "EPSG:900913"),
projection: "EPSG:4326",
});
}

View File

@ -0,0 +1,102 @@
<script>
import {mapActions} from "vuex";
import {ECharts} from '@store/hooks/Echarts';
export default {
name: 'VChart',
props: {
data: {
type: Object,
default: () => {}
},
sizes: {
type: Object,
default: () => {}
},
id: {
type: String,
required: true,
default: ''
},
type: {
type: String,
required: true,
default: ''
},
height: {
type: String,
default: ''
},
maxWidth: {
type: String,
default: ''
},
maxHeight: {
type: String,
default: ''
},
},
data() {
return {
chartStyles: {
maxWidth: `${this.maxWidth}`,
maxHeight: `${this.maxHeight}`,
top: "15px",
padding: "10px",
margin: "10px",
boxShadow: "rgb(0 0 0 / 12%) 2px 3px 7px",
border: "1px solid rgba(0, 0, 0, 0.15)"
}
}
},
computed: {
// ...mapGetters('main', ['activeChartData', 'prevGroupByData', 'activeMenuChartData']),
},
watch: {
},
mounted () {
this.$nextTick(function () {
const chart = new ECharts(this.id, this.sizes)
this.setTypeFunc(this.type, chart, this.data)
chart.onClickedBarCharts(this.updateCharts)
})
},
updated () {
this.$nextTick(function () {
const chart = new ECharts(this.id, this.sizes)
this.setTypeFunc(this.type, chart, this.data)
chart.onClickedBarCharts(this.updateCharts)
})
},
methods: {
...mapActions('layoutMachines', ['updateCharts']),
setTypeFunc: function(type, chart, data) {
switch(type) {
case 'pie': return chart.makePieCharts({...data, type: type})
case 'mount': return chart.makeBarMountCharts({...data, type: type, height: this.height})
case 'mainMl': return chart.makeBarCharts({...data, type: type})
case 'default': return chart.makeBarTypesCharts({...data, type: type})
case 'types': return chart.makeBarTypesCharts({...data, type: type})
case 'without_first_layout': return chart.makeBarTypesCharts({...data, type: type})
case 'ml': return chart.makeBarTypesCharts({...data, type: type})
case 'packLines': return chart.makeLinesPackCharts({...data, type: type})
}
}
}
}
</script>
<template>
<div
:id="id"
class="flex grow justify-center relative overflow-hidden bg-white"
:style="chartStyles"
/>
<div
id="button_close"
class="flex absolute h-max top-[50px] right-[45px]"
/>
</template>
<style scoped>
</style>

View File

@ -1,17 +1,9 @@
<template>
<input
ref="datepicker"
type="text"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 flatpickr-input"
>
</template>
<script>
import flatpickr from "flatpickr";
import { Russian } from "flatpickr/dist/l10n/ru";
export default {
name: 'Datepicker',
name: 'VDatepicker',
components: {},
inject: ['defaultDate'],
props: {
@ -70,3 +62,11 @@ export default {
}
</script>
<template>
<input
ref="datepicker"
type="text"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 flatpickr-input"
>
</template>

View File

@ -1,3 +1,44 @@
<script>
export default {
name: 'VModal',
components: {},
props: {
isOpen: {
default: false,
type: Boolean
},
close: {
default: () => null,
type: Function
},
containerClass: {
default: "",
type: String,
}
},
data() {
return {}
},
computed: {
},
mounted () {
document.addEventListener("keydown", this.onEsc);
},
unmounted() {
document.removeEventListener("keydown", this.onEsc);
},
methods: {
onEsc (e) {
if (e.key === "Escape") {
this.close()
}
}
}
}
</script>
<template>
<div
v-if="isOpen"
@ -8,14 +49,14 @@
id="select_machines_modal"
class="fixed z-[10000] inset-0"
>
<!-- Modal container -->
<!-- VModal container -->
<div class="h-screen flex items-center justify-center p-4">
<!-- Overlay -->
<div
class="absolute z-0 inset-0 bg-gray-500 opacity-75"
aria-hidden="true"
/>
<!-- Modal box -->
<!-- VModal box -->
<div
class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl "
role="dialog"
@ -45,43 +86,3 @@
</div>
</div>
</template>
<script>
export default {
name: 'Modal',
components: {},
props: {
isOpen: {
default: false,
type: Boolean
},
close: {
default: () => null,
type: Function
},
containerClass: {
default: "",
type: String,
}
},
data() {
},
computed: {
},
mounted () {
document.addEventListener("keydown", this.onEsc);
},
unmounted() {
document.removeEventListener("keydown", this.onEsc);
},
methods: {
onEsc (e) {
if (e.key === "Escape") {
this.close()
}
}
}
}
</script>

View File

@ -11,10 +11,10 @@
</template>
<script>
import RawSpinner from './Spinner.vue'
import RawSpinner from './VSpinnerSvg.vue'
export default {
name: 'Spinner',
name: 'VSpinner',
components: {RawSpinner},
props: {
text: {
@ -27,6 +27,7 @@ export default {
}
},
data() {
return {}
},
computed: {
},

View File

@ -22,7 +22,7 @@
<script>
export default {
name: 'RawSpinner',
name: 'VSpinnerSvg',
components: {},
props: {
size: {
@ -31,6 +31,7 @@ export default {
},
},
data() {
return {}
},
computed: {
},

View File

@ -11,10 +11,10 @@ import {
import localization from "./localization";
import { cond, equals, is, mergeAll, sort, T, mergeDeepRight } from "ramda";
import { pipe } from "@helpers/functions";
import Pagination from "./Pagination.vue";
import Pagination from "./VTabulatorPagination.vue";
export default {
name: 'App',
name: 'VTabulator',
components: {
Pagination
},

View File

@ -1,4 +1,4 @@
<!-- eslint-disable -->
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
@ -119,7 +119,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="pagination w-full flex flex-row items-center justify-between gap-3 mt-2 mb-8 xl:mb-0 pb-8 xl:p-2.5 bg-slate-100 border-2 border-solid border-slate-300 rounded-lg flex-col 2xl:flex-row">

View File

@ -1,4 +1,4 @@
<!-- eslint-disable -->
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
@ -43,7 +43,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
{{ console.log('selectedPackMode', selectedPackMode)

View File

@ -1,10 +1,10 @@
<!-- eslint-disable -->
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import PackViewButton from './Button.vue'
import Spinner from "@molecules/Spinner/index.vue"
import Tabulator from "@molecules/Tabulator/index.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import { isEmpty } from "ramda";
export default {
@ -65,7 +65,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="w-full relative">

View File

@ -1,19 +1,21 @@
<script>
import MenuList from './MenuList.vue'
import MobileMenu from './MobileMenu.vue'
import LeftPanel from './LeftPanel.vue'
import Breadcrumbs from './Breadcrumbs.vue'
import LeftPanel from './AppContainerLeftPanel.vue'
import Breadcrumbs from './AppContainerBreadcrumbs.vue'
import RightPanel from './RightPanel.vue'
import AppContainerHeader from './AppContainerHeader.vue'
import {mapGetters} from 'vuex'
export default {
name: 'MenuContainer',
name: 'AppContainer',
components: {
MobileMenu,
MenuList,
LeftPanel,
Breadcrumbs,
RightPanel
RightPanel,
AppContainerHeader
},
data() {
},
@ -40,7 +42,7 @@ export default {
current_user=""
:menu_list="menuList"
/>
<div class="w-full">
<AppContainerHeader>
<div class="flex justify-between items-center">
<LeftPanel />
<Breadcrumbs
@ -54,7 +56,7 @@ export default {
/>
</div>
<div class="sm:hidden flex items-center justify-between" />
</div>
</AppContainerHeader>
</div>
<!-- END: TOP BAR -->
<div class="wrapper">

View File

@ -0,0 +1,21 @@
<script>
export default {
name: "AppContainerHeader",
props: {
},
data() {
return {}
},
computed: {},
methods: {}
}
</script>
<template>
<div class="w-full">
<slot />
</div>
</template>

View File

@ -1,7 +1,7 @@
<script>
export default {
name: 'LeftPanel',
name: 'AppContainerLeftPanel',
components: {},
data() {
return {

View File

@ -129,7 +129,7 @@ export default {
/>
</div>
</div>
<!-- BEGIN: Account Menu -->
<!-- BEGIN: Account AppContainer -->
<div class="intro-x dropdown w-[50px] h-[50px] px-3 flex justify-center items-center">
<div
class="dropdown-toggle rounded-full overflow-hidden shadow-lg image-fit zoom-in scale-110"
@ -169,6 +169,6 @@ export default {
</ul>
</div>
</div>
<!-- END: Account Menu -->
<!-- END: Account AppContainer -->
</div>
</template>

View File

@ -1,10 +0,0 @@
<script setup>
</script>
<template>
<div class="w-full pl-2 flex items-center h-[40px] border-b border-slate-200">
<div>
Hi!
</div>
</div>
</template>

View File

@ -1,20 +0,0 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
name: 'App',
components: {},
data() {
},
computed: {
},
methods: {
}
}
</script>

View File

@ -1,139 +0,0 @@
<template>
<div
class="h-[100vh] z-40 bg-white flex flex-col px-4 pt-8 border-r border-slate-200 transition-all"
:class="{'w-[300px]': isOpenMenu, 'w-[70px]': !isOpenMenu}"
>
<div class="pl-1 flex items-center mb-8 justify-between">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--logos"
width="31.88"
height="32"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 256 257"
>
<defs><linearGradient
id="IconifyId1813088fe1fbc01fb466"
x1="-.828%"
x2="57.636%"
y1="7.652%"
y2="78.411%"
><stop
offset="0%"
stop-color="#41D1FF"
/><stop
offset="100%"
stop-color="#BD34FE"
/></linearGradient><linearGradient
id="IconifyId1813088fe1fbc01fb467"
x1="43.376%"
x2="50.316%"
y1="2.242%"
y2="89.03%"
><stop
offset="0%"
stop-color="#FFEA83"
/><stop
offset="8.333%"
stop-color="#FFDD35"
/><stop
offset="100%"
stop-color="#FFA800"
/></linearGradient></defs><path
fill="url(#IconifyId1813088fe1fbc01fb466)"
d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"
/><path
fill="url(#IconifyId1813088fe1fbc01fb467)"
d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"
/>
</svg>
<div
class="p-1 px-2 rounded-md transition-all cursor-pointer hover:bg-gray-200"
:class="{'rotate-90': !isOpenMenu, '-rotate-90': isOpenMenu}"
@click="toggleMenu"
>
<i class="ri-upload-line" />
</div>
</div>
<div class="flex flex-col">
<div
v-for="{title, icon, link, type, name} in menu"
:key="`${title}${name}`"
>
<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>
<div
v-if="type === 'line'"
class="border-b my-4 border-slate-200"
/>
</div>
</div>
</div>
</template>
<script>
import {mapGetters, mapMutations} from "vuex";
export default {
name: 'App',
components: {},
data() {
const menu = [
{
title: "Главная",
icon: "home-4-line",
link: "/",
type: "link",
name: "main"
},
{
title: "Главная1",
icon: "home-4-line",
link: "/page1",
type: "link",
name: "page1"
},
{
title: "Главная2",
icon: "home-4-line",
link: "/page2",
type: "link",
name: "page2"
},
{
title: "Выход",
icon: "logout-circle-line",
link: "/auth",
type: "link",
name: ""
},
]
return {
menu
}
},
computed: {
...mapGetters('layout', ['isOpenMenu']),
pageName() {
return this.$route.name
}
},
methods: {
...mapMutations('layout', ['toggleMenu']),
}
}
</script>

View File

@ -221,7 +221,7 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Datepicker from "@molecules/Datepicker/index.vue"
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import { FwbTextarea } from 'flowbite-vue'
export default {

View File

@ -23,14 +23,14 @@
class="fixed z-[10000] inset-0 hidden"
phx-remove="[[&quot;transition&quot;,{&quot;time&quot;:200,&quot;to&quot;:null,&quot;transition&quot;:[[&quot;fade-out&quot;],[],[]]}]]"
>
<!-- Modal container -->
<!-- VModal container -->
<div class="h-screen flex items-center justify-center p-4">
<!-- Overlay -->
<div
class="absolute z-0 inset-0 bg-gray-500 opacity-75"
aria-hidden="true"
/>
<!-- Modal box -->
<!-- VModal box -->
<div
class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl "
role="dialog"

View File

@ -102,10 +102,10 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Datepicker from "@molecules/Datepicker/index.vue"
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import {mapGetters, mapMutations, mapActions} from 'vuex'
import Tabulator from "@molecules/Tabulator/index.vue"
import Spinner from "@molecules/Spinner/index.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import MachinesModal from "@molecules/MachinesModal/MachinesModal.vue"
export default {

View File

@ -1,7 +1,6 @@
<template>
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
<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"
>
@ -80,8 +79,8 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import {mapGetters, mapMutations, mapActions} from 'vuex'
import Tabulator from "@molecules/Tabulator/index.vue"
import Spinner from "@molecules/Spinner/index.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
export default {
name: 'LastPacksNum',

View File

@ -1,7 +1,7 @@
<script>
import {mapGetters, mapActions, mapMutations, useStore} from "vuex"
import Button from "@/components/1_atoms/Button.vue"
import Tabulator from "@molecules/Tabulator/index.vue"
import Button from "@atoms/VButton.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
export default {
name: 'AddUsers',
@ -31,7 +31,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
{{ console.log('adminData', adminData)

View File

@ -1,8 +1,8 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import Spinner from "@molecules/Spinner/index.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import {PushAfterTimeout} from '@store/hooks/PushAfterTimeout'
import Accordion from '@atoms/Accordion.vue'
import Accordion from '@atoms/VAccordion.vue'
export default {
name: 'FinderPacks',
@ -41,7 +41,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="rounded w-full transition-all min-h-[500px] relative">

View File

@ -1,12 +1,12 @@
<!-- eslint-disable -->
<script>
import {ref, toRaw, computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import {useRoute, useRouter} from 'vue-router'
import Button from "@/components/1_atoms/Button.vue";
import Button from "@atoms/VButton.vue";
import DoubleSwitch from "@/components/1_atoms/DoubleSwitch.vue";
import Chart from "@/components/2_molecules/Chart/index.vue";
import Chart from "@molecules/VChart/VChart.vue";
import ECharts from '@store/hooks/Echarts';
export default {
@ -64,7 +64,7 @@ export default {
},
},
computed: {
...mapGetters('machines', ['selectedSelects', 'selectsData', 'toggleFilter', 'chartsData', 'activeChartData', 'prevGroupByData', 'activeMenuChartData', 'openMenuChart', 'legendFiltersParams']),
...mapGetters('layoutMachines', ['selectedSelects', 'selectsData', 'toggleFilter', 'chartsData', 'activeChartData', 'prevGroupByData', 'activeMenuChartData', 'openMenuChart', 'legendFiltersParams']),
},
mounted () {
@ -104,7 +104,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="px-2 sm:px-5 pt-1 bg-light">

View File

@ -1,11 +1,11 @@
<!-- eslint-disable -->
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import Modal from '@molecules/Modal/index.vue'
import Accordion from '@atoms/Accordion.vue'
import Modal from '@molecules/VModal/VModal.vue'
import Accordion from '@atoms/VAccordion.vue'
import PackView from '@organisms/PackView/index.vue'
import Spinner from "@molecules/Spinner/index.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import {getMachineInfo} from './helpers'
export default {
@ -69,7 +69,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<Modal

View File

@ -1,9 +1,9 @@
<!-- eslint-disable -->
<script>
import {ref, toRaw, computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import Button from "@/components/1_atoms/Button.vue";
import Button from "@atoms/VButton.vue";
import VueMultiselect from 'vue-multiselect'
export default {
@ -43,7 +43,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div id="ignore:2Qxwqz" class="pb-1">

View File

@ -1,6 +1,6 @@
<script>
import {mapGetters, mapMutations, useStore} from "vuex"
import Tabulator from "@molecules/Tabulator/index.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import { EventStore } from "@store/hooks/EventStore"
export default {

View File

@ -1,8 +1,8 @@
<!-- eslint-disable -->
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import Button from "@/components/1_atoms/Button.vue"
import Button from "@atoms/VButton.vue"
import { EventStore } from "@store/hooks/EventStore"
import moment from 'moment'
@ -76,7 +76,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div id="card" class="pt-3 border w-[23%] min-w-[310px] border-slate-300 rounded transition-all bg-slate-300}">

View File

@ -1,19 +1,19 @@
<!-- eslint-disable -->
<script>
import {computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {useRoute, useRouter} from 'vue-router'
import Button from "@/components/1_atoms/Button.vue"
import Button from "@atoms/VButton.vue"
import VueMultiselect from 'vue-multiselect'
import Filters from "./Filters.vue"
import Machine from "./Machine.vue"
import Charts from "./Charts.vue"
import HistoryViews from "./HistoryViews.vue"
import Table from "./Table.vue"
import MapModal from '@molecules/MapModal/index.vue'
import MapModal from '@molecules/MapModal/MapModal.vue'
import DataModal from "./DataModal/DataModal.vue"
import Spinner from "@molecules/Spinner/index.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import {PushAfterTimeout} from '@store/hooks/PushAfterTimeout'
import {EventStore} from '@store/hooks/EventStore'
@ -140,7 +140,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="px-2 sm:px-5 pt-1 bg-light">

View File

@ -1,6 +1,6 @@
<script>
import {mapGetters, mapActions, mapMutations, useStore} from "vuex"
import Tabulator from "@molecules/Tabulator/index.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import { EventStore } from "@store/hooks/EventStore"
export default {

View File

@ -1,4 +1,4 @@
<!-- eslint-disable -->
<script>
import {computed} from 'vue'
@ -7,7 +7,7 @@ import {useRoute} from 'vue-router'
import Machines from "./Machines/Machines.vue";
import FinderPacks from "./FinderPacks/FinderPacks.vue";
import AddUsers from "./AddUsers/AddUsers.vue";
import Button from "@/components/1_atoms/Button.vue";
import Button from "@atoms/VButton.vue";
export default {
name: 'Main',
@ -65,7 +65,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="col-span-12">

View File

@ -1,7 +1,7 @@
<!-- eslint-disable -->
<script>
import Chart from "@/components/2_molecules/Chart/index.vue";
import Chart from "@molecules/VChart/VChart.vue";
import moment from 'moment'
export default {
@ -55,7 +55,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
{{ console.log('currentSizes.heigth', maxHeight) }}

View File

@ -2,9 +2,9 @@
import {ref, toRaw, computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import {useRoute, useRouter} from 'vue-router'
import Datepicker from "@molecules/Datepicker/index.vue"
import Spinner from "@molecules/Spinner/index.vue"
import Tabulator from "@molecules/Tabulator/index.vue"
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import PackChart from './Chart/Chart.vue'
import VueMultiselect from 'vue-multiselect'
import moment from 'moment'
@ -124,7 +124,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
@ -316,14 +316,14 @@ export default {
class="fixed z-[10000] inset-0 hidden"
phx-remove="[[&quot;transition&quot;,{&quot;time&quot;:200,&quot;to&quot;:null,&quot;transition&quot;:[[&quot;fade-out&quot;],[],[]]}]]"
>
<!-- Modal container -->
<!-- VModal container -->
<div class="h-screen flex items-center justify-center p-4">
<!-- Overlay -->
<div
class="absolute z-0 inset-0 bg-gray-500 opacity-75"
aria-hidden="true"
/>
<!-- Modal box -->
<!-- VModal box -->
<div
class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl "
role="dialog"
@ -370,14 +370,14 @@ export default {
class="fixed z-[10000] inset-0 hidden"
phx-remove="[[&quot;transition&quot;,{&quot;time&quot;:200,&quot;to&quot;:null,&quot;transition&quot;:[[&quot;fade-out&quot;],[],[]]}]]"
>
<!-- Modal container -->
<!-- VModal container -->
<div class="h-screen flex items-center justify-center p-4">
<!-- Overlay -->
<div
class="absolute z-0 inset-0 bg-gray-500 opacity-75"
aria-hidden="true"
/>
<!-- Modal box -->
<!-- VModal box -->
<div
class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl "
role="dialog"
@ -457,14 +457,14 @@ export default {
class="fixed z-[10000] inset-0 hidden"
phx-remove="[[&quot;transition&quot;,{&quot;time&quot;:200,&quot;to&quot;:null,&quot;transition&quot;:[[&quot;fade-out&quot;],[],[]]}]]"
>
<!-- Modal container -->
<!-- VModal container -->
<div class="h-screen flex items-center justify-center p-4">
<!-- Overlay -->
<div
class="absolute z-0 inset-0 bg-gray-500 opacity-75"
aria-hidden="true"
/>
<!-- Modal box -->
<!-- VModal box -->
<div
class="relative max-h-full overflow-y-auto bg-white rounded-lg shadow-xl "
role="dialog"

View File

@ -1,13 +1,7 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
name: 'App',
name: 'Diap',
components: {},
data() {
},
@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@ -1,13 +1,7 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
name: 'App',
name: 'News',
components: {},
data() {
},
@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@ -1,13 +1,7 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
name: 'App',
name: 'Packs',
components: {},
data() {
},
@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@ -1,13 +1,7 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
name: 'App',
name: 'ServiceManage',
components: {},
data() {
},
@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@ -1,105 +0,0 @@
<!-- eslint-disable -->
<script>
import {mapActions, useStore} from "vuex"
import Spinner from "@molecules/Spinner/index.vue"
import { CopyToClipboard } from "@store/hooks/CopyToClipboard"
export default {
name: 'Service',
components: {
Spinner,
},
props: {
idx: {
type: Number,
default: 0
},
name: {
type: String,
default: ""
},
service: {
type: Object,
default: () => {}
},
copyed: {
type: String,
default: "copyed"
},
},
data () {
return {
isCopyed: false
}
},
setup (props, {slots}) {
const store = useStore()
store.dispatch('logger/uploadData', {status: 'info', text: 'Сервис Info'})
},
methods: {
...mapActions('services', ['uploadServiceData']),
isInitParams: function(service) {
if (service?.init_params && typeof service?.init_params === 'object') {
if (service?.init_params?.service && service?.init_params?.machine_addr) return true
}
},
copyText: function (e) {
const id = e.target.getAttribute('id')
const text = e.target.getAttribute('copyOnClickText')
this.isCopyed = true
return new CopyToClipboard('serviceList', text)
}
}
}
</script>
<!-- eslint-disable -->
<template>
<div :key="idx" style="min-width: 240px" class="h-full overflow-hidden shadow-lg rounded-lg h-auto w-80 my-2 md:w-80 p-4 bg-indigo-50 transition duration-200 ease-in-out transform hover:translate-y-1 hover:shadow-2xl">
<div class="w-full flex flex-col h-full justify-center">
<div class="flex my-2 justify-between">
<span class="font-bold"> {{ service?.title }} </span>
<span v-if="service?.is_online || name === 'глобальное хранилище'" class="font-bold text-green-700">доступен</span>
<span v-else class="font-bold text-red-800">отключен </span>
</div>
<hr>
<div class="text-gray-700 my-3 flex items-center flex-grow">
<div v-if="service?.serviceIp || service?.serviceCode" class="flex flex-col gap-4">
<div class="flex flex-col">
<span class="italic text-xs font-bold">Детали</span>
<span v-if="service?.serviceIp" class="italic text-xs">{{ service?.serviceIp }}</span>
<span v-if="service?.serviceCode" class="italic text-xs">{{ service?.serviceCode }}</span>
</div>
<div class="flex flex-col">
<span class="italic text-xs font-bold">Последний перезапуск(UTC):</span>
<span class="italic text-xs">{{ service?.dateStart }}</span>
</div>
<div class="flex flex-col">
<span class="italic text-xs font-bold">Описание сервиса:</span>
<span class="italic text-xs">{{ service?.description || "... нет описания" }}</span>
</div>
</div>
<div v-else class="flex flex-col">
<span class="italic text-xs font-bold">Описание сервиса:</span>
<span class="italic text-xs">Сервис глобального хранилища применяется для условно постоянного хранения данных в кэше</span>
</div>
</div>
<hr>
<div class="mt-2">
<span v-if="isInitParams(service)" class="flex justify-between" >
<span @click="copyText" :copyOnClickText="`${service?.init_params?.service}:${service?.init_params?.machine_addr}`" :copyed="`${isCopyed ? copyed : ''}`" class="copyText italic text-xs flex cursor-pointer" :id="`service_${service?.init_params?.service}`">
<i class="ri-file-copy-2-line text-slate-600 mr-1"></i>
{{ service?.serviceLink }}
</span>
<a :href="`/admin_panel/auth_service?show_service_cache=${name}`" id="selectService" @click="uploadServiceData(service)" class="flex italic text-xs cursor-pointer underline hover:text-gray-500 linear-loader">
открыть
</a>
</span>
<div v-else class="italic text-xs">нет доступа к глоб. хранилищу</div>
</div>
</div>
</div>
</template>

View File

@ -1,10 +1,10 @@
<!-- eslint-disable -->
<script>
import {mapGetters, useStore} from "vuex"
import Service from './Service.vue'
import Spinner from "@molecules/Spinner/index.vue"
import Tabulator from "@molecules/Tabulator/index.vue"
import Service from './ServicesServiceItem.vue'
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
export default {
name: 'Services',
@ -41,7 +41,7 @@ export default {
</script>
<!-- eslint-disable -->
<template>
<div class="col-span-12">

View File

@ -0,0 +1,148 @@
<script>
import {mapActions, useStore} from "vuex"
import { CopyToClipboard } from "@store/hooks/CopyToClipboard"
export default {
name: 'ServicesServiceItem',
props: {
idx: {
type: Number,
default: 0
},
name: {
type: String,
default: ""
},
service: {
type: {
title: String,
serviceIp: String,
serviceCode: String,
dateStart: String,
description: String,
serviceLink: String,
is_online: Boolean,
init_params: Object
},
default: () => {}
},
copyed: {
type: String,
default: "copyed"
},
},
setup () {
const store = useStore()
store.dispatch('logger/uploadData', {status: 'info', text: 'Сервис Info'})
},
data () {
return {
isCopyed: false
}
},
methods: {
...mapActions('services', ['uploadServiceData']),
isInitParams: function(service) {
if (service?.init_params && typeof service?.init_params === 'object') {
if (service?.init_params?.service && service?.init_params?.machine_addr) return true
}
},
copyText: function (e) {
const text = e.target.getAttribute('copyOnClickText')
this.isCopyed = true
return new CopyToClipboard('serviceList', text)
}
}
}
</script>
<template>
<div
:key="idx"
style="min-width: 240px"
class="h-full overflow-hidden shadow-lg rounded-lg w-80 my-2 md:w-80 p-4 bg-indigo-50 transition duration-200 ease-in-out transform hover:translate-y-1 hover:shadow-2xl"
>
<div class="w-full flex flex-col h-full justify-center">
<div class="flex my-2 justify-between">
<span class="font-bold"> {{ service?.title }} </span>
<span
v-if="service?.is_online || name === 'глобальное хранилище'"
class="font-bold text-green-700"
>доступен</span>
<span
v-else
class="font-bold text-red-800"
>отключен </span>
</div>
<hr>
<div class="text-gray-700 my-3 flex items-center flex-grow">
<div
v-if="service?.serviceIp || service?.serviceCode"
class="flex flex-col gap-4"
>
<div class="flex flex-col">
<span class="italic text-xs font-bold">Детали</span>
<span
v-if="service?.serviceIp"
class="italic text-xs"
>{{ service?.serviceIp }}</span>
<span
v-if="service?.serviceCode"
class="italic text-xs"
>{{ service?.serviceCode }}</span>
</div>
<div class="flex flex-col">
<span class="italic text-xs font-bold">Последний перезапуск(UTC):</span>
<span class="italic text-xs">{{ service?.dateStart }}</span>
</div>
<div class="flex flex-col">
<span class="italic text-xs font-bold">Описание сервиса:</span>
<span class="italic text-xs">{{ service?.description || "... нет описания" }}</span>
</div>
</div>
<div
v-else
class="flex flex-col"
>
<span class="italic text-xs font-bold">Описание сервиса:</span>
<span class="italic text-xs">Сервис глобального хранилища применяется для условно постоянного хранения данных в кэше</span>
</div>
</div>
<hr>
<div class="mt-2">
<span
v-if="isInitParams(service)"
class="flex justify-between"
>
<span
:id="`service_${service?.init_params?.service}`"
:copyOnClickText="`${service?.init_params?.service}:${service?.init_params?.machine_addr}`"
:copyed="`${isCopyed ? copyed : ''}`"
class="copyText italic text-xs flex cursor-pointer"
@click="copyText"
>
<i class="ri-file-copy-2-line text-slate-600 mr-1" />
{{ service?.serviceLink }}
</span>
<a
id="selectService"
:href="`/admin_panel/auth_service?show_service_cache=${name}`"
class="flex italic text-xs cursor-pointer underline hover:text-gray-500 linear-loader"
@click="uploadServiceData(service)"
>
открыть
</a>
</span>
<div
v-else
class="italic text-xs"
>
нет доступа к глоб. хранилищу
</div>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,21 @@
<script>
export default {
name: "ComponentTemplate",
props: {
},
data() {
return {}
},
computed: {},
methods: {}
}
</script>
<template>
<div class="">
ComponentTemplate
</div>
</template>

View File

@ -16,7 +16,7 @@ import News from "@admin_pages/News/index.vue"
import Machines from "@pages/Main/Machines/Machines.vue"
import FinderPacks from "@pages/Main/FinderPacks/FinderPacks.vue"
import AddUsers from "@pages/Main/AddUsers/AddUsers.vue"
import Services from "@admin_pages/Services/index.vue"
import Services from "@admin_pages/Services/Services.vue"
import ServiceManage from "@admin_pages/ServiceManage/index.vue"
import {get} from "@store/modules/apiHelpers"
import {cond, T} from 'ramda'

View File

@ -903,4 +903,5 @@ class ECharts {
}
}
export {ECharts}
export default ECharts;

View File

@ -1,6 +1,6 @@
import { toRaw } from 'vue'
import { Logger } from './helpers'
import { loggerInfo } from './StaticData'
import { Logger } from '3-class-complex-assistants'
const initState = {
isPushToServer: true,
@ -32,7 +32,7 @@ const mutations = {
};
const actions = {
uploadData: async ({commit, getters, state}, data) => {
uploadData: async ({commit, state}, data) => {
try{
const callFunc = (text) => (`answerMessage: ${text}`)
@ -42,7 +42,6 @@ const actions = {
const status = data.status
const text = data.text
const allParams = {...serviceInfo, callFunc, isPushToServer}
console.log('allParams', allParams)
const logger = new Logger(allParams)
const loggerAnswer = (status) => {

View File

@ -1,127 +0,0 @@
import {expect, test, vi} from 'vitest'
import {Logger} from './helpers'
import { globalServices } from '@store/modules/services/StaticData'
// import {loggerInfo} from './StaticData'
// import Vue from 'vue'
import {createStore, useStore, Vuex} from 'vuex'
import {store} from './index.js'
import { flushPromises } from '@vue/test-utils'
// const store = useStore()
// store.dispatch('logger/uploadData')
console.log('store', store.mutations)
// Vue.use(Vuex)
const loggerAnswer = store.state.loggerAnswer
const loggerInfo = store.state.serviceInfo
const setLoggerInfo = store.mutations.setServiceInfo
const setLoggerData = store.mutations.setLoggerData
const setLoggerAnswer = store.mutations.setLoggerAnswer
const uploadData = store.actions.uploadData
const mockStore = createStore({
state: {
isPushToServer: true,
serviceInfo: loggerInfo,
loggerAnswer: loggerAnswer
},
mutations: {
setLoggerAnswer: setLoggerAnswer,
},
actions: {
setUploadData: uploadData,
},
})
describe('mutations', () => {
it('Set to empty Service info', () => {
const state = { serviceInfo: loggerInfo }
setLoggerInfo(state, null)
expect(state.serviceInfo).to.equal(null)
})
})
describe('mutations', () => {
it('Set logger data', () => {
const state = { loggerData: null }
setLoggerData(state, loggerInfo)
expect(state.loggerData).to.toMatchObject({logger_level: '4'})
})
})
describe('actions', () => {
it('Set unknown status to loggerAnswer', async () => {
mockStore.dispatch('setUploadData', {status: 'custom', text: 'Test actions'})
expect(mockStore.state.loggerAnswer).toEqual('answerMessage: Неизвестный статус логгера')
})
})
describe('actions', () => {
it('Verify right status UpperCase Text to loggerAnswer', async () => {
mockStore.dispatch('setUploadData', {status: 'Debug', text: 'Test Debug status with UpperCase Text'})
expect(mockStore.state.loggerAnswer).toEqual('answerMessage: Test Debug status with UpperCase Text')
})
})
test('empty logger info', () => {
const newLogger = new Logger()
const loggerDebug = newLogger.debug()
const loggerInfo = newLogger.info()
const loggerWarn = newLogger.warn()
const loggerError = newLogger.error()
expect(loggerDebug).toBeUndefined()
expect(loggerInfo).toBeUndefined()
expect(loggerWarn).toBeUndefined()
expect(loggerError).toBeUndefined()
})
test('sent logger, empty required params', () => {
const callback = (text) => console.log('callback', text)
const allParams = {...loggerInfo, callFunc: callback, isPushToServer: true}
const newLogger = new Logger(allParams)
const loggerWarn = newLogger.warn('', 1)
const loggerError = newLogger.error('Test error')
expect(loggerWarn).toBeUndefined()
expect(loggerError).toBeUndefined()
})
test('sent logger, empty callback function', () => {
const allParams = {...loggerInfo, callFunc: null, isPushToServer: true}
const newLogger = new Logger(allParams)
const loggerDebug = newLogger.debug('Test debug', 0)
const loggerInfos = newLogger.info('Test info', 1)
const loggerWarn = newLogger.warn('Test warn', 2)
const loggerError = newLogger.error('Test error', 3)
expect(loggerDebug).toBe('Отладочная информация отправлена на сервер')
expect(loggerInfos).toBe('Информация отправлена на сервер')
expect(loggerWarn).toBe('Предупреждение отправлено на сервер')
expect(loggerError).toBe('Ошибка отправлена на сервер')
})
test('sent logger, with callback function', () => {
const callback = vi.fn((text) => `callback func - ${text}`)
const allParams = {...loggerInfo, callFunc: callback, isPushToServer: true}
const newLogger = new Logger(allParams)
const loggerDebug = newLogger.debug('Test debug', 1)
const loggerInfos = newLogger.info('Test info', 1)
const loggerWarn = newLogger.warn('Test warn', 1)
const loggerError = newLogger.error('Test error', 1)
expect(loggerDebug).toBe('callback func - Test debug')
expect(loggerInfos).toBe('callback func - Test info')
expect(loggerWarn).toBe('callback func - Test warn')
expect(loggerError).toBe('callback func - Test error')
})

View File

@ -2,7 +2,7 @@ import { isEmpty } from "ramda"
import {globalServices} from './StaticData'
import moment from "moment/dist/moment"
import ru from "moment/dist/locale/ru"
moment.locale("ru", ru)
moment.updateLocale("ru", ru)
class Services {
constructor() {

View File

@ -1,6 +1,6 @@
import {test, describe, expect} from 'vitest'
import { mount} from '@vue/test-utils'
import Accordion from '@atoms/Accordion.vue';
import Accordion from '@atoms/VAccordion.vue';
describe('Accordion', () => {
test('Accordion mounted', () => {

View File

@ -1,6 +1,6 @@
import {test, describe, expect} from 'vitest'
import { mount} from '@vue/test-utils'
import Button from '@atoms/Button.vue';
import Button from '@atoms/VButton.vue';
describe('Accordion', () => {
test('Accordion mounted', () => {

View File

@ -4,7 +4,12 @@ import DoubleSwitch from '@atoms/DoubleSwitch.vue';
describe('DoubleSwitch', () => {
test('DoubleSwitch mounted', () => {
const wrapper = mount(DoubleSwitch)
const wrapper = mount(DoubleSwitch, {
global: {
provide: {
isChecked: false
}}
})
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,10 @@
import {test, describe, expect} from 'vitest'
import { mount} from '@vue/test-utils'
import MapModal from '@molecules/MapModal/MapModal.vue';
describe('MapModal', () => {
test('MapModal mounted', () => {
const wrapper = mount(MapModal)
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,46 @@
import {test, describe, expect, vi} from 'vitest'
import { shallowMount } from '@vue/test-utils'
import VChart from '@molecules/VChart/VChart.vue';
import { createStore } from 'vuex';
import { store as layoutMachines } from '@/store/modules/layoutMachines';
describe('VChart', () => {
test('VChart mounted', () => {
const store = createStore({
modules: {
layoutMachines
}
})
vi.mock('@store/hooks/Echarts', () => {
const html = vi.fn(() => {
return {
getHtml: () => {
return '<div>test</div>'
},
onClickedBarCharts: vi.fn()
}
})
return {
__esModule: true,
ECharts: html
}
})
const wrapper = shallowMount(VChart, {
props: {
id: "",
type: "bar",
},
global: {
mocks: {
$store: store
}
}
})
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,18 @@
import {test, describe, expect, vi} from 'vitest'
import { mount} from '@vue/test-utils'
import VDatepicker from '@molecules/VDatepicker/VDatepicker.vue';
describe('VDatepicker', () => {
test('VDatepicker mounted', () => {
const wrapper = mount(VDatepicker,
{
global: {
provide: {
defaultDate: null
}
}
}
)
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,10 @@
import {test, describe, expect} from 'vitest'
import { mount} from '@vue/test-utils'
import VModal from '@molecules/VModal/VModal.vue';
describe('VModal', () => {
test('VModal mounted', () => {
const wrapper = mount(VModal)
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,10 @@
import {test, describe, expect} from 'vitest'
import { mount} from '@vue/test-utils'
import VSpinner from '@molecules/VSpinner/VSpinner.vue';
describe('VSpinner', () => {
test('VSpinner mounted', () => {
const wrapper = mount(VSpinner)
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -0,0 +1,31 @@
import {test, describe, expect, vi } from 'vitest'
import { mount} from '@vue/test-utils'
import VTabulator from '@molecules/VTabulator/VTabulator.vue';
describe("tests VTabulator component", () => {
vi.mock('tabulator-tables', () => {
const tabulator = vi.fn(() => {
return {
getHtml: () => {
return '<div>test</div>'
}
}
})
return {
__esModule: true,
TabulatorFull: tabulator
}
})
test('exist test of VTabulator', async () => {
const wrapper = mount(VTabulator, {
shallow: true,
})
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -1,4 +1,5 @@
import Services from '@admin_pages/Services/index.vue'
import {it, describe, expect} from 'vitest'
import Services from '@admin_pages/Services/Services.vue'
import { globalServices } from '@store/modules/services/StaticData'
import { mount } from '@vue/test-utils'
import {createStore} from 'vuex'
@ -13,11 +14,11 @@ const store = createStore({
services: (state) => state.services,
},
mutations: {
setServices: (state, updval) => state.services = updval,
setServices: (state, updateValue) => state.services = updateValue,
},
})
describe("Services", () => {
describe("6_admin_pages, page of Services", () => {
it("renders Services, with custom button title", () => {
const wrapper = mount(Services, {
global: {
@ -56,6 +57,7 @@ describe("Services", () => {
})
expect(store.state.services.length).toBeGreaterThan(0)
expect(wrapper.exists()).toBe(true)
})
})
@ -70,5 +72,6 @@ describe("Services", () => {
store.commit('setServices', [])
expect(store.state.services.length).toBe(0)
expect(wrapper.exists()).toBe(true)
})
})

View File

@ -1,40 +1,34 @@
import Service from '@admin_pages/Services/Service.vue'
import {test, describe, expect} from 'vitest'
import Service from '@admin_pages/Services/ServicesServiceItem.vue'
import { globalServices } from '@store/modules/services/StaticData'
import { store as logger } from '@/store/modules/logger';
import { mount } from '@vue/test-utils'
import {createStore} from 'vuex'
const store = createStore({
state() {
return {
modules: {
logger,
services: globalServices,
}
},
getters: {
services: (state) => state.services,
},
mutations: {
setServices: (state, updval) => state.services = updval,
},
})
describe("Service", () => {
it("renders Service, with set props value", async () => {
describe("6_admin_pages, ServicesServiceItem", () => {
test("renders Service, with set props value", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
},
props: {
idx: 1,
},
}
})
await wrapper.setProps({ idx: 3 })
expect(wrapper.html()).toContain(3)
})
})
describe("Service", () => {
it("renders Service with condition success", async () => {
test("renders Service with condition success", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
@ -48,10 +42,8 @@ describe("Service", () => {
expect(wrapper.html()).toContain('доступен')
})
})
describe("Service", () => {
it("renders Service with condition not success", async () => {
test("renders Service with condition not success", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
@ -65,10 +57,8 @@ describe("Service", () => {
expect(wrapper.html()).toContain('отключен')
})
})
describe("Service", () => {
it("renders Service if not service details", async () => {
test("renders Service if not service details", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
@ -80,10 +70,8 @@ describe("Service", () => {
expect(wrapper.html()).toContain('Сервис глобального хранилища применяется для условно постоянного хранения данных в кэше')
})
})
describe("Service", () => {
it("renders Service with set service details", async () => {
test("renders Service with set service details", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
@ -101,10 +89,8 @@ describe("Service", () => {
expect(wrapper.html()).toContain('доступен')
expect(wrapper.html()).toContain('... нет описания')
})
})
describe("Service", () => {
it("renders Service with alert copyText success after click", async () => {
test("renders Service with alert copyText success after click", async () => {
const wrapper = mount(Service, {
global: {
plugins: [store],
@ -120,3 +106,4 @@ describe("Service", () => {
expect(wrapper.html()).toContain('copyed')
})
})

View File

@ -2,9 +2,15 @@
# yarn lockfile v1
"0-tools-eslint@../repo/0-tools-eslint/":
version "0.0.1"
"1-toolkits-helpers@../repo/1-toolkits-helpers/":
version "0.0.6"
"3-class-complex-assistants@../repo/3-class-complex-assistants/":
version "0.0.6"
"@aashutoshrathi/word-wrap@^1.2.3":
version "1.2.6"
resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"

View File

@ -0,0 +1,2 @@
tsup.config.ts
/tests

7
repo/0-tools-eslint/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/node_modules
/dist
.env
.DS_Store

View File

@ -0,0 +1,8 @@
/node_modules
/src
.env
.DS_Store
tsconfig.json
tsup.config.js

View File

@ -0,0 +1,41 @@
{
"name": "3-class-complex-assistants",
"description": "",
"version": "0.0.6",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"scripts": {
"test": "vitest",
"build": "tsup",
"release": "npm run build && npm version patch && npm publish --tag latest",
"release_up": "npm version $(semver $npm_package_version -i minor) && npm publish --tag latest",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts -- --fix"
},
"repository": {
"type": "git",
"url": "https://gitlab.com/niac_vniizht/niac-packs"
},
"publishConfig": {
"registry": "https://vniac.ru:4873"
},
"keywords": [
"Logger",
"helpers",
"utils"
],
"author": "vbuglov",
"license": "ISC",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"eslint": "^8.57.0",
"moment": "^2.30.1",
"tsup": "^8.0.2",
"typescript": "^5.4.2",
"typescript-eslint": "^7.2.0",
"vite": "^5.1.6",
"vitest": "^1.4.0"
}
}

View File

@ -0,0 +1 @@
import jsEslintConfig from './javascript-eslint-config.ts';

View File

@ -0,0 +1,19 @@
let tsEslintConfig = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
],
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
project: './tsconfig.json',
},
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
"@typescript-eslint/ban-types": 'off',
},
}
export default tsEslintConfig;

View File

@ -1,4 +1,4 @@
module.exports = {
vueEslintConfig = {
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended",

View File

@ -0,0 +1,18 @@
{
"noImplicitAny": true,
"esModuleInterop": true,
"strictNullChecks": true,
"moduleResolution": "Node10",
"module": "CommonJs",
"outDir": "dist",
"declaration": true,
"isolatedModules": true,
"noEmit": true,
"include": ["src"],
"exclude": ["node_modules"],
"format": ["esm"],
"compilerOptions": {
"strict": true,
"target": "ES2022"
}
}

View File

@ -0,0 +1,11 @@
// @ts-nocheck
import {defineConfig} from "tsup";
export default defineConfig({
format: ["cjs", "esm"],
entry: ['src/index.ts'],
dts: true,
shims: true,
skipNodeModulesBundle: true,
clean: true,
})