Compare commits
336 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 826d51f66c | |||
| 1d7fc2955f | |||
| c550e7598a | |||
| d5168ce59d | |||
| 380c97655c | |||
| e4ed24de80 | |||
| 8de03b9210 | |||
| 12ece46089 | |||
| 085238fada | |||
| 45c1d83512 | |||
| af9073ab98 | |||
| 800fc35e63 | |||
| d5649d221b | |||
| 5b35fac512 | |||
| d5bc90f668 | |||
| 6d663886f0 | |||
| 85a1a0216e | |||
| 4ac054e947 | |||
| ba70fa1316 | |||
| 77e6b20d0c | |||
| f60263c923 | |||
| 6aec1a75c9 | |||
| d28d600833 | |||
| a353eb3185 | |||
| c5735a6953 | |||
| 7930f7fc8a | |||
| 68f4d54619 | |||
| c4f9738589 | |||
| dd916afd1d | |||
| ea5c9e0028 | |||
| eb7c2d7132 | |||
| ee7c50f59b | |||
| 439f59fedc | |||
| c47d839ce3 | |||
| f77c13cbcf | |||
| dbbbd33100 | |||
| 14d13360a8 | |||
| dc862252ba | |||
| e5fe727ccd | |||
| e836bbed0c | |||
| d4438fd215 | |||
| 1550849360 | |||
| 9d1dc4ffca | |||
| 0397fa788d | |||
| 6e5696b0a6 | |||
| 4537341a57 | |||
| c35c74bd4a | |||
| 25735c5e6e | |||
| 41e60bc69e | |||
| 933bdecb3c | |||
| 10e183d96b | |||
| 5429d39f5e | |||
| ff31e7f903 | |||
| 91f4c6bc57 | |||
| c133eb060b | |||
| 7ffc169d8a | |||
| 1b85cc5f58 | |||
| 72ff857fff | |||
| 96d64e77fc | |||
| 6ceae3f161 | |||
| 8e8e27658c | |||
| 9b6ace394a | |||
| 6cfeaa91bf | |||
| 08b208aeaa | |||
| a089b5275b | |||
| 8425cd4371 | |||
| dbdc517b87 | |||
| e271358a27 | |||
| 66262e3fcd | |||
| 5b2b6bdea2 | |||
| c8587de6d9 | |||
| 1f376085f2 | |||
| f28600a7fa | |||
| d59ead87e6 | |||
| 34d91bc800 | |||
| cf9991d8a0 | |||
| 4ffb79d62b | |||
| d9f5edb4fe | |||
| 1b2112430a | |||
| 0a972a23ef | |||
| 6d52724d06 | |||
| 99415c35d3 | |||
| c3f687d439 | |||
| 266edfd6e6 | |||
| d32d5ad91b | |||
| c3481470cb | |||
| 57e88b9abc | |||
| 44ebf53798 | |||
| 145dc72b6b | |||
| b7f3761940 | |||
| ea7c49dfb3 | |||
| 5d6785813a | |||
| a0054aed14 | |||
| 471e6f5216 | |||
| a617eef00e | |||
| 38e700ecd6 | |||
| da1be0e10a | |||
| f49bb12948 | |||
| 02673a3d70 | |||
| 4ddc7345df | |||
| 5d822684c0 | |||
| 69fa15c70a | |||
| 9192067388 | |||
| 2b41e5b857 | |||
| 674680ff14 | |||
| 475bd2ff10 | |||
| 074d1eb155 | |||
| 378393de89 | |||
| 03e61083a7 | |||
| 0b746fce8c | |||
| 5883e710be | |||
| 3d0695a17b | |||
| 4adb76eeb0 | |||
| 4c41076519 | |||
| 77f61d17fd | |||
| 032a84cbcf | |||
| de9851ebcc | |||
| ff78eba927 | |||
| e4c5f6a322 | |||
| 0a78761928 | |||
| 4843043c29 | |||
| 9e1df1fb61 | |||
| 021474cfb0 | |||
| 7d0e68862c | |||
| 653d45dfc6 | |||
| 4a4e1240a4 | |||
| 14ca48a90d | |||
| a02f9804b1 | |||
| c5efc6fbac | |||
| cacd0a1e4e | |||
| 50375099ab | |||
| 6af67ec741 | |||
| c64112c86a | |||
| 0434702d3b | |||
| dd7d1b0bb0 | |||
| 68934a89a4 | |||
| b88a240ec1 | |||
| eaa34f3359 | |||
| febb22e1bc | |||
| 500f3c1223 | |||
| 221e0c7e82 | |||
| ca19f7e397 | |||
| a71ccd3e1a | |||
| d496c70fa8 | |||
| b9868ba52e | |||
| 59bd3fa2ef | |||
| e14d328ed9 | |||
| 36d71292bc | |||
| 2f6e2e7402 | |||
| e959eac6c5 | |||
| 8bedc4dfc6 | |||
| 73563d5db7 | |||
| 3f818069cd | |||
| cdf0b2a426 | |||
| c29ddeb78c | |||
| b81d98cab7 | |||
| 0e45bca5da | |||
| 715e66879f | |||
| 1747e15dc8 | |||
| 6a923a8e1d | |||
| 25a248e95e | |||
| aa7a6b220e | |||
| deb7b68985 | |||
| 633f05f690 | |||
| 73828867da | |||
| 75685c1e0e | |||
| 496ff95236 | |||
| 7e25327832 | |||
| 272c9f50f8 | |||
| 255e07372e | |||
| 279bbfa4db | |||
| a5c829faf5 | |||
| 5fdfaeac5e | |||
| 9beb30e3d5 | |||
| 48582e2eea | |||
| 2e721fb8bf | |||
| f93c1fbfec | |||
| c06e7b6468 | |||
| 22a6d266cb | |||
| 5f8a16401b | |||
| c9be01aa29 | |||
| 4ec058b33c | |||
| 27a5d2a406 | |||
| 58169e26f6 | |||
| fee1f4bbd5 | |||
| 240817acc3 | |||
| db3be87dd8 | |||
| 1665134d6f | |||
| df289ab734 | |||
| f74440ba6f | |||
| a25dbe9fd5 | |||
| 4fff136d6b | |||
| d06f2d5d2e | |||
| 9f68d628d0 | |||
| d64b906dac | |||
| f3e193e68a | |||
| 5640ce9f2b | |||
| 50100eb2f9 | |||
| e478c510b2 | |||
| 7ea558642f | |||
| 493145f7f2 | |||
| 4f72535365 | |||
| 8e3bf80715 | |||
| 6da586d08a | |||
| be53b9c7fb | |||
| 94ed1160a1 | |||
| 859d8d2631 | |||
| 5f3abd73c5 | |||
| d71c8bb6f9 | |||
| a3db13d79c | |||
| 8cb3da66f2 | |||
| 6e07897ac0 | |||
| 726b859f5c | |||
| 651c60707a | |||
| d4fee84603 | |||
| 86539cdf23 | |||
| 69772460b8 | |||
| 6988a83355 | |||
| b6425564c8 | |||
| caf0a9b4c5 | |||
| bd5f433d6e | |||
| 8d9cc721d6 | |||
| cceeffe49d | |||
| fcb8357489 | |||
| ceffd8e675 | |||
| 5aa53521f7 | |||
| d8b559694b | |||
| c82ac04a91 | |||
| 284bdcbf2a | |||
| 7f4df98349 | |||
| aecbcf62df | |||
| 2a817365a6 | |||
| ecf3a00cab | |||
| beb2f3c0d4 | |||
| a65b09981b | |||
| 4ec544e8a9 | |||
| 7e108c5183 | |||
| 72361b157e | |||
| 1cc4d76e4d | |||
| 846d4d0547 | |||
| 751cadd218 | |||
| 3b44adff44 | |||
| 29a02dd98f | |||
| c5e68c4d03 | |||
| 95f7c2a4d9 | |||
| 84412822ff | |||
| 42bb056e66 | |||
| 053e9d2b6a | |||
| c729d75541 | |||
| a9b72d0b7a | |||
| 95a027f284 | |||
| dbba83b28b | |||
| 65abe550f5 | |||
| 531108c25a | |||
| bcf750d451 | |||
| 0a8bfe4c52 | |||
| 0f19bc767a | |||
| 8eb0266874 | |||
| ae5b5ff965 | |||
| 3a0c4bc151 | |||
| 4f5fcb3189 | |||
| 3a2978bbe3 | |||
| a81cc4559b | |||
| 065143c359 | |||
| 1661881127 | |||
| 93aa889414 | |||
| 2a131ab1fb | |||
| 387f42985a | |||
| 6c83ce90bf | |||
| 3d519e874f | |||
| 99cdb3442a | |||
| a6c0fe86c8 | |||
| 828421efe0 | |||
| 21bacb1c95 | |||
| 0d9a3f4b4f | |||
| 76b8534d63 | |||
| 0821fd708e | |||
| b0a9939446 | |||
| 2a64b8f10d | |||
| dc1c457ea4 | |||
| 1f95bc5230 | |||
| 5a06920e5b | |||
| ee0d9e7ed4 | |||
| 30ad3ad4f2 | |||
| c2bd5a8a1b | |||
| 7101d0972d | |||
| 82bbfcdf70 | |||
| b90ac6c09e | |||
| 76d0ff88f1 | |||
| 951afcedeb | |||
| 96de3f0dcc | |||
| 03950eef66 | |||
| 6dd8cb2dad | |||
| aae51d4139 | |||
| 9994a541b1 | |||
| bc3a603ba2 | |||
| 7857377cab | |||
| 0034f43be4 | |||
| c09fc81886 | |||
| 30f72d518d | |||
| 9b86e07152 | |||
| 4e0fb5dc01 | |||
| a392991030 | |||
| ff7ca27fe6 | |||
| 94cd7aaa60 | |||
| 843289d8d7 | |||
| 66cae68e19 | |||
| b38e50396a | |||
| 7888e59117 | |||
| 46e700583d | |||
| fc56c38c45 | |||
| 9594e2c21a | |||
| a8bab5283b | |||
| 1cc799706c | |||
| 5ee8f72652 | |||
| 942f883b91 | |||
| 54b47d44e5 | |||
| f9aaf21f7a | |||
| d79705ca5c | |||
| 55c64d5f0a | |||
| 4ca1c7bb9c | |||
| abc8fda98e | |||
| aaec23d210 | |||
| 0af7b68138 | |||
| ae24eaf8e4 | |||
| f73a07daee | |||
| 89f5bf2e95 | |||
| 8137c1ff95 | |||
| 4b0d9b887e | |||
| 506064cf9a | |||
| 825e25434a | |||
| 32c601d50a | |||
| b88a96237e | |||
| 6c724440d7 | |||
| 71016e63bb | |||
| fb85352ce3 |
@@ -0,0 +1,18 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: [
|
||||||
|
'plugin:vue/vue3-essential',
|
||||||
|
'eslint:recommended',
|
||||||
|
'@vue/eslint-config-typescript',
|
||||||
|
'@vue/eslint-config-prettier/skip-formatting'
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'vue/multi-word-component-names': 'off'
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# This file was auto-generated by the Firebase CLI
|
||||||
|
# https://github.com/firebase/firebase-tools
|
||||||
|
|
||||||
name: Deploy to Firebase Hosting on PR
|
name: Deploy to Firebase Hosting on PR
|
||||||
'on': pull_request
|
'on': pull_request
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
|
/dev-dist
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
@@ -30,6 +31,7 @@ node_modules
|
|||||||
.firebase
|
.firebase
|
||||||
.firebaserc
|
.firebaserc
|
||||||
|
|
||||||
|
# Env
|
||||||
.env
|
.env
|
||||||
|
|
||||||
.fake
|
.fake
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/prettierrc",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"trailingComma": "none"
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/cli-plugin-babel/preset'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"hosting": {
|
"hosting": {
|
||||||
"public": "dist",
|
"public": "dist",
|
||||||
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
|
"ignore": [
|
||||||
|
"firebase.json",
|
||||||
|
"**/.*",
|
||||||
|
"**/node_modules/**"
|
||||||
|
],
|
||||||
"rewrites": [
|
"rewrites": [
|
||||||
{
|
{
|
||||||
"source": "**",
|
"source": "**",
|
||||||
@@ -10,4 +14,3 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="pl">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||||
|
|
||||||
|
<meta name="keywords" content="Stacjownik, TD2, Train Driver 2, stacjownik-td2, stacjownik, td2.info.pl" />
|
||||||
|
<meta name="description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" />
|
||||||
|
|
||||||
|
<title>Stacjownik</title>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||||
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
|
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
|
||||||
|
<meta name="msapplication-TileColor" content="#da532c" />
|
||||||
|
<meta name="theme-color" content="#222222" />
|
||||||
|
|
||||||
|
<link rel="icon" href="favicon-64.png" sizes="64x64" type="image/png" />
|
||||||
|
<link rel="icon" href="favicon-62.png" sizes="62x62" type="image/png" />
|
||||||
|
<link rel="icon" href="favicon-32.png" sizes="32x32" type="image/png" />
|
||||||
|
<link rel="icon" href="favicon-16.png" sizes="16x16" type="image/png" />
|
||||||
|
<link rel="icon" href="favicon.ico" />
|
||||||
|
|
||||||
|
<!-- Static OpenGraph meta -->
|
||||||
|
<meta name="description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" />
|
||||||
|
<meta property="og:url" content="https://stacjownik-td2.web.app/" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:title" content="Stacjownik" />
|
||||||
|
<meta property="og:description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" />
|
||||||
|
<meta property="og:image" content="https://raw.githubusercontent.com/Spythere/api/main/thumbnails/stacjownik.jpg" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta property="og:site_name" content="Stacjownik" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="Stacjownik" />
|
||||||
|
<meta name="twitter:description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" />
|
||||||
|
<meta name="twitter:image" content="https://raw.githubusercontent.com/Spythere/api/main/thumbnails/stacjownik.jpg" />
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500;700&display=swap" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,37 +1,44 @@
|
|||||||
{
|
{
|
||||||
"name": "stacjownik",
|
"name": "stacjownik",
|
||||||
"version": "1.9.9",
|
"version": "1.18.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"dev": "vite",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"deploy-prod": "npm run build && firebase deploy --only hosting:prod",
|
"deploy": "yarn build && firebase deploy --only hosting",
|
||||||
"deploy-dev": "npm run build && firebase deploy --only hosting:dev"
|
"preview": "yarn build && vite preview",
|
||||||
|
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||||
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.12.1",
|
"core-js": "^3.32.2",
|
||||||
"dotenv": "^8.6.0",
|
"dotenv": "^16.3.1",
|
||||||
"firebase": "^9.8.1",
|
"firebase": "^10.4.0",
|
||||||
"howler": "^2.2.1",
|
"howler": "^2.2.4",
|
||||||
"pinia": "^2.0.14",
|
"pinia": "^2.1.6",
|
||||||
"socket.io-client": "^4.4.1",
|
"sass": "^1.67.0",
|
||||||
"vue": "^3.2.34",
|
"socket.io-client": "^4.7.2",
|
||||||
"vue-i18n": "^9.1.6",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.0.0-0",
|
"vue-i18n": "^9.4.1",
|
||||||
"vuex": "^4.0.2"
|
"vue-router": "^4.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.35",
|
"@types/node": "^20.6.2",
|
||||||
"@vue/cli-plugin-babel": "^5.0.4",
|
"@vite-pwa/assets-generator": "^0.0.10",
|
||||||
"@vue/cli-plugin-router": "^5.0.4",
|
"@vitejs/plugin-vue": "^4.3.4",
|
||||||
"@vue/cli-plugin-typescript": "^5.0.4",
|
"axios": "^1.5.0",
|
||||||
"@vue/cli-plugin-vuex": "^5.0.4",
|
"prettier": "^3.0.3",
|
||||||
"@vue/cli-service": "^5.0.4",
|
"typescript": "^5.2.2",
|
||||||
"@vue/compiler-sfc": "^3.1.0",
|
"vite": "^4.4.9",
|
||||||
"axios": "^0.21.1",
|
"vite-plugin-pwa": "^0.16.5",
|
||||||
"sass": "^1.32.13",
|
"vue-tsc": "^1.8.11",
|
||||||
"sass-loader": "^8.0.2",
|
"@vue/eslint-config-prettier": "^8.0.0",
|
||||||
"typescript": "^4.7.3"
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
|
"@vue/tsconfig": "^0.4.0",
|
||||||
|
"eslint": "^8.49.0",
|
||||||
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
|
"@rushstack/eslint-patch": "^1.3.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
|||||||
|
After Width: | Height: | Size: 951 B |
|
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 537 B |
|
Before Width: | Height: | Size: 482 B After Width: | Height: | Size: 482 B |
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
|
Before Width: | Height: | Size: 170 B After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 932 B |
|
After Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 256 B After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect y="-0.00012207" width="60" height="60" fill="#898989"/>
|
||||||
|
<path d="M29.0126 32.4897V10.2511V9.52028H30.4337V10.2511V57.234H29.0126V32.4897Z" fill="#BFBFBF"/>
|
||||||
|
<path d="M26.955 29.3992V32.9949L29.7672 36.9105" stroke="black" stroke-width="0.61183"/>
|
||||||
|
<rect x="29.0051" y="34.0686" width="1.42857" height="22.8196" fill="white"/>
|
||||||
|
<rect x="29.0051" y="34.0686" width="1.42857" height="5.18627" fill="#FF0000"/>
|
||||||
|
<rect x="29.0051" y="54.8137" width="1.42857" height="5.18627" fill="#FF0000"/>
|
||||||
|
<rect x="29.0051" y="44.4412" width="1.42857" height="5.18627" fill="#FF0000"/>
|
||||||
|
<rect x="27.8749" y="31.8649" width="3.75" height="2.17823" fill="white"/>
|
||||||
|
<path d="M33.5 28.5111V8.61545V8.11176H26V28.5111H33.5Z" fill="black"/>
|
||||||
|
<path d="M29.6364 5.00276C27.1289 5.09112 26.2239 7.044 26 8.11176H33.5C33.3134 6.97036 32.1438 4.91439 29.6364 5.00276Z" fill="black"/>
|
||||||
|
<path d="M29.8636 31.6201C32.3711 31.5317 33.2761 29.5789 33.5 28.5111H26C26.1865 29.6525 27.3561 31.7085 29.8636 31.6201Z" fill="black"/>
|
||||||
|
<ellipse cx="29.887" cy="11.8168" rx="1.38696" ry="1.28474" fill="#212121"/>
|
||||||
|
<ellipse cx="29.887" cy="8.0135" rx="1.38696" ry="1.28474" fill="#212121"/>
|
||||||
|
<ellipse cx="29.887" cy="15.6151" rx="1.38696" ry="1.28474" fill="#212121"/>
|
||||||
|
<ellipse cx="29.887" cy="19.6834" rx="1.38696" ry="1.28474" fill="#212121"/>
|
||||||
|
<ellipse cx="29.887" cy="23.7518" rx="1.38696" ry="1.28474" fill="#212121"/>
|
||||||
|
<ellipse cx="29.887" cy="27.8201" rx="1.38696" ry="1.28474" fill="#00FF0A"/>
|
||||||
|
<ellipse cx="29.887" cy="19.769" rx="1.38696" ry="1.28474" fill="#00FF0A"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 632 B |
|
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 398 B |
|
Before Width: | Height: | Size: 938 B After Width: | Height: | Size: 938 B |
|
Before Width: | Height: | Size: 356 B After Width: | Height: | Size: 356 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1020 B |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
|
Before Width: | Height: | Size: 384 B After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
@@ -0,0 +1,18 @@
|
|||||||
|
<svg width="144" height="147" viewBox="0 0 144 147" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_d_1343_19)">
|
||||||
|
<path d="M115.039 101.247C116.397 98.6665 115.405 95.4739 112.824 94.1167C110.243 92.7594 107.05 93.7514 105.693 96.3323L115.039 101.247ZM89.4447 44.0402L94.1179 46.4977L99.0329 37.1513L94.3597 34.6938L89.4447 44.0402ZM105.693 96.3323C95.7398 115.259 72.3278 122.534 53.4008 112.581L48.4858 121.927C72.5746 134.595 102.372 125.336 115.039 101.247L105.693 96.3323ZM53.4008 112.581C34.4739 102.627 27.1993 79.2155 37.1525 60.2885L27.8061 55.3735C15.1383 79.4623 24.397 109.259 48.4858 121.927L53.4008 112.581ZM37.1525 60.2885C47.1057 41.3616 70.5177 34.087 89.4447 44.0402L94.3597 34.6938C70.2709 22.026 40.4738 31.2846 27.8061 55.3735L37.1525 60.2885Z" fill="white"/>
|
||||||
|
<path d="M91.2258 38.7627L101.056 20.0698L116.15 51.8695L81.3956 57.4555L91.2258 38.7627Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d_1343_19" x="18.1328" y="20.0698" width="102.017" height="115.531" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="4"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1343_19"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1343_19" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 863 B After Width: | Height: | Size: 863 B |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" ?><svg enable-background="new 0 0 32 32" id="Glyph" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M27.414,24.586l-5.077-5.077C23.386,17.928,24,16.035,24,14c0-5.514-4.486-10-10-10S4,8.486,4,14 s4.486,10,10,10c2.035,0,3.928-0.614,5.509-1.663l5.077,5.077c0.78,0.781,2.048,0.781,2.828,0 C28.195,26.633,28.195,25.367,27.414,24.586z M7,14c0-3.86,3.14-7,7-7s7,3.14,7,7s-3.14,7-7,7S7,17.86,7,14z" id="XMLID_223_" fill="white" /></svg>
|
||||||
|
After Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 478 B After Width: | Height: | Size: 478 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M23.75 3.75H22.5V1.25H20V3.75H10V1.25H7.5V3.75H6.25C4.875 3.75 3.75 4.875 3.75 6.25V23.75C3.75 25.125 4.875 26.25 6.25 26.25H23.75C25.125 26.25 26.25 25.125 26.25 23.75V6.25C26.25 4.875 25.125 3.75 23.75 3.75ZM23.75 23.75H6.25V11.25H23.75V23.75ZM6.25 8.75V6.25H23.75V8.75H6.25ZM8.75 13.75H21.25V16.25H8.75V13.75ZM8.75 18.75H17.5V21.25H8.75V18.75Z" fill="#F2E147"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 477 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M23.75 3.75H22.5V1.25H20V3.75H10V1.25H7.5V3.75H6.25C4.875 3.75 3.75 4.875 3.75 6.25V23.75C3.75 25.125 4.875 26.25 6.25 26.25H23.75C25.125 26.25 26.25 25.125 26.25 23.75V6.25C26.25 4.875 25.125 3.75 23.75 3.75ZM23.75 23.75H6.25V11.25H23.75V23.75ZM6.25 8.75V6.25H23.75V8.75H6.25ZM8.75 13.75H21.25V16.25H8.75V13.75ZM8.75 18.75H17.5V21.25H8.75V18.75Z" fill="#66FF6C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 477 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M23.75 3.75H22.5V1.25H20V3.75H10V1.25H7.5V3.75H6.25C4.875 3.75 3.75 4.875 3.75 6.25V23.75C3.75 25.125 4.875 26.25 6.25 26.25H23.75C25.125 26.25 26.25 25.125 26.25 23.75V6.25C26.25 4.875 25.125 3.75 23.75 3.75ZM23.75 23.75H6.25V11.25H23.75V23.75ZM6.25 8.75V6.25H23.75V8.75H6.25ZM8.75 13.75H21.25V16.25H8.75V13.75ZM8.75 18.75H17.5V21.25H8.75V18.75Z" fill="#898989"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 477 B |
|
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -1,54 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="pl">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
||||||
|
|
||||||
<meta name="keywords" content="Stacjownik, TD2, Train Driver 2, stacjownik-td2" />
|
|
||||||
<meta name="description" content="Automatycznie odświeżana strona wyświetlająca stacje w Train Driver 2!" />
|
|
||||||
|
|
||||||
<title>Stacjownik</title>
|
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
|
||||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c" />
|
|
||||||
<meta name="theme-color" content="#ffffff" />
|
|
||||||
|
|
||||||
<link rel="icon" href="favicon-64.png" sizes="64x64" type="image/png" />
|
|
||||||
<link rel="icon" href="favicon-32.png" sizes="32x32" type="image/png" />
|
|
||||||
<link rel="icon" href="favicon-62.png" sizes="62x62" type="image/png" />
|
|
||||||
<link rel="icon" href="favicon-16.png" sizes="16x16" type="image/png" />
|
|
||||||
<link rel="icon" href="favicon.ico" />
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;700&display=swap" rel="stylesheet" />
|
|
||||||
|
|
||||||
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const firebaseConfig = {
|
|
||||||
apiKey: 'AIzaSyBI36X2-p7vU1flxoJdCEc0noByyTe1mpw',
|
|
||||||
authDomain: 'stacjownik-td2.firebaseapp.com',
|
|
||||||
databaseURL: 'https://stacjownik-td2.firebaseio.com',
|
|
||||||
projectId: 'stacjownik-td2',
|
|
||||||
storageBucket: 'stacjownik-td2.appspot.com',
|
|
||||||
};
|
|
||||||
|
|
||||||
firebase.initializeApp(firebaseConfig);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<strong
|
|
||||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please
|
|
||||||
enable it to continue.</strong
|
|
||||||
>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "",
|
"name": "Stacjownik TD2",
|
||||||
"short_name": "",
|
"short_name": "Stacjownik",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#ffffff",
|
"theme_color": "#ffc014",
|
||||||
"background_color": "#ffffff",
|
"background_color": "#4d4d4d",
|
||||||
"display": "standalone"
|
"display": "standalone",
|
||||||
|
"start_url": "."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
@import './styles/responsive.scss';
|
@import './styles/responsive.scss';
|
||||||
@import './styles/variables.scss';
|
@import './styles/variables.scss';
|
||||||
@import './styles/global.scss';
|
@import './styles/global.scss';
|
||||||
@import './styles/scenery_status.scss';
|
|
||||||
|
|
||||||
// VUE ROUTE CHANGE ANIMATION
|
// VUE ROUTE CHANGE ANIMATION
|
||||||
.view-anim {
|
.view-anim {
|
||||||
@@ -17,22 +16,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-anim {
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active {
|
||||||
|
transition: all $animDuration $animType;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-enter-from,
|
||||||
|
&-leave-to {
|
||||||
|
transform: translateY(-25%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.route {
|
.route {
|
||||||
margin: 0 0.2em;
|
margin: 0 0.2em;
|
||||||
|
|
||||||
&-active {
|
&-active,
|
||||||
|
&[data-active='true'] {
|
||||||
color: $accentCol;
|
color: $accentCol;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// APP
|
// APP
|
||||||
.app {
|
#app {
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
@include smallScreen() {
|
@include smallScreen() {
|
||||||
font-size: calc(0.4rem + 1.4vw);
|
font-size: calc(0.65rem + 0.8vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screenLandscape() {
|
||||||
|
font-size: calc(0.45rem + 0.8vw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +58,8 @@
|
|||||||
.app_container {
|
.app_container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
height: 100vh;
|
|
||||||
min-height: 800px;
|
min-height: 100vh;
|
||||||
|
|
||||||
header {
|
header {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -68,168 +86,16 @@
|
|||||||
border-radius: 0 0 1em 1em;
|
border-radius: 0 0 1em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error icon
|
|
||||||
.wip-alert {
|
|
||||||
padding: 0 0.5em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-error {
|
|
||||||
width: 13em;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HEADER
|
|
||||||
.app_header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
background-color: $primaryCol;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
&_body {
|
|
||||||
max-width: 21em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
width: 1350px;
|
|
||||||
padding: 0.5em 0.3em 0 0.3em;
|
|
||||||
border-radius: 0 0 1em 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_brand {
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&_info {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_links {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
border-radius: 0.7em;
|
|
||||||
|
|
||||||
font-size: 1.25em;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_icons {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: flex-end;
|
|
||||||
padding: 0.5em 0.5em;
|
|
||||||
|
|
||||||
@include smallScreen() {
|
|
||||||
right: auto;
|
|
||||||
left: 0.75em;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ICONS
|
|
||||||
.icons {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&-top {
|
|
||||||
img {
|
|
||||||
width: 2.5em;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-bottom {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin-left: 0.6em;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 1.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include smallScreen() {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin: 0.25em 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// COUNTER
|
|
||||||
.info_counter {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin: 0 0.15em;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 1.35em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// REGION SELECTION
|
|
||||||
.info_region {
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.select-box_content button {
|
|
||||||
background-color: transparent;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 0.1em 0.5em;
|
|
||||||
color: paleturquoise;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FOOTER
|
// FOOTER
|
||||||
footer.app_footer {
|
footer.app_footer {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 1.1em;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
|
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
background: #111;
|
background: #111;
|
||||||
|
|||||||
@@ -1,71 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app">
|
|
||||||
<div class="app_container">
|
<div class="app_container">
|
||||||
<!-- <div class="wip-alert">
|
<transition name="modal-anim">
|
||||||
<img class="icon-error" :src="iconError" alt="error" />
|
<keep-alive>
|
||||||
<h2>Stacjownik tymczasowo nieaktywny!</h2>
|
<TrainModal v-if="store.chosenModalTrainId" />
|
||||||
<p>Absolutny zakaz wjazdu!</p>
|
</keep-alive>
|
||||||
</div> -->
|
</transition>
|
||||||
<header class="app_header">
|
|
||||||
<div class="header_container">
|
|
||||||
<div class="header_icons">
|
|
||||||
<span class="icons-top">
|
|
||||||
<img :src="icons.pl" alt="icon-pl" @click="changeLang('en')" v-if="currentLang == 'pl'" />
|
|
||||||
<img :src="icons.en" alt="icon-en" @click="changeLang('pl')" v-else />
|
|
||||||
</span>
|
|
||||||
<span class="icons-bottom">
|
|
||||||
<a href="https://www.paypal.com/paypalme/spythere" target="_blank">
|
|
||||||
<img :src="icons.dollar" alt="icon paypal" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://discord.gg/x2mpNN3svk" target="_blank">
|
<AppHeader :current-lang="currentLang" @change-lang="changeLang" />
|
||||||
<img :src="icons.discord" alt="icon discord" />
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="header_body">
|
|
||||||
<status-indicator />
|
|
||||||
<span class="header_brand">
|
|
||||||
<img :src="brand_logo" alt="Stacjownik" />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="header_info">
|
|
||||||
<Clock />
|
|
||||||
|
|
||||||
<div class="info_counter">
|
|
||||||
<img src="@/assets/icon-dispatcher.svg" alt="icon dispatcher" />
|
|
||||||
<span class="text--primary">{{ onlineDispatchers.length }}</span>
|
|
||||||
<span class="text--grayed"> / </span>
|
|
||||||
<span class="text--primary">{{ trainList.length }}</span>
|
|
||||||
<img src="@/assets/icon-train.svg" alt="icon train" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="info_region">
|
|
||||||
<SelectBox :itemList="computedRegions" :defaultItemIndex="0" @selected="changeRegion" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="header_links">
|
|
||||||
<router-link class="route" active-class="route-active" to="/" exact>
|
|
||||||
{{ $t('app.sceneries') }}
|
|
||||||
</router-link>
|
|
||||||
/
|
|
||||||
<router-link class="route" active-class="route-active" to="/trains">{{ $t('app.trains') }}</router-link>
|
|
||||||
/
|
|
||||||
<router-link class="route" active-class="route-active" to="/journal">
|
|
||||||
{{ $t('app.journal') }}
|
|
||||||
</router-link>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="app_main">
|
<main class="app_main">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<!-- <transition name="view-anim" mode="out-in"> -->
|
<keep-alive exclude="JournalView">
|
||||||
<keep-alive>
|
<component :is="Component" :key="$route.name" />
|
||||||
<component :is="Component" :key="$route.path" />
|
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</router-view>
|
</router-view>
|
||||||
</main>
|
</main>
|
||||||
@@ -73,120 +19,99 @@
|
|||||||
<footer class="app_footer">
|
<footer class="app_footer">
|
||||||
©
|
©
|
||||||
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
|
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
|
||||||
{{ new Date().getUTCFullYear() }} | v{{ VERSION }}
|
{{ new Date().getUTCFullYear() }} |
|
||||||
|
<a :href="releaseURL" target="_blank">v{{ VERSION }}{{ isOnProductionHost ? '' : 'dev' }}</a>
|
||||||
|
<br />
|
||||||
|
<a href="https://discord.gg/x2mpNN3svk">
|
||||||
|
<img src="/images/icon-discord.png" alt="" /> <b>{{ $t('footer.discord') }}</b>
|
||||||
|
</a>
|
||||||
|
|
||||||
<div style="display: none">∫ ukryta taktyczna całka do programowania w HTMLu</div>
|
<div style="display: none">∫ ukryta taktyczna całka do programowania w HTMLu</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, provide, ref } from 'vue';
|
import { defineComponent, watch } from 'vue';
|
||||||
|
|
||||||
import Clock from '@/components/App/Clock.vue';
|
import Clock from './components/App/Clock.vue';
|
||||||
import StorageManager from '@/scripts/managers/storageManager';
|
|
||||||
|
|
||||||
import packageInfo from '.././package.json';
|
import packageInfo from '.././package.json';
|
||||||
import options from '@/data/options.json';
|
|
||||||
|
|
||||||
import StatusIndicator from '@/components/App/StatusIndicator.vue';
|
|
||||||
import SelectBox from '@/components/Global/SelectBox.vue';
|
|
||||||
import { useStore } from './store/store';
|
import { useStore } from './store/store';
|
||||||
|
import StatusIndicator from './components/App/StatusIndicator.vue';
|
||||||
|
import SelectBox from './components/Global/SelectBox.vue';
|
||||||
|
import TrainModal from './components/Global/TrainModal.vue';
|
||||||
|
import StorageManager from './scripts/managers/storageManager';
|
||||||
|
import AppHeader from './components/App/AppHeader.vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
Clock,
|
Clock,
|
||||||
StatusIndicator,
|
StatusIndicator,
|
||||||
SelectBox,
|
SelectBox,
|
||||||
},
|
TrainModal,
|
||||||
|
AppHeader
|
||||||
setup() {
|
|
||||||
const store = useStore();
|
|
||||||
store.connectToAPI();
|
|
||||||
|
|
||||||
const isFilterCardVisible = ref(false);
|
|
||||||
|
|
||||||
provide('isFilterCardVisible', isFilterCardVisible);
|
|
||||||
|
|
||||||
return {
|
|
||||||
store,
|
|
||||||
isFilterCardVisible,
|
|
||||||
onlineDispatchers: computed(() =>
|
|
||||||
store.stationList.filter((station) => station.onlineInfo && station.onlineInfo.region == store.region.id)
|
|
||||||
),
|
|
||||||
|
|
||||||
dispatcherDataStatus: store.dataStatuses.dispatchers,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
trainList() {
|
|
||||||
return this.store.trainList.filter((train) => train.online);
|
|
||||||
},
|
|
||||||
|
|
||||||
computedRegions() {
|
|
||||||
return this.options.regions.map((region) => {
|
|
||||||
const regionStationCount =
|
|
||||||
this.store.apiData.stations?.filter((station) => station.region == region.id && station.isOnline).length || 0;
|
|
||||||
const regionTrainCount = this.store.apiData.trains?.filter((train) => train.region == region.id && train.online).length || 0;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: region.id,
|
|
||||||
value: `${region.value} <div class='text--grayed'>${regionStationCount} / ${regionTrainCount}</div>`,
|
|
||||||
selectedValue: region.value,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
VERSION: packageInfo.version,
|
VERSION: packageInfo.version,
|
||||||
updateModalVisible: false,
|
store: useStore(),
|
||||||
hasReleaseNotes: false,
|
|
||||||
options,
|
|
||||||
|
|
||||||
currentLang: 'pl',
|
currentLang: 'pl',
|
||||||
|
releaseURL: '',
|
||||||
brand_logo: require('@/assets/stacjownik-header-logo.svg'),
|
isOnProductionHost: location.hostname == 'stacjownik-td2.web.app'
|
||||||
|
|
||||||
icons: {
|
|
||||||
en: require('@/assets/icon-en.jpg'),
|
|
||||||
pl: require('@/assets/icon-pl.svg'),
|
|
||||||
error: require('@/assets/icon-error.svg'),
|
|
||||||
dollar: require('@/assets/icon-dollar.svg'),
|
|
||||||
dispatcher: require('@/assets/icon-dispatcher.svg'),
|
|
||||||
train: require('@/assets/icon-train.svg'),
|
|
||||||
discord: require('@/assets/icon-discord.png'),
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.loadLang();
|
this.loadLang();
|
||||||
|
this.store.connectToAPI();
|
||||||
|
|
||||||
|
this.store.isOffline = !window.navigator.onLine;
|
||||||
|
|
||||||
|
window.addEventListener('offline', () => {
|
||||||
|
this.store.isOffline = true;
|
||||||
|
|
||||||
|
this.store.apiData = {
|
||||||
|
stations: [],
|
||||||
|
dispatchers: [],
|
||||||
|
trains: [],
|
||||||
|
connectedSocketCount: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
this.store.setStatuses();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('online', () => {
|
||||||
|
this.store.isOffline = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
if (StorageManager.getStringValue('version') != this.VERSION) {
|
this.setReleaseURL();
|
||||||
StorageManager.setStringValue('version', this.VERSION);
|
|
||||||
|
|
||||||
if (this.hasReleaseNotes) StorageManager.setBooleanValue('version_notes_read', false);
|
watch(
|
||||||
|
() => this.store.blockScroll,
|
||||||
|
(value) => {
|
||||||
|
if (value) document.body.classList.add('no-scroll');
|
||||||
|
else document.body.classList.remove('no-scroll');
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
this.updateModalVisible = this.hasReleaseNotes && !StorageManager.getBooleanValue('version_notes_read');
|
watch: {
|
||||||
|
'$route.query.region': {
|
||||||
this.updateToNewestVersion();
|
immediate: true,
|
||||||
|
handler(regionQuery: string) {
|
||||||
|
if (regionQuery) {
|
||||||
|
this.store.region.id = regionQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggleUpdateModal() {
|
|
||||||
this.updateModalVisible = !this.updateModalVisible;
|
|
||||||
StorageManager.setBooleanValue('version_notes_read', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
changeRegion(region: { id: string; value: string }) {
|
|
||||||
this.store.changeRegion(region);
|
|
||||||
},
|
|
||||||
|
|
||||||
changeLang(lang: string) {
|
changeLang(lang: string) {
|
||||||
this.$i18n.locale = lang;
|
this.$i18n.locale = lang;
|
||||||
this.currentLang = lang;
|
this.currentLang = lang;
|
||||||
@@ -194,12 +119,18 @@ export default defineComponent({
|
|||||||
StorageManager.setStringValue('lang', lang);
|
StorageManager.setStringValue('lang', lang);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateToNewestVersion() {
|
async setReleaseURL() {
|
||||||
if (!StorageManager.isRegistered('unavailable-status')) {
|
try {
|
||||||
StorageManager.setBooleanValue('unavailable-status', true);
|
const releaseData = await (
|
||||||
StorageManager.setBooleanValue('ending-status', true);
|
await axios.get('https://api.github.com/repos/Spythere/stacjownik/releases/latest')
|
||||||
StorageManager.setBooleanValue('no-space-status', true);
|
).data;
|
||||||
StorageManager.setBooleanValue('afk-status', true);
|
|
||||||
|
if (!releaseData) return;
|
||||||
|
|
||||||
|
this.releaseURL = releaseData.html_url;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Wystąpił błąd podczas pobierania danych z API GitHuba: ${error}`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -219,8 +150,8 @@ export default defineComponent({
|
|||||||
this.changeLang('en');
|
this.changeLang('en');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="60" height="60" fill="#898989"/>
|
|
||||||
<path d="M30.5 6.04878H35.2195" stroke="#BFBFBF"/>
|
|
||||||
<path d="M27.9024 4.00303C25.2115 4.10008 24.2403 6.24494 24 7.41767H32.0488C31.8486 6.16406 30.5934 3.90598 27.9024 4.00303Z" fill="black"/>
|
|
||||||
<path d="M33.0244 29.6688V5.47793V4.68292H34.4878V5.47793V56.5854H33.0244V32.5H27.5V28.5V28.0163L28.5 28V31.5L31.9268 31.5447H33.0244V29.6688Z" fill="#BFBFBF"/>
|
|
||||||
<path d="M28.1463 29.2683C30.8373 29.1712 31.8085 27.0264 32.0488 25.8537H24C24.2002 27.1073 25.4554 29.3654 28.1463 29.2683Z" fill="black"/>
|
|
||||||
<path d="M32.0488 25.8537V7.86993V7.41464H24V25.8537H32.0488Z" fill="black"/>
|
|
||||||
<path d="M25 26V29.5L33.8781 44.9756" stroke="black"/>
|
|
||||||
<rect x="33.0244" y="31.5447" width="1.46341" height="25.0407" fill="white"/>
|
|
||||||
<rect x="33.0244" y="31.5447" width="1.46341" height="5.69106" fill="#FF0000"/>
|
|
||||||
<rect x="33.0244" y="42.9268" width="1.46341" height="5.69106" fill="#FF0000"/>
|
|
||||||
<rect x="33.0244" y="54.3089" width="1.46341" height="5.69106" fill="#FF0000"/>
|
|
||||||
<ellipse cx="27.9024" cy="7.40022" rx="1.46341" ry="1.40022" fill="#212121"/>
|
|
||||||
<ellipse cx="27.9024" cy="11.8343" rx="1.46341" ry="1.40022" fill="#212121"/>
|
|
||||||
<ellipse cx="27.9024" cy="16.2683" rx="1.46341" ry="1.40022" fill="#FF0000"/>
|
|
||||||
<ellipse cx="27.9024" cy="20.7023" rx="1.46341" ry="1.40022" fill="#212121"/>
|
|
||||||
<ellipse cx="27.9024" cy="25.1364" rx="1.46341" ry="1.40022" fill="#212121"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,249 @@
|
|||||||
|
<template>
|
||||||
|
<header class="app_header">
|
||||||
|
<div class="header_container">
|
||||||
|
<div class="header_icons">
|
||||||
|
<span class="icons-top">
|
||||||
|
<img
|
||||||
|
src="/images/icon-pl.svg"
|
||||||
|
alt="icon-pl"
|
||||||
|
@click="changeLang('en')"
|
||||||
|
v-if="currentLang == 'pl'"
|
||||||
|
/>
|
||||||
|
<img src="/images/icon-en.jpg" alt="icon-en" @click="changeLang('pl')" v-else />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header_body">
|
||||||
|
<StatusIndicator />
|
||||||
|
|
||||||
|
<span class="header_brand">
|
||||||
|
<router-link to="/">
|
||||||
|
<img src="/images/stacjownik-header-logo.svg" alt="Stacjownik" />
|
||||||
|
</router-link>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="header_info">
|
||||||
|
<Clock />
|
||||||
|
|
||||||
|
<div class="info_counter">
|
||||||
|
<img src="/images/icon-dispatcher.svg" alt="icon dispatcher" />
|
||||||
|
<span class="text--primary">{{ onlineDispatchersCount }}</span>
|
||||||
|
|
||||||
|
<!-- <span class="g-tooltip">
|
||||||
|
<b class="text--primary">{{ factorU }}U</b>
|
||||||
|
<div class="content">Test</div>
|
||||||
|
</span> -->
|
||||||
|
|
||||||
|
<span class="text--grayed"> / </span>
|
||||||
|
<span class="text--primary">{{ onlineTrainsCount }}</span>
|
||||||
|
<img src="/images/icon-train.svg" alt="icon train" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="info_region">
|
||||||
|
<SelectBox :itemList="computedRegions" :defaultItemIndex="0" @selected="changeRegion" />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="header_links">
|
||||||
|
<router-link class="route" active-class="route-active" to="/" exact>
|
||||||
|
{{ $t('app.sceneries') }}
|
||||||
|
</router-link>
|
||||||
|
/
|
||||||
|
<router-link class="route" active-class="route-active" to="/trains">{{
|
||||||
|
$t('app.trains')
|
||||||
|
}}</router-link>
|
||||||
|
/
|
||||||
|
<router-link
|
||||||
|
class="route"
|
||||||
|
active-class="route-active"
|
||||||
|
:data-active="$route.path.startsWith('/journal')"
|
||||||
|
to="/journal"
|
||||||
|
>
|
||||||
|
{{ $t('app.journal') }}
|
||||||
|
</router-link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
|
import options from '../../data/options.json';
|
||||||
|
import SelectBox from '../Global/SelectBox.vue';
|
||||||
|
import StatusIndicator from './StatusIndicator.vue';
|
||||||
|
import Clock from './Clock.vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
emits: ['changeLang'],
|
||||||
|
props: {
|
||||||
|
currentLang: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
store: useStore()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
changeRegion(region: { id: string; value: string }) {
|
||||||
|
this.store.changeRegion(region);
|
||||||
|
},
|
||||||
|
|
||||||
|
changeLang(lang: string) {
|
||||||
|
this.$emit('changeLang', lang);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
onlineTrainsCount() {
|
||||||
|
return this.store.trainList.filter((train) => train.online).length;
|
||||||
|
},
|
||||||
|
|
||||||
|
onlineDispatchersCount() {
|
||||||
|
return this.store.onlineSceneryList.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
factorU() {
|
||||||
|
return this.onlineDispatchersCount == 0
|
||||||
|
? '-'
|
||||||
|
: (this.onlineTrainsCount / this.onlineDispatchersCount).toFixed(2);
|
||||||
|
},
|
||||||
|
|
||||||
|
computedRegions() {
|
||||||
|
return options.regions.map((region) => {
|
||||||
|
const regionStationCount =
|
||||||
|
this.store.apiData.stations?.filter(
|
||||||
|
(station) => station.region == region.id && station.isOnline
|
||||||
|
).length || 0;
|
||||||
|
const regionTrainCount =
|
||||||
|
this.store.apiData.trains?.filter((train) => train.region == region.id && train.online)
|
||||||
|
.length || 0;
|
||||||
|
return {
|
||||||
|
id: region.id,
|
||||||
|
value: `${region.value} <div class='text--grayed'>${regionStationCount} / ${regionTrainCount}</div>`,
|
||||||
|
selectedValue: region.value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: { SelectBox, StatusIndicator, Clock }
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../styles/variables.scss';
|
||||||
|
@import '../../styles/responsive.scss';
|
||||||
|
|
||||||
|
// HEADER
|
||||||
|
.app_header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
background-color: $primaryCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
&_body {
|
||||||
|
position: relative;
|
||||||
|
max-width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
border-radius: 0 0 1em 1em;
|
||||||
|
|
||||||
|
@include smallScreen {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&_brand {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&_info {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
font-size: 1.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
border-radius: 0.7em;
|
||||||
|
|
||||||
|
font-size: 1.25em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_icons {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
@include smallScreen {
|
||||||
|
transform: translateX(85%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICONS
|
||||||
|
.icons-top {
|
||||||
|
img {
|
||||||
|
width: 2.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// COUNTER
|
||||||
|
.info_counter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin: 0 0.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 1.35em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// REGION SELECTION
|
||||||
|
.info_region {
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.select-box_content button {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0.1em 0.5em;
|
||||||
|
color: paleturquoise;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,32 +2,33 @@
|
|||||||
<div class="clock">{{ computedDate }}</div>
|
<div class="clock">{{ computedDate }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref } from "vue";
|
import { computed, defineComponent, ref } from 'vue';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "clock",
|
name: 'VueClock',
|
||||||
data: () => ({
|
data: () => ({
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now()
|
||||||
}),
|
}),
|
||||||
setup() {
|
setup() {
|
||||||
let timestamp = ref(Date.now());
|
let timestamp = ref(Date.now());
|
||||||
|
|
||||||
const computedDate = computed(() => new Date(timestamp.value).toLocaleString("pl-PL", {
|
const computedDate = computed(() =>
|
||||||
hour: "2-digit",
|
new Date(timestamp.value).toLocaleString('pl-PL', {
|
||||||
minute: "2-digit",
|
hour: '2-digit',
|
||||||
second: "2-digit",
|
minute: '2-digit',
|
||||||
}));
|
second: '2-digit'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
setInterval(() => (timestamp.value = Date.now()), 1000);
|
setInterval(() => (timestamp.value = Date.now()), 1000);
|
||||||
|
|
||||||
return { computedDate }
|
return { computedDate };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "../../styles/responsive.scss";
|
@import '../../styles/responsive.scss';
|
||||||
|
|
||||||
.clock {
|
.clock {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="loading">{{message}}</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from "@vue/runtime-core";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: ["message"],
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.loading {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
min-height: 100%;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
|
|
||||||
font-size: calc(0.75rem + 1vw);
|
|
||||||
|
|
||||||
color: #fdc62f;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -43,7 +43,13 @@
|
|||||||
<g v-if="greenBlinkLight" filter="url(#filter0_d_843_28)">
|
<g v-if="greenBlinkLight" filter="url(#filter0_d_843_28)">
|
||||||
<circle cx="15" cy="17" r="7" fill="#00FF0A" />
|
<circle cx="15" cy="17" r="7" fill="#00FF0A" />
|
||||||
|
|
||||||
<animate attributeType="XML" attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite" />
|
<animate
|
||||||
|
attributeType="XML"
|
||||||
|
attributeName="opacity"
|
||||||
|
values="1;0;1"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g v-if="redTopLight" filter="url(#filter1_d_843_28)">
|
<g v-if="redTopLight" filter="url(#filter1_d_843_28)">
|
||||||
@@ -56,7 +62,13 @@
|
|||||||
<g v-if="redBottomLight" filter="url(#filter3_d_843_28)">
|
<g v-if="redBottomLight" filter="url(#filter3_d_843_28)">
|
||||||
<circle cx="15" cy="74" r="7" fill="#F40000" />
|
<circle cx="15" cy="74" r="7" fill="#F40000" />
|
||||||
|
|
||||||
<animate attributeType="XML" attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite" />
|
<animate
|
||||||
|
attributeType="XML"
|
||||||
|
attributeName="opacity"
|
||||||
|
values="1;0;1"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
@@ -82,7 +94,12 @@
|
|||||||
<feComposite in2="hardAlpha" operator="out" />
|
<feComposite in2="hardAlpha" operator="out" />
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 1 0 0 0 0 0.04 0 0 0 1 0" />
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 1 0 0 0 0 0.04 0 0 0 1 0" />
|
||||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_843_28" result="shape" />
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="effect1_dropShadow_843_28"
|
||||||
|
result="shape"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
<filter
|
<filter
|
||||||
id="filter1_d_843_28"
|
id="filter1_d_843_28"
|
||||||
@@ -104,7 +121,12 @@
|
|||||||
<feGaussianBlur stdDeviation="2.5" />
|
<feGaussianBlur stdDeviation="2.5" />
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 0.770833 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" />
|
<feColorMatrix type="matrix" values="0 0 0 0 0.770833 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" />
|
||||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_843_28" result="shape" />
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="effect1_dropShadow_843_28"
|
||||||
|
result="shape"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
<filter
|
<filter
|
||||||
id="filter2_d_843_28"
|
id="filter2_d_843_28"
|
||||||
@@ -126,7 +148,12 @@
|
|||||||
<feGaussianBlur stdDeviation="2.5" />
|
<feGaussianBlur stdDeviation="2.5" />
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.72 0 0 0 0 0 0 0 0 1 0" />
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.72 0 0 0 0 0 0 0 0 1 0" />
|
||||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_843_28" result="shape" />
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="effect1_dropShadow_843_28"
|
||||||
|
result="shape"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
<filter
|
<filter
|
||||||
id="filter3_d_843_28"
|
id="filter3_d_843_28"
|
||||||
@@ -148,7 +175,12 @@
|
|||||||
<feGaussianBlur stdDeviation="2.5" />
|
<feGaussianBlur stdDeviation="2.5" />
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 0.770833 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" />
|
<feColorMatrix type="matrix" values="0 0 0 0 0.770833 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" />
|
||||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_843_28" />
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_843_28" result="shape" />
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="effect1_dropShadow_843_28"
|
||||||
|
result="shape"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
@@ -161,29 +193,26 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DataStatus } from '@/scripts/enums/DataStatus';
|
import { defineComponent } from 'vue';
|
||||||
import { StoreData } from '@/scripts/interfaces/StoreData';
|
import { DataStatus } from '../../scripts/enums/DataStatus';
|
||||||
import { useStore } from '@/store/store';
|
import { useStore } from '../../store/store';
|
||||||
import { StoreState } from '@/store/storeTypes';
|
import { StoreState } from '../../scripts/interfaces/store/storeTypes';
|
||||||
import { computed, defineComponent, watch } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
icons: {
|
|
||||||
statusIndicator: require('@/assets/signal-status-indicator.svg'),
|
|
||||||
},
|
|
||||||
tooltipActive: false,
|
tooltipActive: false,
|
||||||
indicator: {
|
indicator: {
|
||||||
|
offline: false,
|
||||||
status: DataStatus.Loading,
|
status: DataStatus.Loading,
|
||||||
message: 'data-status.S3',
|
message: 'data-status.S3'
|
||||||
},
|
},
|
||||||
|
|
||||||
greenLight: false,
|
greenLight: false,
|
||||||
greenBlinkLight: false,
|
greenBlinkLight: false,
|
||||||
redTopLight: false,
|
redTopLight: false,
|
||||||
orangeLight: false,
|
orangeLight: false,
|
||||||
redBottomLight: false,
|
redBottomLight: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -196,6 +225,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
dataStatus: store.dataStatuses,
|
dataStatus: store.dataStatuses,
|
||||||
|
store
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -209,6 +239,13 @@ export default defineComponent({
|
|||||||
const trainsDataStatus = statuses.trains;
|
const trainsDataStatus = statuses.trains;
|
||||||
const dispatcherDataStatus = statuses.dispatchers;
|
const dispatcherDataStatus = statuses.dispatchers;
|
||||||
|
|
||||||
|
if (this.store.isOffline) {
|
||||||
|
this.setSignalStatus(DataStatus.Initialized);
|
||||||
|
this.indicator.status = DataStatus.Initialized;
|
||||||
|
this.indicator.message = 'data-status.S1-offline';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (connectionStatus == DataStatus.Error) {
|
if (connectionStatus == DataStatus.Error) {
|
||||||
this.setSignalStatus(connectionStatus);
|
this.setSignalStatus(connectionStatus);
|
||||||
this.indicator.status = connectionStatus;
|
this.indicator.status = connectionStatus;
|
||||||
@@ -243,8 +280,8 @@ export default defineComponent({
|
|||||||
this.indicator.status = DataStatus.Loaded;
|
this.indicator.status = DataStatus.Loaded;
|
||||||
this.indicator.message = 'data-status.S2';
|
this.indicator.message = 'data-status.S2';
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
@@ -255,6 +292,10 @@ export default defineComponent({
|
|||||||
this.orangeLight = false;
|
this.orangeLight = false;
|
||||||
this.redBottomLight = false;
|
this.redBottomLight = false;
|
||||||
|
|
||||||
|
if (status == DataStatus.Initialized) {
|
||||||
|
this.redTopLight = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == DataStatus.Loaded) {
|
if (status == DataStatus.Loaded) {
|
||||||
this.greenLight = true;
|
this.greenLight = true;
|
||||||
}
|
}
|
||||||
@@ -271,8 +312,8 @@ export default defineComponent({
|
|||||||
if (status == DataStatus.Loading) {
|
if (status == DataStatus.Loading) {
|
||||||
this.greenBlinkLight = true;
|
this.greenBlinkLight = true;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -294,10 +335,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
.status-indicator {
|
.status-indicator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transform: translateX(12em);
|
right: 0;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
|
transform: translateX(1.5em);
|
||||||
}
|
}
|
||||||
|
|
||||||
.indicator {
|
.indicator {
|
||||||
@@ -322,7 +364,7 @@ export default defineComponent({
|
|||||||
background-color: #171717;
|
background-color: #171717;
|
||||||
border-radius: 0.75em;
|
border-radius: 0.75em;
|
||||||
|
|
||||||
min-width: 13em;
|
width: 13em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: none;
|
overflow: none;
|
||||||
|
|
||||||
@@ -346,22 +388,16 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
@include midScreen() {
|
@include midScreen() {
|
||||||
left: 50%;
|
left: auto;
|
||||||
top: 100%;
|
right: 200%;
|
||||||
|
|
||||||
transform: translate(-50%, 0);
|
|
||||||
margin-left: 0;
|
|
||||||
margin-top: 0.75em;
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
border-left: 10px solid transparent;
|
|
||||||
border-right: 10px solid transparent;
|
border-right: 10px solid transparent;
|
||||||
border-bottom: 10px solid #171717;
|
border-left: 12px solid #171717;
|
||||||
|
right: 0;
|
||||||
|
left: auto;
|
||||||
|
|
||||||
top: 0;
|
transform: translate(100%, -50%);
|
||||||
left: 50%;
|
|
||||||
|
|
||||||
transform: translate(-50%, -100%);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section
|
|
||||||
class="updates card"
|
|
||||||
v-if="cardOpen"
|
|
||||||
>
|
|
||||||
<h2>Ostatnie aktualizacje w Stacjowniku</h2>
|
|
||||||
<p>Tutaj będą pojawiać się informacje o kolejnych nowościach na stronie :)</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(update, i) in updates"
|
|
||||||
:key="i"
|
|
||||||
>
|
|
||||||
<div>{{update.date}}</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
v-for="(line, l) in content"
|
|
||||||
:key="l"
|
|
||||||
>{{line}}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from "@vue/runtime-core";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
updates: {
|
|
||||||
date: "08/08/20",
|
|
||||||
content: [
|
|
||||||
"Lekko odświeżono wygląd strony, dodano nowy widok z pociągami online",
|
|
||||||
"Dodano animacje zmieniania widoków (zakładek)",
|
|
||||||
"Dodano przycisk zamykający kartę z filtrami",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<button class="action-btn">
|
<button class="action-btn btn--filled">
|
||||||
<div class="button_content">
|
<div class="button_content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -7,55 +7,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({});
|
export default defineComponent({});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "../../styles/variables";
|
@import '../../styles/variables';
|
||||||
@import "../../styles/responsive";
|
@import '../../styles/responsive';
|
||||||
|
|
||||||
.action-btn {
|
|
||||||
background: #333;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
color: #bdbdbd;
|
|
||||||
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
padding: 0.35em 0.65em;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&.outlined {
|
|
||||||
border: 1px solid white;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 1.25em;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 0.35em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 1em;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.open {
|
|
||||||
color: $accentCol;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
color: $accentCol;
|
|
||||||
background: #5c5c5c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button_content {
|
.button_content {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<button
|
||||||
|
class="btn btn--option btn--load-data"
|
||||||
|
v-if="!scrollNoMoreData && scrollDataLoaded && list.length >= 15"
|
||||||
|
@click="addHistoryData"
|
||||||
|
>
|
||||||
|
{{ $t('journal.load-data') }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { PropType, defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
scrollNoMoreData: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollDataLoaded: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
list: {
|
||||||
|
type: Array as PropType<any[]>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['addHistoryData'],
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
addHistoryData() {
|
||||||
|
this.$emit('addHistoryData');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -12,7 +12,7 @@ import { defineComponent } from 'vue';
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export default defineComponent({
|
|||||||
.loading {
|
.loading {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div class="progress-bar">
|
||||||
|
<span class="bar-bg"></span>
|
||||||
|
<span
|
||||||
|
class="bar-fg"
|
||||||
|
:style="{ width: `${~~progressPercent}%`, backgroundColor: bgColor }"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
progressPercent: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
progressType: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
bgColor() {
|
||||||
|
switch (this.progressType) {
|
||||||
|
case 'abandoned':
|
||||||
|
return 'salmon';
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 'springgreen';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.progress-bar {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 6em;
|
||||||
|
height: 1em;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
|
||||||
|
.bar-fg,
|
||||||
|
.bar-bg {
|
||||||
|
position: absolute;
|
||||||
|
height: 1em;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-fg {
|
||||||
|
background-color: springgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-bg {
|
||||||
|
background-color: #5b5b5b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,39 +7,31 @@
|
|||||||
@keypress="updateValue"
|
@keypress="updateValue"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<img
|
<img class="search-exit" src="/images/icon-exit.svg" alt="exit-icon" @click="clearSearchValue" />
|
||||||
class="search-exit"
|
|
||||||
:src="exitIcon"
|
|
||||||
alt="exit-icon"
|
|
||||||
@click="clearValue"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, watch } from "vue";
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data: () => ({
|
emits: ['update:searchedValue', 'clearValue'],
|
||||||
exitIcon: require("@/assets/icon-exit.svg"),
|
|
||||||
}),
|
|
||||||
emits: ["update:searchedValue", "clearValue"],
|
|
||||||
props: {
|
props: {
|
||||||
searchedValue: {
|
searchedValue: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true
|
||||||
},
|
},
|
||||||
updateOnInput: {
|
updateOnInput: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true
|
||||||
},
|
},
|
||||||
titleToTranslate: {
|
titleToTranslate: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true
|
||||||
},
|
},
|
||||||
clearValue: {
|
clearValue: {
|
||||||
type: Function,
|
type: Function
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
@@ -49,32 +41,32 @@ export default defineComponent({
|
|||||||
watch(
|
watch(
|
||||||
() => compSearchedValue.value,
|
() => compSearchedValue.value,
|
||||||
(value) => {
|
(value) => {
|
||||||
emit("update:searchedValue", value);
|
emit('update:searchedValue', value);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearValue = () => {
|
const clearSearchValue = () => {
|
||||||
compSearchedValue.value = "";
|
compSearchedValue.value = '';
|
||||||
emit("clearValue");
|
emit('clearValue');
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateValue = (e) => {
|
const updateValue = (e: any) => {
|
||||||
if (!props.updateOnInput && e.keyCode == 13)
|
if (!props.updateOnInput && e.keyCode == 13)
|
||||||
emit("update:searchedValue", compSearchedValue.value);
|
emit('update:searchedValue', compSearchedValue.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
compSearchedValue,
|
compSearchedValue,
|
||||||
updateValue,
|
updateValue,
|
||||||
clearValue,
|
clearSearchValue
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "../../styles/responsive";
|
@import '../../styles/responsive';
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
&-box {
|
&-box {
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
<div class="select-box">
|
<div class="select-box">
|
||||||
<div class="select-box_content">
|
<div class="select-box_content">
|
||||||
<button class="selected" @click="toggleBox">
|
<button class="selected" @click="toggleBox">
|
||||||
<span class="text--primary">{{ prefix }}</span>
|
|
||||||
<span>{{ computedSelectedItem.selectedValue || computedSelectedItem.value }}</span>
|
<span>{{ computedSelectedItem.selectedValue || computedSelectedItem.value }}</span>
|
||||||
|
|
||||||
|
<div class="arrow">
|
||||||
|
<img :src="`/images/icon-arrow-${listOpen ? 'asc' : 'desc'}.svg`" alt="Arrow icon" />
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ul class="options" :ref="(el) => (listRef = el as Element)">
|
<ul class="options" :ref="(el) => (listRef = el as Element)">
|
||||||
@@ -16,21 +19,21 @@
|
|||||||
>
|
>
|
||||||
<label :for="item.id" v-if="listOpen">
|
<label :for="item.id" v-if="listOpen">
|
||||||
<input type="button" :id="item.id" name="select-box" @click="selectOption(item)" />
|
<input type="button" :id="item.id" name="select-box" @click="selectOption(item)" />
|
||||||
<span :style="computedSelectedItem.id == item.id ? 'color: gold;' : ''" v-html="item.value"> </span>
|
<span
|
||||||
|
:style="computedSelectedItem.id == item.id ? 'color: gold;' : ''"
|
||||||
|
v-html="item.value"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</transition>
|
</transition>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="arrow">
|
|
||||||
<img :src="listOpen ? ascIcon : descIcon" alt="arrow-icon" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, Ref, ref } from '@vue/runtime-core';
|
import { defineComponent, Ref, ref, computed } from 'vue';
|
||||||
|
|
||||||
interface Item {
|
interface Item {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -44,24 +47,19 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
itemList: {
|
itemList: {
|
||||||
type: Array as () => Item[],
|
type: Array as () => Item[],
|
||||||
required: true,
|
required: true
|
||||||
},
|
},
|
||||||
|
|
||||||
defaultItemIndex: {
|
defaultItemIndex: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
prefix: {
|
prefix: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
ascIcon: require('@/assets/icon-arrow-asc.svg'),
|
|
||||||
descIcon: require('@/assets/icon-arrow-desc.svg'),
|
|
||||||
}),
|
|
||||||
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
let listRef: Ref<Element | null> = ref(null);
|
let listRef: Ref<Element | null> = ref(null);
|
||||||
@@ -73,7 +71,10 @@ export default defineComponent({
|
|||||||
let selectedItem: Ref<Item> = ref(props.itemList[props.defaultItemIndex]);
|
let selectedItem: Ref<Item> = ref(props.itemList[props.defaultItemIndex]);
|
||||||
|
|
||||||
const computedSelectedItem = computed(() => {
|
const computedSelectedItem = computed(() => {
|
||||||
return props.itemList.find((item) => item.id === selectedItem.value.id) || props.itemList[props.defaultItemIndex];
|
return (
|
||||||
|
props.itemList.find((item) => item.id === selectedItem.value.id) ||
|
||||||
|
props.itemList[props.defaultItemIndex]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -82,10 +83,23 @@ export default defineComponent({
|
|||||||
selectedItem,
|
selectedItem,
|
||||||
listRef,
|
listRef,
|
||||||
buttonRef,
|
buttonRef,
|
||||||
activeEl,
|
activeEl
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
'$route.query': {
|
||||||
|
immediate: true,
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal.region) {
|
||||||
|
const item = this.itemList.find((it) => it.id == newVal.region);
|
||||||
|
|
||||||
|
if (item) this.selectedItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
selectOption(item: Item) {
|
selectOption(item: Item) {
|
||||||
this.selectedItem = item;
|
this.selectedItem = item;
|
||||||
@@ -103,8 +117,8 @@ export default defineComponent({
|
|||||||
clickedOutside() {
|
clickedOutside() {
|
||||||
this.listOpen = false;
|
this.listOpen = false;
|
||||||
this.buttonRef?.blur();
|
this.buttonRef?.blur();
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -133,44 +147,25 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.select-box {
|
.select-box {
|
||||||
position: relative;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow {
|
.arrow {
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 0;
|
|
||||||
padding: 0.5em;
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 1.35em;
|
width: 1.35em;
|
||||||
}
|
}
|
||||||
|
|
||||||
transform: translateY(-50%);
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button.selected {
|
button.selected {
|
||||||
background: #333;
|
color: paleturquoise;
|
||||||
color: white;
|
|
||||||
|
|
||||||
font-size: 1em;
|
font-weight: bold;
|
||||||
|
padding: 0.1em 0.5em;
|
||||||
padding: 0.35em 0.5em;
|
|
||||||
margin-right: 1.4em;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
background: #555;
|
background-color: #262626;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,8 +186,9 @@ ul.options {
|
|||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
li.option {
|
li.option {
|
||||||
@@ -206,6 +202,7 @@ li.option {
|
|||||||
appearance: none;
|
appearance: none;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
background: none;
|
||||||
|
|
||||||
&:focus + span {
|
&:focus + span {
|
||||||
color: $accentCol;
|
color: $accentCol;
|
||||||
@@ -221,11 +218,11 @@ li.option {
|
|||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: hsla(0, 0%, 15%, 0.95);
|
background-color: #262626f2;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: hsla(0, 0%, 20%, 0.95);
|
background-color: #333333f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
|
|||||||
@@ -1,19 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<span class="status-badge" :class="statusID" v-if="isOnline">
|
||||||
|
{{ $t(`status.${statusID}`) }}
|
||||||
|
{{ statusID == 'online' ? timestampToString(statusTimestamp!) : '' }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="status-badge free" v-else>
|
||||||
|
{{ $t('status.free') }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import dateMixin from '../../mixins/dateMixin';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
statusID: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
statusTimestamp: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
isOnline: {
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [dateMixin]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
$free: #8a8a8a;
|
$free: #8a8a8a;
|
||||||
$ending: #e6c300;
|
$ending: #e6c300;
|
||||||
$no-limit: #117fc9;
|
$no-limit: #117fc9;
|
||||||
$unav: #ff3d5d;
|
$unav: #ff3d5d;
|
||||||
$brb: #e6a100;
|
$brb: #e6a100;
|
||||||
$no-space: #222;
|
$no-space: #222;
|
||||||
$taken: #09a116;
|
$online: #09a116;
|
||||||
$unknown: rgb(185, 60, 60);
|
$unknown: rgb(185, 60, 60);
|
||||||
|
|
||||||
.status-badge {
|
.status-badge {
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
padding: 0.2em .55em;
|
padding: 0.2em 0.55em;
|
||||||
|
|
||||||
background-color: $taken;
|
background-color: $online;
|
||||||
|
|
||||||
&.free {
|
&.free {
|
||||||
background-color: $free;
|
background-color: $free;
|
||||||
@@ -45,6 +77,7 @@ $unknown: rgb(185, 60, 60);
|
|||||||
|
|
||||||
&.no-space {
|
&.no-space {
|
||||||
background-color: $no-space;
|
background-color: $no-space;
|
||||||
|
border: 1px solid white;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
@@ -54,3 +87,4 @@ $unknown: rgb(185, 60, 60);
|
|||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div class="stock-list">
|
||||||
|
<ul>
|
||||||
|
<li v-for="(stockName, i) in trainStockList" :key="i">
|
||||||
|
<p>
|
||||||
|
{{ stockName.split(':')[0].split('_').splice(0, 2).join(' ') }}
|
||||||
|
{{ stockName.split(':')[1] }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<img
|
||||||
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockName.split(':')[0]}${
|
||||||
|
/^EN/.test(stockName) ? 'rb' : ''
|
||||||
|
}.png`"
|
||||||
|
@error="onImageError($event, stockName)"
|
||||||
|
width="400"
|
||||||
|
height="60"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-if="/^(EN|2EN)/.test(stockName)"
|
||||||
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockName.split(':')[0]}s.png`"
|
||||||
|
@error="
|
||||||
|
(event) => ((event.target as HTMLImageElement).src = '/images/icon-loco-ezt-s.png')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
class="train-thumbnail"
|
||||||
|
v-if="/^EN71/.test(stockName)"
|
||||||
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockName.split(':')[0]}s.png`"
|
||||||
|
@error="
|
||||||
|
(event) => ((event.target as HTMLImageElement).src = '/images/icon-loco-ezt-s.png')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
class="train-thumbnail"
|
||||||
|
v-if="/^(EN|2EN)/.test(stockName)"
|
||||||
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockName.split(':')[0]}ra.png`"
|
||||||
|
@error="
|
||||||
|
(event) => ((event.target as HTMLImageElement).src = '/images/icon-loco-ezt-ra.png')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { PropType, defineComponent } from 'vue';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
|
import { RollingStockInfo } from '../../scripts/interfaces/github_api/StockInfoGithubData';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
trainStockList: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
store: useStore()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onImageError(event: Event, stockName: string) {
|
||||||
|
const fallbackName =
|
||||||
|
Object.keys(this.store.rollingStockData!.info).find((type) => {
|
||||||
|
return this.store.rollingStockData!.info[type as keyof RollingStockInfo].find(
|
||||||
|
(v) => v[0] === stockName.split(':')[0]
|
||||||
|
);
|
||||||
|
}) || 'vehicle-unknown';
|
||||||
|
|
||||||
|
(event.target as HTMLImageElement).src = `/images/icon-${fallbackName}.png`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.stock-list {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-list ul {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
overflow: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul > li > span {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-height: 60px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,12 +4,12 @@
|
|||||||
class="date arrival"
|
class="date arrival"
|
||||||
v-if="!stop.beginsHere"
|
v-if="!stop.beginsHere"
|
||||||
:class="{
|
:class="{
|
||||||
delayed: stop.arrivalDelay > 0 && stop.confirmed,
|
delayed: stop.arrivalDelay > 0 && (stop.confirmed || stop.stopped),
|
||||||
preponed: stop.arrivalDelay < 0 && stop.confirmed,
|
preponed: stop.arrivalDelay < 0 && (stop.confirmed || stop.stopped),
|
||||||
'on-time': stop.arrivalDelay == 0 && stop.confirmed,
|
'on-time': stop.arrivalDelay == 0 && stop.confirmed
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span v-if="stop.arrivalDelay != 0 && stop.confirmed">
|
<span v-if="stop.arrivalDelay != 0 && (stop.confirmed || stop.stopped)">
|
||||||
<s>{{ timestampToString(stop.arrivalTimestamp) }}</s>
|
<s>{{ timestampToString(stop.arrivalTimestamp) }}</s>
|
||||||
{{ timestampToString(stop.arrivalRealTimestamp) }}
|
{{ timestampToString(stop.arrivalRealTimestamp) }}
|
||||||
({{ stop.arrivalDelay > 0 ? '+' : '' }}{{ stop.arrivalDelay }})
|
({{ stop.arrivalDelay > 0 ? '+' : '' }}{{ stop.arrivalDelay }})
|
||||||
@@ -20,16 +20,20 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="date stop" v-if="stop.stopTime" :class="stop.stopType.replace(', ', '-')">
|
<span
|
||||||
|
class="date stop"
|
||||||
|
v-if="stop.stopTime || stop.stopped"
|
||||||
|
:class="stop.stopType.replace(', ', '-')"
|
||||||
|
>
|
||||||
{{ stop.stopTime }} {{ stop.stopType == '' ? 'pt' : stop.stopType }}
|
{{ stop.stopTime }} {{ stop.stopType == '' ? 'pt' : stop.stopType }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class="date departure"
|
class="date departure"
|
||||||
v-if="!stop.terminatesHere && stop.stopTime != 0"
|
v-if="!stop.terminatesHere && (stop.stopTime != 0 || stop.stopped)"
|
||||||
:class="{
|
:class="{
|
||||||
delayed: stop.departureDelay > 0 && stop.confirmed,
|
delayed: stop.departureDelay > 0 && stop.confirmed,
|
||||||
preponed: stop.departureDelay < 0 && stop.confirmed,
|
preponed: stop.departureDelay < 0 && stop.confirmed
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span v-if="stop.departureDelay != 0 && stop.confirmed">
|
<span v-if="stop.departureDelay != 0 && stop.confirmed">
|
||||||
@@ -47,9 +51,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import dateMixin from '@/mixins/dateMixin';
|
|
||||||
import TrainStop from '@/scripts/interfaces/TrainStop';
|
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import dateMixin from '../../mixins/dateMixin';
|
||||||
|
import TrainStop from '../../scripts/interfaces/TrainStop';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
mixins: [dateMixin],
|
mixins: [dateMixin],
|
||||||
@@ -57,13 +61,13 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
stop: {
|
stop: {
|
||||||
type: Object as () => TrainStop,
|
type: Object as () => TrainStop,
|
||||||
required: true,
|
required: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
<template>
|
||||||
|
<div class="train-modal" v-if="chosenTrain" @keydown.esc="closeModal">
|
||||||
|
<div class="modal_background" @click="closeModal"></div>
|
||||||
|
<div class="modal_content" ref="content" tabindex="0">
|
||||||
|
<button class="btn exit" @click="closeModal">
|
||||||
|
<img src="/images/icon-exit.svg" alt="close card" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<TrainInfo :train="chosenTrain" :extended="false" ref="trainInfo" />
|
||||||
|
<TrainSchedule :train="chosenTrain" tabindex="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import modalTrainMixin from '../../mixins/modalTrainMixin';
|
||||||
|
import trainInfoMixin from '../../mixins/trainInfoMixin';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
|
import TrainInfo from '../TrainsView/TrainInfo.vue';
|
||||||
|
import TrainSchedule from '../TrainsView/TrainSchedule.vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { TrainInfo, TrainSchedule },
|
||||||
|
mixins: [trainInfoMixin, modalTrainMixin],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isTopBarVisible: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const store = useStore();
|
||||||
|
|
||||||
|
return {
|
||||||
|
store
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
activated() {
|
||||||
|
const contentEl = this.$refs['content'] as HTMLElement;
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
contentEl.focus();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleContentScroll(e: Event) {
|
||||||
|
const trainInfoCompHeight: number = (
|
||||||
|
this.$refs['trainInfo'] as any
|
||||||
|
).$el.getBoundingClientRect().height;
|
||||||
|
|
||||||
|
const posTop = (e.target as HTMLElement).scrollTop;
|
||||||
|
this.isTopBarVisible = posTop > trainInfoCompHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../styles/responsive.scss';
|
||||||
|
@import '../../styles/card.scss';
|
||||||
|
|
||||||
|
.top-info-bar-anim {
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active {
|
||||||
|
transition: all 150ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-enter-from,
|
||||||
|
&-leave-to {
|
||||||
|
transform: translate(-50%, -50%) scale(0.8);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.exit {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
margin: 0.5em 1em;
|
||||||
|
|
||||||
|
padding: 0.25em;
|
||||||
|
|
||||||
|
z-index: 201;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 1.5rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.train-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal_background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
background-color: rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal_content {
|
||||||
|
position: relative;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
margin-top: 1em;
|
||||||
|
|
||||||
|
width: 95vw;
|
||||||
|
max-height: 96vh;
|
||||||
|
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
box-shadow: 0 0 15px 10px #0e0e0e;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include midScreen {
|
||||||
|
.exit {
|
||||||
|
margin: 0.5em;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include smallScreen {
|
||||||
|
.modal_content {
|
||||||
|
max-height: 85vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<img class="train-thumbnail" :src="placeholderUrl" v-if="isNotFound" />
|
||||||
|
|
||||||
|
<img
|
||||||
|
class="train-thumbnail"
|
||||||
|
v-else
|
||||||
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${name.split(':')[0]}${
|
||||||
|
stockType == 'loco-ezt' ? 'rb' : ''
|
||||||
|
}.png`"
|
||||||
|
@error="onImageError"
|
||||||
|
@load="onImageLoad"
|
||||||
|
width="220"
|
||||||
|
height="60"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
|
import { RollingStockInfo } from '../../scripts/interfaces/github_api/StockInfoGithubData';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
onlyFirstSegment: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
store: useStore(),
|
||||||
|
isNotFound: false,
|
||||||
|
isLoaded: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
url() {
|
||||||
|
return `https://rj.td2.info.pl/dist/img/thumbnails/${this.name.split(':')[0]}.png`;
|
||||||
|
},
|
||||||
|
|
||||||
|
placeholderUrl() {
|
||||||
|
return `/images/icon-${this.stockType}.png`;
|
||||||
|
},
|
||||||
|
|
||||||
|
stockType() {
|
||||||
|
if (!this.store.rollingStockData) return 'vehicle-unknown';
|
||||||
|
|
||||||
|
return (
|
||||||
|
Object.keys(this.store.rollingStockData.info).find((type) => {
|
||||||
|
return this.store.rollingStockData?.info[type as keyof RollingStockInfo].find(
|
||||||
|
(v) => v[0] === this.name.split(':')[0]
|
||||||
|
);
|
||||||
|
}) || 'vehicle-unknown'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onImageError() {
|
||||||
|
this.isNotFound = true;
|
||||||
|
this.isLoaded = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
onImageLoad() {
|
||||||
|
this.isNotFound = false;
|
||||||
|
this.isLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.train-thumbnail {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
max-height: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
<template>
|
||||||
|
<section class="daily-stats">
|
||||||
|
<span :data-active="statsStatus">
|
||||||
|
<b v-if="statsStatus == DataStatus.Loading">
|
||||||
|
{{ $t('app.loading') }}
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<b v-else-if="stats.distanceSum == null">
|
||||||
|
{{ $t('journal.daily-stats-info') }}
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<span class="stats-list" v-else>
|
||||||
|
<h3>
|
||||||
|
{{ $t('journal.daily-stats-title') }}
|
||||||
|
<b class="text--primary">{{ new Date().toLocaleDateString($i18n.locale) }}</b>
|
||||||
|
</h3>
|
||||||
|
<hr style="margin-bottom: 0.5em" />
|
||||||
|
|
||||||
|
<div v-if="stats.totalTimetables">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-total">
|
||||||
|
<template #count>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ stats.totalTimetables }}
|
||||||
|
{{ $t('journal.timetable-count', stats.totalTimetables) }}
|
||||||
|
</b>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #distance>
|
||||||
|
<b class="text--primary"> {{ stats.distanceSum?.toFixed(2) }} km</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="stats.timetableId">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-longest">
|
||||||
|
<template #id>
|
||||||
|
<router-link :to="`/journal/timetables?timetableId=${stats.timetableId}`">
|
||||||
|
<b>{{ stats.timetableId }}</b>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
<template #author>
|
||||||
|
<router-link :to="`/journal/dispatchers?dispatcherName=${stats.timetableAuthor}`">
|
||||||
|
<b>{{ stats.timetableAuthor }}</b>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
<template #driver>
|
||||||
|
<b class="text--primary">{{ stats.timetableDriver }}</b>
|
||||||
|
</template>
|
||||||
|
<template #distance>
|
||||||
|
<b class="text--primary">{{ stats.timetableRouteDistance }} km</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="topDispatchers.length == 1">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-most-active-dr">
|
||||||
|
<template #dispatcher>
|
||||||
|
<router-link :to="`/journal/dispatchers?dispatcherName=${topDispatchers[0].name}`">
|
||||||
|
<b>{{ topDispatchers[0].name }}</b>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
<template #count>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ topDispatchers[0].count }}
|
||||||
|
{{ $t('journal.timetable-count', topDispatchers[0].count) }}
|
||||||
|
</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="topDispatchers.length > 1">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-most-active-dr-many">
|
||||||
|
<template #dispatchers>
|
||||||
|
<span v-for="(disp, i) in topDispatchers" :key="i">
|
||||||
|
<span v-if="i == topDispatchers.length - 1"> {{ $t('general.and') }} </span>
|
||||||
|
|
||||||
|
<router-link :to="`/journal/dispatchers?dispatcherName=${disp.name}`">
|
||||||
|
<b>{{ disp.name }}</b>
|
||||||
|
</router-link>
|
||||||
|
|
||||||
|
<span v-if="i < topDispatchers.length - 2">, </span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #count>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ topDispatchers[0].count }}
|
||||||
|
{{ $t('journal.timetable-count', topDispatchers[0].count) }}
|
||||||
|
</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="stats.longestDuties.length > 0">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-longest-duties">
|
||||||
|
<template #dispatcher>
|
||||||
|
<router-link
|
||||||
|
:to="`/journal/dispatchers?dispatcherName=${stats.longestDuties[0].name}`"
|
||||||
|
>
|
||||||
|
<b>{{ stats.longestDuties[0].name }}</b>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #station>{{ stats.longestDuties[0].station }}</template>
|
||||||
|
|
||||||
|
<template #duration>
|
||||||
|
{{ calculateDuration(stats.longestDuties[0].duration) }}
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="stats.mostActiveDrivers.length > 0">
|
||||||
|
•
|
||||||
|
<i18n-t keypath="journal.timetable-stats-most-active-driver">
|
||||||
|
<template #driver>
|
||||||
|
<b class="text--primary">{{ stats.mostActiveDrivers[0].name }}</b>
|
||||||
|
</template>
|
||||||
|
<template #distance>
|
||||||
|
<b class="text--primary">{{ stats.mostActiveDrivers[0].distance.toFixed(2) }} km</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import axios from 'axios';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import dateMixin from '../../mixins/dateMixin';
|
||||||
|
import { DataStatus } from '../../scripts/enums/DataStatus';
|
||||||
|
import {
|
||||||
|
ITimetablesDailyStats,
|
||||||
|
ITimetablesDailyStatsResponse
|
||||||
|
} from '../../scripts/interfaces/api/StatsAPIData';
|
||||||
|
import { URLs } from '../../scripts/utils/apiURLs';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
mixins: [dateMixin],
|
||||||
|
emits: ['toggleStatsOpen'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
DataStatus,
|
||||||
|
statsStatus: DataStatus.Loading,
|
||||||
|
intervalId: -1,
|
||||||
|
|
||||||
|
stats: {
|
||||||
|
totalTimetables: 0,
|
||||||
|
distanceSum: 0,
|
||||||
|
distanceAvg: 0,
|
||||||
|
timetableAuthor: '',
|
||||||
|
timetableDriver: '',
|
||||||
|
timetableId: 0,
|
||||||
|
timetableRouteDistance: 0,
|
||||||
|
longestDuties: [],
|
||||||
|
mostActiveDrivers: [],
|
||||||
|
mostActiveDispatchers: []
|
||||||
|
} as ITimetablesDailyStats
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
activated() {
|
||||||
|
this.startFetchingDailyStats();
|
||||||
|
this.$emit('toggleStatsOpen', true);
|
||||||
|
},
|
||||||
|
|
||||||
|
deactivated() {
|
||||||
|
this.stopFetchingDailyStats();
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
topDispatchers() {
|
||||||
|
if (this.stats.mostActiveDispatchers.length == 0) return [];
|
||||||
|
const maxCount = this.stats.mostActiveDispatchers[0].count;
|
||||||
|
|
||||||
|
return this.stats.mostActiveDispatchers.filter((disp) => disp.count === maxCount);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async fetchDailyTimetableStats() {
|
||||||
|
try {
|
||||||
|
const res: ITimetablesDailyStatsResponse = await (
|
||||||
|
await axios.get(`${URLs.stacjownikAPI}/api/getDailyTimetableStats`)
|
||||||
|
).data;
|
||||||
|
|
||||||
|
this.stats = {
|
||||||
|
totalTimetables: res.totalTimetables,
|
||||||
|
distanceSum: res.distanceSum,
|
||||||
|
distanceAvg: res.distanceAvg,
|
||||||
|
timetableAuthor: res.maxTimetable?.authorName || '',
|
||||||
|
timetableDriver: res.maxTimetable?.driverName || '',
|
||||||
|
timetableId: res.maxTimetable?.id || 0,
|
||||||
|
timetableRouteDistance: res.maxTimetable?.routeDistance || 0,
|
||||||
|
|
||||||
|
mostActiveDispatchers: res.mostActiveDispatchers,
|
||||||
|
mostActiveDrivers: res.mostActiveDrivers,
|
||||||
|
longestDuties: res.longestDuties
|
||||||
|
};
|
||||||
|
|
||||||
|
this.statsStatus = DataStatus.Loaded;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ups! Wystąpił błąd podczas pobierania statystyk rozkładów jazdy...');
|
||||||
|
this.statsStatus = DataStatus.Error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
startFetchingDailyStats() {
|
||||||
|
this.fetchDailyTimetableStats();
|
||||||
|
|
||||||
|
if (this.intervalId != -1) return;
|
||||||
|
|
||||||
|
this.intervalId = setInterval(this.fetchDailyTimetableStats, 60000);
|
||||||
|
},
|
||||||
|
|
||||||
|
stopFetchingDailyStats() {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
this.intervalId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../styles/responsive.scss';
|
||||||
|
|
||||||
|
.daily-stats {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.daily-stats > span[data-active='0'] {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-list a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include smallScreen {
|
||||||
|
h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="stats_container" v-click-outside="() => (cardVisible = false)">
|
<div class="stats_container" v-click-outside="() => (cardVisible = false)">
|
||||||
<button class="stats_button btn btn--option" @click="toggleCard">
|
<button class="stats_button" @click="toggleCard">
|
||||||
Statystyki dyżurnego {{ store.dispatcherStatsName }}
|
Statystyki dyżurnego {{ store.dispatcherStatsName }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<h3>STATYSTYKI WYSTAWIONYCH ROZKŁADÓW</h3>
|
<h3>STATYSTYKI WYSTAWIONYCH ROZKŁADÓW</h3>
|
||||||
|
|
||||||
<div class="info-stats" v-if="store.dispatcherStatsData._count._all">
|
<div class="info-stats" v-if="store.dispatcherStatsData._count._all">
|
||||||
<span class="stat-badge">
|
<span class="stat-badge">
|
||||||
<span>LICZBA</span>
|
<span>LICZBA</span>
|
||||||
@@ -35,8 +36,9 @@
|
|||||||
|
|
||||||
<h3>OSTATNIE WYSTAWIONE ROZKŁADY</h3>
|
<h3>OSTATNIE WYSTAWIONE ROZKŁADY</h3>
|
||||||
<div class="last-timetables">
|
<div class="last-timetables">
|
||||||
<div class="timetable-row" v-for="timetable in timetables">
|
<div class="timetable-row" v-for="timetable in timetables" :key="timetable.id">
|
||||||
#{{ timetable.timetableId }} | <b>{{ timetable.trainCategoryCode }} {{ timetable.trainNo }}</b> |
|
#{{ timetable.timetableId }} |
|
||||||
|
<b>{{ timetable.trainCategoryCode }} {{ timetable.trainNo }}</b> |
|
||||||
{{ timetable.driverName }} ({{ timetable.routeDistance }}km)
|
{{ timetable.driverName }} ({{ timetable.routeDistance }}km)
|
||||||
<div>{{ timetable.route.replace('|', ' > ') }}</div>
|
<div>{{ timetable.route.replace('|', ' > ') }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,12 +50,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DispatcherStatsAPIData } from '@/scripts/interfaces/api/DispatcherStatsAPIData';
|
|
||||||
import { TimetableHistory } from '@/scripts/interfaces/api/TimetablesAPIData';
|
|
||||||
import { URLs } from '@/scripts/utils/apiURLs';
|
|
||||||
import { useStore } from '@/store/store';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { computed, defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { DispatcherStatsAPIData } from '../../scripts/interfaces/api/DispatcherStatsAPIData';
|
||||||
|
import { TimetableHistory } from '../../scripts/interfaces/api/TimetablesAPIData';
|
||||||
|
import { URLs } from '../../scripts/utils/apiURLs';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
import Loading from '../Global/Loading.vue';
|
import Loading from '../Global/Loading.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -62,15 +64,8 @@ export default defineComponent({
|
|||||||
setup() {
|
setup() {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
|
||||||
const statsData2 = computed(async () => {
|
|
||||||
return await (
|
|
||||||
await axios.get(`${URLs.stacjownikAPI}/api/getDispatcherInfo?name=${store.dispatcherStatsName}`)
|
|
||||||
).data;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
store,
|
store
|
||||||
statsData2,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -78,7 +73,7 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
cardVisible: false,
|
cardVisible: false,
|
||||||
lastDispatcherName: '',
|
lastDispatcherName: '',
|
||||||
timetables: [] as TimetableHistory[],
|
timetables: [] as TimetableHistory[]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -96,18 +91,22 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const statsData: DispatcherStatsAPIData = await (
|
const statsData: DispatcherStatsAPIData = await (
|
||||||
await axios.get(`${URLs.stacjownikAPI}/api/getDispatcherInfo?name=${this.store.dispatcherStatsName}`)
|
await axios.get(
|
||||||
|
`${URLs.stacjownikAPI}/api/getDispatcherInfo?name=${this.store.dispatcherStatsName}`
|
||||||
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
const timetables: TimetableHistory[] = await (
|
const timetables: TimetableHistory[] = await (
|
||||||
await axios.get(`${URLs.stacjownikAPI}/api/getTimetables?authorName=${this.store.dispatcherStatsName}`)
|
await axios.get(
|
||||||
|
`${URLs.stacjownikAPI}/api/getTimetables?authorName=${this.store.dispatcherStatsName}`
|
||||||
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
this.timetables = timetables;
|
this.timetables = timetables;
|
||||||
this.store.dispatcherStatsData = statsData;
|
this.store.dispatcherStatsData = statsData;
|
||||||
this.lastDispatcherName = this.store.dispatcherStatsName;
|
this.lastDispatcherName = this.store.dispatcherStatsName;
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -161,42 +160,7 @@ h3 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-stats {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.last-timetables {
|
.last-timetables {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-badge {
|
|
||||||
margin-right: 0.5em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
|
|
||||||
span {
|
|
||||||
padding: 0.25em 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
span:first-child {
|
|
||||||
background-color: #4d4d4d;
|
|
||||||
}
|
|
||||||
|
|
||||||
span:last-child {
|
|
||||||
background-color: $accentCol;
|
|
||||||
color: black;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include smallScreen() {
|
|
||||||
.stats_card {
|
|
||||||
text-align: center;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
border-radius: 0 0 1em 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card-dimmer" @click="closeCard"></div>
|
|
||||||
|
|
||||||
<div class="stats-card card">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title">
|
|
||||||
STATYSTYKI MASZYNISTY <span class="text--primary">{{ store.driverStatsName.toUpperCase() }}</span>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div class="loading" v-if="!store.driverStatsData">Ładowanie...</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<div class="info-stats" v-if="store.driverStatsData._sum.routeDistance != null">
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>PRZEBYTO</span>
|
|
||||||
<span>{{ store.driverStatsData._sum.routeDistance.toFixed(2) }}km</span>
|
|
||||||
</span>
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>PORZUCONO</span>
|
|
||||||
<span>
|
|
||||||
{{ (store.driverStatsData._sum.routeDistance - store.driverStatsData._sum.currentDistance).toFixed(2) }}km
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>WYPEŁNIONO</span>
|
|
||||||
<span>{{ store.driverStatsData._count.fulfilled }} RJ</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>PORZUCONO</span>
|
|
||||||
<span>{{ store.driverStatsData._count._all - store.driverStatsData._count.fulfilled }} RJ</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>ZATWIERDZONO</span>
|
|
||||||
<span>{{ store.driverStatsData._sum.confirmedStopsCount }} stacji</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stat-badge">
|
|
||||||
<span>PORZUCONO</span>
|
|
||||||
<span>
|
|
||||||
{{ store.driverStatsData._sum.allStopsCount - store.driverStatsData._sum.confirmedStopsCount }}
|
|
||||||
stacji
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { DriverStatsAPIData } from '@/scripts/interfaces/api/DriverStatsAPIData';
|
|
||||||
import { TimetableHistory } from '@/scripts/interfaces/api/TimetablesAPIData';
|
|
||||||
import { URLs } from '@/scripts/utils/apiURLs';
|
|
||||||
import { useStore } from '@/store/store';
|
|
||||||
import axios from 'axios';
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
emits: ['closeCard'],
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
const store = useStore();
|
|
||||||
return {
|
|
||||||
store,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
test: Math.random(),
|
|
||||||
lastDispatcherName: '',
|
|
||||||
|
|
||||||
lastTimetables: [] as TimetableHistory[],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
activated() {
|
|
||||||
this.fetchDispatcherStats();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
async fetchDispatcherStats() {
|
|
||||||
this.store.driverStatsData = undefined;
|
|
||||||
|
|
||||||
const statsData: DriverStatsAPIData = await (
|
|
||||||
await axios.get(`${URLs.stacjownikAPI}/api/getDriverInfo?name=${this.store.driverStatsName}`)
|
|
||||||
).data;
|
|
||||||
|
|
||||||
const recentTimetablesData: TimetableHistory[] = await (
|
|
||||||
await axios.get(`${URLs.stacjownikAPI}/api/getTimetables?driverName=${this.store.driverStatsName}`)
|
|
||||||
).data;
|
|
||||||
|
|
||||||
this.store.driverStatsData = statsData;
|
|
||||||
this.lastTimetables = recentTimetablesData || [];
|
|
||||||
},
|
|
||||||
|
|
||||||
closeCard() {
|
|
||||||
this.$emit('closeCard');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../styles/responsive.scss';
|
|
||||||
|
|
||||||
.timetable-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 4fr 1fr 1fr 2fr 2fr;
|
|
||||||
gap: 0.2em;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
min-width: 100px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
background-color: #4d4d4d;
|
|
||||||
padding: 0.5em 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include smallScreen() {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
padding: 0.2em 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
background-color: #4d4d4d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||