Compare commits

..

13 Commits

Author SHA1 Message Date
b874d9000a Merge pull request 'move_users' (#5) from move_users into master
28c13c00ec
movied users from old project to new project anover repository, updated tests, cleared warns and errors in tests
2024-04-03 09:28:15 +00:00
e2fe94c1de updated Service of users 2024-04-03 12:11:27 +03:00
327f716fe9 updated Service of Users, updated tests 2024-04-03 11:58:49 +03:00
7c03bbd48c Merge pull request 'eslint_fixes' (#3) from eslint_fixes into master
Reviewed-on: https://vniac.ru:8998/vbuglov/frontend-apps/pulls/3
Reviewed-by: vbuglov <v.a.buglov@gmail.com>
2024-04-02 15:10:34 +00:00
e2dee69e71 update store for sibling components in Main Page 2024-04-02 17:48:24 +03:00
70cb21c9af fixed eslint errors 2024-04-02 16:59:42 +03:00
2b2ad786b2 clear logs, added logger, replace cebab to camelcase 2024-04-02 12:32:17 +03:00
053f6ef711 fix(eslint app): prepere eslint --fix 2024-04-02 10:56:36 +03:00
3b44337cb5 fix(eslint app): prepere to eslint --fix 2024-04-02 10:46:20 +03:00
28c13c00ec movied users from old project to new project anover repository, updated tests, cleared warns and errors in tests 2024-04-01 15:26:46 +03:00
10114ff67e fix(app): readmi 2024-04-01 09:42:52 +03:00
1ff1a31c31 fix(a[[): readmi 2024-04-01 09:40:21 +03:00
2b37e59afc feat(app): tests 2024-04-01 09:37:52 +03:00
202 changed files with 13946 additions and 8790 deletions

View File

@@ -1,59 +1,13 @@
HOOK_NAME=pre-push
HOOK_PATH=.git/hooks/$(HOOK_NAME)
restart:
docker build -t proxy-ui-vue .
docker run -d --name proxy-ui-vue --rm -p 5000:80 proxy-ui-vue
build_repo:
@echo "Building repo..."
cd repo && make build
@echo "Building success!"
stoprestart:
docker stop proxy-ui-vue
docker build -t proxy-ui-vue .
docker run -d --name proxy-ui-vue --rm -p 5000:80 proxy-ui-vue
packs_list:
cd repo && make packs_list
rmrestart:
docker image rm proxy-ui-vue
docker build -t proxy-ui-vue .
docker stop proxy-ui-vue
docker run -d --name proxy-ui-vue --rm -p 5000:80 proxy-ui-vue
pre_proxy_hook:
@echo "Setting up pre-push hook..."
@rm -f $(HOOK_PATH)
@echo '#!/bin/sh' >> $(HOOK_PATH)
@echo 'echo "Running lint for proxy-ui"' >> $(HOOK_PATH)
@echo 'cd ./proxy-ui-app' >> $(HOOK_PATH)
@echo 'yarn lint' >> $(HOOK_PATH)
@echo 'if [ $$? -ne 0 ]; then' >> $(HOOK_PATH)
@echo ' echo "Tests failed, push aborted."' >> $(HOOK_PATH)
@echo ' exit 1' >> $(HOOK_PATH)
@echo 'fi' >> $(HOOK_PATH)
@echo 'echo "Running tests for proxy-ui"' >> $(HOOK_PATH)
@echo 'yarn test_ones' >> $(HOOK_PATH)
@echo 'if [ $$? -ne 0 ]; then' >> $(HOOK_PATH)
@echo ' echo "Tests failed, push aborted."' >> $(HOOK_PATH)
@echo ' exit 1' >> $(HOOK_PATH)
@echo 'fi' >> $(HOOK_PATH)
@echo 'exit 0' >> $(HOOK_PATH)
@chmod +x $(HOOK_PATH)
@echo "Pre-push hook set successfully."
pre_users_hook:
@echo "Setting up pre-push hook..."
@rm -f $(HOOK_PATH)
@echo '#!/bin/sh' >> $(HOOK_PATH)
@echo 'echo "Running lint for proxy-ui"' >> $(HOOK_PATH)
@echo 'cd ./users-manage' >> $(HOOK_PATH)
@echo 'yarn lint' >> $(HOOK_PATH)
@echo 'if [ $$? -ne 0 ]; then' >> $(HOOK_PATH)
@echo ' echo "Tests failed, push aborted."' >> $(HOOK_PATH)
@echo ' exit 1' >> $(HOOK_PATH)
@echo 'fi' >> $(HOOK_PATH)
@echo 'echo "Running tests for proxy-ui"' >> $(HOOK_PATH)
@echo 'yarn test_ones' >> $(HOOK_PATH)
@echo 'if [ $$? -ne 0 ]; then' >> $(HOOK_PATH)
@echo ' echo "Tests failed, push aborted."' >> $(HOOK_PATH)
@echo ' exit 1' >> $(HOOK_PATH)
@echo 'fi' >> $(HOOK_PATH)
@echo 'exit 0' >> $(HOOK_PATH)
@chmod +x $(HOOK_PATH)
@echo "Pre-push hook set successfully."
list_packs:
make packs_list

View File

@@ -1,14 +1,47 @@
# Репозиторий фронтенд приложений
* Репозиторий будет переименован. microapps-admin-vue -> frontend-apps
## Приложения:
* live_monitor_vue - приложение калькулятора
* proxy-ui-app - приложение управления роутерами на сайтах и сайтами
* users-manage - приложение управления пользователями
* [repo](./repo/Readme.md) - Репозиторий пакетов
* [repo](./repo/README.md) - Репозиторий пакетов
### Установка пакета
## Скачивание и установка
* По умолчанию пакеты в гите хранятся сыром виде. После скачиваия репозитория необходимо выполнить команду установки пакетов.
```bash
make build_repo
```
## Список пакетов в репозитории
### Пример команды
```bash
make packs_list
```
### Команда для Makefile в папке проекта
```makefile
packs_list:
cd .. && make packs_list
list_packs:
make packs_list
```
## Установка пакета
### Упрощенная установка пакета.
* Команда должена быть прописана команда в Makefile.
```bash
make add pack="1-toolkits-helpers"
```
### Команда в Makefile
```makefile
add:
ifeq ($(pack),)
$(error mn is not set)
endif
yarn add "../repo/${pack}/"
```
### Общий случай:
* Для того чтобы установить пакет из репозитория, необходимо указать путь к пакету. Путь может быть абсолютным или относительным. Путь указывается к папке, содержащей файл `package.json`. Путь указывается относительно файла, в котором выполняется команда установки.
```bash

View File

@@ -3,6 +3,7 @@ module.exports = {
"eslint:recommended",
"plugin:vue/vue3-recommended",
],
"ignorePatterns": ["temp.js", "**/node_modules/*", "**/dist/*", "**/public/*", "**/build/*"],
rules: {
"no-multiple-empty-lines": ["error", {max: 2, "maxBOF": 0}],
"vue/component-tags-order": ["error", {

View File

@@ -1,9 +1,14 @@
HOOK_NAME=pre-push
HOOK_PATH=../.git/hooks/$(HOOK_NAME)
prehook:
@echo "Setting up pre-push hook..."
clearhook:
@echo "clear hooks"
@rm -f $(HOOK_PATH)
@echo "hooks cleared"
prehook:
make clearhook
@echo '#!/bin/sh' >> $(HOOK_PATH)
@echo 'echo "Running lint for live_monitor_vue"' >> $(HOOK_PATH)
@echo 'cd ./live_monitor_vue' >> $(HOOK_PATH)

View File

@@ -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>

View File

@@ -11,8 +11,8 @@
"preview": "vite preview",
"test": "vitest",
"test_ones": "vitest run",
"lint": "eslint --ext .js, **/*.vue",
"lint_fix": "eslint --ext .js, **/*.vue --fix"
"lint": "eslint 'src/**/*.{js,vue}'",
"lint_fix": "eslint 'src/**/*.{js,vue}' --fix"
},
"dependencies": {
"0-tools-eslint": "../repo/0-tools-eslint/",

View 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;
}

View File

@@ -1,9 +1,8 @@
<script>
export default {
name: 'DoubleSwitch',
inject: ['isChecked'],
props: {
machine: {
type: Object,
@@ -26,13 +25,12 @@ export default {
default: ''
},
},
emits: ['switched'],
computed: {
},
mounted () {
},
inject: ['isChecked'],
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}`
@@ -46,7 +44,6 @@ export default {
</script>
<template>
<label class="relative inline-flex items-center cursor-pointer">
<input
@@ -55,11 +52,12 @@ export default {
type="checkbox"
:checked="isChecked"
@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>
:style="{background: !isChecked ? firstColor : secondColor}"
/>
<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

@@ -1,13 +1,3 @@
<template>
<ButtonModal
text="Выбрать машину"
btnClass="col-span-4"
containerClass="pt-10 px-4 min-w-[80vw]"
>
<Tabulator v-bind="tabulatorOptions" />
</ButtonModal>
</template>
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
@@ -49,3 +39,13 @@ export default {
}
</script>
<template>
<ButtonModal
text="Выбрать машину"
btnClass="col-span-4"
containerClass="pt-10 px-4 min-w-[80vw]"
>
<Tabulator v-bind="tabulatorOptions" />
</ButtonModal>
</template>

View File

@@ -37,6 +37,8 @@ export default {
default: ""
}
},
computed: {
},
updated () {
this.$nextTick(function () {
if (this.data && this.id && this.open) {
@@ -45,8 +47,6 @@ export default {
}
})
},
computed: {
},
methods: {
}
}

View File

@@ -196,11 +196,11 @@ const setTooltip = (map, coordinates, machine, tooltip_id, content_id, closer_id
tooltipText.classList.add(content_id)
if (feature) {
const container = tooltip.getElement();
const props = feature.getProperties()
const container = tooltip.getElement()
// const props = feature.getProperties()
const coordsFormated = feature.getGeometry()
const coordsFormat = feature.getGeometry().getFlatCoordinates()
// const coordsFormated = feature.getGeometry()
// const coordsFormat = feature.getGeometry().getFlatCoordinates()
// const hdms = toLonLat(coordinates)
@@ -228,12 +228,9 @@ const setTooltip = (map, coordinates, machine, tooltip_id, content_id, closer_id
});
map.on('pointermove', function (e) {
const pixel = map.getEventPixel(e.originalEvent);
const hit = map.hasFeatureAtPixel(pixel);
// console.log('hit', hit)
// console.log('pixel', pixel)
// console.log('map', map)
// map.getTarget().style.cursor = hit ? 'pointer' : '';
const pixel = map.getEventPixel(e.originalEvent)
const hit = map.hasFeatureAtPixel(pixel)
map.getTarget().style.cursor = hit ? 'pointer' : ''
})
onClose.addEventListener('click', onClosed)

View File

@@ -39,7 +39,7 @@ export default {
enableTime: this.enableTime,
dateFormat: this._dateFormat,
locale: Russian,
onChange: (a,_b,_c) => {
onChange: (a) => {
this.onchange(a[0])
}
});

View File

@@ -1,15 +1,3 @@
<template>
<div class="w-fit flex items-center">
<RawSpinner
class="mr-2"
/>
<span
v-if="!disableText"
class="text-lg text-slate-700"
>{{ text }}</span>
</div>
</template>
<script>
import RawSpinner from './VSpinnerSvg.vue'
@@ -36,3 +24,15 @@ export default {
}
</script>
<template>
<div class="w-fit flex items-center">
<RawSpinner
class="mr-2"
/>
<span
v-if="!disableText"
class="text-lg text-slate-700"
>{{ text }}</span>
</div>
</template>

View File

@@ -1,24 +1,3 @@
<template>
<svg
aria-hidden="true"
:width="size"
:height="size"
class="text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
</template>
<script>
export default {
@@ -40,3 +19,24 @@ export default {
}
</script>
<template>
<svg
aria-hidden="true"
:width="size"
:height="size"
class="text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
</template>

View File

@@ -5,11 +5,10 @@ import {
sorter,
renderGroupHeader,
groupByFunction,
makedFiltering,
tablefy
} from "./helper";
import localization from "./localization";
import { cond, equals, is, mergeAll, sort, T, mergeDeepRight } from "ramda";
import { is, sort, mergeDeepRight } from "ramda";
import { pipe } from "@helpers/functions";
import Pagination from "./VTabulatorPagination.vue";
@@ -116,7 +115,7 @@ export default {
data: this.data,
groupStartOpen: false,
groupHeader: function (value, count, data, group) {
groupHeader: function (value, count) {
return value + "<span>(" + count + " записей)</span>";
},
};
@@ -189,6 +188,6 @@ export default {
</div>
</div>
<div v-if="pagination">
<Pagination :params="pagination"/>
<Pagination :params="pagination" />
</div>
</template>

View File

@@ -1,12 +1,9 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import { validation } from './helper'
import { Alert } from "@store/hooks/Alert"
export default {
name: 'Pagination',
name: 'TabulatorPagination',
components: {
},
props: {
@@ -26,8 +23,8 @@ export default {
},
watch: {
params: {
handler(value, oldValue) {
if(value) {
handler(newValue) {
if(newValue) {
const loader = document.querySelector(`#table_loder_${this.params.id}`)
loader.style.display = 'none'
}
@@ -39,7 +36,7 @@ export default {
},
methods: {
selectOptions: (selectOption, paginationOptions) => {
const options = selectOption ? selectOption : optionsDefault
const options = selectOption ? selectOption : []
const currentOptions = options.filter((el) => {
if(el <= Math.ceil(paginationOptions.total / 10) * 10) {
return el
@@ -120,58 +117,142 @@ export default {
</script>
<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">
<div class="pagination-left flex flex-row gap-1">
<div class="current-entries flex text-sm font-bold">Показаны {{currentEntries(params?.paginationOptions)}}</div>
<div class="count-entries flex text-sm font-bold">(Всего записей - {{params?.paginationOptions?.total}})</div>
<div class="current-entries flex text-sm font-bold">
Показаны {{ currentEntries(params?.paginationOptions) }}
</div>
<div class="count-entries flex text-sm font-bold">
(Всего записей - {{ params?.paginationOptions?.total }})
</div>
</div>
<div class="pagination-right flex flex-col xl:flex-row items-center gap-3">
<div :id="`table_loder_${params.id}`" class="hidden w-full h-auto bg-light flex items-center justify-center px-2"><div type-node="loader" class="flex my_margin-3 items-center justify-center">
<div
:id="`table_loder_${params.id}`"
class="hidden w-full h-auto bg-light flex items-center justify-center px-2"
>
<div
type-node="loader"
class="flex my_margin-3 items-center justify-center"
>
<div role="status">
<svg aria-hidden="true" class="mr-2 w-6 h-6 text-gray-400 animate-spin dark:text-gray-400 fill-white" viewBox="0 0 100 101" fill="none" >
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
<svg
aria-hidden="true"
class="mr-2 w-6 h-6 text-gray-400 animate-spin dark:text-gray-400 fill-white"
viewBox="0 0 100 101"
fill="none"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
</div>
</div></div>
</div>
</div>
<div class="buttons flex h-fit gap-1 sm:gap-3 text-sm">
<div class="flex gap-1 sm:gap-3" v-if="params.paginationOptions.page_number > 1">
<div
v-if="params.paginationOptions.page_number > 1"
class="flex gap-1 sm:gap-3"
>
<div v-if="params.paginationOptions.page_number - 1 !== 1">
<button :table_btn="`${params.id}`" class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: 1, pageSize: params.paginationOptions.page_size})">
<button
:table_btn="`${params.id}`"
class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: 1, pageSize: params.paginationOptions.page_size})"
>
<span>1</span>
</button>
</div>
<button :table_btn="`${params.id}`" class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: params.paginationOptions.page_number - 1, pageSize: params.paginationOptions.page_size})">
<span class="hidden sm:flex">Назад</span><i class="ri-arrow-left-line sm:hidden"></i>
<button
:table_btn="`${params.id}`"
class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: params.paginationOptions.page_number - 1, pageSize: params.paginationOptions.page_size})"
>
<span class="hidden sm:flex">Назад</span><i class="ri-arrow-left-line sm:hidden" />
</button>
<button :table_btn="`${params.id}`" class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: params.paginationOptions.page_number - 1, pageSize: params.paginationOptions.page_size})">
<span>{{params.paginationOptions.page_number - 1}}</span>
<button
:table_btn="`${params.id}`"
class="previous flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: params.paginationOptions.page_number - 1, pageSize: params.paginationOptions.page_size})"
>
<span>{{ params.paginationOptions.page_number - 1 }}</span>
</button>
</div>
<button :table_btn="`${params.id}`" class="active flex items-center text-blue-700 font-bold bg-white py-1 px-3 gap-2 rounded cursor-default">
<span>{{params.paginationOptions.page_number}}</span>
<button
:table_btn="`${params.id}`"
class="active flex items-center text-blue-700 font-bold bg-white py-1 px-3 gap-2 rounded cursor-default"
>
<span>{{ params.paginationOptions.page_number }}</span>
</button>
<div class="flex gap-1 sm:gap-3" v-if="params.paginationOptions.page_number < params.paginationOptions.total_pages">
<button :table_btn="`${params.id}`" class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: params.paginationOptions.page_number + 1, pageSize: params.paginationOptions.page_size})">
<span>{{params.paginationOptions.page_number + 1}}</span>
<div
v-if="params.paginationOptions.page_number < params.paginationOptions.total_pages"
class="flex gap-1 sm:gap-3"
>
<button
:table_btn="`${params.id}`"
class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: params.paginationOptions.page_number + 1, pageSize: params.paginationOptions.page_size})"
>
<span>{{ params.paginationOptions.page_number + 1 }}</span>
</button>
<button :table_btn="`${params.id}`" class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: params.paginationOptions.page_number + 1, pageSize: params.paginationOptions.page_size})">
<span class="hidden sm:flex">Вперёд</span><i class="ri-arrow-right-line sm:hidden"></i>
<button
:table_btn="`${params.id}`"
class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: params.paginationOptions.page_number + 1, pageSize: params.paginationOptions.page_size})"
>
<span class="hidden sm:flex">Вперёд</span><i class="ri-arrow-right-line sm:hidden" />
</button>
<div v-if="params.paginationOptions.page_number + 1 !== params.paginationOptions.total_pages">
<button :table_btn="`${params.id}`" class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded" @click="setPagination({pageNumber: params.paginationOptions.total_pages, pageSize: params.paginationOptions.page_size})">
<span>{{params.paginationOptions.total_pages}}</span>
<button
:table_btn="`${params.id}`"
class="next flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-3 gap-2 rounded"
@click="setPagination({pageNumber: params.paginationOptions.total_pages, pageSize: params.paginationOptions.page_size})"
>
<span>{{ params.paginationOptions.total_pages }}</span>
</button>
</div>
</div>
</div>
<div class="flex flex-row items-center justify-center gap-2"><input v-on:input="updateInputValue" :class="`page-input-${params.id}`" class="flex max-w-[80px] items-center text-slate-700 text-sm font-bold focus-visible:outline-blue-300 bg-white py-1 px-2 gap-2 rounded" value="" placeholder="Страница"/><button @click="setPaginationButton" disabled :class="`page-button-${params.id}`" class="opacity-50 flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-1 rounded">Перейти</button></div>
<div id="select-on-page" class="select-on-page flex items-center justify-center gap-3 p-1 text-sm text-slate-700 font-bold">
<div class="flex flex-row items-center justify-center gap-2">
<input
:class="`page-input-${params.id}`"
class="flex max-w-[80px] items-center text-slate-700 text-sm font-bold focus-visible:outline-blue-300 bg-white py-1 px-2 gap-2 rounded"
value=""
placeholder="Страница"
@input="updateInputValue"
><button
disabled
:class="`page-button-${params.id}`"
class="opacity-50 flex items-center text-white font-bold bg-slate-600 hover:bg-slate-700 py-1 px-1 rounded"
@click="setPaginationButton"
>
Перейти
</button>
</div>
<div
id="select-on-page"
class="select-on-page flex items-center justify-center gap-3 p-1 text-sm text-slate-700 font-bold"
>
Показать
<select name="on_page" v-bind:value="params.paginationOptions.page_size" v-on:change="updateSelectedValue" :table_option="`${params.id}`" class="flex text-gray-700 pl-3 pr-9 py-0.5 rounded cursor-pointer border-none" style="--tw-ring-color:focus: none" >
<option :key={idx} v-for="(el, idx) in selectOptions(params.selectOption, params.paginationOptions)" :value="`${el === 'Все' ? params.paginationOptions.total : el}`">
<select
name="on_page"
:value="params.paginationOptions.page_size"
:table_option="`${params.id}`"
class="flex text-gray-700 pl-3 pr-9 py-0.5 rounded cursor-pointer border-none"
style="--tw-ring-color:focus: none"
@change="updateSelectedValue"
>
<option
v-for="(el, idx) in selectOptions(params.selectOption, params.paginationOptions)"
:key="{idx}"
:value="`${el === 'Все' ? params.paginationOptions.total : el}`"
>
{{ el }}
</option>`
</select>

View File

@@ -1,4 +1,4 @@
import { always, cond, equals, is, T, mergeLeft } from "ramda";
import { always, cond, equals, is, T, pipe, mergeLeft } from "ramda";
import Handlebars from "handlebars/dist/cjs/handlebars";
import moment from "moment";
import presetConfig from './presetConfig'
@@ -20,7 +20,7 @@ const tablefy = (list = []) => {
return list.map((el) => mergeLeft(el, defaultData(el?.title || "")))
}
const math = (value, operator, operand, options) => {
const math = (value, operator, operand) => {
var left = parseFloat(value);
var right = parseFloat(operand);
@@ -138,7 +138,8 @@ const link = (col) => ({
[
"from_list",
(list, param_string) => {
const [key, value] = param_string.split(",")
return list.find(el => el[key] === value)
}
],
[
@@ -334,9 +335,9 @@ const makedFiltering = (id, filterParams, selectedFilter, clearFilters) => {
const validation = (value, pagination) => {
const pipe = (...fns) => (...x) => fns.reduce((error, validator) => error || validator(...x), undefined)
const required = value => {
return value ? undefined : "*"
}
// const required = value => {
// return value ? undefined : "*"
// }
const minPage = length => value => {
value = value.replace(/\s+/g, '')
return value >= length ? undefined : `Номер страницы должен быть больше или равен ${length}`

View File

@@ -1,52 +1,5 @@
import { cond, T } from "ramda";
const text = `
0 Конфигурация не установлена (по умолчанию)
1 Стандартная конфигурация МРТ (МПТ/АВФ)
2 Стандартная конфигурация ЖДСМ
3 Стандартная конфигурация УК/ВПО
4 ЩОМ/РМ (Акселерометр)
5 СМ (Сибирский ПГУПС)
6 СМ (зарезервировано)
7 Эмуляция платы БКП
8 Конфигурация Блок-М
40 Эмуляторы
41 Эмуляторы (CAN1 + CAN2 (Блок-М) + ModBus
50 Стандартная конфигурация ModBus Master (опрос внешних устройств)
51 Стандартная конфигурация ModBus Master (опрос плат АС КРСПС)
52 Конфигурация трекера (электрички и т.п.)
53 Конфигурация трекер + счетчик импульсов + акселерометр
54 РадарП
55 СДРГО
100 ПМА-1М РПМ
101 ЩОМ-1400 РПМ
102 АМ-140 СКРТ РПМ
103 АС-01 РПМ
104 ТЭС ПСС-1К РПМ
105 ПСС-2П РПМ
200 РПБ-01 ВНИКТИ
201 МПК Спецлоко
202 УК 25/25 ВНИКТИ
203 СЗ-800 ВНИКТИ
300 ЩОМ-1200С ТЖДМ
301 ЩОМ-2000 ТЖДМc
302 ССГС-1 ТЖДМ
303 ВПО-С ТЖДМ
304 МПВ ТЖДМ
305 УПК ТЖДМ
306 ПРЛ-М ТЖДМ
307 РУ-700 ТЖДМ
308 МПВ Секция 2 ТЖДМ
1911 Конфигурация для отладки
4096 Настраиваемая конфигурация
`
//TODO SERGEY
const parse = () => {
text
return {}
}
const get_f1_preset = (el) => {
const r = {
0: "Конфигурация не установлена (по умолчанию)",

View File

@@ -8,10 +8,8 @@ import {
propEq,
findIndex,
update,
is,
cond,
T,
isNil
} from "ramda";
let getPackSettings = (userId, page, packStructId, func) => {
@@ -30,7 +28,7 @@ let getPackSettings = (userId, page, packStructId, func) => {
}
};
const prepDiscretes = (from, to, arr) =>
const prepDiscretes = (from, to) =>
range(from, to + 1).map((el) => ({
title: el,
dataIndex: `disc${el}`,
@@ -79,17 +77,14 @@ const withCustomSettings = (_columns, requestSettings) => {
let columns = _columns
if (requestSettings?.colors?.isOn) {
}
if (requestSettings?.colors?.isOn) {
let colors = requestSettings.colors.list.filter((el) => el.isOn);
colors = groupBy((c) => c.param)(colors);
coloredParams = Object.keys(colors);
let colors = requestSettings.colors.list.filter((el) => el.isOn)
colors = groupBy((c) => c.param)(colors)
const coloredParams = Object.keys(colors)
columns = columns.map((el) => {
if (coloredParams.includes(el.dataIndex)) {
return {
...el,
onCell: (data, index) => {
onCell: (data) => {
let colrSettings = colors[el.dataIndex];
let value = data[el.dataIndex];
let color = find(({ from, untill }) =>
@@ -147,23 +142,22 @@ const withCustomSettings = (_columns, requestSettings) => {
}
}
return columns;
return columns
};
const fetch_sorter_field = (sorter, req_params) => {
const date_param = req_params?.settings?.date_param
return cond([
[() => sorter?.field, () => sorter.field],
[is(Array), field_from_arr(sorter, date_param)],
[isNil, () => date_param],
])(sorter)
}
const field_from_arr = (sorter, date_param) => () => {
const field = sorter.find((el) => `${el?.field}`.includes("dt"))?.field
return field || date_param
}
// const fetch_sorter_field = (sorter, req_params) => {
// const date_param = req_params?.settings?.date_param
// return cond([
// [() => sorter?.field, () => sorter.field],
// [is(Array), field_from_arr(sorter, date_param)],
// [isNil, () => date_param],
// ])(sorter)
// }
// const field_from_arr = (sorter, date_param) => () => {
// const field = sorter.find((el) => `${el?.field}`.includes("dt"))?.field
// return field || date_param
// }
const get_f1_preset = (el) => {
const r = {
@@ -401,6 +395,6 @@ let parseFunc2 = (string) => {
const parseFunc3 = (string) => {
const f = new Function(`return (${string})`)
return f()
}
}
export {parseFunc, parseFunc2, parseFunc3}

View File

@@ -21,7 +21,7 @@ const monthNames = [
];
export const reformateDateString = (date, format = "full") =>
!!date ? reformate(date, format) : null;
date ? reformate(date, format) : null;
const reformate = (date, format) =>
cond([

View File

@@ -1,4 +1,3 @@
import { parse } from "handlebars/dist/cjs/handlebars/compiler/base";
import { cond, T, isEmpty } from "ramda";
const setPackColumns = (name) => {
@@ -163,6 +162,7 @@ const prepareSetPackColumns = (name, data) => {
if (data.length === 0) {
return []
}
break
case 'raw':
return setPackColumns('Сырые')
case 'unrecognized':

View File

@@ -1,7 +1,5 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {mapGetters, mapActions} from "vuex"
export default {
name: 'PackViewButton',
@@ -30,7 +28,7 @@ export default {
},
idx: {
type: Number,
default: ""
default: 0
}
},
computed: {
@@ -44,14 +42,30 @@ export default {
</script>
<template>
{{ console.log('selectedPackMode', selectedPackMode)
}}
<button @click="updateModePack(mode)" v-bind:key="idx" type="button" class="w-full">
<input name="switchTableMode" type="radio" :id="name" :value="name" :checked="active" class="hidden peer" required="">
<label :for="name" :class="labelClass" class="transition-all w-full border-slate-600 w-full block cursor-pointer py-1 text-ssm sm:text-sm hover:bg-slate-700 hover:text-white text-slate-600 border-slate-600
peer-checked:bg-slate-600 peer-checked:text-white">
<button
:key="idx"
type="button"
class="w-full"
@click="updateModePack(mode)"
>
<input
:id="name"
name="switchTableMode"
type="radio"
:value="name"
:checked="active"
class="hidden peer"
required=""
>
<label
:for="name"
:class="labelClass"
class="transition-all w-full border-slate-600 w-full block cursor-pointer py-1 text-ssm sm:text-sm hover:bg-slate-700 hover:text-white text-slate-600 border-slate-600
peer-checked:bg-slate-600 peer-checked:text-white"
>
{{ inner }}
</label>
</button>

View File

@@ -1,7 +1,5 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {mapGetters, mapActions} from "vuex"
import PackViewButton from './Button.vue'
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
@@ -24,11 +22,6 @@ export default {
default: ""
},
},
data () {
return {
hasData: false
}
},
setup (props, {slots}) {
const hasDescription = slots.description != undefined
const hasError = slots.error != undefined
@@ -38,12 +31,10 @@ export default {
hasError
}
},
updated () {
this.$nextTick(function () {
if (!isEmpty(this.packData)) {
this.hasData = true
data () {
return {
hasData: false
}
})
},
computed: {
...mapGetters('machines', ['packData', 'selectPackStructs', 'selectedPackStruct']),
@@ -54,6 +45,13 @@ export default {
{mode: 'unrecognized', isActive: false, name: 'switch_unrecognized', inner: 'нераспознанные', labelClass: 'rounded-r-lg border'},
])
},
updated () {
this.$nextTick(function () {
if (!isEmpty(this.packData)) {
this.hasData = true
}
})
},
methods: {
...mapActions('machines', ['updateSelectStruct']),
updateSelectedValue: function (e) {
@@ -66,26 +64,43 @@ export default {
</script>
<template>
<div class="w-full relative">
{{
console.log('packData', packData)
}}
<div v-if="!hasData" class="w-full h-[50px] rounded-xl bg-slate-200 hidden" :id="`${id}_loader`">
<Spinner/>
<div
v-if="!hasData"
:id="`${id}_loader`"
class="w-full h-[50px] rounded-xl bg-slate-200 hidden"
>
<Spinner />
</div>
<div v-if="hasData" :id="id" class="w-full rounded-md bg-light border-rounded p-4">
<div
v-if="hasData"
:id="id"
class="w-full rounded-md bg-light border-rounded p-4"
>
<div class="grid grid-cols-12 mb-6">
<div class="flex flex-col gap-1 col-span-12 sm:col-span-4 md:col-span-5 lg:col-span-5 2xl:col-span-7 sm:mb-0">
<h2 :id="`${id}_pack_name`" class=" text-lg">Пакет: <span v-if="selectPackStructs" >{{selectPackStructs[0]?.packNumber}}</span></h2>
<div v-if="hasDescription" class="text-xs text-slate-500">
<h2
:id="`${id}_pack_name`"
class=" text-lg"
>
Пакет: <span v-if="selectPackStructs">{{ selectPackStructs[0]?.packNumber }}</span>
</h2>
<div
v-if="hasDescription"
class="text-xs text-slate-500"
>
<slot name="description" />
</div>
</div>
<!-- <form phx-change="c_packs_mode:on_click" :id="`${id}_table_active`" class="col-span-12 sm:col-span-8 md:col-span-7 lg:col-span-7 2xl:col-span-5 flex justify-center hidden"> -->
<div class="col-span-12 sm:col-span-8 md:col-span-7 lg:col-span-7 2xl:col-span-5 flex justify-center">
<PackViewButton v-for="(button, idx) in buttonsData"
<PackViewButton
v-for="(button, idx) in buttonsData"
:key="idx"
:idx="idx"
:mode="button.mode"
:name="button.name"
@@ -96,24 +111,53 @@ export default {
</div>
<!-- </form> -->
</div>
<div class="relative" :id="id">
<div id="selectStructContainer" class="flex gap-2 items-center mb-2">
<div
:id="id"
class="relative"
>
<div
id="selectStructContainer"
class="flex gap-2 items-center mb-2"
>
<span>Выберите структуру:</span>
<select v-if="selectPackStructs" id="selectStruct" name="struct" v-bind:value="selectedPackStruct.id" v-on:change="updateSelectedValue" class=" w-fit bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block 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" style="--tw-ring-color:focus: none" >
<option :key={idx} v-for="(el, idx) in selectPackStructs" :value="el.id">
<select
v-if="selectPackStructs"
id="selectStruct"
name="struct"
:value="selectedPackStruct.id"
class=" w-fit bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block 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"
style="--tw-ring-color:focus: none"
@change="updateSelectedValue"
>
<option
v-for="(el, idx) in selectPackStructs"
:key="{idx}"
:value="el.id"
>
{{ el.name }}
</option>
</select>
</div>
<div :id="`${id}_report`" class="tab-pane active bg-light relative shadow text-center min-h-[300px] relative rounded-md w-full relative">
<div
:id="`${id}_report`"
class="tab-pane active bg-light relative shadow text-center min-h-[300px] relative rounded-md w-full relative"
>
<Tabulator v-bind="packData" />
<div v-if="isLoader" class="w-full h-[50px] rounded-xl bg-slate-200 hidden" :id="`${id}_loader`">
<Spinner/>
<div
v-if="isLoader"
:id="`${id}_loader`"
class="w-full h-[50px] rounded-xl bg-slate-200 hidden"
>
<Spinner />
</div>
</div>
</div>
</div>
<div v-if="hasError" :id="`${id}_error`" class="w-full rounded-md bg-light border-rounded p-4 flex flex-col gap-5 items-center justify-center hidden">
<div
v-if="hasError"
:id="`${id}_error`"
class="w-full rounded-md bg-light border-rounded p-4 flex flex-col gap-5 items-center justify-center hidden"
>
<slot name="error" />
</div>
</div>

View File

@@ -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">

View File

@@ -9,8 +9,6 @@ export default {
default: null
},
},
data() {
},
computed: {
},
methods: {

View File

@@ -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

View File

@@ -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>

View File

@@ -1,24 +1,29 @@
<!-- eslint-disable vue/prop-name-casing -->
<script>
import {mapGetters, mapMutations} 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 +32,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 +52,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 +72,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 +87,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 +129,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 +155,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>

View File

@@ -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> -->

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -0,0 +1,14 @@
<script>
export default {
name: "PacksContainerBody"
}
</script>
<template>
<div class="">
ComponentTemplate
</div>
</template>

View File

@@ -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>

View File

@@ -1,3 +1,18 @@
<script>
export default {
name: 'App',
components: {},
data() {
},
computed: {
},
methods: {
}
}
</script>
<template>
<svg
width="1008"
@@ -965,18 +980,3 @@
</defs>
</svg>
</template>
<script>
export default {
name: 'App',
components: {},
data() {
},
computed: {
},
methods: {
}
}
</script>

View File

@@ -1,3 +1,18 @@
<script>
export default {
name: 'App',
components: {},
data() {
},
computed: {
},
methods: {
}
}
</script>
<template>
<div class="hidden 2xl:flex w-full h-[100vh] overflow-hidden bg-white">
<div class="h-full overflow-hidden flex flex-col justify-between translate-y-1">
@@ -32,21 +47,6 @@
</div>
</template>
<script>
export default {
name: 'App',
components: {},
data() {
},
computed: {
},
methods: {
}
}
</script>
<style scoped>

View File

@@ -2,7 +2,7 @@
import Login from './Login.vue'
export default {
name: 'Auth',
name: 'AuthPage',
components: {
Login
},

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,3 +1,29 @@
<script>
import TaskModal from './TaskModal.vue'
import TaskHistory from './TaskHistory.vue'
export default {
name: 'TaskComponent',
components: {
TaskModal,
TaskHistory
},
props: {
index: {
default: 0,
type: Number
}
},
data() {
},
computed: {
},
methods: {
}
}
</script>
<template>
<div class="flex justify-between w-full border border-slate-300 p-1 flex-col md:flex-row hover:bg-slate-300 hover:border-slate-600 transition-all">
<div class="flex gap-1 items-center">
@@ -67,30 +93,3 @@
</div>
</div>
</template>
<script>
import TaskModal from './TaskModal.vue'
import TaskHistory from './TaskHistory.vue'
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
export default {
name: 'Task',
components: {
TaskModal,
TaskHistory
},
props: {
index: {
default: 0,
type: Number
}
},
data() {
},
computed: {
},
methods: {
}
}
</script>

View File

@@ -1,3 +1,35 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
export default {
name: 'TaskHistory',
components: {
ButtonModal,
},
props: {
taskId: {
default: "",
type: String
}
},
data() {
return {
task: "",
task_description: "",
task_name: ""
}
},
computed: {
},
methods: {
onToggle: ({isOpen}) => {
console.log(isOpen)
}
}
}
</script>
<template>
<ButtonModal
forcedBtnClass=" "
@@ -12,36 +44,3 @@
1234
</ButtonModal>
</template>
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import {data} from './historyData'
export default {
name: 'TaskHistory',
components: {
ButtonModal,
},
props: {
taskId: {
default: "",
type: String
}
},
data() {
return {
task: "",
task_description: "",
task_name: ""
}
},
computed: {
},
methods: {
onToggle: ({isOpen}) => {
console.log(isOpen)
}
}
}
</script>

View File

@@ -1,3 +1,39 @@
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import { FwbTextarea } from 'flowbite-vue'
export default {
name: 'TaskModal',
components: {
Datepicker,
ButtonModal,
FwbTextarea
},
props: {
taskId: {
default: "",
type: String
}
},
data() {
return {
task: "",
task_description: "",
task_name: ""
}
},
computed: {
},
methods: {
onToggle: ({isOpen}) => {
console.log(isOpen)
}
}
}
</script>
<template>
<ButtonModal
forcedBtnClass=" "
@@ -218,39 +254,3 @@
</form>
</ButtonModal>
</template>
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import { FwbTextarea } from 'flowbite-vue'
export default {
name: 'TaskModal',
components: {
Datepicker,
ButtonModal,
FwbTextarea
},
props: {
taskId: {
default: "",
type: String
}
},
data() {
return {
task: "",
task_description: "",
task_name: ""
}
},
computed: {
},
methods: {
onToggle: ({isOpen}) => {
console.log(isOpen)
}
}
}
</script>

View File

@@ -1,3 +1,26 @@
<script>
import Task from './Task.vue'
import TaskModal from './TaskModal.vue'
export default {
name: 'CronPage',
components: {
Task,
TaskModal,
},
data() {
},
computed: {
tasks () {
return [1,2,3,4]
}
},
methods: {
}
}
</script>
<template>
<div class="flex flex-col gap-3 bg-light h-full w-full col-span-12 rounded-xl p-2">
<TaskModal taskId="new">
@@ -135,27 +158,3 @@
</div>
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue'
import Task from './Task.vue'
import TaskModal from './TaskModal.vue'
export default {
name: 'Cron',
components: {
Task,
TaskModal,
},
data() {
},
computed: {
tasks () {
return [1,2,3,4]
}
},
methods: {
}
}
</script>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -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>

View File

@@ -1,81 +1,3 @@
<template>
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
<form
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"
>
<h1 class="font-medium leading-tight text-xl mb-4 text-slate-600">
Последние пакеты
</h1>
<div class="grid gap-3 mb-3 ">
<div class="relative ">
<label
for="imei"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
>
Номер пакета
</label>
<input
id="selected_imei"
required=""
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 "
placeholder="Номер пакета"
name="imei"
type="text"
autocomplete="off"
:value="imei"
@input="(e) => setImei(e.target.value)"
>
</div>
</div>
<div class="grid gap-3 grid-cols-4">
<button
type="button"
class="col-span-4 lg:col-span-4 cursor-pointer text-white bg-primary hover:brightness-90 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-ssm w-full sm:w-auto px-5 py-1 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 transition_up"
@click="uploadData"
>
Выгрузить
</button>
<ButtonModal btnClass="cursor-pointer col-span-4 bg-transparent hover:bg-primary text-primary font-semibold hover:text-white py-1 text-ssm px-4 border border-primary hover:border-transparent rounded-lg text-center transition_up">
<template #button>
<div id="question">
<i class="ri-question-mark" />
</div>
</template>
<div class="overflow-auto min-w-[70vw] h-[70vh] pt-10 px-4">
<div style="display: flex; flex-direction: column; gap: 1rem;">
<span style="font-size: 1.1em; font-weight: bold;">Страница предназначена для получения сведений о последних полученных пакетах, в результате выдающая список машин, которые имели данный пакет за 3х месячный период (иначе запрос становится слишком долгим)<br></span><span style="border-left: 5px solid rgba(0, 0, 0, 0.45); padding: 10px 5px;"><span style="font-weight: bold;">Работа со страницей</span><br><span>Поля выбора находятся на странице. Чтобы загразить данные необходимо -<ol style="font-size: 0.9em; margin-bottom: 0px;"><li>1. ввести номер пакета</li><li>2. нажать на кнопку 'загрузить' и дождаться загрузки</li></ol></span></span>
</div>
</div>
</ButtonModal>
</div>
</form>
<div class="lg:col-span-8 xl:col-span-9 2xl:col-span-10 col-span-12 bg-light shadow">
<div
v-if="pageState == 'await'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md "
>
<span> Выберите машину и нажмите выгрузить</span>
</div>
<div
v-if="pageState == 'loading'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md w-full h-full flex items-center justify-center"
>
<Spinner />
</div>
<div
v-if="pageState == 'isLoaded'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md "
>
<Tabulator v-bind="tabulatorOtps" />
</div>
</div>
</div>
</template>
<script>
import ButtonModal from '@molecules/ButtonModal/ButtonModal.vue'
import {mapGetters, mapMutations, mapActions} from 'vuex'
@@ -168,3 +90,81 @@ export default {
}
}
</script>
<template>
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
<form
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"
>
<h1 class="font-medium leading-tight text-xl mb-4 text-slate-600">
Последние пакеты
</h1>
<div class="grid gap-3 mb-3 ">
<div class="relative ">
<label
for="imei"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
>
Номер пакета
</label>
<input
id="selected_imei"
required=""
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 "
placeholder="Номер пакета"
name="imei"
type="text"
autocomplete="off"
:value="imei"
@input="(e) => setImei(e.target.value)"
>
</div>
</div>
<div class="grid gap-3 grid-cols-4">
<button
type="button"
class="col-span-4 lg:col-span-4 cursor-pointer text-white bg-primary hover:brightness-90 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-ssm w-full sm:w-auto px-5 py-1 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 transition_up"
@click="uploadData"
>
Выгрузить
</button>
<ButtonModal btnClass="cursor-pointer col-span-4 bg-transparent hover:bg-primary text-primary font-semibold hover:text-white py-1 text-ssm px-4 border border-primary hover:border-transparent rounded-lg text-center transition_up">
<template #button>
<div id="question">
<i class="ri-question-mark" />
</div>
</template>
<div class="overflow-auto min-w-[70vw] h-[70vh] pt-10 px-4">
<div style="display: flex; flex-direction: column; gap: 1rem;">
<span style="font-size: 1.1em; font-weight: bold;">Страница предназначена для получения сведений о последних полученных пакетах, в результате выдающая список машин, которые имели данный пакет за 3х месячный период (иначе запрос становится слишком долгим)<br></span><span style="border-left: 5px solid rgba(0, 0, 0, 0.45); padding: 10px 5px;"><span style="font-weight: bold;">Работа со страницей</span><br><span>Поля выбора находятся на странице. Чтобы загразить данные необходимо -<ol style="font-size: 0.9em; margin-bottom: 0px;"><li>1. ввести номер пакета</li><li>2. нажать на кнопку 'загрузить' и дождаться загрузки</li></ol></span></span>
</div>
</div>
</ButtonModal>
</div>
</form>
<div class="lg:col-span-8 xl:col-span-9 2xl:col-span-10 col-span-12 bg-light shadow">
<div
v-if="pageState == 'await'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md "
>
<span> Выберите машину и нажмите выгрузить</span>
</div>
<div
v-if="pageState == 'loading'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md w-full h-full flex items-center justify-center"
>
<Spinner />
</div>
<div
v-if="pageState == 'isLoaded'"
id="report_packs"
class="tab-pane active relative text-center min-h-[300px] relative rounded-md "
>
<Tabulator v-bind="tabulatorOtps" />
</div>
</div>
</div>
</template>

View File

@@ -1,5 +1,5 @@
<script>
import {mapGetters, mapActions, mapMutations, useStore} from "vuex"
import {mapGetters, useStore} from "vuex"
import Button from "@atoms/VButton.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
@@ -32,17 +32,22 @@ export default {
</script>
<template>
{{ console.log('adminData', adminData)
}}
<div class="rounded w-full pt-4 pb-1 bg-light cursor-pointer transition-all">
<div class="mx-2 mb-3">
<a :href="`/html/admin/manage/new?prev_page=/\?page_display_mode=users`">
<Button title="Создать" classBtn="cursor-pointer text-white bg-primary hover:brightness-90 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-ssm w-full px-5 py-1 text-center transition-all " />
<Button
title="Создать"
classBtn="cursor-pointer text-white bg-primary hover:brightness-90 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-ssm w-full px-5 py-1 text-center transition-all "
/>
</a>
</div>
<div id="admin_list" class="tab-pane m-4 active bg-light relative col-span-12 text-center min-h-[300px] rounded-md tabulator">
<div
id="admin_list"
class="tab-pane m-4 active bg-light relative col-span-12 text-center min-h-[300px] rounded-md tabulator"
>
<Tabulator v-bind="adminData" />
</div>
</div>

View File

@@ -1,5 +1,5 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {mapGetters, mapActions, useStore} from "vuex"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import {PushAfterTimeout} from '@store/hooks/PushAfterTimeout'
import Accordion from '@atoms/VAccordion.vue'
@@ -42,54 +42,106 @@ export default {
</script>
<template>
<div class="rounded w-full transition-all min-h-[500px] relative">
<div v-if="!packsGroups" id="dataLoader" class="h-full absolute inset-0 flex flex-row items-center grow transition items-center justify-center bg-light appear_from_opacity-3 z-30 rounded p-2">
<Spinner style="padding: 0"/>
<div
v-if="!packsGroups"
id="dataLoader"
class="h-full absolute inset-0 flex flex-row items-center grow transition items-center justify-center bg-light appear_from_opacity-3 z-30 rounded p-2"
>
<Spinner style="padding: 0" />
</div>
<div v-if="packsGroups" phx-change="update_pack_filter" class="p-5 flex flex-col gap-4 bg-light relative items-center">
<div id="searchInput" class="w-full flex flex-col gap-2" >
<div class="font-bold">Поиск (название и номер): </div>
<input v-bind:value="searchValue" v-on:change="updateSearchValue" :status="status" class="pl-2 py-1 rounded-r-md w-full max-h-[29px] text-sm border-none focus-visible:outline-blue-300" placeholder="Название и номер через пробел"/>
<div
v-if="packsGroups"
phx-change="update_pack_filter"
class="p-5 flex flex-col gap-4 bg-light relative items-center"
>
<div
id="searchInput"
class="w-full flex flex-col gap-2"
>
<div class="font-bold">
Поиск (название и номер):
</div>
<div class="border-2 rounded-lg w-full bottom-0"></div>
<input
:value="searchValue"
:status="status"
class="pl-2 py-1 rounded-r-md w-full max-h-[29px] text-sm border-none focus-visible:outline-blue-300"
placeholder="Название и номер через пробел"
@change="updateSearchValue"
>
</div>
<div class="border-2 rounded-lg w-full bottom-0" />
</div>
<div
v-if="packsGroups?.length === 0"
id="no_data"
class="w-full min-h-[80vh] bg-light dark:bg-slate-900 dark:text-slate-300 relative"
>
<div class="flex items-center justify-center text-lg font-bold pt-5">
Пакеты не найдены
</div>
<div v-if="packsGroups?.length === 0" id="no_data" class="w-full min-h-[80vh] bg-light dark:bg-slate-900 dark:text-slate-300 relative">
<div class="flex items-center justify-center text-lg font-bold pt-5">Пакеты не найдены</div>
</div>
<div class="bg-light">
<div v-if="packsGroups?.length > 0" class="grid grid-cols-12 gap-3 p-4">
<div :key="idx" v-for="(group, idx) in packsGroups" class="col-span-12 sm:col-span-6 lg:col-span-4">
<Accordion :isOpen="isOpen" :id="`pack_group_${group.pack_group_id}`">
<div
v-if="packsGroups?.length > 0"
class="grid grid-cols-12 gap-3 p-4"
>
<div
v-for="(group, idx) in packsGroups"
:key="idx"
class="col-span-12 sm:col-span-6 lg:col-span-4"
>
<Accordion
:id="`pack_group_${group.pack_group_id}`"
:isOpen="isOpen"
>
<template #header>
<div v-if="group.order_index" id="packsInfoTitle" class="font-bold text-sm">
<div
v-if="group.order_index"
id="packsInfoTitle"
class="font-bold text-sm"
>
<span class="text-slate-500 font-bold">
{{ group.order_index }}.
</span>
<span class="font-bold">
{{ group.title }}
</span></div>
</span>
</div>
</template>
<template #body>
<div class="flex flex-col gap-2">
<table >
<table>
<thead>
<tr>
<th class="items-center justify-center pb-2">Название</th>
<th class="items-center justify-center pb-2">
Название
</th>
</tr>
</thead>
<tbody>
<tr v-for="struct in group.pack_structs" >
<tr
v-for="(struct, index) in group.pack_structs"
:key="index"
>
<td class="items-center justify-center py-2">
<div class="flex gap-2 w-full">
<div class="w-full text-left decoration-dashed cursor-pointer hover:text-slate-800 transition-all">
{{ struct.name }}
</div>
<a class="bg-slate-500 hover:bg-slate-700 text-white text-xs font-bold py-1 px-3 rounded transition-all h-fit" target="_blank" :href="`/html/packs/${group.link}?pack=${struct.name}`">
<a
class="bg-slate-500 hover:bg-slate-700 text-white text-xs font-bold py-1 px-3 rounded transition-all h-fit"
target="_blank"
:href="`/html/packs/${group.link}?pack=${struct.name}`"
>
таблица
</a>
<a class="bg-slate-500 hover:bg-slate-700 text-white text-xs font-bold py-1 px-3 rounded transition-all h-fit" target="_blank" :href="`/admin_panel/packs/${group.pack_group_id}/${struct.id}`">карточка</a>
<a
class="bg-slate-500 hover:bg-slate-700 text-white text-xs font-bold py-1 px-3 rounded transition-all h-fit"
target="_blank"
:href="`/admin_panel/packs/${group.pack_group_id}/${struct.id}`"
>карточка</a>
</div>
</td>
</tr>

View File

@@ -1,21 +1,22 @@
<script>
import {ref, toRaw, computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import {useRoute, useRouter} from 'vue-router'
import Button from "@atoms/VButton.vue";
import {computed} from 'vue'
import {mapGetters, mapMutations, mapActions} from "vuex";
import {useRoute} from 'vue-router'
import DoubleSwitch from "@/components/1_atoms/DoubleSwitch.vue";
import Chart from "@molecules/VChart/VChart.vue";
import ECharts from '@store/hooks/Echarts';
export default {
name: 'Charts',
name: 'ChartsComponent',
components: {
Button,
Chart,
DoubleSwitch
},
provide() {
return {
isChecked: computed(() => this.isChartTypes),
}
},
setup() {
const route = useRoute()
const path = computed(() => route.path)
@@ -31,15 +32,12 @@ export default {
isChartTypes: this.isChartTypesUrl,
}
},
provide() {
return {
isChecked: computed(() => this.isChartTypes),
}
computed: {
...mapGetters('layoutMachines', ['selectedSelects', 'selectsData', 'toggleFilter', 'chartsData', 'activeChartData', 'prevGroupByData', 'activeMenuChartData', 'openMenuChart', 'legendFiltersParams']),
},
watch: {
activeChartData: {
handler(newValue, oldValue) {
console.log('newValue - activeChartData', newValue)
handler(newValue) {
if (newValue.id && newValue.type && newValue.data) {
const chart = new ECharts(newValue.id)
const isSelectedLegend = this.legendFiltersParams.length > 0 && this.legendFiltersParams[0].id === newValue.id
@@ -51,8 +49,7 @@ export default {
// deep: true
},
activeMenuChartData: {
handler(newValue, oldValue) {
// console.log('newValue - activeMenuChartData', newValue)
handler(newValue) {
if (newValue.groupByInfo && newValue.groupByInfo.chartId) {
const chart = new ECharts(newValue.groupByInfo.chartId)
chart.setMenuChart(newValue)
@@ -63,9 +60,6 @@ export default {
},
},
},
computed: {
...mapGetters('layoutMachines', ['selectedSelects', 'selectsData', 'toggleFilter', 'chartsData', 'activeChartData', 'prevGroupByData', 'activeMenuChartData', 'openMenuChart', 'legendFiltersParams']),
},
mounted () {
},
@@ -105,21 +99,55 @@ export default {
</script>
<template>
<div class="px-2 sm:px-5 pt-1 bg-light">
<div class="relative">
<div class="doubleSwitch flex justify-end mt-3 mb-2">
<DoubleSwitch name="chartsView" @switched="onToggleCharts" firstColor="#8b5cf6" secondColor="#2563eb" firstTitle="Общий вид" secondTitle="По типам" />
<DoubleSwitch
name="chartsView"
firstColor="#8b5cf6"
secondColor="#2563eb"
firstTitle="Общий вид"
secondTitle="По типам"
@switched="onToggleCharts"
/>
</div>
<div v-if="!isChartTypes" id="main" class="relative flex flex-wrap justify-center w-full h-full mb-3" >
<div v-for="(chart, idx) in chartsData.main">
<Chart :idx="idx" :id="chart.id" :type="chart.type" :height="chart.height" :maxHeight="chart.maxHeight" :data="chart.data"/>
<div
v-if="!isChartTypes"
id="main"
class="relative flex flex-wrap justify-center w-full h-full mb-3"
>
<div
v-for="(chart, idx) in chartsData.main"
:key="idx"
>
<Chart
:id="chart.id"
:idx="idx"
:type="chart.type"
:height="chart.height"
:maxHeight="chart.maxHeight"
:data="chart.data"
/>
</div>
</div>
<div v-if="isChartTypes" id="types" class="relative flex flex-wrap justify-center w-full h-full mb-3" >
<div v-for="(chart, idx) in chartsData.types">
<Chart :idx="idx" :id="chart.id" :type="chart.type" :height="chart.height" :maxHeight="chart.maxHeight" :data="chart.data"/>
<div
v-if="isChartTypes"
id="types"
class="relative flex flex-wrap justify-center w-full h-full mb-3"
>
<div
v-for="(chart, idx) in chartsData.types"
:key="idx"
>
<Chart
:id="chart.id"
:idx="idx"
:type="chart.type"
:height="chart.height"
:maxHeight="chart.maxHeight"
:data="chart.data"
/>
</div>
</div>
</div>

View File

@@ -1,7 +1,5 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {mapGetters, mapActions} from "vuex"
import Modal from '@molecules/VModal/VModal.vue'
import Accordion from '@atoms/VAccordion.vue'
import PackView from '@organisms/PackView/index.vue'
@@ -48,6 +46,9 @@ export default {
machineOverInfo: null
}
},
computed: {
...mapGetters('machines', ['machineInfo', 'reportPacks']),
},
updated () {
this.$nextTick(function () {
if (this.data && this.id && this.open) {
@@ -59,9 +60,6 @@ export default {
}
})
},
computed: {
...mapGetters('machines', ['machineInfo', 'reportPacks']),
},
methods: {
...mapActions('machines', ['loadPack']),
}
@@ -70,7 +68,6 @@ export default {
</script>
<template>
<Modal
v-if="open"
@@ -82,37 +79,86 @@ export default {
</div>
{{ console.log('reportPacks', reportPacks)
}}
<div :id="id" class="w-[95vw] h-[85vh] m-auto p-5">
<div v-if="!machineInfo" id="dataLoader" class=" h-full flex justify-center items-center">
<Spinner style="padding: 0"/>
<div
:id="id"
class="w-[95vw] h-[85vh] m-auto p-5"
>
<div
v-if="!machineInfo"
id="dataLoader"
class=" h-full flex justify-center items-center"
>
<Spinner style="padding: 0" />
</div>
<div v-if="machineInfo" class="w-full flex flex-col gap-5">
<div
v-if="machineInfo"
class="w-full flex flex-col gap-5"
>
<div class="w-full">
<Accordion id="machineInfo">
<template #header>
<div v-if="machineInfo?.machine_name" id="machineInfoTitle" class="font-bold text-xl">{{ machineInfo.machine_name }}</div>
<div
v-if="machineInfo?.machine_name"
id="machineInfoTitle"
class="font-bold text-xl"
>
{{ machineInfo.machine_name }}
</div>
</template>
<template #body>
<div v-if="machineInfo.machine_info?.length > 0" id="machineInfoBody" class="flex w-full justify-start 2xl:justify-between gap-3 flex-wrap">
<div
v-if="machineInfo.machine_info?.length > 0"
id="machineInfoBody"
class="flex w-full justify-start 2xl:justify-between gap-3 flex-wrap"
>
<div class="flex p-4">
<div class="flex mr-8 flex-col bg-slate-200 p-3 rounded">
<h2 clas="font-bold flex items-center"><i class="ri-flashlight-line mr-1" /> Основная информация</h2>
<h2 clas="font-bold flex items-center">
<i class="ri-flashlight-line mr-1" /> Основная информация
</h2>
<div class="mt-2 p-2 rounded-md flex flex-col bg-slate-300">
<div v-if="machineMainInfo?.length > 0" class="flex flex-col gap-2">
<div :key="idx" v-for="(info, idx) in machineMainInfo" class="flex items-center items-center bg-slate-200 px-3 py-2 rounded-md">
<div class="text-slate-700 font-bold mr-2">{{ info.title }}</div>
<div class="text-slate-500">{{ info.val }}</div>
<div
v-if="machineMainInfo?.length > 0"
class="flex flex-col gap-2"
>
<div
v-for="(info, idx) in machineMainInfo"
:key="idx"
class="flex items-center items-center bg-slate-200 px-3 py-2 rounded-md"
>
<div class="text-slate-700 font-bold mr-2">
{{ info.title }}
</div>
<div class="text-slate-500">
{{ info.val }}
</div>
</div>
</div>
</div>
<div style="min-width: 300px;" class="flex flex-col bg-slate-200 p-3 rounded">
<h2 clas="font-bold flex items-center"><i class="ri-git-pull-request-line mr-1"></i> Дополнительно</h2>
</div>
<div
style="min-width: 300px;"
class="flex flex-col bg-slate-200 p-3 rounded"
>
<h2 clas="font-bold flex items-center">
<i class="ri-git-pull-request-line mr-1" /> Дополнительно
</h2>
<div class="mt-2 p-2 rounded-md flex flex-col bg-slate-300">
<div v-if="machineOverInfo?.length > 0" class="flex flex-col gap-2">
<div :key="idx" v-for="(info, idx) in machineOverInfo" class="flex items-center items-center bg-slate-200 px-3 py-2 rounded-md">
<div class="text-slate-700 font-bold mr-2">{{ info.title }}</div>
<div class="text-slate-500">{{ info.val }}</div>
<div
v-if="machineOverInfo?.length > 0"
class="flex flex-col gap-2"
>
<div
v-for="(info, idx) in machineOverInfo"
:key="idx"
class="flex items-center items-center bg-slate-200 px-3 py-2 rounded-md"
>
<div class="text-slate-700 font-bold mr-2">
{{ info.title }}
</div>
<div class="text-slate-500">
{{ info.val }}
</div>
</div>
</div>
</div>
@@ -122,38 +168,62 @@ export default {
</template>
</Accordion>
</div>
<Accordion :isOpen="true" id="machine_packs">
<Accordion
id="machine_packs"
:isOpen="true"
>
<template #header>
<div class="font-bold text-xl">Пакеты</div>
<div class="font-bold text-xl">
Пакеты
</div>
</template>
<template #body>
<div class="flex flex-col gap-4">
<div id="packReportButtons">
<div class="flex flex-col gap-5">
<div class="grid grid-cols-12 gap-3">
<div v-if="reportPacks.length === 0" class="flex items-center justify-center text-slate-700 text-2xl font-bold col-span-12">
<div
v-if="reportPacks.length === 0"
class="flex items-center justify-center text-slate-700 text-2xl font-bold col-span-12"
>
<h2>Нет данных по машине</h2>
</div>
<div :key="idx" v-if="reportPacks.length > 0" v-for="(pack, idx) in reportPacks" class="col-span-6 sm:col-span-4 lg:col-span-3 xl:col-span-2 flex items-start flex gap-1 justify-center rounded-md bg-slate-300">
<div v-if="reportPacks.length > 0">
<div
v-for="(pack, idx) in reportPacks"
:key="idx"
class="col-span-6 sm:col-span-4 lg:col-span-3 xl:col-span-2 flex items-start flex gap-1 justify-center rounded-md bg-slate-300"
>
<div class="flex-col flex-grow flex py-1">
<div class="flex text-slate-700 font-medium px-3 text-slate-700">
<div class="mr-1">Номер</div>
<div class="mr-1">
Номер
</div>
<div>{{ pack.pack_number }}</div>
</div>
<div class="text-slate-600 flex px-3 text-slate-600">
<div class="mr-1">Количество</div>
<div class="mr-1">
Количество
</div>
<div>{{ pack.count }}</div>
</div>
</div>
<div @click="loadPack(pack.pack_number)" class="h-full flex items-center justify-center text-white rounded-md px-3 text-center cursor-pointer transitiona-all bg-slate-400 hover:bg-slate-600">
<i class="ri-eye-line"></i>
<div
class="h-full flex items-center justify-center text-white rounded-md px-3 text-center cursor-pointer transitiona-all bg-slate-400 hover:bg-slate-600"
@click="loadPack(pack.pack_number)"
>
<i class="ri-eye-line" />
</div>
</div>
</div>
</div>
</div>
<div class="w-full h-[1px] bg-slate-300"></div>
<PackView :isLoader="false" id="machineReport">
</div>
<div class="w-full h-[1px] bg-slate-300" />
<PackView
id="machineReport"
:isLoader="false"
>
<template #description>
<span class="text-slate-400 text-sm">последние 30</span>
</template>

View File

@@ -1,7 +1,7 @@
const getMachineInfo = (info, isMain) => {
const mainInfo = ["Текущая симкарта", "Последняя коммуникация", "Предприятие приписки", "Текущее устройство"]
if (isMain) {
return info.reduce((acc, el, idx) => {
return info.reduce((acc, el) => {
if (mainInfo.includes(Object.keys(el)[0])) {
const item = {title: Object.keys(el)[0], val: Object.values(el)[0]}
acc.push(item)
@@ -12,7 +12,7 @@ const getMachineInfo = (info, isMain) => {
}, [])
}
if (!isMain) {
return info.reduce((acc, el, idx) => {
return info.reduce((acc, el) => {
if (!mainInfo.includes(Object.keys(el)[0])) {
const item = {title: Object.keys(el)[0], val: Object.values(el)[0]}
acc.push(item)

View File

@@ -1,15 +1,10 @@
<script>
import {ref, toRaw, computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import Button from "@atoms/VButton.vue";
import {mapGetters, mapMutations, mapActions} from "vuex"
import VueMultiselect from 'vue-multiselect'
export default {
name: 'Filters',
name: 'FiltersComponent',
components: {
Button,
VueMultiselect
},
setup() {
@@ -22,14 +17,14 @@ export default {
}
},
computed: {
...mapGetters('machines', ['selectedSelects', 'selectsData', 'toggleFilter', 'selectedData']),
...mapGetters('layoutMachines', ['selectedSelects', 'selectsData', 'toggleFilter', 'selectedData']),
},
mounted () {
},
methods: {
...mapMutations('machines', ['setSelectedSelect', 'setToggleFilter']),
...mapActions('machines', ['updateSelects']),
...mapMutations('layoutMachines', ['setSelectedSelect', 'setToggleFilter']),
...mapActions('layoutMachines', ['updateSelects']),
updateSelectedSelects: function(value) {
if (value.length > 0) {
this.updateSelects({key: 'set', value: value})
@@ -44,25 +39,38 @@ export default {
</script>
<template>
<div id="ignore:2Qxwqz" class="pb-1">
<div
id="ignore:2Qxwqz"
class="pb-1"
>
{{ console.log('selectedData' ,selectedData)
}}
<div v-if="toggleFilter" wrapper_class="grid grid-cols-12 gap-2" selects_class="col-span-12 sm:col-span-6 lg:col-span-3" class="grid grid-cols-12 gap-2 mb-3 border-t border-slate-300 pt-3" fields={@filters_fields} id="SelectFilters" phx-hook="SelectFilters">
<div v-for="selectData in selectsData" class="col-span-12 sm:col-span-6 lg:col-span-3">
<div
v-if="toggleFilter"
id="SelectFilters"
wrapper_class="grid grid-cols-12 gap-2"
selects_class="col-span-12 sm:col-span-6 lg:col-span-3"
class="grid grid-cols-12 gap-2 mb-3 border-t border-slate-300 pt-3"
fields="{@filters_fields}"
phx-hook="SelectFilters"
>
<div
v-for="(selectData, idx) in selectsData"
:key="idx"
class="col-span-12 sm:col-span-6 lg:col-span-3"
>
<VueMultiselect
:multiple="true"
v-model="selectedSelects[selectData.key]"
:multiple="true"
label="name"
track-by="name"
:options="selectData.data"
:placeholder="selectData.title"
:showLabels="false"
@update:model-value="updateSelectedSelects"
@remove="removedOption"
:showLabels="false"
>
</VueMultiselect>
/>
</div>
</div>
</div>

View File

@@ -13,10 +13,10 @@ export default {
// const updatedData = historyData.filter((el, idx, arr) => arr.findIndex((item) => item.machine_id === el.machine_id) === idx).slice(0, 50) // uniq values
const updatedData = isHistoryData ? historyData.slice(0, 50) : []
const store = useStore()
store.commit('machines/setHistoryData', updatedData)
store.commit('layoutMachines/setHistoryData', updatedData)
},
computed: {
...mapGetters('machines', ['historyData']),
...mapGetters('layoutMachines', ['historyData']),
tabulatorOtps() {
return {
dataSource: this.historyData,
@@ -51,7 +51,7 @@ export default {
}
},
methods: {
...mapMutations('machines', ['setHistoryData']),
...mapMutations('layoutMachines', ['setHistoryData']),
}
}

View File

@@ -1,15 +1,11 @@
<script>
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import Button from "@atoms/VButton.vue"
import {mapGetters, mapMutations, mapActions} from "vuex"
import { EventStore } from "@store/hooks/EventStore"
import moment from 'moment'
export default {
name: 'Machine',
name: 'MachineComponent',
components: {
Button,
},
props: {
machine: {
@@ -33,18 +29,18 @@ export default {
}
},
computed: {
...mapGetters('machines', ['machinesData', 'historyData', 'historyMachines']),
...mapGetters('layoutMachines', ['machinesData', 'historyData', 'historyMachines']),
},
mounted () {
},
methods: {
...mapMutations('machines', ['setInitHistory', 'setHistoryData', 'setHistoryMachines']),
...mapActions('machines', ['openMapModal', 'openDataModal']),
...mapMutations('layoutMachines', ['setInitHistory', 'setHistoryData', 'setHistoryMachines']),
...mapActions('layoutMachines', ['openMapModal', 'openDataModal']),
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}`
},
cardFunc: function(value) {
cardFunc: function() {
this.initLocalStorage = new EventStore()
if (this.machine.machine_id) {
const valueStorage = {machine_id: this.machine.machine_id, machine_type: this.machine.machine_type, link: `/html/askr_devices/analyze_device/${this.machine.device_number}`, created_at: moment().format('HH:mm:ss DD-MM-YY')}
@@ -77,41 +73,94 @@ export default {
</script>
<template>
<div id="card" class="pt-3 border w-[23%] min-w-[310px] border-slate-300 rounded transition-all bg-slate-300}">
<div
id="card"
class="pt-3 border w-[23%] min-w-[310px] border-slate-300 rounded transition-all bg-slate-300}"
>
<div class="h-full flex flex-col gap-5 relative text-left justify-between">
<div class="flex flex-col items-end absolute text-white top-[-0.75rem] right-0 h-full min-w-[173px] p-2" style="backdrop-filter: blur(10px);">
<div class="mb-2 text-right drop-shadow" search-mode="machine_id">ID: {{ machine?.machine_id }}</div>
<div class="flex flex-row">
<span>{{ machine.railway_name }}</span><i class="ri-route-line ml-2" title="Дорога:"/>
<div
class="flex flex-col items-end absolute text-white top-[-0.75rem] right-0 h-full min-w-[173px] p-2"
style="backdrop-filter: blur(10px);"
>
<div
class="mb-2 text-right drop-shadow"
search-mode="machine_id"
>
ID: {{ machine?.machine_id }}
</div>
<div class="flex flex-row">
<span>{{ machine.org_name }}</span><i class="ri-building-2-line ml-2" title="Компания:"/>
<span>{{ machine.railway_name }}</span><i
class="ri-route-line ml-2"
title="Дорога:"
/>
</div>
<div class="flex flex-row">
<span>{{ machine.nomer_zn8 }}</span><i class="ri-number-8 ml-2" title="8зн номер:"/>
<span>{{ machine.org_name }}</span><i
class="ri-building-2-line ml-2"
title="Компания:"
/>
</div>
<div class="flex flex-row" search-mode="device_number">
<span>{{ machine.device_number }}</span><i class="ri-rss-line ml-2" title="Устройство:"/>
<div class="flex flex-row">
<span>{{ machine.nomer_zn8 }}</span><i
class="ri-number-8 ml-2"
title="8зн номер:"
/>
</div>
<div
class="flex flex-row"
search-mode="device_number"
>
<span>{{ machine.device_number }}</span><i
class="ri-rss-line ml-2"
title="Устройство:"
/>
</div>
</div>
<div class="flex flex-col w-full mt-4 mb-2 pl-4 mt-1 z-[1]">
<div class="text-slate-800 font-bold m-0" search-mode="machine_type">{{ machine.machine_type }}</div>
<div :machine_id="machine.machine_id" history_click="/html/askr_devices/analyze_comm/#{@machine?.imei}" class="text-slate-500 text-xs underline-offset-4" search-mode="imei">{{ machine.imei }}</div>
<div
class="text-slate-800 font-bold m-0"
search-mode="machine_type"
>
{{ machine.machine_type }}
</div>
<div
:machine_id="machine.machine_id"
history_click="/html/askr_devices/analyze_comm/#{@machine?.imei}"
class="text-slate-500 text-xs underline-offset-4"
search-mode="imei"
>
{{ machine.imei }}
</div>
</div>
<div class="flex lg:flex-row flex-col gap-1 my-2 px-2 z-[1]">
<div class="flex">
<a :href="`/html/askr_devices/analyze_device/${machine.device_number}`" id="to_card_machine" no-init="false" @click="cardFunc(machine)" target="_blank" :class="buttonClass('bg-primary text-white')">Карточка</a>
<a
id="to_card_machine"
:href="`/html/askr_devices/analyze_device/${machine.device_number}`"
no-init="false"
target="_blank"
:class="buttonClass('bg-primary text-white')"
@click="cardFunc(machine)"
>Карточка</a>
</div>
<div class="flex gap-1">
<div @click="mapFunc(machine)" :class="buttonClass('bg-white/25 hover:bg-slate-400 hover:text-white')"><i class="ri-map-pin-line"/></div>
<div @click="dataFunc(machine)" :class="buttonClass('bg-white/25 hover:bg-slate-400 hover:text-white')">30</div>
<div
:class="buttonClass('bg-white/25 hover:bg-slate-400 hover:text-white')"
@click="mapFunc(machine)"
>
<i class="ri-map-pin-line" />
</div>
<div
:class="buttonClass('bg-white/25 hover:bg-slate-400 hover:text-white')"
@click="dataFunc(machine)"
>
30
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>

View File

@@ -1,9 +1,7 @@
<script>
import {computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex"
import {useRoute, useRouter} from 'vue-router'
import {useRoute} from 'vue-router'
import Button from "@atoms/VButton.vue"
import VueMultiselect from 'vue-multiselect'
import Filters from "./Filters.vue"
@@ -18,7 +16,7 @@ import {PushAfterTimeout} from '@store/hooks/PushAfterTimeout'
import {EventStore} from '@store/hooks/EventStore'
export default {
name: 'Machines',
name: 'MachinesComponent',
components: {
Button,
Filters,
@@ -37,12 +35,6 @@ export default {
default: 'static',
},
},
data () {
return {
openMap: false,
openData: false,
}
},
setup () {
const initLocalStorage = new EventStore()
const store = useStore()
@@ -60,10 +52,24 @@ export default {
store.commit('layoutMachines/setHistoryData', updatedData)
store.dispatch('layoutMachines/uploadData', externalParams)
},
data () {
return {
openMap: false,
openData: false,
}
},
computed: {
...mapGetters('layoutMachines', ['searchModes', 'searchValue', 'selectedSearchMode', 'leftTopButtons', 'rightTopButtons', 'selectedMode', 'toggleFilter', 'activeFilterBtn', 'mapData', 'machinesData']),
...mapGetters('layout', ['isOpenMenu']),
},
watch: {
isSuccessSearch: {
handler(newValue, oldValue) {
console.log('isSuccessSearch', newValue, oldValue)
},
deep: true
},
},
mounted () {
},
@@ -83,14 +89,6 @@ export default {
const store = useStore();
store.dispatch('layoutMachines/resetStore')
},
watch: {
isSuccessSearch: {
handler(newValue, oldValue) {
console.log('isSuccessSearch', newValue, oldValue)
},
deep: true
},
},
methods: {
...mapMutations('layoutMachines', ['setSearchMode', 'setSelectedMode', 'setToggleFilter', 'setActiveFilterBtn']),
...mapActions('layoutMachines', ['updateSearch', 'clearFilters']),
@@ -141,13 +139,15 @@ export default {
</script>
<template>
<div class="px-2 sm:px-5 pt-1 bg-light">
<div class="relative">
<div class="grid grid-cols-12 gap-4 md:gap-3 lg:gap-4 pb-3">
<div class="flex items-center col-span-12 sm:col-span-8 lg:col-span-5 xl:col-span-4 2xl:col-span-3">
<div id="search" class="relative w-full max-w-[150px] h-[31px] pl-1 py-1 bg-white border border-primary rounded-l-md z-30">
<div
id="search"
class="relative w-full max-w-[150px] h-[31px] pl-1 py-1 bg-white border border-primary rounded-l-md z-30"
>
<VueMultiselect
v-model="selectedSearchMode"
label="name"
@@ -156,50 +156,126 @@ export default {
placeholder=""
:showLabels="false"
@update:model-value="updateSearchMode"
>
</VueMultiselect>
/>
</div>
<div id="searchInput" class="relative w-full border-r border-t border-b border-primary rounded-r-md">
<input v-bind:value="searchValue" v-on:change="updateSearchValue" :status="status" class="pl-1 py-1 rounded-r-md w-full max-h-[29px] border-none focus-visible:outline-blue-300"/>
<div
id="searchInput"
class="relative w-full border-r border-t border-b border-primary rounded-r-md"
>
<input
:value="searchValue"
:status="status"
class="pl-1 py-1 rounded-r-md w-full max-h-[29px] border-none focus-visible:outline-blue-300"
@change="updateSearchValue"
>
</div>
</div>
<!-- {{ console.log('machinesData', machinesData) }} -->
<ul id="machinesMode" class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center">
<li v-bind:key="idx" v-for="(mode, idx) in leftTopButtons">
<Button :onClick="updateMode" :selected="mode.key" :classIcon="mode.class" :classBtn="[mode.key === 'cards' ? 'rounded-r-none' : 'rounded-l-none', selectedMode === mode.key ? 'text-white bg-primary focus:ring-4 focus:outline-none focus:ring-blue-300' : 'bg-transparent', 'w-full min-w-[88px] h-[30px] border border-primary rounded-md']" />
<ul
id="machinesMode"
class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center"
>
<li
v-for="(mode, idx) in leftTopButtons"
:key="idx"
>
<Button
:onClick="updateMode"
:selected="mode.key"
:classIcon="mode.class"
:classBtn="[mode.key === 'cards' ? 'rounded-r-none' : 'rounded-l-none', selectedMode === mode.key ? 'text-white bg-primary focus:ring-4 focus:outline-none focus:ring-blue-300' : 'bg-transparent', 'w-full min-w-[88px] h-[30px] border border-primary rounded-md']"
/>
</li>
</ul>
<div id="historyMode" class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center">
<Button :onClick="updateMode" selected="history" title="Просмотры" :classBtn="[selectedMode === 'history' ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', 'w-full min-w-[88px] h-[30px] bg-primary text-white border border-primary rounded-md']" />
<div
id="historyMode"
class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center"
>
<Button
:onClick="updateMode"
selected="history"
title="Просмотры"
:classBtn="[selectedMode === 'history' ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', 'w-full min-w-[88px] h-[30px] bg-primary text-white border border-primary rounded-md']"
/>
</div>
<div id="chartsMode" class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center">
<Button :onClick="updateMode" selected="charts" classIcon="ri-pie-chart-2-line" :classBtn="[selectedMode === 'charts' ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', 'w-full min-w-[88px] h-[30px] bg-primary text-white border border-primary rounded-md']" />
<div
id="chartsMode"
class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center"
>
<Button
:onClick="updateMode"
selected="charts"
classIcon="ri-pie-chart-2-line"
:classBtn="[selectedMode === 'charts' ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', 'w-full min-w-[88px] h-[30px] bg-primary text-white border border-primary rounded-md']"
/>
</div>
<ul id="filtersButtons" class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center">
<li v-bind:key="idx" v-for="(mode, idx) in rightTopButtons">
<Button :onClick="setFilteredAction" :selected="mode.key" :title="mode.name" :classIcon="mode.iconClass" :classBtn="[activeFilterBtn === mode.key ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', mode.key === 'filter' ? 'rounded-r-none' : 'rounded-l-none', mode.classBtn, 'w-full min-w-[88px] h-[30px] border border-primary rounded-md']" />
<ul
id="filtersButtons"
class="flex col-span-6 sm:col-span-4 md:col-span-4 lg:col-span-3 xl:col-span-2 justify-center"
>
<li
v-for="(mode, idx) in rightTopButtons"
:key="idx"
>
<Button
:onClick="setFilteredAction"
:selected="mode.key"
:title="mode.name"
:classIcon="mode.iconClass"
:classBtn="[activeFilterBtn === mode.key ? 'focus:ring-4 focus:outline-none focus:ring-blue-300' : '', mode.key === 'filter' ? 'rounded-r-none' : 'rounded-l-none', mode.classBtn, 'w-full min-w-[88px] h-[30px] border border-primary rounded-md']"
/>
</li>
</ul>
</div>
<div id="filters" v-if="toggleFilter">
<div
v-if="toggleFilter"
id="filters"
>
<Filters />
</div>
<div class="border-2 rounded-lg w-full bottom-0"></div>
<div id="listMachines" v-if="selectedMode === 'cards'" class="w-full min-h-[80vh] p-4 bg-light dark:bg-slate-900 dark:text-slate-300 relative">
<ul v-if="selectedMode === 'cards'" class="flex flex-wrap gap-4 w-full justify-center align-center">
<div class="border-2 rounded-lg w-full bottom-0" />
<div
v-if="selectedMode === 'cards'"
id="listMachines"
class="w-full min-h-[80vh] p-4 bg-light dark:bg-slate-900 dark:text-slate-300 relative"
>
<ul
v-if="selectedMode === 'cards'"
class="flex flex-wrap gap-4 w-full justify-center align-center"
>
<!-- <li v-for="machine in machinesData" class="w-full sm:w-1/2 md:w-1/2 lg:w-1/2 xl:w-1/2 p-2 border-2 border-primary rounded-md"> -->
<li v-for="machine in machinesData" class="">
<Machine :machine="machine" :openMap="toggleMap" :openData="toggleData" />
<li
v-for="(machine, idx) in machinesData"
:key="idx"
class=""
>
<Machine
:machine="machine"
:openMap="toggleMap"
:openData="toggleData"
/>
</li>
</ul>
</div>
<div id="tableMachines" v-if="selectedMode === 'table'" class="tab-pane bg-light relative py-4 text-center min-h-[300px] relative rounded-md w-full">
<div
v-if="selectedMode === 'table'"
id="tableMachines"
class="tab-pane bg-light relative py-4 text-center min-h-[300px] relative rounded-md w-full"
>
<Table />
</div>
<div id="historyViews" v-if="selectedMode === 'history'" class="tab-pane bg-light relative shadow text-center min-h-[300px] relative w-full p-4">
<div
v-if="selectedMode === 'history'"
id="historyViews"
class="tab-pane bg-light relative shadow text-center min-h-[300px] relative w-full p-4"
>
<HistoryViews />
</div>
<div id="charts" v-if="selectedMode === 'charts'" class="w-full min-h-[80vh] pb-5 bg-light dark:bg-slate-900 dark:text-slate-300 relative">
<div
v-if="selectedMode === 'charts'"
id="charts"
class="w-full min-h-[80vh] pb-5 bg-light dark:bg-slate-900 dark:text-slate-300 relative"
>
<!-- <.loader :if={@display_config.is_loading_charts} /> -->
<div>
<Charts />
@@ -210,10 +286,10 @@ export default {
<div class="flex items-center justify-center text-lg font-bold pt-5">Нет данных</div>
</div> -->
<MapModal
id="mapModal"
:open="openMap"
:close="closeMap"
:data="mapData"
id="mapModal"
headerClass="border-b p-4 font-bold"
>
<template #header>
@@ -221,18 +297,38 @@ export default {
Карта
</div>
</template>
<div v-if="!mapData" id="map_loader" class="flex justify-center" style="width: 95vw; height: 82vh;">
<div
v-if="!mapData"
id="map_loader"
class="flex justify-center"
style="width: 95vw; height: 82vh;"
>
<Spinner />
</div>
<div v-if="mapData" id="mapModal" style="width: 95vw; height: 82vh;"></div>
<div id="popup" class="ol-popup hidden transition-all">
<a href="#" id="popup-closer" class="ol-popup-closer hover:no-underline top-2 right-2 ">
<i class="ri-close-fill"></i>
<div
v-if="mapData"
id="mapModal"
style="width: 95vw; height: 82vh;"
/>
<div
id="popup"
class="ol-popup hidden transition-all"
>
<a
id="popup-closer"
href="#"
class="ol-popup-closer hover:no-underline top-2 right-2 "
>
<i class="ri-close-fill" />
</a>
<div id="popup-content"></div>
<div id="popup-content" />
</div>
</MapModal>
<DataModal id="dataModal" :open="openData" :close="closeData" />
<DataModal
id="dataModal"
:open="openData"
:close="closeData"
/>
</div>
</div>
</template>

View File

@@ -1,10 +1,9 @@
<script>
import {mapGetters, mapActions, mapMutations, useStore} from "vuex"
import {mapGetters, mapActions, mapMutations} from "vuex"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
import { EventStore } from "@store/hooks/EventStore"
export default {
name: 'Table',
name: 'TableComponent',
components: {Tabulator},
data () {
@@ -12,7 +11,7 @@ export default {
}
},
computed: {
...mapGetters('machines', ['tableData', 'pagination']),
...mapGetters('layoutMachines', ['tableData', 'pagination']),
tabulatorOtps() {
return {
dataSource: this.tableData,
@@ -82,8 +81,8 @@ export default {
}
},
methods: {
...mapMutations('machines', ['setHistoryData']),
...mapActions('machines', ['updatePagination']),
...mapMutations('layoutMachines', ['setHistoryData']),
...mapActions('layoutMachines', ['updatePagination']),
}
}

View File

@@ -1,20 +1,12 @@
<script>
import {computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
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 "@atoms/VButton.vue";
export default {
name: 'Main',
name: 'MainPage',
components: {
Machines,
FinderPacks,
AddUsers,
Button
},
setup() {
@@ -66,17 +58,27 @@ export default {
</script>
<template>
<div class="col-span-12">
<div class="p-2 sm:px-5 pt-1 bg-light rounded-t-xl">
<div class="relative">
<div class="flex gap-3 sm:gap-7 w-full lg:w-[50%]">
<router-link :to="{name: page.link}" @click="setPage(page)" v-for="(page, idx) in pages" class="flex w-full">
<Button v-bind:key="idx" type="button" :title="page.name" :classBtn="[selectedPage.key !== page.key ? 'border-transparent': 'border-slate-500', 'flex border-b-4']" />
<router-link
v-for="(page, idx) in pages"
:key="idx"
:to="{name: page.link}"
class="flex w-full"
@click="setPage(page)"
>
<Button
:key="idx"
type="button"
:title="page.name"
:classBtn="[selectedPage.key !== page.key ? 'border-transparent': 'border-slate-500', 'flex border-b-4']"
/>
</router-link>
</div>
<div class="border-2 rounded-lg w-full bottom-0 absolute"/>
<div class="border-2 rounded-lg w-full bottom-0 absolute" />
</div>
</div>
<router-view />

View File

@@ -1,9 +1,3 @@
<template>
<div>
123
</div>
</template>
<script>
export default {
@@ -18,3 +12,9 @@ export default {
}
</script>
<template>
<div>
123
</div>
</template>

View File

@@ -1,5 +1,3 @@
<script>
import Chart from "@molecules/VChart/VChart.vue";
import moment from 'moment'
@@ -56,10 +54,21 @@ export default {
</script>
<template>
{{ console.log('currentSizes.heigth', maxHeight) }}
<div v-if="displayView === 'chart'" id="packChartWrapper" class="relative flex flex-wrap justify-center w-full h-full mb-3" >
<Chart id="packChart" type="packLines" height="800" :data="chartData(curerentTableData)" :sizes="currentSizes" :maxWidth="`${maxWidth}px`" :maxHeight="`${maxHeight}px`" />
<div
v-if="displayView === 'chart'"
id="packChartWrapper"
class="relative flex flex-wrap justify-center w-full h-full mb-3"
>
<Chart
id="packChart"
type="packLines"
height="800"
:data="chartData(curerentTableData)"
:sizes="currentSizes"
:maxWidth="`${maxWidth}px`"
:maxHeight="`${maxHeight}px`"
/>
</div>
</template>

View File

@@ -1,7 +1,7 @@
<script>
import {ref, toRaw, computed} from 'vue'
import {computed} from 'vue'
import {mapGetters, mapMutations, mapActions, useStore} from "vuex";
import {useRoute, useRouter} from 'vue-router'
import {useRoute} from 'vue-router'
import Datepicker from "@molecules/VDatepicker/VDatepicker.vue"
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
@@ -10,7 +10,7 @@ import VueMultiselect from 'vue-multiselect'
import moment from 'moment'
export default {
name: 'Packs',
name: 'PacksPage',
components: {
Datepicker,
VueMultiselect,
@@ -125,7 +125,6 @@ export default {
</script>
<template>
<div class="grid grid-cols-12 gap-6 col-span-12 h-full">
{{
@@ -138,42 +137,58 @@ export default {
</h1>
<div class="grid gap-3 mb-3 ">
<div class="grid grid-cols-1">
<label for="date" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">
<label
for="date"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Дата
</label>
<Datepicker id="date" :onchange="setDate" />
<Datepicker
id="date"
:onchange="setDate"
/>
</div>
<div phx-feedback-for="imei">
<label for="selectedImei" class="block text-sm leading-6 text-zinc-800 dark:text-white">
<label
for="selectedImei"
class="block text-sm leading-6 text-zinc-800 dark:text-white"
>
imei
</label>
<input
id="selectedImei"
type="text"
name="imei"
v-bind:value="packsSettings.imei"
v-on:change="setImei"
:value="packsSettings.imei"
class="block w-full rounded-lg border-zinc-300 py-[1px] px-[11px] text-zinc-900 focus:outline-none focus:ring-4 text-sm sm:leading-6 phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400 phx-no-feedback:focus:ring-zinc-800/5 border-zinc-300 focus:border-zinc-400 focus:ring-zinc-800/5 "
placeholder="imei"
required=""
@change="setImei"
>
</div>
<div>
<label for="selectedPack" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
<label
for="selectedPack"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
>Выбрать пакет</label>
<div id="selected_settings_name_wrapper" class="w-full">
<div id="packsOptions" class="col-span-12 sm:col-span-6 lg:col-span-3 rounded-lg">
<div
id="selected_settings_name_wrapper"
class="w-full"
>
<div
id="packsOptions"
class="col-span-12 sm:col-span-6 lg:col-span-3 rounded-lg"
>
<VueMultiselect
name="selectedPack"
v-model="packsSettings.selectedPack"
name="selectedPack"
label="name"
track-by="name"
:options="packsSettings.selectedPackGroup"
:placeholder="packsSettings.selectedPack?.name"
@update:model-value="setPack"
:showLabels="false"
>
</VueMultiselect>
@update:model-value="setPack"
/>
</div>
</div>
</div>
@@ -181,9 +196,9 @@ export default {
<div class="grid gap-3 grid-cols-4">
<input
type="submit"
@click="fetchPack(packsSettings)"
class="col-span-4 lg:col-span-4 cursor-pointer text-white bg-primary hover:brightness-90 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-ssm w-full sm:w-auto px-5 py-1 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 transition_up"
value="Выгрузить"
@click="fetchPack(packsSettings)"
>
<div
phx-click="load_pack_settings"
@@ -206,15 +221,22 @@ export default {
</div>
</div>
</div>
<div id="packageDisplay" class="relative lg:col-span-8 xl:col-span-9 2xl:col-span-10 col-span-12 bg-light shadow">
<div v-if="!isLoading && curerentTableData.dataSource" id="tableButtons" class="w-full">
<div
id="packageDisplay"
class="relative lg:col-span-8 xl:col-span-9 2xl:col-span-10 col-span-12 bg-light shadow"
>
<div
v-if="!isLoading && curerentTableData.dataSource"
id="tableButtons"
class="w-full"
>
<div class="w-full flex justify-end">
<div class="flex gap-3 pt-4 pb-2 pr-4">
<div class="">
<button
type="button"
@click="setOpenColumnSelect"
class="flex items-center transition-all justify-center py-2 px-3 bg-light text-sm font-medium text-slate-700 focus:outline-none rounded-lg border border-dashed border-slate-400 hover:text-blue-800 hover:border-blue-900 hover:shadow focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
@click="setOpenColumnSelect"
>
<i class="ri-settings-3-line" />
</button>
@@ -225,9 +247,9 @@ export default {
>
<button
type="button"
@click="toggleDisplayView"
class="flex items-center transition-all justify-center py-2 px-3 bg-light text-sm font-medium text-slate-700 focus:outline-none rounded-lg border border-dashed border-slate-400 hover:text-blue-800 hover:border-blue-900 hover:shadow focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
phx-click="[[&quot;toggle&quot;,{&quot;display&quot;:null,&quot;ins&quot;:[[],[],[]],&quot;outs&quot;:[[],[],[]],&quot;time&quot;:200,&quot;to&quot;:&quot;#graphic_btn_inactive&quot;}],[&quot;toggle&quot;,{&quot;display&quot;:null,&quot;ins&quot;:[[],[],[]],&quot;outs&quot;:[[],[],[]],&quot;time&quot;:200,&quot;to&quot;:&quot;#graphic_btn_active&quot;}],[&quot;toggle&quot;,{&quot;display&quot;:null,&quot;ins&quot;:[[],[],[]],&quot;outs&quot;:[[],[],[]],&quot;time&quot;:200,&quot;to&quot;:&quot;#pack_table_warapper&quot;}],[&quot;toggle&quot;,{&quot;display&quot;:null,&quot;ins&quot;:[[],[],[]],&quot;outs&quot;:[[],[],[]],&quot;time&quot;:200,&quot;to&quot;:&quot;#pack_graphic_wrapper&quot;}],[&quot;push&quot;,{&quot;event&quot;:&quot;toggle_display_data&quot;}]]"
@click="toggleDisplayView"
>
<i class="ri-bar-chart-grouped-line" />
</button>
@@ -277,33 +299,55 @@ export default {
</div>
</div>
</div>
<div v-if="columnSelector" id="colums_select_wrapper" class="w-full">
<div
v-if="columnSelector"
id="colums_select_wrapper"
class="w-full"
>
<VueMultiselect
name="selectedPack"
v-model="selectedColumnsSelect"
name="selectedPack"
label="name"
track-by="name"
:options="columnsSelect"
:placeholder="null"
@select="addedOption"
@remove="removedOption"
:showLabels="false"
:multiple="true"
:group-select="true"
>
</VueMultiselect>
@select="addedOption"
@remove="removedOption"
/>
</div>
<div v-if="displayView === 'table'" id="packTableWarapper">
<div
v-if="displayView === 'table'"
id="packTableWarapper"
>
{{ console.log('getters.isLoading', isLoading) }}
<div id="reportPacks" class="tab-pane active text-center min-h-[300px] rounded-md ">
<Tabulator v-if="!isLoading && curerentTableData.dataSource" v-bind="curerentTableData" />
<span v-if="!isLoading && !curerentTableData.dataSource" class="absolute flex w-full justify-center items-center mt-2"> Выберите пакет и нажмите выгрузить</span>
<div v-if="isLoading && !curerentTableData.dataSource" class="absolute flex w-full h-full justify-center items-center bg-slate-50" id="packLoader">
<div
id="reportPacks"
class="tab-pane active text-center min-h-[300px] rounded-md "
>
<Tabulator
v-if="!isLoading && curerentTableData.dataSource"
v-bind="curerentTableData"
/>
<span
v-if="!isLoading && !curerentTableData.dataSource"
class="absolute flex w-full justify-center items-center mt-2"
> Выберите пакет и нажмите выгрузить</span>
<div
v-if="isLoading && !curerentTableData.dataSource"
id="packLoader"
class="absolute flex w-full h-full justify-center items-center bg-slate-50"
>
<Spinner />
</div>
</div>
</div>
<PackChart :displayView="displayView" :curerentTableData="curerentTableData" />
<PackChart
:displayView="displayView"
:curerentTableData="curerentTableData"
/>
</div>
<div>
<button

View File

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

View File

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

View File

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

View File

@@ -1,30 +1,24 @@
<script>
import {mapGetters, useStore} from "vuex"
import Service from './ServicesServiceItem.vue'
import Spinner from "@molecules/VSpinner/VSpinner.vue"
import Tabulator from "@molecules/VTabulator/VTabulator.vue"
export default {
name: 'Services',
name: 'ServicesPage',
components: {
Service,
Spinner,
Tabulator,
},
props: {
},
setup () {
const store = useStore()
store.dispatch('services/uploadData')
},
data () {
return {
isOpenServices: false,
titleServicesButton: 'Показать больше'
}
},
setup (props, {slots}) {
const store = useStore()
store.dispatch('services/uploadData')
},
computed: {
...mapGetters('services', ['services']),
},
@@ -42,25 +36,42 @@ export default {
</script>
<template>
<div class="col-span-12">
<div class="flex flex-col mt-4 shadow-md mb-1 mx-5 bg-white" style="max-width: calc(100vw - 40px); margin-bottom: 30px;">
<div
class="flex flex-col mt-4 shadow-md mb-1 mx-5 bg-white"
style="max-width: calc(100vw - 40px); margin-bottom: 30px;"
>
<div class="flex flex-col flex-wrap justify-between px-4 pb-2 pt-8 w-full">
<div class="text-lg font-bold text-center text-gray-600">Информация о сети (кэш)</div>
<div class="text-lg font-bold text-center text-gray-600">
Информация о сети (кэш)
</div>
<div class="flex flex-col max-w-full">
<div>
Сервисы, записывающие данные в кэш
</div>
<div id="serviceList" :class="`flex flex-wrap h-auto flex-row mt-4 overflow-x-auto w-full gap-4 transition-all pb-4 ${isOpenServices ? 'max-h-full' : 'max-h-[220px]'}`">
<div v-for="(service, idx) in sortingServices(services)">
<Service :idx="idx" :name="service.service || service.name" :service="service" />
<div
id="serviceList"
:class="`flex flex-wrap h-auto flex-row mt-4 overflow-x-auto w-full gap-4 transition-all pb-4 ${isOpenServices ? 'max-h-full' : 'max-h-[220px]'}`"
>
<div
v-for="(service, idx) in sortingServices(services)"
:key="idx"
>
<Service
:idx="idx"
:name="service.service || service.name"
:service="service"
/>
</div>
</div>
</div>
</div>
<button @click="toggleServices(isOpenServices)" class="w-full max-h-[90px] py-2.5 px-5 text-sm font-medium text-gray-900 bg-gray-100 border-t border-gray-200 hover:bg-gray-100 hover:text-slate-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
{{titleServicesButton}}
<button
class="w-full max-h-[90px] py-2.5 px-5 text-sm font-medium text-gray-900 bg-gray-100 border-t border-gray-200 hover:bg-gray-100 hover:text-slate-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
@click="toggleServices(isOpenServices)"
>
{{ titleServicesButton }}
</button>
</div>
</div>

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line no-undef
export default dom = (() => {
const getNodeList = (arg) => {
if (typeof arg === "string" && arg.trim().slice(0, 1) !== "<") {

View File

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

View File

@@ -1,7 +1,7 @@
import {createRouter, createWebHistory} from "vue-router";
import Main from "@pages/Main/index.vue"
import Auth from "@pages/Auth/index.vue"
import Communication from "@pages/Communication/index.vue"
// import Communication from "@pages/Communication/index.vue"
import LastPacksNum from "@pages/LastPacksNum/index.vue"
import Fuel from "@pages/Fuel/index.vue"
import Cron from "@pages/Cron/index.vue"
@@ -12,14 +12,13 @@ import Packs from "@pages/Packs/index.vue"
import FileViewer from "@pages/FileViewer/index.vue"
import NotFound from "@pages/404/index.vue"
import Diap from "@admin_pages/Diap/index.vue"
import News from "@admin_pages/News/index.vue"
// 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/Services.vue"
import ServiceManage from "@admin_pages/ServiceManage/index.vue"
import {get} from "@store/modules/apiHelpers"
import {cond, T} from 'ramda'
// import ServiceManage from "@admin_pages/ServiceManage/index.vue"
// import {get} from "@store/modules/apiHelpers"
const routes = [
@@ -124,17 +123,17 @@ const router = createRouter({
routes
});
const logout = (from, next) => {
localStorage.removeItem("token")
sessionStorage.setItem("pathname", from.fullPath)
next()
}
// const logout = (from, next) => {
// localStorage.removeItem("token")
// sessionStorage.setItem("pathname", from.fullPath)
// next()
// }
const auth_check = async () => {
return await get("/api/auth/loginStatus", ({data}) => {
return data
})
}
// const auth_check = async () => {
// return await get("/api/auth/loginStatus", ({data}) => {
// return data
// })
// }
// router.beforeEach(async (to, from, next) => {
// const status = await auth_check()

View 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

View File

@@ -1,4 +1,3 @@
class ServiceOfMachines {
constructor(adapter, store) {
this.adapter = adapter
@@ -9,14 +8,14 @@ class ServiceOfMachines {
return await this.adapter.getModalMachines()
}
async putModalMachines(machines) {
async setModalMachines(machines) {
const result = await this.store.dispatch('machines/saveModalMachines', machines)
return result
}
async makeFetchAndPutModalMachines() {
const machines = await this.fetchModalMachines()
await this.putModalMachines(machines)
await this.setModalMachines(machines)
return machines
}
}

View File

@@ -18,7 +18,7 @@ export class CopyToClipboard {
copy (text, id) {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text)
this.fallbackCopyTextToClipboard(text)
return
}
navigator.clipboard.writeText(text).then(function() {

View File

@@ -131,27 +131,29 @@ const updatedGroupByData = (idx, prevGroupByFilters, groupByKey, groupByValue) =
const choiceTypeBarTypesCharts = (params) => {
switch(params.type) {
case 'ml':
case 'ml': {
const yAxisMlData = params.yAxisData.sort().map((el) => {
return `${el.key !== null ? el.key : 'Нет данных'} ${el.val}`
}).sort((a, b) => a - b).reverse()
const xAxisMlData = params.xAxisData.map((item) => item.map((el) => el))
const mlData = xAxisMlData.sort().map((el) => prepareBarTypesMlData(el, params))
return {axisData: yAxisMlData, updatedData: groupByBarTypesData(mlData, xAxisMlData, chartsFiltersNamesMl)}
case 'mount':
}
case 'mount': {
const xAxisMountData = params.yAxisData.sort((a, b) => a.key - b.key).map((el) => {
return `${el.key !== null ? el.key : 'Нет данных'} \n ${el.val}`})
const mountData = params.xAxisData.sort().map((el) => prepareBarTypesData(el, params.xAxisData, params))
return {axisData: xAxisMountData, updatedData: groupByBarTypesData(mountData, params.xAxisData, chartsFiltersNames)}
}
default :
default : {
const yAxisDefaultData = params.yAxisData.sort().map((el) => {
return `${el.key !== null ? el.key : 'Нет данных'} ${el.val}`
}).sort((a, b) => a - b).reverse()
const defaultData = params.xAxisData.sort().map((el) => prepareBarTypesData(el, params.xAxisData, params))
return {axisData: yAxisDefaultData, updatedData: groupByBarTypesData(defaultData, params.xAxisData, chartsFiltersNames)}
}
}
}
export {isEqualKeyValue, getTextWidth, updatedGroupByData, choiceTypeBarTypesCharts}

View File

@@ -3,10 +3,10 @@ import {
TitleComponent,
TooltipComponent,
LegendComponent
} from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
} from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import {colorList, colorListBar, orderCharts, title, openMachine, groupByKeys, typesCharts} from './staticData'
import {viewGraphicsPieBar, viewGraphicsTypesBar} from "./graphicElements";
@@ -145,7 +145,7 @@ const linesPackConfig = (params, id, windowConfig) => {
}
const pieConfig = (params, id, windowConfig) => {
const data = params.machines.map((el, idx) => {
const data = params.machines.map((el) => {
el.color = colorList(el.name)
el.order = orderCharts(el.name)
return el
@@ -230,7 +230,7 @@ const barConfig = (params, id, windowConfig) => {
// console.log('params', params)
const countMachinesWithoutMl = params?.machines?.[params?.machines?.length - 1]?.key === 'routes_without_ml' ? params?.machines?.[params?.machines?.length - 1]?.values : 0
const data = params?.machines?.map((el, idx) => {
const data = params?.machines?.map((el) => {
el.itemStyle = {color: colorListBar(params.type, el.name)}
return el
}).sort((a, b) => a?.value - b?.value).reverse()
@@ -359,7 +359,7 @@ const barTypesConfig = (params, id, windowConfig, enableDataZoom) => {
})
// console.log('dataWithoutZero', dataWithoutZero)
const series = dataWithoutZero.map((charts, idx) => {
const series = dataWithoutZero.map((charts) => {
const [title] = choiceTypeBarTypesCharts(params).updatedData.dataCustomTitle.flat().filter((el) => el?.name == charts[0]?.name)
return {
name: `${title?.name} ${title?.count} id:${id}`,
@@ -547,7 +547,7 @@ const config = (params) => {
series: params.series
}
}
}
class ECharts {
constructor(id, sizes = {}) {
@@ -557,7 +557,7 @@ class ECharts {
const clientHeight = window.innerHeight
this.isMobile = clientWidth < 768
this.currentWidth = clientWidth - 100
// const currentheight = clientHeight + 70
this.currentheight = clientHeight + 70
this.widthChart = sizes.width ? sizes.width : 450
this.heightChart = sizes.height ? sizes.height : 350
this.mountHeightChart = 350
@@ -891,7 +891,7 @@ class ECharts {
this.initCharts.on('legendselectchanged', (params) => {
if(params.name.indexOf('id:') > 0) {
// Берём все данные производные из имени, так как это активный элемент легенды
const id = params.name.slice((params.name.indexOf('id:') + 3))
// const id = params.name.slice((params.name.indexOf('id:') + 3))
const nameIdxEnd = (params.name.indexOf('id:') - 1)
const namePrepare = params.name.slice(0, nameIdxEnd)
const name = namePrepare.slice(0, namePrepare.lastIndexOf(' '))

View File

@@ -66,7 +66,7 @@ const orderCharts = (name) => {
}
}
const title = (id, count, countWithoutMl = '') => {
const title = (id) => {
switch(id) {
case 'commun_pie': return `Связь с СПС`
case 'commun_pie_cdim': return `Связь с СПС, ЦДИМ`
@@ -93,8 +93,11 @@ const title = (id, count, countWithoutMl = '') => {
}
const openMachine = (data) => {
const [currentEl] = data?.linkData?.filter((el) => el?.machine_type === data?.groupByData[data?.groupByKey])
const currentArr = data?.linkData?.filter((el) => el?.machine_type === data?.groupByData[data?.groupByKey])
if (currentArr?.length > 0) {
const currentEl = currentArr[0]
window.open(`/html/askr_devices/analyze_device/${currentEl.device_number}`, '_blank')
}
}
const groupByKeys = {

View File

@@ -376,6 +376,6 @@ const sizeOptions = (width = 600, height = 400) => {
width: width,
height: height
}
}
}
export {axisBarConfig, windowConfig, sizeOptions}

View File

@@ -12,6 +12,7 @@ import { store as packs } from '@/store/modules/packs';
import { store as services } from '@/store/modules/services';
import { store as logger } from '@/store/modules/logger';
// eslint-disable-next-line no-undef
let debug = process.env.NODE_ENV !== 'production';
debug = false;

View File

@@ -20,7 +20,7 @@ const columns = [
log: true,
render: `
<div class="flex items-center gap-2">
<a target="_blank" href="/html/admin/manage/{{ id }}?prev_page=/\?current_mode=users"><i class="cursor-pointer ri-pencil-line text-slate-700"></i></a>
<a target="_blank" href="/html/admin/manage/{{ id }}?prev_page=/?current_mode=users"><i class="cursor-pointer ri-pencil-line text-slate-700"></i></a>
</div>
`
}
@@ -583,6 +583,6 @@ const users = {
},
],
height: "200px"
}
}
export { columns, users }

View File

@@ -1,6 +1,5 @@
import {toRaw} from 'vue'
import {columns, users} from './StaticData'
import {equals, isEmpty, uniq} from 'ramda'
import {isEmpty} from 'ramda'
const initState = {
adminData: [],
@@ -24,7 +23,7 @@ const mutations = {
};
const actions = {
uploadData: async ({commit, getters, state}, historyData) => {
uploadData: async ({commit}, historyData) => {
try{
/*
@@ -41,7 +40,7 @@ const actions = {
}
*/
console.log('historyData', historyData)
const adminList = !isEmpty(users) ? users : []
const report = {

View File

@@ -1,12 +1,8 @@
import {get, post} from '../apiHelpers'
import {groupBy} from 'ramda'
import {toRaw} from "vue"
import {cond, T, equals} from 'ramda'
import axios from 'axios';
import {orisMenu} from './menuList'
const initState = {
current_user: null,
currentUser: null,
errorMsg: null,
token: null,
inited: false,
@@ -17,7 +13,7 @@ const state = {
...initState
};
const current_user = (token) => ({
const setCurrentUser = (token) => ({
position: "",
first_name: "Сергей",
last_name: "Шлыков",
@@ -31,17 +27,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,
};

View File

@@ -1,12 +1,10 @@
const orisMenu = [
{
type: "simple_link",
icon: "home",
show: "Главная",
link: "/",
router: "main"
router: "machines"
},
{
type: "simple_link",

View File

@@ -1,5 +1,3 @@
import moment from 'moment'
const initState = {
}

View File

@@ -793,5 +793,4 @@ const packsGroups = [
]
export { packsGroups }

View File

@@ -1,6 +1,5 @@
import {toRaw} from 'vue'
import {packsGroups} from './StaticData'
import {equals, isEmpty, uniq} from 'ramda'
import {isEmpty} from 'ramda'
const initState = {
@@ -36,7 +35,7 @@ const mutations = {
};
const actions = {
uploadData: async ({commit, getters, state}, historyData) => {
uploadData: async ({commit}) => {
try{
/*
@@ -81,7 +80,7 @@ const actions = {
console.error(err)
}
},
updateSearch: async ({commit, getters, state}, updatedValue) => {
updateSearch: async ({commit, state}, updatedValue) => {
try {
const groups = state.packsGroupsDefault
const readyValue = updatedValue?.toLowerCase().split(' ')

View File

@@ -35,7 +35,7 @@ const mutations = {
const actions = {
uploadData: ({commit, state}) => {
uploadData: ({state}) => {
setTimeout(() => {
state.pageState = 'loading'
}, 500);

View File

@@ -1,5 +1,3 @@
import moment from 'moment'
const initState = {
imei: "",
pageState: "await", // await | loading | isLoaded | error
@@ -38,7 +36,7 @@ const mutations = {
const actions = {
uploadData: ({commit, state}) => {
uploadData: ({state}) => {
setTimeout(() => {
state.pageState = 'loading'
}, 500);

View File

@@ -1,52 +1,88 @@
import {initScreenListener, disableScreenListener} from "./stateHelpers.js";
const state = {
const initState = {
height: 0,
width: 0,
inited: false,
isOpenMenu: false,
mobile_menu_opened: false,
show_menu: true,
is_enabled_menu: true
isOpenedMobileMenu: false,
isEnabledMenu: true,
isShowMenu: true,
initedScreenListener: false,
};
const state = {
...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 = {

View File

@@ -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}

View 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 }

Some files were not shown because too many files have changed in this diff Show More