Compare commits

...

22 Commits

Author SHA1 Message Date
Spythere ebfaf06a44 Merge pull request #72 from Spythere/development
Wersja 1.19.4
2023-12-11 13:02:05 +01:00
Spythere 5a651aedf8 imports hotfix 2023-12-11 12:58:41 +01:00
Spythere b66af014b9 lock sync 2023-12-10 15:29:29 +01:00
Spythere 634c9e1514 bump wersji: 1.19.4 2023-12-10 15:23:54 +01:00
Spythere c4132a9be2 cleanup http c.d. 2023-12-10 15:23:27 +01:00
Spythere 82a9a9165f cleanup http 2023-12-10 15:22:33 +01:00
Spythere fcac03c0a4 Merge pull request #71 from Spythere/development
Wersja 1.19.3
2023-12-10 00:56:21 +01:00
Spythere 39c3cf2329 restrukturyzacja storów 2023-12-09 16:18:23 +01:00
Spythere 59f4a0cb66 zmniejszenie czasu odpytywania z serwera 2023-12-08 20:00:17 +01:00
Spythere e2b42d16a4 poprawki scrollBehavior 2023-12-08 18:55:06 +01:00
Spythere e23663ed28 fix: brak ładowania danych o historii scenerii przy bezpośrednim wejściu z poz. URL 2023-12-08 18:15:49 +01:00
Spythere dc7846c31e bump wersji: 1.19.3 2023-12-08 17:15:16 +01:00
Spythere d875433d56 ulepszone zapamiętywanie zakładek statystyk w dzienniku 2023-12-08 17:14:49 +01:00
Spythere 71e5044cb4 poprawki designu dziennika RJ 2023-12-08 16:20:17 +01:00
Spythere e83aa40f82 aktualizacja endpointu API statystyk 2023-12-08 16:16:14 +01:00
Spythere d1c0e0b898 Merge pull request #70 from Spythere/development
Wersja 1.19.2
2023-12-07 16:29:53 +01:00
Spythere 26a7c69886 bump: 1.19.2 2023-12-07 16:18:21 +01:00
Spythere 0dc2c505db poprawki do braku pokazywania się niezapisanych scenerii 2023-12-07 16:16:06 +01:00
Spythere 188857d335 fix: rozkłady jazdy pokazują się na innych serwerach 2023-12-06 20:29:28 +01:00
Spythere 3dbbb3b4f9 Merge pull request #69 from Spythere/development
Wersja 1.19.1
2023-12-02 23:04:55 +01:00
Spythere 07a77c463b bump 1.19.1 2023-12-02 23:04:24 +01:00
Spythere 1a8e2231dd przejście z WS na komunikację http 2023-12-02 23:02:08 +01:00
49 changed files with 11046 additions and 703 deletions
+20 -157
View File
@@ -1,12 +1,12 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.19.0", "version": "1.19.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "stacjownik", "name": "stacjownik",
"version": "1.19.0", "version": "1.19.4",
"dependencies": { "dependencies": {
"core-js": "^3.32.2", "core-js": "^3.32.2",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
@@ -14,7 +14,6 @@
"howler": "^2.2.4", "howler": "^2.2.4",
"pinia": "^2.1.6", "pinia": "^2.1.6",
"sass": "^1.67.0", "sass": "^1.67.0",
"socket.io-client": "^4.7.2",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-i18n": "^9.4.1", "vue-i18n": "^9.4.1",
"vue-router": "^4.2.4" "vue-router": "^4.2.4"
@@ -2841,12 +2840,6 @@
"integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==", "integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==",
"dev": true "dev": true
}, },
"node_modules/@socket.io/component-emitter": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
"license": "MIT"
},
"node_modules/@surma/rollup-plugin-off-main-thread": { "node_modules/@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
@@ -3857,9 +3850,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001503", "version": "1.0.30001565",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz",
"integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -3874,8 +3867,7 @@
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ]
"license": "CC-BY-4.0"
}, },
"node_modules/chalk": { "node_modules/chalk": {
"version": "2.4.2", "version": "2.4.2",
@@ -4164,6 +4156,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
@@ -4406,28 +4399,6 @@
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"node_modules/engine.io-client": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz",
"integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.20.5", "version": "1.20.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz",
@@ -6341,6 +6312,7 @@
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/muggle-string": { "node_modules/muggle-string": {
@@ -7566,34 +7538,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/socket.io-client": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.8.0-beta.0", "version": "0.8.0-beta.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
@@ -8208,11 +8152,10 @@
"dev": true "dev": true
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "4.4.9", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
"integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.18.10", "esbuild": "^0.18.10",
"postcss": "^8.4.27", "postcss": "^8.4.27",
@@ -8784,27 +8727,6 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xml-name-validator": { "node_modules/xml-name-validator": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
@@ -8814,14 +8736,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -10808,11 +10722,6 @@
"integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==", "integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==",
"dev": true "dev": true
}, },
"@socket.io/component-emitter": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
},
"@surma/rollup-plugin-off-main-thread": { "@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
@@ -11513,9 +11422,9 @@
"dev": true "dev": true
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001503", "version": "1.0.30001565",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz",
"integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==",
"dev": true "dev": true
}, },
"chalk": { "chalk": {
@@ -11731,6 +11640,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": { "requires": {
"ms": "2.1.2" "ms": "2.1.2"
} }
@@ -11891,23 +11801,6 @@
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"engine.io-client": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz",
"integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"engine.io-parser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ=="
},
"es-abstract": { "es-abstract": {
"version": "1.20.5", "version": "1.20.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz",
@@ -13234,7 +13127,8 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}, },
"muggle-string": { "muggle-string": {
"version": "0.3.1", "version": "0.3.1",
@@ -14051,26 +13945,6 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true "dev": true
}, },
"socket.io-client": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
}
},
"socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
}
},
"source-map": { "source-map": {
"version": "0.8.0-beta.0", "version": "0.8.0-beta.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
@@ -14503,9 +14377,9 @@
"dev": true "dev": true
}, },
"vite": { "vite": {
"version": "4.4.9", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
"integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
"dev": true, "dev": true,
"requires": { "requires": {
"esbuild": "^0.18.10", "esbuild": "^0.18.10",
@@ -14902,23 +14776,12 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true "dev": true
}, },
"ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"requires": {}
},
"xml-name-validator": { "xml-name-validator": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
"dev": true "dev": true
}, },
"xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
},
"y18n": { "y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+8 -9
View File
@@ -1,6 +1,6 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.19.0", "version": "1.19.4",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -18,27 +18,26 @@
"howler": "^2.2.4", "howler": "^2.2.4",
"pinia": "^2.1.6", "pinia": "^2.1.6",
"sass": "^1.67.0", "sass": "^1.67.0",
"socket.io-client": "^4.7.2",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-i18n": "^9.4.1", "vue-i18n": "^9.4.1",
"vue-router": "^4.2.4" "vue-router": "^4.2.4"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@types/node": "^20.6.2", "@types/node": "^20.6.2",
"@vite-pwa/assets-generator": "^0.0.10", "@vite-pwa/assets-generator": "^0.0.10",
"@vitejs/plugin-vue": "^4.3.4", "@vitejs/plugin-vue": "^4.3.4",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.4.0",
"axios": "^1.5.0", "axios": "^1.5.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"vite": "^4.4.9", "vite": "^4.4.9",
"vite-plugin-pwa": "^0.16.5", "vite-plugin-pwa": "^0.16.5",
"vue-tsc": "^1.8.11", "vue-tsc": "^1.8.11"
"@vue/eslint-config-prettier": "^8.0.0",
"@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%",
+7 -8
View File
@@ -39,12 +39,13 @@ import Clock from './components/App/Clock.vue';
import packageInfo from '.././package.json'; import packageInfo from '.././package.json';
import { regions } from './data/options.json'; import { regions } from './data/options.json';
import { useStore } from './store/mainStore'; import { useMainStore } from './store/mainStore';
import StatusIndicator from './components/App/StatusIndicator.vue'; import StatusIndicator from './components/App/StatusIndicator.vue';
import TrainModal from './components/Global/TrainModal.vue'; import TrainModal from './components/Global/TrainModal.vue';
import AppHeader from './components/App/AppHeader.vue'; import AppHeader from './components/App/AppHeader.vue';
import axios from 'axios'; import axios from 'axios';
import StorageManager from './managers/storageManager'; import StorageManager from './managers/storageManager';
import { useApiStore } from './store/apiStore';
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -56,7 +57,8 @@ export default defineComponent({
data: () => ({ data: () => ({
VERSION: packageInfo.version, VERSION: packageInfo.version,
store: useStore(), store: useMainStore(),
apiStore: useApiStore(),
currentLang: 'pl', currentLang: 'pl',
releaseURL: '', releaseURL: '',
@@ -65,18 +67,15 @@ export default defineComponent({
created() { created() {
this.loadLang(); this.loadLang();
this.store.connectToAPI(); this.apiStore.setupAPI();
this.store.isOffline = !window.navigator.onLine; this.store.isOffline = !window.navigator.onLine;
window.addEventListener('offline', () => { window.addEventListener('offline', () => {
this.store.isOffline = true; this.store.isOffline = true;
this.apiStore.activeData = undefined;
this.store.activeData.activeSceneries = []; this.apiStore.setDataStatuses();
this.store.activeData.trains = [];
this.store.activeData.connectedSocketCount = 0;
this.store.setStatuses();
}); });
window.addEventListener('online', () => { window.addEventListener('online', () => {
+2 -2
View File
@@ -68,7 +68,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import StatusIndicator from './StatusIndicator.vue'; import StatusIndicator from './StatusIndicator.vue';
import Clock from './Clock.vue'; import Clock from './Clock.vue';
import RegionDropdown from '../Global/RegionDropdown.vue'; import RegionDropdown from '../Global/RegionDropdown.vue';
@@ -84,7 +84,7 @@ export default defineComponent({
setup() { setup() {
return { return {
store: useStore() store: useMainStore()
}; };
}, },
+6 -5
View File
@@ -194,9 +194,9 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { StoreState } from '../../store/typings'; import { useMainStore } from '../../store/mainStore';
import { useStore } from '../../store/mainStore';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
data() { data() {
@@ -221,10 +221,11 @@ export default defineComponent({
}, },
setup() { setup() {
const store = useStore(); const store = useMainStore();
const apiStore = useApiStore();
return { return {
dataStatus: store.dataStatuses, dataStatus: apiStore.dataStatuses,
store store
}; };
}, },
@@ -233,7 +234,7 @@ export default defineComponent({
dataStatus: { dataStatus: {
deep: true, deep: true,
handler(statuses: StoreState['dataStatuses']) { handler(statuses: any) {
const connectionStatus = statuses.connection; const connectionStatus = statuses.connection;
const sceneryDataStatus = statuses.sceneries; const sceneryDataStatus = statuses.sceneries;
const trainsDataStatus = statuses.trains; const trainsDataStatus = statuses.trains;
+2 -2
View File
@@ -12,7 +12,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
export default defineComponent({ export default defineComponent({
emits: ['toggleModal'], emits: ['toggleModal'],
@@ -23,7 +23,7 @@ export default defineComponent({
data() { data() {
return { return {
store: useStore() store: useMainStore()
}; };
}, },
+2 -2
View File
@@ -30,7 +30,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, Ref, ref } from 'vue'; import { defineComponent, Ref, ref } from 'vue';
import { regions as regionsJSON } from '../../data/options.json'; import { regions as regionsJSON } from '../../data/options.json';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
interface Item { interface Item {
id: string; id: string;
@@ -41,7 +41,7 @@ interface Item {
export default defineComponent({ export default defineComponent({
data() { data() {
return { return {
store: useStore(), store: useMainStore(),
selectedItemIndex: 0, selectedItemIndex: 0,
listOpen: false listOpen: false
}; };
+4 -4
View File
@@ -50,8 +50,8 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import { useStore } from '../../store/mainStore';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -63,15 +63,15 @@ export default defineComponent({
data() { data() {
return { return {
store: useStore() apiStore: useApiStore()
}; };
}, },
methods: { methods: {
onImageError(event: Event, stockName: string) { onImageError(event: Event, stockName: string) {
const fallbackName = const fallbackName =
Object.keys(this.store.rollingStockData!.info).find((type) => { Object.keys(this.apiStore.rollingStockData!.info).find((type) => {
return this.store.rollingStockData!.info[type as keyof API.RollingStock.Info].find( return this.apiStore.rollingStockData!.info[type as keyof API.RollingStock.Info].find(
(v) => v[0] === stockName.split(':')[0] (v) => v[0] === stockName.split(':')[0]
); );
}) || 'vehicle-unknown'; }) || 'vehicle-unknown';
+5 -5
View File
@@ -16,8 +16,8 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../../store/mainStore';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -34,7 +34,7 @@ export default defineComponent({
data() { data() {
return { return {
store: useStore(), apiStore: useApiStore(),
isNotFound: false, isNotFound: false,
isLoaded: false isLoaded: false
}; };
@@ -50,11 +50,11 @@ export default defineComponent({
}, },
stockType() { stockType() {
if (!this.store.rollingStockData) return 'vehicle-unknown'; if (!this.apiStore.rollingStockData) return 'vehicle-unknown';
return ( return (
Object.keys(this.store.rollingStockData.info).find((type) => { Object.keys(this.apiStore.rollingStockData.info).find((type) => {
return this.store.rollingStockData?.info[type as keyof API.RollingStock.Info].find( return this.apiStore.rollingStockData?.info[type as keyof API.RollingStock.Info].find(
(v) => v[0] === this.name.split(':')[0] (v) => v[0] === this.name.split(':')[0]
); );
}) || 'vehicle-unknown' }) || 'vehicle-unknown'
+5 -10
View File
@@ -50,18 +50,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from 'axios';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { URLs } from '../../scripts/utils/apiURLs'; import { useMainStore } from '../../store/mainStore';
import { useStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import http from '../../http';
export default defineComponent({ export default defineComponent({
components: { Loading }, components: { Loading },
setup() { setup() {
const store = useStore(); const store = useMainStore();
return { return {
store store
@@ -90,15 +89,11 @@ export default defineComponent({
} }
const statsData: API.DispatcherStats.Response = await ( const statsData: API.DispatcherStats.Response = await (
await axios.get( await http.get('api/getDispatcherInfo?name=${this.store.dispatcherStatsName}')
`${URLs.stacjownikAPI}/api/getDispatcherInfo?name=${this.store.dispatcherStatsName}`
)
).data; ).data;
const timetables: API.TimetableHistory.Response = await ( const timetables: API.TimetableHistory.Response = await (
await axios.get( await http.get('api/getTimetables?authorName=${this.store.dispatcherStatsName}')
`${URLs.stacjownikAPI}/api/getTimetables?authorName=${this.store.dispatcherStatsName}`
)
).data; ).data;
this.timetables = timetables; this.timetables = timetables;
@@ -5,15 +5,12 @@
{{ $t('app.loading') }} {{ $t('app.loading') }}
</b> </b>
<b v-else-if="stats.distanceSum == null">
{{ $t('journal.daily-stats-info') }}
</b>
<span class="stats-list" v-else> <span class="stats-list" v-else>
<h3> <h3>
{{ $t('journal.daily-stats-title') }} {{ $t('journal.daily-stats-title') }}
<b class="text--primary">{{ new Date().toLocaleDateString($i18n.locale) }}</b> <b class="text--primary">{{ new Date().toLocaleDateString($i18n.locale) }}</b>
</h3> </h3>
<hr style="margin-bottom: 0.5em" /> <hr style="margin-bottom: 0.5em" />
<div v-if="stats.totalTimetables"> <div v-if="stats.totalTimetables">
@@ -133,17 +130,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from 'axios';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import { URLs } from '../../scripts/utils/apiURLs';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import http from '../../http';
export default defineComponent({ export default defineComponent({
name: 'journal-daily-stats',
mixins: [dateMixin], mixins: [dateMixin],
emits: ['toggleStatsOpen'], // emits: ['toggleStatsOpen'],
data() { data() {
return { return {
@@ -157,7 +155,7 @@ export default defineComponent({
activated() { activated() {
this.startFetchingDailyStats(); this.startFetchingDailyStats();
this.$emit('toggleStatsOpen', true); // this.$emit('toggleStatsOpen', true);
}, },
deactivated() { deactivated() {
@@ -176,23 +174,7 @@ export default defineComponent({
methods: { methods: {
async fetchDailyTimetableStats() { async fetchDailyTimetableStats() {
try { try {
const res: API.DailyStats.Response = await ( const res: API.DailyStats.Response = await (await http.get('api/getDailyStats')).data;
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.stats = res; this.stats = res;
@@ -208,7 +190,7 @@ export default defineComponent({
if (this.intervalId != -1) return; if (this.intervalId != -1) return;
this.intervalId = setInterval(this.fetchDailyTimetableStats, 60000); this.intervalId = window.setInterval(this.fetchDailyTimetableStats, 60000);
}, },
stopFetchingDailyStats() { stopFetchingDailyStats() {
@@ -125,7 +125,7 @@
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import { regions } from '../../data/options.json'; import { regions } from '../../data/options.json';
import AddDataButton from '../Global/AddDataButton.vue'; import AddDataButton from '../Global/AddDataButton.vue';
@@ -160,7 +160,7 @@ export default defineComponent({
data() { data() {
return { return {
Status, Status,
store: useStore(), store: useMainStore(),
regions regions
}; };
}, },
@@ -55,13 +55,15 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
export default defineComponent({ export default defineComponent({
name: 'journal-driver-stats',
data() { data() {
return { return {
store: useStore(), store: useMainStore(),
Status: Status Status: Status
}; };
} }
+6 -11
View File
@@ -110,14 +110,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from 'axios';
import { defineComponent, inject, PropType } from 'vue'; import { defineComponent, inject, PropType } from 'vue';
import keyMixin from '../../mixins/keyMixin'; import keyMixin from '../../mixins/keyMixin';
import { URLs } from '../../scripts/utils/apiURLs'; import { useMainStore } from '../../store/mainStore';
import { useStore } from '../../store/mainStore';
import { Journal } from './typings'; import { Journal } from './typings';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import http from '../../http';
export default defineComponent({ export default defineComponent({
emits: ['onSearchConfirm', 'onOptionsReset', 'onRefreshData'], emits: ['onSearchConfirm', 'onOptionsReset', 'onRefreshData'],
@@ -158,7 +157,7 @@ export default defineComponent({
dispatcherSuggestions: [] as string[], dispatcherSuggestions: [] as string[],
searchTimeout: 0, searchTimeout: 0,
store: useStore(), store: useMainStore(),
JournalFilterSection: Journal.FilterSection JournalFilterSection: Journal.FilterSection
}; };
@@ -184,8 +183,6 @@ export default defineComponent({
watch: { watch: {
async 'store.driverStatsName'() { async 'store.driverStatsName'() {
await this.fetchDriverStats(); await this.fetchDriverStats();
// if (value) this.store.currentStatsTab = 'driver';
}, },
async 'searchersValues.search-driver'(value: string | undefined) { async 'searchersValues.search-driver'(value: string | undefined) {
@@ -218,9 +215,7 @@ export default defineComponent({
this.store.driverStatsStatus = Status.Data.Loading; this.store.driverStatsStatus = Status.Data.Loading;
const statsData: API.DriverStats.Response = await ( const statsData: API.DriverStats.Response = await (
await axios.get( await http.get(`api/getDriverInfo?name=${this.store.driverStatsName}`)
`${URLs.stacjownikAPI}/api/getDriverInfo?name=${this.store.driverStatsName}`
)
).data; ).data;
this.store.driverStatsData = statsData; this.store.driverStatsData = statsData;
@@ -240,10 +235,10 @@ export default defineComponent({
window.clearTimeout(this.searchTimeout); window.clearTimeout(this.searchTimeout);
this.searchTimeout = setTimeout(async () => { this.searchTimeout = window.setTimeout(async () => {
try { try {
const suggestions: string[] = await ( const suggestions: string[] = await (
await axios.get(`${URLs.stacjownikAPI}/api/get${type}Suggestions?name=${value}`) await http.get(`api/get${type}Suggestions?name=${value}`)
).data; ).data;
this[`${type}Suggestions`] = suggestions; this[`${type}Suggestions`] = suggestions;
+40 -59
View File
@@ -1,27 +1,26 @@
<template> <template>
<div class="journal-stats" v-if="!store.isOffline"> <div class="journal-stats" v-if="!store.isOffline">
<div class="tabs"> <div class="stats-buttons">
<button <button
v-for="tab in data.tabs" v-for="button in data.statsButtons"
:key="tab.name" :key="button.name"
class="btn--filled" class="btn--filled btn--image"
:data-selected="tab.name == store.currentStatsTab && areStatsOpen" :data-selected="button.name == currentStatsTab"
:data-inactive="tab.inactive" @click="onTabButtonClick(button.name)"
:data-disabled="tab.inactive"
:disabled="tab.inactive"
@click="onTabButtonClick(tab.name)"
> >
{{ $t(tab.titlePath) }} <img
v-if="button.iconName"
:src="`/images/icon-${button.iconName}.svg`"
:alt="button.iconName"
/>
{{ $t(button.localeKey) }}
</button> </button>
</div> </div>
<div class="stats-tab" v-show="areStatsOpen"> <div class="stats-tab" v-show="currentStatsTab !== null">
<keep-alive> <keep-alive>
<JournalDailyStats <JournalDailyStats v-if="currentStatsTab == 'journal-daily-stats'" />
v-if="store.currentStatsTab == 'daily'" <JournalDriverStats v-else-if="currentStatsTab == 'journal-driver-stats'" />
@toggleStatsOpen="toggleStatsOpen"
/>
<JournalDriverStats v-else-if="store.currentStatsTab == 'driver'" />
</keep-alive> </keep-alive>
</div> </div>
</div> </div>
@@ -29,68 +28,50 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, reactive, Ref, ref, watch } from 'vue'; import { computed, onMounted, reactive, Ref, ref, watch } from 'vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import JournalDailyStats from './DailyStats.vue'; import JournalDailyStats from './JournalDailyStats.vue';
import JournalDriverStats from './JournalDriverStats.vue'; import JournalDriverStats from './JournalDriverStats.vue';
import StorageManager from '../../managers/storageManager'; import StorageManager from '../../managers/storageManager';
// Types export type JournalStatsTab = 'journal-driver-stats' | 'journal-daily-stats';
type TStatTab = 'daily' | 'driver';
// Variables const store = useMainStore();
const store = useStore(); const currentStatsTab: Ref<JournalStatsTab | null> = ref(null);
const lastDailyStatsOpen = ref(false);
const areStatsOpen = ref(false);
const lastClickedTab: Ref<'daily' | 'driver' | null> = ref(null);
let data = reactive({ let data = reactive({
tabs: [ statsButtons: [
{ {
name: 'daily', name: 'journal-daily-stats',
titlePath: 'journal.daily-stats-title' localeKey: 'journal.daily-stats-title',
iconName: 'stats'
}, },
{ {
name: 'driver', name: 'journal-driver-stats',
titlePath: 'journal.driver-stats-title' localeKey: 'journal.driver-stats-title',
// inactive: true, iconName: 'user'
} }
] as { name: TStatTab; titlePath: string; inactive?: boolean }[] ] as { name: JournalStatsTab; localeKey: string; iconName?: string }[]
}); });
// Methods function onTabButtonClick(tab: JournalStatsTab) {
function onTabButtonClick(tab: TStatTab) { currentStatsTab.value = tab == currentStatsTab.value ? null : tab;
if (lastClickedTab.value == tab || !lastClickedTab.value || !areStatsOpen.value) StorageManager.setStringValue('journalStatsTab', currentStatsTab.value ?? '');
areStatsOpen.value = !areStatsOpen.value;
if (tab == 'daily') {
StorageManager.setBooleanValue('dailyStatsOpen', areStatsOpen.value);
lastDailyStatsOpen.value = areStatsOpen.value;
}
store.currentStatsTab = tab;
lastClickedTab.value = tab;
if (areStatsOpen.value == false) store.currentStatsTab = null;
}
function toggleStatsOpen(open: boolean) {
areStatsOpen.value = open;
} }
watch( watch(
computed(() => store.driverStatsData), computed(() => store.driverStatsData),
(statsData) => { (newData, prevData) => {
store.currentStatsTab = statsData ? 'driver' : lastClickedTab.value; currentStatsTab.value =
areStatsOpen.value = statsData ? true : lastClickedTab.value !== null; JSON.stringify(prevData) !== JSON.stringify(newData) && newData !== undefined
? 'journal-driver-stats'
: currentStatsTab.value;
} }
); );
onMounted(() => { onMounted(() => {
if (StorageManager.getBooleanValue('dailyStatsOpen')) { const storedTab = StorageManager.getStringValue('journalStatsTab');
areStatsOpen.value = true;
store.currentStatsTab = 'daily'; if (storedTab && storedTab !== '') currentStatsTab.value = storedTab as JournalStatsTab;
}
}); });
</script> </script>
@@ -98,7 +79,7 @@ onMounted(() => {
@import '../../styles/JournalStats.scss'; @import '../../styles/JournalStats.scss';
@import '../../styles/variables.scss'; @import '../../styles/variables.scss';
.tabs { .stats-buttons {
position: relative; position: relative;
display: flex; display: flex;
@@ -42,7 +42,7 @@ import { defineComponent, PropType } from 'vue';
import Loading from '../../Global/Loading.vue'; import Loading from '../../Global/Loading.vue';
import AddDataButton from '../../Global/AddDataButton.vue'; import AddDataButton from '../../Global/AddDataButton.vue';
import TimetableHistoryList from './TimetableHistoryList.vue'; import TimetableHistoryList from './TimetableHistoryList.vue';
import { useStore } from '../../../store/mainStore'; import { useMainStore } from '../../../store/mainStore';
import { Status } from '../../../typings/common'; import { Status } from '../../../typings/common';
import { API } from '../../../typings/api'; import { API } from '../../../typings/api';
@@ -71,7 +71,7 @@ export default defineComponent({
data() { data() {
return { return {
Status, Status,
store: useStore() store: useMainStore()
}; };
} }
}); });
@@ -111,16 +111,17 @@ export default defineComponent({
gap: 0.5em; gap: 0.5em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
@include smallScreen() {
justify-content: center;
}
} }
.info-date { .info-date {
margin-right: 0.5em; margin-right: 0.5em;
} }
.badges {
display: flex;
gap: 0.25em;
}
.info-badge { .info-badge {
padding: 0.05em 0.35em; padding: 0.05em 0.35em;
color: black; color: black;
@@ -142,7 +143,14 @@ export default defineComponent({
cursor: pointer; cursor: pointer;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center;
align-items: center; align-items: center;
gap: 0.25em; gap: 0.25em;
} }
@include smallScreen {
.item-general {
justify-content: center;
}
}
</style> </style>
@@ -33,6 +33,8 @@
> >
{{ historyItem.dispatcherLevel >= 2 ? historyItem.dispatcherLevel : 'L' }} {{ historyItem.dispatcherLevel >= 2 ? historyItem.dispatcherLevel : 'L' }}
</b> </b>
<b v-else>?</b>
</td> </td>
<td class="text--primary"> <td class="text--primary">
<b>{{ historyItem.dispatcherRate }}</b> <b>{{ historyItem.dispatcherRate }}</b>
@@ -66,17 +68,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from 'axios';
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { URLs } from '../../scripts/utils/apiURLs';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import listObserverMixin from '../../mixins/listObserverMixin'; import listObserverMixin from '../../mixins/listObserverMixin';
import { OnlineScenery } from '../../store/typings'; import { OnlineScenery } from '../../store/typings';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import http from '../../http';
export default defineComponent({ export default defineComponent({
name: 'SceneryDispatchersHistory', name: 'SceneryDispatchersHistory',
@@ -84,12 +85,10 @@ export default defineComponent({
components: { Loading }, components: { Loading },
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
required: true
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<OnlineScenery>
required: false
} }
}, },
@@ -113,12 +112,20 @@ export default defineComponent({
countFrom = 0, countFrom = 0,
countLimit = 30 countLimit = 30
): Promise<API.DispatcherHistory.Response | null> { ): Promise<API.DispatcherHistory.Response | null> {
if (!this.station && !this.onlineScenery) {
this.dataStatus = Status.Data.Loaded;
return null;
}
try { try {
this.dataStatus = Status.Data.Loading; this.dataStatus = Status.Data.Loading;
const requestString = `${URLs.stacjownikAPI}/api/getDispatchers?stationName=${this.station.name}&countFrom=${countFrom}&countLimit=${countLimit}`; const requestString = `api/getDispatchers?stationName=${
this.station?.name || this.onlineScenery?.name
}&countFrom=${countFrom}&countLimit=${countLimit}`;
const historyAPIData: API.DispatcherHistory.Response = await ( const historyAPIData: API.DispatcherHistory.Response = await (
await axios.get(requestString) await http.get(requestString)
).data; ).data;
this.dataStatus = Status.Data.Loaded; this.dataStatus = Status.Data.Loaded;
@@ -130,7 +137,9 @@ export default defineComponent({
} }
}, },
navigateToHistory() { navigateToHistory() {
this.$router.push(`/journal/dispatchers?sceneryName=${this.station.name}`); this.$router.push(
`/journal/dispatchers?sceneryName=${this.station?.name || this.onlineScenery?.name}`
);
} }
} }
}); });
+10 -8
View File
@@ -1,11 +1,11 @@
<template> <template>
<section class="info-header"> <section class="info-header">
<a class="scenery-name" :href="station.generalInfo?.url" target="_blank"> <a class="scenery-name" :href="station?.generalInfo?.url" target="_blank">
{{ station.name }} {{ stationName.replace(/_/g, ' ') }}
</a> </a>
<div class="scenery-abbrev"> <div class="scenery-abbrev" v-if="station?.generalInfo?.abbr">
{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo?.abbr }}</b> {{ $t('scenery.abbrev') }} <b>{{ station.generalInfo.abbr }}</b>
</div> </div>
<div class="scenery-hash" v-if="onlineScenery?.hash">#{{ onlineScenery.hash }}</div> <div class="scenery-hash" v-if="onlineScenery?.hash">#{{ onlineScenery.hash }}</div>
@@ -20,13 +20,16 @@ import { OnlineScenery } from '../../store/typings';
export default defineComponent({ export default defineComponent({
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
},
stationName: {
type: String,
required: true required: true
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<OnlineScenery>
required: false
} }
} }
}); });
@@ -58,4 +61,3 @@ export default defineComponent({
font-size: 1.2em; font-size: 1.2em;
} }
</style> </style>
../../store/storeTypes
+6 -8
View File
@@ -1,10 +1,10 @@
<template> <template>
<div class="scenery-info"> <div class="scenery-info">
<section> <section>
<div class="scenery-info-general" v-if="station.generalInfo"> <div class="scenery-info-general">
<SceneryInfoIcons :station="station" /> <SceneryInfoIcons :station="station" />
<div class="scenery-general-list"> <div class="scenery-general-list" v-if="station?.generalInfo">
<span> <span>
<b>{{ $t('availability.title') }}:</b> <b>{{ $t('availability.title') }}:</b>
{{ $t(`availability.${station.generalInfo.availability}`) }} {{ $t(`availability.${station.generalInfo.availability}`) }}
@@ -46,11 +46,11 @@
</span> </span>
</div> </div>
<SceneryInfoRoutes :station="station" /> <SceneryInfoRoutes v-if="station" :station="station" />
<div <div
class="scenery-authors" class="scenery-authors"
v-if="station.generalInfo.authors && station.generalInfo.authors.length > 0" v-if="station?.generalInfo?.authors && station.generalInfo.authors.length > 0"
> >
<b> <b>
{{ {{
@@ -102,13 +102,11 @@ export default defineComponent({
}, },
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
required: true
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<OnlineScenery>
required: false
} }
} }
}); });
@@ -1,24 +1,33 @@
<template> <template>
<section class="info-icons"> <section class="info-icons">
<span <span v-if="!station || !station.generalInfo">
v-if="station.generalInfo && station.generalInfo.reqLevel >= 0" <img
class="scenery-icon icon-info level" class="icon-info"
:style="calculateExpStyle(station.generalInfo.reqLevel)" src="/images/icon-unknown.svg"
> alt="icon-unknown"
{{ station.generalInfo.reqLevel >= 2 ? station.generalInfo.reqLevel : 'L' }} :title="$t('desc.unknown')"
/>
</span> </span>
<span <span
v-if="station.generalInfo" v-if="station?.generalInfo && station?.generalInfo.reqLevel >= 0"
class="scenery-icon icon-info level"
:style="calculateExpStyle(station?.generalInfo.reqLevel)"
>
{{ station?.generalInfo.reqLevel >= 2 ? station?.generalInfo.reqLevel : 'L' }}
</span>
<span
v-if="station?.generalInfo"
class="scenery-icon icon-info" class="scenery-icon icon-info"
:class="station.generalInfo.controlType.replace('+', '-')" :class="station?.generalInfo.controlType.replace('+', '-')"
:title="$t('desc.control-type') + $t(`controls.${station.generalInfo.controlType}`)" :title="$t('desc.control-type') + $t(`controls.${station?.generalInfo.controlType}`)"
v-html="getControlTypeAbbrev(station.generalInfo.controlType)" v-html="getControlTypeAbbrev(station?.generalInfo.controlType)"
> >
</span> </span>
<img <img
v-if="station.generalInfo?.SUP" v-if="station?.generalInfo?.SUP"
class="icon-info" class="icon-info"
src="/images/icon-SUP.svg" src="/images/icon-SUP.svg"
alt="SUP (RASP-UZK)" alt="SUP (RASP-UZK)"
@@ -26,7 +35,7 @@
/> />
<img <img
v-if="station.generalInfo?.signalType" v-if="station?.generalInfo?.signalType"
class="icon-info" class="icon-info"
:src="`/images/icon-${station.generalInfo.signalType}.svg`" :src="`/images/icon-${station.generalInfo.signalType}.svg`"
:alt="station.generalInfo.signalType" :alt="station.generalInfo.signalType"
@@ -34,7 +43,7 @@
/> />
<img <img
v-if="station.generalInfo?.availability == 'nonPublic'" v-if="station?.generalInfo?.availability == 'nonPublic'"
class="icon-info" class="icon-info"
src="/images/icon-lock.svg" src="/images/icon-lock.svg"
alt="Non-public scenery" alt="Non-public scenery"
@@ -42,7 +51,7 @@
/> />
<img <img
v-if="station.generalInfo?.availability == 'unavailable'" v-if="station?.generalInfo?.availability == 'unavailable'"
class="icon-info" class="icon-info"
src="/images/icon-unavailable.svg" src="/images/icon-unavailable.svg"
alt="Unavailable scenery" alt="Unavailable scenery"
@@ -50,7 +59,7 @@
/> />
<img <img
v-if="station.generalInfo?.availability == 'abandoned'" v-if="station?.generalInfo?.availability == 'abandoned'"
class="icon-info" class="icon-info"
src="/images/icon-abandoned.svg" src="/images/icon-abandoned.svg"
alt="Abandoned scenery" alt="Abandoned scenery"
@@ -58,20 +67,12 @@
/> />
<img <img
v-if="station.generalInfo?.lines" v-if="station?.generalInfo?.lines"
class="icon-info" class="icon-info"
src="/images/icon-real.svg" src="/images/icon-real.svg"
alt="real scenery" alt="real scenery"
:title="`${$t('desc.real')} ${station.generalInfo.lines}`" :title="`${$t('desc.real')} ${station.generalInfo.lines}`"
/> />
<img
v-if="!station.generalInfo"
class="icon-info"
src="/images/icon-unknown.svg"
alt="icon-unknown"
:title="$t('desc.unknown')"
/>
</section> </section>
</template> </template>
@@ -85,8 +86,7 @@ export default defineComponent({
mixins: [stationInfoMixin, styleMixin], mixins: [stationInfoMixin, styleMixin],
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
required: true
} }
} }
}); });
+17 -11
View File
@@ -13,7 +13,7 @@
</span> </span>
</span> </span>
<span class="header_links"> <span class="header_links" v-if="station">
<a <a
:href="`https://pragotron-td2.web.app/board?name=${station.name}`" :href="`https://pragotron-td2.web.app/board?name=${station.name}`"
target="_blank" target="_blank"
@@ -48,7 +48,7 @@
<transition-group name="list-anim"> <transition-group name="list-anim">
<div <div
style="padding-bottom: 5em" style="padding-bottom: 5em"
v-if="store.dataStatuses.trains == 0 && computedScheduledTrains.length == 0" v-if="apiStore.dataStatuses.trains == 0 && computedScheduledTrains.length == 0"
key="list-loading" key="list-loading"
> >
<Loading /> <Loading />
@@ -187,10 +187,11 @@ import Loading from '../Global/Loading.vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import routerMixin from '../../mixins/routerMixin'; import routerMixin from '../../mixins/routerMixin';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import ScheduledTrainStatus from './ScheduledTrainStatus.vue'; import ScheduledTrainStatus from './ScheduledTrainStatus.vue';
import { OnlineScenery } from '../../store/typings'; import { OnlineScenery } from '../../store/typings';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
name: 'SceneryTimetable', name: 'SceneryTimetable',
@@ -201,12 +202,10 @@ export default defineComponent({
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
required: true
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<OnlineScenery>
required: false
} }
}, },
@@ -226,7 +225,8 @@ export default defineComponent({
const route = useRoute(); const route = useRoute();
const currentURL = computed(() => `${location.origin}${route.fullPath}`); const currentURL = computed(() => `${location.origin}${route.fullPath}`);
const store = useStore(); const apiStore = useApiStore();
const mainStore = useMainStore();
const chosenCheckpoint = ref( const chosenCheckpoint = ref(
props.station?.generalInfo?.checkpoints?.length == 0 props.station?.generalInfo?.checkpoints?.length == 0
@@ -237,25 +237,29 @@ export default defineComponent({
return { return {
currentURL, currentURL,
chosenCheckpoint, chosenCheckpoint,
store apiStore,
mainStore
}; };
}, },
computed: { computed: {
tabliceZbiorczeHref() { tabliceZbiorczeHref() {
let url = `https://tablice-td2.web.app/?station=${this.station.name}`; let url = `https://tablice-td2.web.app/?station=${this.station!.name}`;
if (this.chosenCheckpoint) url += `&checkpoint=${this.chosenCheckpoint}`; if (this.chosenCheckpoint) url += `&checkpoint=${this.chosenCheckpoint}`;
return url; return url;
}, },
computedScheduledTrains() { computedScheduledTrains() {
if (!this.station) return [];
return ( return (
this.onlineScenery?.scheduledTrains this.onlineScenery?.scheduledTrains
?.filter( ?.filter(
(train) => (train) =>
train.checkpointName.toLocaleLowerCase() == train.checkpointName.toLocaleLowerCase() ==
(this.chosenCheckpoint || this.station.name).toLocaleLowerCase() (this.chosenCheckpoint || this.station!.name).toLocaleLowerCase() &&
train.region == this.mainStore.region.id
) )
.sort((a, b) => { .sort((a, b) => {
if (a.stopStatusID > b.stopStatusID) return 1; if (a.stopStatusID > b.stopStatusID) return 1;
@@ -272,6 +276,8 @@ export default defineComponent({
methods: { methods: {
loadSelectedOption() { loadSelectedOption() {
if (!this.station) return;
this.chosenCheckpoint = this.chosenCheckpoint =
this.station.generalInfo?.checkpoints[0]?.checkpointName || this.station.name; this.station.generalInfo?.checkpoints[0]?.checkpointName || this.station.name;
}, },
@@ -63,29 +63,26 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from 'axios';
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { URLs } from '../../scripts/utils/apiURLs';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import listObserverMixin from '../../mixins/listObserverMixin'; import listObserverMixin from '../../mixins/listObserverMixin';
import { OnlineScenery } from '../../store/typings'; import { OnlineScenery } from '../../store/typings';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import http from '../../http';
export default defineComponent({ export default defineComponent({
name: 'SceneryTimetablesHistory', name: 'SceneryTimetablesHistory',
mixins: [dateMixin, listObserverMixin], mixins: [dateMixin, listObserverMixin],
props: { props: {
station: { station: {
type: Object as PropType<Station>, type: Object as PropType<Station>
required: true
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<OnlineScenery>
required: false
} }
}, },
@@ -103,10 +100,17 @@ export default defineComponent({
methods: { methods: {
async fetchAPIData(countFrom = 0, countLimit = 15) { async fetchAPIData(countFrom = 0, countLimit = 15) {
try { if (!this.station && !this.onlineScenery) {
const requestString = `${URLs.stacjownikAPI}/api/getTimetables?issuedFrom=${this.station.name}&countFrom=${countFrom}&countLimit=${countLimit}`; this.dataStatus = Status.Data.Loaded;
return;
}
const response: API.TimetableHistory.Response = await (await axios.get(requestString)).data; try {
const requestString = `api/getTimetables?issuedFrom=${
this.station?.name || this.onlineScenery?.name
}&countFrom=${countFrom}&countLimit=${countLimit}`;
const response: API.TimetableHistory.Response = await (await http.get(requestString)).data;
this.historyList = response; this.historyList = response;
@@ -117,7 +121,9 @@ export default defineComponent({
}, },
navigateToHistory() { navigateToHistory() {
this.$router.push(`/journal/timetables?issuedFrom=${this.station.name}`); this.$router.push(
`/journal/timetables?issuedFrom=${this.station?.name || this.onlineScenery?.name}`
);
} }
}, },
components: { Loading } components: { Loading }
@@ -139,7 +139,7 @@ import { defineComponent, inject } from 'vue';
import keyMixin from '../../mixins/keyMixin'; import keyMixin from '../../mixins/keyMixin';
import routerMixin from '../../mixins/routerMixin'; import routerMixin from '../../mixins/routerMixin';
import { useStationFiltersStore } from '../../store/stationFiltersStore'; import { useStationFiltersStore } from '../../store/stationFiltersStore';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import FilterOption from './FilterOption.vue'; import FilterOption from './FilterOption.vue';
import StorageManager from '../../managers/storageManager'; import StorageManager from '../../managers/storageManager';
@@ -163,7 +163,7 @@ export default defineComponent({
setup() { setup() {
const isVisible = inject('isFilterCardVisible'); const isVisible = inject('isFilterCardVisible');
const store = useStore(); const store = useMainStore();
const filterStore = useStationFiltersStore(); const filterStore = useStationFiltersStore();
return { return {
+9 -6
View File
@@ -116,7 +116,7 @@
<td class="station_dispatcher-name"> <td class="station_dispatcher-name">
<span v-if="station.onlineInfo?.dispatcherName"> <span v-if="station.onlineInfo?.dispatcherName">
<b <b
v-if="store.donatorsData.includes(station.onlineInfo.dispatcherName)" v-if="apiStore.donatorsData.includes(station.onlineInfo.dispatcherName)"
:title="$t('donations.dispatcher-message')" :title="$t('donations.dispatcher-message')"
@click.stop="openDonationModal" @click.stop="openDonationModal"
> >
@@ -294,11 +294,12 @@ import stationInfoMixin from '../../mixins/stationInfoMixin';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { useStationFiltersStore } from '../../store/stationFiltersStore'; import { useStationFiltersStore } from '../../store/stationFiltersStore';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames'; import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames';
import StationStatusBadge from '../Global/StationStatusBadge.vue'; import StationStatusBadge from '../Global/StationStatusBadge.vue';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -325,17 +326,19 @@ export default defineComponent({
}, },
setup() { setup() {
const store = useStore(); const mainStore = useMainStore();
const apiStore = useApiStore();
const stationFiltersStore = useStationFiltersStore(); const stationFiltersStore = useStationFiltersStore();
const isDataLoaded = computed(() => { const isDataLoaded = computed(() => {
return store.dataStatuses.sceneries != Status.Data.Loading; return apiStore.dataStatuses.sceneries != Status.Data.Loading;
}); });
return { return {
isDataLoaded, isDataLoaded,
stationFiltersStore, stationFiltersStore,
store mainStore,
apiStore
}; };
}, },
@@ -357,7 +360,7 @@ export default defineComponent({
openDonationModal(e: Event) { openDonationModal(e: Event) {
this.$emit('toggleDonationModal', true); this.$emit('toggleDonationModal', true);
this.store.modalLastClickedTarget = e.target; this.mainStore.modalLastClickedTarget = e.target;
}, },
openForumSite(e: Event, url: string | undefined) { openForumSite(e: Event, url: string | undefined) {
+5 -3
View File
@@ -35,7 +35,7 @@
<div class="train-driver"> <div class="train-driver">
<b <b
v-if="store.donatorsData.includes(train.driverName)" v-if="apiStore.donatorsData.includes(train.driverName)"
:title="$t('donations.driver-message')" :title="$t('donations.driver-message')"
> >
{{ train.driverName }} {{ train.driverName }}
@@ -126,7 +126,8 @@ import trainInfoMixin from '../../mixins/trainInfoMixin';
import Train from '../../scripts/interfaces/Train'; import Train from '../../scripts/interfaces/Train';
import ProgressBar from '../Global/ProgressBar.vue'; import ProgressBar from '../Global/ProgressBar.vue';
import TrainThumbnail from '../Global/TrainThumbnail.vue'; import TrainThumbnail from '../Global/TrainThumbnail.vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
mixins: [trainInfoMixin, styleMixin], mixins: [trainInfoMixin, styleMixin],
@@ -145,7 +146,8 @@ export default defineComponent({
data() { data() {
return { return {
store: useStore() store: useMainStore(),
apiStore: useApiStore()
}; };
} }
}); });
+2 -2
View File
@@ -72,7 +72,7 @@
import { computed, defineComponent, PropType } from 'vue'; import { computed, defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Train from '../../scripts/interfaces/Train'; import Train from '../../scripts/interfaces/Train';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import StopDate from '../Global/StopDate.vue'; import StopDate from '../Global/StopDate.vue';
import StockList from '../Global/StockList.vue'; import StockList from '../Global/StockList.vue';
import { TrainStop } from '../../store/typings'; import { TrainStop } from '../../store/typings';
@@ -92,7 +92,7 @@ export default defineComponent({
setup(props) { setup(props) {
return { return {
store: useStore(), store: useMainStore(),
lastConfirmed: computed(() => { lastConfirmed: computed(() => {
return props.train.timetableData!.followingStops.findIndex( return props.train.timetableData!.followingStops.findIndex(
+6 -4
View File
@@ -16,7 +16,7 @@
<hr style="margin: 0.5em 0" /> <hr style="margin: 0.5em 0" />
<div v-if="store.dataStatuses.trains == Status.Loaded && regionTrains.length > 0"> <div v-if="apiStore.dataStatuses.trains == Status.Loaded && regionTrains.length > 0">
<div class="top-list general"> <div class="top-list general">
<transition-group tag="ul" name="stats-anim"> <transition-group tag="ul" name="stats-anim">
<li class="badge" key="timetable-count"> <li class="badge" key="timetable-count">
@@ -88,7 +88,7 @@
</div> </div>
</div> </div>
<div v-else-if="store.dataStatuses.trains != Status.Loaded"> <div v-else-if="apiStore.dataStatuses.trains != Status.Loaded">
{{ $t('train-stats.stats-loading') }} {{ $t('train-stats.stats-loading') }}
</div> </div>
@@ -102,8 +102,9 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore';
interface ITop { interface ITop {
name: string; name: string;
@@ -127,7 +128,8 @@ export default defineComponent({
data() { data() {
return { return {
showOptions: false, showOptions: false,
store: useStore(), store: useMainStore(),
apiStore: useApiStore(),
Status: Status.Data Status: Status.Data
}; };
}, },
+9 -6
View File
@@ -1,16 +1,16 @@
<template> <template>
<transition name="status-anim" mode="out-in" tag="div" class="train-table"> <transition name="status-anim" mode="out-in" tag="div" class="train-table">
<div :key="store.dataStatuses.trains"> <div :key="apiStore.dataStatuses.trains">
<div class="table-info" key="offline" v-if="store.isOffline"> <div class="table-info" key="offline" v-if="store.isOffline">
{{ $t('app.offline') }} {{ $t('app.offline') }}
</div> </div>
<Loading v-else-if="trains.length == 0 && store.dataStatuses.trains == 0" key="loading" /> <Loading v-else-if="trains.length == 0 && apiStore.dataStatuses.trains == 0" key="loading" />
<div <div
class="table-info" class="table-info"
key="no-trains" key="no-trains"
v-else-if="trains.length == 0 && store.dataStatuses.trains != 0" v-else-if="trains.length == 0 && apiStore.dataStatuses.trains != 0"
> >
{{ $t('trains.no-trains') }} {{ $t('trains.no-trains') }}
</div> </div>
@@ -35,10 +35,11 @@
import { defineComponent, inject, PropType, Ref } from 'vue'; import { defineComponent, inject, PropType, Ref } from 'vue';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import Train from '../../scripts/interfaces/Train'; import Train from '../../scripts/interfaces/Train';
import { useStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import TrainInfo from './TrainInfo.vue'; import TrainInfo from './TrainInfo.vue';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
components: { Loading, TrainInfo }, components: { Loading, TrainInfo },
@@ -53,7 +54,8 @@ export default defineComponent({
mixins: [modalTrainMixin], mixins: [modalTrainMixin],
setup() { setup() {
const store = useStore(); const store = useMainStore();
const apiStore = useApiStore();
const searchedTrain = inject('searchedTrain') as Ref<string>; const searchedTrain = inject('searchedTrain') as Ref<string>;
const searchedDriver = inject('searchedDriver') as Ref<string>; const searchedDriver = inject('searchedDriver') as Ref<string>;
@@ -61,6 +63,7 @@ export default defineComponent({
searchedTrain, searchedTrain,
searchedDriver, searchedDriver,
store, store,
apiStore,
sorterActive: inject('sorterActive') as { sorterActive: inject('sorterActive') as {
id: string | number; id: string | number;
dir: number; dir: number;
@@ -72,7 +75,7 @@ export default defineComponent({
dataStatus() { dataStatus() {
if (this.store.isOffline) return Status.Data.Offline; if (this.store.isOffline) return Status.Data.Offline;
if (this.trains.length == 0 && this.store.dataStatuses.trains == Status.Data.Loading) if (this.trains.length == 0 && this.apiStore.dataStatuses.trains == Status.Data.Loading)
return Status.Data.Loading; return Status.Data.Loading;
return Status.Data.Loaded; return Status.Data.Loaded;
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
import axios from 'axios';
const http = axios.create({
baseURL:
import.meta.env.VITE_API_MODE === 'development'
? 'http://localhost:3001'
: 'https://stacjownik.spythere.eu'
});
export default http;
+2 -2
View File
@@ -405,8 +405,8 @@
"two-way-routes": "Two way routes", "two-way-routes": "Two way routes",
"option-active-timetables": "Active timetables", "option-active-timetables": "Active timetables",
"option-timetables-history": "Timetables history", "option-timetables-history": "Timetables history PL1",
"option-dispatchers-history": "Dispatchers history", "option-dispatchers-history": "Dispatchers history PL1",
"timetable-author-title": "Issued by", "timetable-author-title": "Issued by",
"timetable-author-unknown": "Author unknown", "timetable-author-unknown": "Author unknown",
+2 -2
View File
@@ -386,8 +386,8 @@
"two-way-routes": "Szlaki dwutorowe", "two-way-routes": "Szlaki dwutorowe",
"option-active-timetables": "Aktywne rozkłady jazdy", "option-active-timetables": "Aktywne rozkłady jazdy",
"option-timetables-history": "Historia rozkładów", "option-timetables-history": "Historia rozkładów PL1",
"option-dispatchers-history": "Historia dyżurów", "option-dispatchers-history": "Historia dyżurów PL1",
"timetable-author-title": "Wydany przez", "timetable-author-title": "Wydany przez",
"timetable-author-unknown": "Autor nieznany", "timetable-author-unknown": "Autor nieznany",
+3 -3
View File
@@ -1,16 +1,16 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../store/mainStore'; import { useApiStore } from '../store/apiStore';
export default defineComponent({ export default defineComponent({
data() { data() {
return { return {
store: useStore() apiStore: useApiStore()
}; };
}, },
methods: { methods: {
isDonator(name: string) { isDonator(name: string) {
return this.store.donatorsData.includes(name); return this.apiStore.donatorsData.includes(name);
} }
} }
}); });
+2 -2
View File
@@ -1,10 +1,10 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useStore } from '../store/mainStore'; import { useMainStore } from '../store/mainStore';
export default defineComponent({ export default defineComponent({
data() { data() {
return { return {
store: useStore() store: useMainStore()
}; };
}, },
+1 -3
View File
@@ -61,12 +61,10 @@ const routes: Array<RouteRecordRaw> = [
const router = createRouter({ const router = createRouter({
scrollBehavior(to, from, savedPosition) { scrollBehavior(to, from, savedPosition) {
if (to.name == 'SceneryView' && from.name && from.query['view'] === undefined) if (to.name == 'SceneryView' && from.name !== to.name && from.query['view'] === undefined)
return { el: `.app_main` }; return { el: `.app_main` };
if (savedPosition) return savedPosition; if (savedPosition) return savedPosition;
// if (from.name == 'SceneryView' && to.name == 'StationsView') return { el: `.last-selected`, top: 20 };
}, },
history: createWebHistory(), history: createWebHistory(),
routes routes
-7
View File
@@ -1,7 +0,0 @@
export const URLs = {
stacjownikAPI:
import.meta.env.VITE_APP_API_DEV === '1' && !import.meta.env.PROD
? 'http://localhost:3001'
: 'https://stacjownik.spythere.eu',
stacjownikAPIDev: 'localhost:3000'
};
+114
View File
@@ -0,0 +1,114 @@
import { defineStore } from 'pinia';
import http from '../http';
import { API } from '../typings/api';
import axios from 'axios';
import { Status } from '../typings/common';
import { StationJSONData } from './typings';
export const useApiStore = defineStore('apiStore', {
state: () => ({
dataStatuses: {
connection: Status.Data.Loading,
sceneries: Status.Data.Loading,
timetables: Status.Data.Loading,
dispatchers: Status.Data.Loading,
trains: Status.Data.Loading
},
activeData: undefined as API.ActiveData.Response | undefined,
rollingStockData: undefined as API.RollingStock.Response | undefined,
donatorsData: [] as API.Donators.Response,
sceneryData: [] as StationJSONData[]
}),
actions: {
async setupAPI() {
// Static data
this.fetchStockInfoData();
this.fetchDonatorsData();
this.fetchStationsGeneralInfo();
this.scheduleFetchActiveData();
},
async setDataStatuses() {
if (!this.activeData?.activeSceneries) {
this.dataStatuses.sceneries = Status.Data.Error;
this.dataStatuses.trains = Status.Data.Error;
this.dataStatuses.dispatchers = Status.Data.Error;
return;
}
this.dataStatuses.sceneries = Status.Data.Loaded;
this.dataStatuses.trains = !this.activeData.trains ? Status.Data.Warning : Status.Data.Loaded;
this.dataStatuses.dispatchers = Status.Data.Loaded;
},
async fetchDonatorsData() {
try {
const response = await http.get<API.Donators.Response>('api/getDonators');
this.donatorsData = response.data;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania informacji o donatorach:', error);
}
},
async fetchStockInfoData() {
try {
this.rollingStockData = (
await axios.get<API.RollingStock.Response>(
'https://raw.githubusercontent.com/Spythere/api/main/td2/data/stockInfo.json'
)
).data;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania informacji o taborze z API:', error);
}
},
async scheduleFetchActiveData() {
if (import.meta.env.VITE_API_MODE === 'mock') {
const mockActiveData = await import('../data/mockActiveData.json');
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = mockActiveData;
this.setDataStatuses();
console.warn('Stacjownik działa w trybie mockowania danych z WS');
return;
}
try {
const data = (await http.get<API.ActiveData.Response>('api/getActiveData')).data;
this.activeData = data;
this.dataStatuses.connection = Status.Data.Loaded;
this.setDataStatuses();
} catch (error) {
this.dataStatuses.connection = Status.Data.Error;
console.error('Wystąpił błąd podczas pobierania danych online z API!');
} finally {
setTimeout(
() => {
this.scheduleFetchActiveData();
},
~~(1000 * (Math.random() * (25 - 20) + 25))
);
}
},
async fetchStationsGeneralInfo() {
const sceneryData: StationJSONData[] = (await http.get<StationJSONData[]>('api/getSceneries'))
.data;
if (!sceneryData) {
this.dataStatuses.sceneries = Status.Data.Error;
return;
}
this.sceneryData = sceneryData;
}
}
});
+102 -140
View File
@@ -1,38 +1,20 @@
import axios from 'axios';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { io } from 'socket.io-client';
import StationRoutes from '../scripts/interfaces/StationRoutes'; import StationRoutes from '../scripts/interfaces/StationRoutes';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
import { URLs } from '../scripts/utils/apiURLs';
import { parseSpawns, getScheduledTrains, getStationTrains } from './utils'; import { parseSpawns, getScheduledTrains, getStationTrains } from './utils';
import { OnlineScenery, ScheduledTrain, StationJSONData, StoreState } from './typings'; import { OnlineScenery, ScheduledTrain, StoreState } from './typings';
import packageInfo from '../../package.json';
import { Websocket, API } from '../typings/api';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
import Station from '../scripts/interfaces/Station';
import { useApiStore } from './apiStore';
import { API } from '../typings/api';
export const useStore = defineStore('store', { export const useMainStore = defineStore('store', {
state: () => state: () =>
({ ({
activeData: {} as unknown,
rollingStockData: undefined,
donatorsData: [],
stationList: [],
regionOnlineCounters: [],
routesList: [],
sceneryData: [],
lastDispatcherStatuses: [],
region: { id: 'eu', value: 'PL1' }, region: { id: 'eu', value: 'PL1' },
trainCount: 0,
stationCount: 0,
webSocket: undefined,
isOffline: false, isOffline: false,
dispatcherStatsName: '', dispatcherStatsName: '',
@@ -44,31 +26,15 @@ export const useStore = defineStore('store', {
chosenModalTrainId: undefined, chosenModalTrainId: undefined,
dataStatuses: {
connection: Status.Data.Loading,
sceneries: Status.Data.Loading,
timetables: Status.Data.Loading,
dispatchers: Status.Data.Loading,
trains: Status.Data.Loading
},
currentStatsTab: null,
blockScroll: false, blockScroll: false,
listenerLaunched: false, modalLastClickedTarget: null
modalLastClickedTarget: null,
tooltip: {
content: '',
visible: false,
x: 0,
y: 0
}
}) as StoreState, }) as StoreState,
getters: { getters: {
trainList(): Train[] { trainList(): Train[] {
return (this.activeData?.trains ?? []) const apiStore = useApiStore();
return (apiStore.activeData?.trains ?? [])
.filter((train) => train.timetable || train.online) .filter((train) => train.timetable || train.online)
.map((train) => { .map((train) => {
const stock = train.stockString.split(';'); const stock = train.stockString.split(';');
@@ -87,7 +53,7 @@ export const useStore = defineStore('store', {
distance: train.distance, distance: train.distance,
signal: train.signal, signal: train.signal,
online: train.online, online: Boolean(train.online),
driverId: train.driverId, driverId: train.driverId,
driverName: train.driverName, driverName: train.driverName,
currentStationName: train.currentStationName, currentStationName: train.currentStationName,
@@ -119,10 +85,12 @@ export const useStore = defineStore('store', {
}, },
onlineSceneryList(state): OnlineScenery[] { onlineSceneryList(state): OnlineScenery[] {
if (state.isOffline) return []; const apiStore = useApiStore();
if (!state.activeData?.activeSceneries) return [];
return state.activeData?.activeSceneries.reduce((list, scenery) => { if (state.isOffline) return [];
if (!apiStore.activeData?.activeSceneries) return [];
return apiStore.activeData?.activeSceneries.reduce((list, scenery) => {
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return list; if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return list;
if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return list; if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return list;
@@ -181,20 +149,12 @@ export const useStore = defineStore('store', {
return list; return list;
}, [] as OnlineScenery[]); }, [] as OnlineScenery[]);
}
}, },
actions: {
async fetchStationsGeneralInfo() {
const sceneryData: StationJSONData[] = await (
await axios.get(`${URLs.stacjownikAPI}/api/getSceneries`)
).data;
if (!sceneryData) { stationList(): Station[] {
this.dataStatuses.sceneries = Status.Data.Error; const apiStore = useApiStore();
return;
}
this.stationList = sceneryData.map((scenery) => { return apiStore.sceneryData.map((scenery) => {
return { return {
name: scenery.name, name: scenery.name,
@@ -243,95 +203,97 @@ export const useStore = defineStore('store', {
} }
}; };
}); });
},
async connectToWebsocket() {
if (import.meta.env.VITE_APP_WS_DEV === '1') {
const mockWebsocketData = await import('../data/mockWebsocketData.json');
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = mockWebsocketData as any;
this.setStatuses();
console.warn('Stacjownik działa w trybie mockowania danych z WS');
return;
} }
const socket = io(URLs.stacjownikAPI, {
transports: ['websocket', 'polling'],
rememberUpgrade: true,
reconnection: true
});
socket.emit('CONNECTION', { version: packageInfo.version });
socket.on('connect_error', () => {
this.dataStatuses.connection = Status.Data.Error;
});
socket.on('UPDATE', (data: Websocket.ActiveData) => {
this.activeData = data;
this.dataStatuses.connection = Status.Data.Loaded;
this.setStatuses();
});
socket.emit('FETCH_DATA', { version: packageInfo.version }, (data: Websocket.ActiveData) => {
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = data;
this.setStatuses();
});
this.webSocket = socket;
}, },
actions: {
async processStationsOnlineInfo(activeData: API.ActiveData.Response) {
if (!activeData.activeSceneries) return;
async connectToAPI() { const onlineSceneries = activeData.activeSceneries.reduce((acc, scenery) => {
this.connectToWebsocket(); const savedStation = this.stationList.find((st) => scenery.stationName === st.name);
this.fetchStockInfoData();
this.fetchDonatorsData(); if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return acc;
this.fetchStationsGeneralInfo(); if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return acc;
const station = this.stationList.find((s) => s.name === scenery.stationName);
const scheduledTrains = getScheduledTrains(this.trainList, scenery, station?.generalInfo);
const stationTrains = getStationTrains(
this.trainList,
scheduledTrains,
this.region.id,
scenery
);
// Remove checkpoint duplicates
const uniqueScheduledTrains = scheduledTrains.reduce(
(uniqueList, sTrain) =>
uniqueList.find((v) => v.trainId === sTrain.trainId)
? uniqueList
: [...uniqueList, sTrain],
[] as ScheduledTrain[]
);
const dispatcherTimestamp =
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT
? Date.now() + 25500000
: scenery.dispatcherStatus > 5
? scenery.dispatcherStatus
: null;
const onlineInfo = {
name: scenery.stationName,
hash: scenery.stationHash,
region: scenery.region,
maxUsers: scenery.maxUsers,
currentUsers: scenery.currentUsers,
spawns: parseSpawns(scenery.spawnString),
dispatcherName: scenery.dispatcherName,
dispatcherRate: scenery.dispatcherRate,
dispatcherId: scenery.dispatcherId,
dispatcherExp: scenery.dispatcherExp,
dispatcherIsSupporter: scenery.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
dispatcherStatus: scenery.dispatcherStatus,
dispatcherTimestamp: dispatcherTimestamp,
isOnline: scenery.isOnline == 1,
scheduledTrainCount: {
all: uniqueScheduledTrains.length,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length
}
};
if (savedStation) savedStation.onlineInfo = onlineInfo;
else
this.stationList.push({
name: onlineInfo.name,
onlineInfo: onlineInfo
});
acc.push(onlineInfo);
return acc;
}, [] as OnlineScenery[]);
// Reset online info of already offline sceneries
this.stationList
.filter(
(station) =>
station.onlineInfo &&
onlineSceneries.findIndex(
(os) => os.region == station.onlineInfo!.region && station.name == os.name
) != -1
)
.forEach((station) => (station.onlineInfo = undefined));
}, },
async changeRegion(region: StoreState['region']) { async changeRegion(region: StoreState['region']) {
this.region = region; this.region = region;
},
async fetchStockInfoData() {
try {
this.rollingStockData = (
await axios.get<API.RollingStock.Response>(
'https://raw.githubusercontent.com/Spythere/api/main/td2/data/stockInfo.json'
)
).data;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania informacji o taborze z API:', error);
}
},
async fetchDonatorsData() {
try {
const response = await axios.get<API.Donators.Response>(
`${URLs.stacjownikAPI}/api/getDonators`
);
if (response.data) this.donatorsData = response.data;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania informacji o donatorach:', error);
}
},
async setStatuses() {
if (!this.activeData.activeSceneries) {
this.dataStatuses.sceneries = Status.Data.Error;
this.dataStatuses.trains = Status.Data.Error;
this.dataStatuses.dispatchers = Status.Data.Error;
return;
}
this.dataStatuses.sceneries = Status.Data.Loaded;
this.dataStatuses.trains = !this.activeData.trains ? Status.Data.Warning : Status.Data.Loaded;
this.dataStatuses.dispatchers = Status.Data.Loaded;
} }
} }
}); });
+16 -4
View File
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import inputData from '../data/options.json'; import inputData from '../data/options.json';
import { useStore } from './mainStore'; import { useMainStore } from './mainStore';
import { filterStations, sortStations } from '../scripts/utils/filterUtils'; import { filterStations, sortStations } from '../scripts/utils/filterUtils';
import { HeadIdsTypes } from '../scripts/data/stationHeaderNames'; import { HeadIdsTypes } from '../scripts/data/stationHeaderNames';
import StorageManager from '../managers/storageManager'; import StorageManager from '../managers/storageManager';
@@ -70,14 +70,26 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
}, },
filteredStationList: (state) => { filteredStationList: (state) => {
const store = useStore(); const store = useMainStore();
return store.stationList const savedStationNames = store.stationList.map((s) => s.name);
.map((station) => ({
const onlineUnsavedStations = store.onlineSceneryList
.filter((os) => !savedStationNames.includes(os.name) && os.region == store.region.id)
.map((os) => ({
name: os.name,
generalInfo: undefined,
onlineInfo: os
}));
return [
...onlineUnsavedStations,
...store.stationList.map((station) => ({
...station, ...station,
onlineInfo: store.onlineSceneryList.find( onlineInfo: store.onlineSceneryList.find(
(os) => os.name == station.name && os.region == store.region.id (os) => os.name == station.name && os.region == store.region.id
) )
})) }))
]
.filter((station) => filterStations(station, state.filters)) .filter((station) => filterStations(station, state.filters))
.sort((a, b) => sortStations(a, b, state.sorterActive)); .sort((a, b) => sortStations(a, b, state.sorterActive));
} }
+3 -38
View File
@@ -1,6 +1,5 @@
import { Socket } from 'socket.io-client';
import Station from '../scripts/interfaces/Station'; import Station from '../scripts/interfaces/Station';
import { API, Websocket } from '../typings/api'; import { API } from '../typings/api';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault'; export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
@@ -12,26 +11,8 @@ export interface RegionCounters {
} }
export interface StoreState { export interface StoreState {
stationList: Station[];
activeData: Websocket.ActiveData;
rollingStockData?: API.RollingStock.Response;
donatorsData: API.Donators.Response;
regionOnlineCounters: RegionCounters[];
lastDispatcherStatuses: {
hash: string;
statusTimestamp: number;
statusID: Status.ActiveDispatcher;
}[];
sceneryData: any[][];
region: { id: string; value: string }; region: { id: string; value: string };
trainCount: number;
stationCount: number;
webSocket?: Socket;
isOffline: boolean; isOffline: boolean;
dispatcherStatsName: string; dispatcherStatsName: string;
@@ -43,26 +24,8 @@ export interface StoreState {
chosenModalTrainId?: string; chosenModalTrainId?: string;
currentStatsTab: 'daily' | 'driver' | null;
dataStatuses: {
connection: Status.Data;
sceneries: Status.Data;
timetables: Status.Data;
dispatchers: Status.Data;
trains: Status.Data;
};
listenerLaunched: boolean;
blockScroll: boolean; blockScroll: boolean;
modalLastClickedTarget: EventTarget | null; modalLastClickedTarget: EventTarget | null;
tooltip: {
visible: boolean;
x: number;
y: number;
content: string;
};
} }
export interface StationRoutesInfo { export interface StationRoutesInfo {
@@ -166,6 +129,8 @@ export interface ScheduledTrain {
stopLabel: string; stopLabel: string;
stopStatus: StopStatus; stopStatus: StopStatus;
stopStatusID: number; stopStatusID: number;
region: string;
} }
export enum StopStatus { export enum StopStatus {
+2
View File
@@ -175,6 +175,8 @@ export function getCheckpointTrain(
stopStatus: trainStopStatus.stopStatus, stopStatus: trainStopStatus.stopStatus,
stopStatusID: trainStopStatus.stopStatusID, stopStatusID: trainStopStatus.stopStatusID,
region: train.region,
arrivingLine, arrivingLine,
departureLine, departureLine,
+14 -16
View File
@@ -1,6 +1,12 @@
import { Status } from './common'; import { Status } from './common';
export namespace API { export namespace API {
export namespace ActiveData {
export interface Response {
activeSceneries?: API.ActiveSceneries.Response;
trains?: API.ActiveTrains.Response;
}
}
export namespace DispatcherHistory { export namespace DispatcherHistory {
export type Response = Data[]; export type Response = Data[];
@@ -116,9 +122,9 @@ export namespace API {
driverLevel?: number; driverLevel?: number;
currentStationName: string; currentStationName: string;
currentStationHash: string; currentStationHash?: string;
online: boolean; online: number;
lastSeen: number; lastSeen: number;
region: string; region: string;
@@ -132,16 +138,16 @@ export namespace API {
stopNameRAW: string; stopNameRAW: string;
stopType: string; stopType: string;
stopDistance: number; stopDistance: number;
pointId: number; pointId: string;
mainStop: boolean; mainStop: boolean;
arrivalLine: string; arrivalLine: string | null;
arrivalTimestamp: number; arrivalTimestamp: number;
arrivalRealTimestamp: number; arrivalRealTimestamp: number;
arrivalDelay: number; arrivalDelay: number;
departureLine: string; departureLine: string | null;
departureTimestamp: number; departureTimestamp: number;
departureRealTimestamp: number; departureRealTimestamp: number;
departureDelay: number; departureDelay: number;
@@ -150,9 +156,9 @@ export namespace API {
beginsHere: boolean; beginsHere: boolean;
terminatesHere: boolean; terminatesHere: boolean;
confirmed: boolean; confirmed: number;
stopped: boolean; stopped: number;
stopTime: number; stopTime: number | null;
} }
export interface Timetable { export interface Timetable {
@@ -280,14 +286,6 @@ export namespace API {
} }
} }
export namespace Websocket {
export interface ActiveData {
activeSceneries?: API.ActiveSceneries.Response;
trains?: API.ActiveTrains.Response;
connectedSocketCount: number;
}
}
export namespace GithubAPI { export namespace GithubAPI {
export namespace Release { export namespace Release {
export interface Author { export interface Author {
+5 -10
View File
@@ -32,11 +32,9 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, provide, reactive, Ref, ref } from 'vue'; import { defineComponent, provide, reactive, Ref, ref } from 'vue';
import axios from 'axios';
import JournalOptions from '../components/JournalView/JournalOptions.vue'; import JournalOptions from '../components/JournalView/JournalOptions.vue';
import { URLs } from '../scripts/utils/apiURLs'; import { useMainStore } from '../store/mainStore';
import { useStore } from '../store/mainStore';
import JournalDispatchersList from '../components/JournalView/JournalDispatchersList.vue'; import JournalDispatchersList from '../components/JournalView/JournalDispatchersList.vue';
import JournalHeader from '../components/JournalView/JournalHeader.vue'; import JournalHeader from '../components/JournalView/JournalHeader.vue';
@@ -44,8 +42,7 @@ import { LocationQuery } from 'vue-router';
import { Journal } from '../components/JournalView/typings'; import { Journal } from '../components/JournalView/typings';
import { API } from '../typings/api'; import { API } from '../typings/api';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
import http from '../http';
const DISPATCHERS_API_URL = `${URLs.stacjownikAPI}/api/getDispatchers`;
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -105,7 +102,7 @@ export default defineComponent({
const scrollElement: Ref<HTMLElement | null> = ref(null); const scrollElement: Ref<HTMLElement | null> = ref(null);
return { return {
store: useStore(), store: useMainStore(),
sorterActive, sorterActive,
searchersValues, searchersValues,
@@ -183,9 +180,7 @@ export default defineComponent({
this.countFromIndex = this.historyList.length; this.countFromIndex = this.historyList.length;
const responseData: API.DispatcherHistory.Response = await ( const responseData: API.DispatcherHistory.Response = await (
await axios.get( await http.get(`api/getDispatchers?${this.currentQuery}&countFrom=${this.countFromIndex}`)
`${DISPATCHERS_API_URL}?${this.currentQuery}&countFrom=${this.countFromIndex}`
)
).data; ).data;
if (!responseData) return; if (!responseData) return;
@@ -232,7 +227,7 @@ export default defineComponent({
if (reset) this.dataStatus = Status.Data.Loading; if (reset) this.dataStatus = Status.Data.Loading;
const responseData: API.DispatcherHistory.Response = await ( const responseData: API.DispatcherHistory.Response = await (
await axios.get(`${DISPATCHERS_API_URL}?${this.currentQuery}`) await http.get(`api/getDispatchers?${this.currentQuery}`)
).data; ).data;
if (!responseData) { if (!responseData) {
+5 -8
View File
@@ -35,7 +35,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, provide, reactive, Ref, ref } from 'vue'; import { defineComponent, provide, reactive, Ref, ref } from 'vue';
import axios from 'axios';
import dateMixin from '../mixins/dateMixin'; import dateMixin from '../mixins/dateMixin';
import routerMixin from '../mixins/routerMixin'; import routerMixin from '../mixins/routerMixin';
@@ -45,8 +44,7 @@ import JournalOptions from '../components/JournalView/JournalOptions.vue';
import JournalStats from '../components/JournalView/JournalStats.vue'; import JournalStats from '../components/JournalView/JournalStats.vue';
import JournalHeader from '../components/JournalView/JournalHeader.vue'; import JournalHeader from '../components/JournalView/JournalHeader.vue';
import { URLs } from '../scripts/utils/apiURLs'; import { useMainStore } from '../store/mainStore';
import { useStore } from '../store/mainStore';
import { LocationQuery } from 'vue-router'; import { LocationQuery } from 'vue-router';
@@ -54,8 +52,7 @@ import JournalTimetablesList from '../components/JournalView/JournalTimetables/J
import { Journal } from '../components/JournalView/typings'; import { Journal } from '../components/JournalView/typings';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
import { API } from '../typings/api'; import { API } from '../typings/api';
import http from '../http';
const TIMETABLES_API_URL = `${URLs.stacjownikAPI}/api/getTimetables`;
export const journalTimetableFilters: Journal.TimetableFilter[] = [ export const journalTimetableFilters: Journal.TimetableFilter[] = [
{ {
@@ -194,7 +191,7 @@ export default defineComponent({
scrollElement, scrollElement,
store: useStore() store: useMainStore()
}; };
}, },
@@ -272,7 +269,7 @@ export default defineComponent({
this.currentQueryParams['countFrom'] = this.timetableHistory.length; this.currentQueryParams['countFrom'] = this.timetableHistory.length;
const responseData: API.TimetableHistory.Response = await ( const responseData: API.TimetableHistory.Response = await (
await axios.get(`${TIMETABLES_API_URL}`, { await http.get('api/getTimetables', {
params: { ...this.currentQueryParams } params: { ...this.currentQueryParams }
}) })
).data; ).data;
@@ -365,7 +362,7 @@ export default defineComponent({
try { try {
const responseData: API.TimetableHistory.Response = await ( const responseData: API.TimetableHistory.Response = await (
await axios.get(`${TIMETABLES_API_URL}`, { await http.get('api/getTimetables', {
params: this.currentQueryParams params: this.currentQueryParams
}) })
).data; ).data;
+28 -10
View File
@@ -1,14 +1,17 @@
<template> <template>
<div class="scenery-view"> <div class="scenery-view">
<div class="scenery-offline" v-if="!stationInfo && store.dataStatuses.sceneries == 2"> <!-- <div
class="scenery-offline"
v-if="!stationInfo && !onlineSceneryInfo && store.dataStatuses.sceneries == 2"
>
<div>{{ $t('scenery.no-scenery') }}</div> <div>{{ $t('scenery.no-scenery') }}</div>
<action-button> <action-button>
<router-link to="/">{{ $t('scenery.return-btn') }}</router-link> <router-link to="/">{{ $t('scenery.return-btn') }}</router-link>
</action-button> </action-button>
</div> </div> -->
<div class="scenery-wrapper" v-if="stationInfo" ref="card-wrapper"> <div class="scenery-wrapper" ref="card-wrapper">
<div class="scenery-left"> <div class="scenery-left">
<div class="scenery-actions"> <div class="scenery-actions">
<button class="back-btn btn" :title="$t('scenery.return-btn')" @click="navigateTo('/')"> <button class="back-btn btn" :title="$t('scenery.return-btn')" @click="navigateTo('/')">
@@ -16,7 +19,11 @@
</button> </button>
</div> </div>
<SceneryHeader :station="stationInfo" :onlineScenery="onlineSceneryInfo" /> <SceneryHeader
:stationName="station"
:station="stationInfo"
:onlineScenery="onlineSceneryInfo"
/>
<SceneryInfo :station="stationInfo" :onlineScenery="onlineSceneryInfo" /> <SceneryInfo :station="stationInfo" :onlineScenery="onlineSceneryInfo" />
</div> </div>
@@ -33,7 +40,14 @@
</button> </button>
</div> </div>
<keep-alive> <div
v-if="
apiStore.dataStatuses.sceneries == Status.Loading ||
apiStore.dataStatuses.trains == Status.Loading
"
></div>
<keep-alive v-else>
<component <component
:is="currentMode" :is="currentMode"
:onlineScenery="onlineSceneryInfo" :onlineScenery="onlineSceneryInfo"
@@ -50,7 +64,7 @@
import { computed, defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import routerMixin from '../mixins/routerMixin'; import routerMixin from '../mixins/routerMixin';
import { useStore } from '../store/mainStore'; import { useMainStore } from '../store/mainStore';
import SceneryInfo from '../components/SceneryView/SceneryInfo.vue'; import SceneryInfo from '../components/SceneryView/SceneryInfo.vue';
import SceneryHeader from '../components/SceneryView/SceneryHeader.vue'; import SceneryHeader from '../components/SceneryView/SceneryHeader.vue';
@@ -58,6 +72,8 @@ import SceneryTimetable from '../components/SceneryView/SceneryTimetable.vue';
import SceneryTimetablesHistory from '../components/SceneryView/SceneryTimetablesHistory.vue'; import SceneryTimetablesHistory from '../components/SceneryView/SceneryTimetablesHistory.vue';
import SceneryDispatchersHistory from '../components/SceneryView/SceneryDispatchersHistory.vue'; import SceneryDispatchersHistory from '../components/SceneryView/SceneryDispatchersHistory.vue';
import ActionButton from '../components/Global/ActionButton.vue'; import ActionButton from '../components/Global/ActionButton.vue';
import { Status } from '../typings/common';
import { useApiStore } from '../store/apiStore';
enum SceneryViewMode { enum SceneryViewMode {
'TIMETABLES_ACTIVE', 'TIMETABLES_ACTIVE',
@@ -92,7 +108,9 @@ export default defineComponent({
mixins: [routerMixin], mixins: [routerMixin],
data: () => ({ data: () => ({
store: useStore(), store: useMainStore(),
apiStore: useApiStore(),
viewModes: [ viewModes: [
{ {
id: 'scenery.option-active-timetables', id: 'scenery.option-active-timetables',
@@ -110,7 +128,8 @@ export default defineComponent({
sceneryViewMode: SceneryViewMode, sceneryViewMode: SceneryViewMode,
selectedCheckpoint: '', selectedCheckpoint: '',
currentViewCompontent: 'SceneryTimetable', currentViewCompontent: 'SceneryTimetable',
onlineFrom: -1 onlineFrom: -1,
Status: Status.Data
}), }),
// activated() { // activated() {
@@ -185,8 +204,6 @@ button.back-btn {
&-view { &-view {
display: flex; display: flex;
justify-content: center; justify-content: center;
min-height: 100vh;
} }
&-offline { &-offline {
@@ -215,6 +232,7 @@ button.back-btn {
width: 100%; width: 100%;
max-width: 1700px; max-width: 1700px;
min-height: 100vh;
margin: 1rem 0; margin: 1rem 0;
text-align: center; text-align: center;
+2 -2
View File
@@ -21,7 +21,7 @@ import { defineComponent } from 'vue';
import StationTable from '../components/StationsView/StationTable.vue'; import StationTable from '../components/StationsView/StationTable.vue';
import StationFilterCard from '../components/StationsView/StationFilterCard.vue'; import StationFilterCard from '../components/StationsView/StationFilterCard.vue';
import { useStationFiltersStore } from '../store/stationFiltersStore'; import { useStationFiltersStore } from '../store/stationFiltersStore';
import { useStore } from '../store/mainStore'; import { useMainStore } from '../store/mainStore';
import Donation from '../components/Global/Donation.vue'; import Donation from '../components/Global/Donation.vue';
export default defineComponent({ export default defineComponent({
@@ -37,7 +37,7 @@ export default defineComponent({
STORAGE_KEY: 'options_saved', STORAGE_KEY: 'options_saved',
focusedStationName: '', focusedStationName: '',
filterStore: useStationFiltersStore(), filterStore: useStationFiltersStore(),
store: useStore(), store: useMainStore(),
isDonationModalOpen: false isDonationModalOpen: false
}), }),
+2 -2
View File
@@ -21,7 +21,7 @@ import TrainOptions from '../components/TrainsView/TrainOptions.vue';
import TrainTable from '../components/TrainsView/TrainTable.vue'; import TrainTable from '../components/TrainsView/TrainTable.vue';
import modalTrainMixin from '../mixins/modalTrainMixin'; import modalTrainMixin from '../mixins/modalTrainMixin';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
import { useStore } from '../store/mainStore'; import { useMainStore } from '../store/mainStore';
import { TrainFilter, trainFilters } from '../components/TrainsView/typings'; import { TrainFilter, trainFilters } from '../components/TrainsView/typings';
import { filteredTrainList } from '../managers/trainFilterManager'; import { filteredTrainList } from '../managers/trainFilterManager';
import TrainStats from '../components/TrainsView/TrainStats.vue'; import TrainStats from '../components/TrainsView/TrainStats.vue';
@@ -58,7 +58,7 @@ export default defineComponent({
}), }),
setup() { setup() {
const store = useStore(); const store = useMainStore();
const initTrainFilters = [...trainFilters.map((f) => ({ ...f }))]; const initTrainFilters = [...trainFilters.map((f) => ({ ...f }))];
const sorterActive = reactive({ id: 'routeDistance', dir: -1 }); const sorterActive = reactive({ id: 'routeDistance', dir: -1 });
+7 -56
View File
@@ -1577,11 +1577,6 @@
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz" resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz"
integrity sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA== integrity sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==
"@socket.io/component-emitter@~3.1.0":
version "3.1.0"
resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz"
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
"@surma/rollup-plugin-off-main-thread@^2.2.3": "@surma/rollup-plugin-off-main-thread@^2.2.3":
version "2.2.3" version "2.2.3"
resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz" resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz"
@@ -2143,9 +2138,9 @@ callsites@^3.0.0:
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
caniuse-lite@^1.0.30001400: caniuse-lite@^1.0.30001400:
version "1.0.30001503" version "1.0.30001565"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz"
integrity sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw== integrity sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==
chalk@^2.4.2: chalk@^2.4.2:
version "2.4.2" version "2.4.2"
@@ -2319,7 +2314,7 @@ de-indent@^1.0.2:
resolved "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz" resolved "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz"
integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4" version "4.3.4"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -2454,22 +2449,6 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
engine.io-client@~6.5.2:
version "6.5.2"
resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz"
integrity sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
engine.io-parser "~5.2.1"
ws "~8.11.0"
xmlhttprequest-ssl "~2.0.0"
engine.io-parser@~5.2.1:
version "5.2.1"
resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz"
integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==
es-abstract@^1.19.0, es-abstract@^1.20.4: es-abstract@^1.19.0, es-abstract@^1.20.4:
version "1.20.5" version "1.20.5"
resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz"
@@ -4215,24 +4194,6 @@ slash@^3.0.0:
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
socket.io-client@^4.7.2:
version "4.7.2"
resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz"
integrity sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.2"
engine.io-client "~6.5.2"
socket.io-parser "~4.2.4"
socket.io-parser@~4.2.4:
version "4.2.4"
resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz"
integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
source-map-js@^1.0.2, "source-map-js@>=0.6.2 <2.0.0": source-map-js@^1.0.2, "source-map-js@>=0.6.2 <2.0.0":
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
@@ -4631,9 +4592,9 @@ vite-plugin-pwa@^0.16.5:
workbox-window "^7.0.0" workbox-window "^7.0.0"
"vite@^3.1.0 || ^4.0.0", vite@^4.0.0, vite@^4.4.9: "vite@^3.1.0 || ^4.0.0", vite@^4.0.0, vite@^4.4.9:
version "4.4.9" version "4.5.1"
resolved "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz" resolved "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz"
integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA== integrity sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==
dependencies: dependencies:
esbuild "^0.18.10" esbuild "^0.18.10"
postcss "^8.4.27" postcss "^8.4.27"
@@ -4934,21 +4895,11 @@ wrappy@1:
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
ws@~8.11.0:
version "8.11.0"
resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz"
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
xml-name-validator@^4.0.0: xml-name-validator@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz"
integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
xmlhttprequest-ssl@~2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz"
integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
y18n@^5.0.5: y18n@^5.0.5:
version "5.0.8" version "5.0.8"
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"