Compare commits

...

33 Commits

Author SHA1 Message Date
Spythere 5c4c486643 Wersja 1.21.0
Wersja 1.21.0
2024-02-12 15:14:50 +01:00
Spythere 755c729a9b brakujące tłumaczenia; poprawki 2024-02-12 14:58:59 +01:00
Spythere 3ac8d60c5c filtry aktywnych RJ 2024-02-11 15:30:19 +01:00
Spythere dcff3b088f poprawki filtrowania statusów 2024-02-10 23:11:13 +01:00
Spythere 90b2099955 checkpointy; hotfixy 2024-02-10 22:42:35 +01:00
Spythere fc0c04ec9d bump: 1.21.0 2024-02-10 01:31:08 +01:00
Spythere 41b335555a wyświetlanie RJ dla scenerii offline 2024-02-10 01:30:43 +01:00
Spythere 60f7b3bbb5 Wersja 1.20.5
Wersja 1.20.5
2024-02-03 14:36:57 +01:00
Spythere eaefe955a7 bump: 1.20.5 2024-02-02 21:14:29 +01:00
Spythere edaa4f2684 cleanup 2024-02-02 21:14:16 +01:00
Spythere 30fce3787b usprawnienia pobierania danych; statusy SWDR na semaforze 2024-02-02 21:13:21 +01:00
Spythere 4716f1c7a4 Wersja 1.20.4
Wersja 1.20.4
2024-01-30 16:44:55 +01:00
Spythere bb7ccf98fd bump wersji 2024-01-30 16:41:27 +01:00
Spythere c06d75b981 lock fix; linting 2024-01-30 14:00:38 +01:00
Spythere c7da8477fa przywrócenie komunikacji po WS (test) 2024-01-30 13:58:47 +01:00
Spythere e43f1e0819 Wersja 1.20.3
Wersja 1.20.3
2024-01-26 13:59:23 +01:00
Spythere f130e6900b hotfix: brak komentarzy dla ostatniej stacji w RJ 2024-01-26 13:54:47 +01:00
Spythere db205915be bump wersji 2024-01-26 13:39:04 +01:00
Spythere 05c38e10e3 hotfix postojów pt w SRJP 2024-01-26 13:38:45 +01:00
Spythere a8f683a585 mock data 2024-01-26 13:38:28 +01:00
Spythere 68f6fc8a42 Wersja 1.20.2
Wersja 1.20.2
2024-01-24 20:37:35 +01:00
Spythere 6d3b32cd7d bump: 1.20.2 2024-01-24 20:35:49 +01:00
Spythere fadecc9d2c fix literówki w tłumaczeniu 2024-01-24 20:35:15 +01:00
Spythere 50602cb6db Merge pull request #74 from Spythere/development
- rozbudowany szczegółówy RJ pociągu
- hotfixy do pobierania danych z API
2024-01-13 17:54:17 +01:00
Spythere 186ce81819 hotfix: filtrowanie aktywnych rj do odpowiednich regionów 2024-01-13 17:28:16 +01:00
Spythere f836a075b0 hotfix: pobieranie historii RJ nieznanych scenerii 2024-01-13 15:41:40 +01:00
Spythere 9acf3c740c dodano wybór z listy autorów w filtrach 2024-01-06 17:40:43 +01:00
Spythere bc1c1bd3d2 filtrowanie ukrytych szlaków 2024-01-06 14:47:20 +01:00
Spythere 2348277b95 poprawki do SRJP 2024-01-06 14:10:59 +01:00
Spythere cd5f489df7 bump wersji: 1.20.1 2024-01-06 14:06:50 +01:00
Spythere f74962222b przywrócenie SRJP bez pokazywania dod. informacji 2024-01-06 14:05:40 +01:00
Spythere e7f651d2b9 poprawki ułożenia elementów progress bara SRJP, elektryfikacja szlaku 2024-01-02 15:44:48 +01:00
Spythere 4862328090 rozbudowany szczegółówy RJ pociągu 2024-01-01 22:49:19 +01:00
43 changed files with 1569 additions and 3310 deletions
+148 -20
View File
@@ -1,12 +1,12 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.19.4", "version": "1.20.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "stacjownik", "name": "stacjownik",
"version": "1.19.4", "version": "1.20.3",
"dependencies": { "dependencies": {
"core-js": "^3.32.2", "core-js": "^3.32.2",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
@@ -14,6 +14,7 @@
"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.4",
"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"
@@ -2840,6 +2841,11 @@
"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=="
},
"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",
@@ -4156,7 +4162,6 @@
"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"
@@ -4399,6 +4404,26 @@
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"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==",
"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",
@@ -5061,9 +5086,9 @@
"dev": true "dev": true
}, },
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.2", "version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -5071,7 +5096,6 @@
"url": "https://github.com/sponsors/RubenVerborgh" "url": "https://github.com/sponsors/RubenVerborgh"
} }
], ],
"license": "MIT",
"engines": { "engines": {
"node": ">=4.0" "node": ">=4.0"
}, },
@@ -6312,7 +6336,6 @@
"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": {
@@ -7538,6 +7561,32 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/socket.io-client": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
"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==",
"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",
@@ -8152,9 +8201,9 @@
"dev": true "dev": true
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "4.5.1", "version": "4.5.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz",
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"esbuild": "^0.18.10", "esbuild": "^0.18.10",
@@ -8727,6 +8776,26 @@
"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==",
"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",
@@ -8736,6 +8805,14 @@
"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",
@@ -10722,6 +10799,11 @@
"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",
@@ -11640,7 +11722,6 @@
"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"
} }
@@ -11801,6 +11882,23 @@
"once": "^1.4.0" "once": "^1.4.0"
} }
}, },
"engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"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",
@@ -12286,9 +12384,9 @@
"dev": true "dev": true
}, },
"follow-redirects": { "follow-redirects": {
"version": "1.15.2", "version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true "dev": true
}, },
"form-data": { "form-data": {
@@ -13127,8 +13225,7 @@
"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",
@@ -13945,6 +14042,26 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true "dev": true
}, },
"socket.io-client": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
"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",
@@ -14377,9 +14494,9 @@
"dev": true "dev": true
}, },
"vite": { "vite": {
"version": "4.5.1", "version": "4.5.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz",
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==",
"dev": true, "dev": true,
"requires": { "requires": {
"esbuild": "^0.18.10", "esbuild": "^0.18.10",
@@ -14776,12 +14893,23 @@
"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",
+2 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.20.0", "version": "1.21.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -18,6 +18,7 @@
"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.4",
"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"
+2 -2
View File
@@ -1,4 +1,4 @@
<svg width="160" height="150" viewBox="0 0 160 150" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="160" height="150" viewBox="0 0 160 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.163 139L80 12.4204L149.837 139H80H10.163Z" stroke="white" stroke-width="12"/> <path d="M10.163 139L80 12.4204L149.837 139H80H10.163Z" stroke="salmon" stroke-width="15"/>
<path d="M85.4488 50.3354V80.6619C85.4488 83.8784 85.2898 87.0418 84.9717 90.1522C84.6536 93.2273 84.2294 96.4968 83.6992 99.9606H74.8451C74.315 96.4968 73.8908 93.2273 73.5727 90.1522C73.2546 87.0418 73.0955 83.8784 73.0955 80.6619V50.3354H85.4488ZM71.0808 119.789C71.0808 118.694 71.2752 117.651 71.664 116.661C72.0882 115.672 72.6537 114.823 73.3606 114.117C74.1029 113.41 74.9689 112.844 75.9585 112.42C76.9482 111.996 78.0086 111.784 79.1396 111.784C80.2354 111.784 81.278 111.996 82.2677 112.42C83.2574 112.844 84.1057 113.41 84.8126 114.117C85.5195 114.823 86.085 115.672 86.5092 116.661C86.9333 117.651 87.1454 118.694 87.1454 119.789C87.1454 120.921 86.9333 121.981 86.5092 122.971C86.085 123.925 85.5195 124.756 84.8126 125.462C84.1057 126.169 83.2574 126.717 82.2677 127.106C81.278 127.53 80.2354 127.742 79.1396 127.742C78.0086 127.742 76.9482 127.53 75.9585 127.106C74.9689 126.717 74.1029 126.169 73.3606 125.462C72.6537 124.756 72.0882 123.925 71.664 122.971C71.2752 121.981 71.0808 120.921 71.0808 119.789Z" fill="#FFFBFB"/> <path d="M85.4488 50.3354V80.6619C85.4488 83.8784 85.2898 87.0418 84.9717 90.1522C84.6536 93.2273 84.2294 96.4968 83.6992 99.9606H74.8451C74.315 96.4968 73.8908 93.2273 73.5727 90.1522C73.2546 87.0418 73.0955 83.8784 73.0955 80.6619V50.3354H85.4488ZM71.0808 119.789C71.0808 118.694 71.2752 117.651 71.664 116.661C72.0882 115.672 72.6537 114.823 73.3606 114.117C74.1029 113.41 74.9689 112.844 75.9585 112.42C76.9482 111.996 78.0086 111.784 79.1396 111.784C80.2354 111.784 81.278 111.996 82.2677 112.42C83.2574 112.844 84.1057 113.41 84.8126 114.117C85.5195 114.823 86.085 115.672 86.5092 116.661C86.9333 117.651 87.1454 118.694 87.1454 119.789C87.1454 120.921 86.9333 121.981 86.5092 122.971C86.085 123.925 85.5195 124.756 84.8126 125.462C84.1057 126.169 83.2574 126.717 82.2677 127.106C81.278 127.53 80.2354 127.742 79.1396 127.742C78.0086 127.742 76.9482 127.53 75.9585 127.106C74.9689 126.717 74.1029 126.169 73.3606 125.462C72.6537 124.756 72.0882 123.925 71.664 122.971C71.2752 121.981 71.0808 120.921 71.0808 119.789Z" fill="white"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

+9 -10
View File
@@ -33,16 +33,17 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, watch } from 'vue'; import { defineComponent, watch } from 'vue';
import axios from 'axios';
import packageInfo from '.././package.json';
import Clock from './components/App/Clock.vue'; import Clock from './components/App/Clock.vue';
import packageInfo from '.././package.json';
import { useMainStore } 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 AppHeader from './components/App/AppHeader.vue'; import AppHeader from './components/App/AppHeader.vue';
import axios from 'axios'; import TrainModal from './components/TrainsView/TrainModal.vue';
import StorageManager from './managers/storageManager'; import StorageManager from './managers/storageManager';
import { useApiStore } from './store/apiStore'; import { useApiStore } from './store/apiStore';
import { Status } from './typings/common'; import { Status } from './typings/common';
@@ -51,8 +52,8 @@ export default defineComponent({
components: { components: {
Clock, Clock,
StatusIndicator, StatusIndicator,
TrainModal, AppHeader,
AppHeader TrainModal
}, },
data: () => ({ data: () => ({
@@ -85,7 +86,7 @@ export default defineComponent({
this.setReleaseURL(); this.setReleaseURL();
this.setupOfflineHandling(); this.setupOfflineHandling();
this.apiStore.setupAPI(); this.apiStore.setupAPIData();
}, },
setupOfflineHandling() { setupOfflineHandling() {
@@ -100,16 +101,14 @@ export default defineComponent({
handleOfflineMode() { handleOfflineMode() {
this.store.isOffline = true; this.store.isOffline = true;
this.apiStore.stopActiveDataScheduler();
this.apiStore.activeData = undefined; this.apiStore.activeData = undefined;
this.apiStore.dataStatuses.connection = Status.Data.Offline; this.apiStore.dataStatuses.connection = Status.Data.Offline;
}, },
handleOnlineMode() { handleOnlineMode() {
this.store.isOffline = false; this.store.isOffline = false;
this.apiStore.setupAPI(); this.apiStore.setupAPIData();
}, },
changeLang(lang: string) { changeLang(lang: string) {
+2 -2
View File
@@ -100,8 +100,8 @@ export default defineComponent({
}, },
onlineDispatchersCount() { onlineDispatchersCount() {
return this.store.onlineSceneryList.filter( return this.store.activeSceneryList.filter(
(scenery) => scenery.region == this.store.region.id (scenery) => scenery.region == this.store.region.id && scenery.dispatcherId != -1
).length; ).length;
}, },
+95 -104
View File
@@ -36,11 +36,11 @@
<circle id="Ellipse 18" cx="15" cy="17" r="7" fill="#393838" /> <circle id="Ellipse 18" cx="15" cy="17" r="7" fill="#393838" />
</g> </g>
<g v-if="greenLight" filter="url(#filter0_d_843_28)"> <g v-if="indicator.lights.greenLight" filter="url(#filter0_d_843_28)">
<circle cx="15" cy="17" r="7" fill="#00FF0A" /> <circle cx="15" cy="17" r="7" fill="#00FF0A" />
</g> </g>
<g v-if="greenBlinkLight" filter="url(#filter0_d_843_28)"> <g v-if="indicator.lights.greenBlinkLight" filter="url(#filter0_d_843_28)">
<circle cx="15" cy="17" r="7" fill="#00FF0A" /> <circle cx="15" cy="17" r="7" fill="#00FF0A" />
<animate <animate
@@ -52,14 +52,14 @@
/> />
</g> </g>
<g v-if="redTopLight" filter="url(#filter1_d_843_28)"> <g v-if="indicator.lights.redTopLight" filter="url(#filter1_d_843_28)">
<circle cx="15" cy="36" r="7" fill="#F40000" /> <circle cx="15" cy="36" r="7" fill="#F40000" />
</g> </g>
<g v-if="orangeLight" filter="url(#filter2_d_843_28)"> <g v-if="indicator.lights.orangeLight" filter="url(#filter2_d_843_28)">
<circle cx="15" cy="55" r="7" fill="#FFB800" /> <circle cx="15" cy="55" r="7" fill="#FFB800" />
</g> </g>
<g v-if="redBottomLight" filter="url(#filter3_d_843_28)"> <g v-if="indicator.lights.redBottomLight" filter="url(#filter3_d_843_28)">
<circle cx="15" cy="74" r="7" fill="#F40000" /> <circle cx="15" cy="74" r="7" fill="#F40000" />
<animate <animate
@@ -186,7 +186,11 @@
</svg> </svg>
<transition name="tooltip-anim"> <transition name="tooltip-anim">
<div v-html="$t(indicator.message)" class="indicator-tooltip" v-if="tooltipActive"></div> <div
v-html="$t('data-status.' + indicator.message)"
class="indicator-tooltip"
v-if="tooltipActive"
></div>
</transition> </transition>
</div> </div>
</div> </div>
@@ -194,125 +198,112 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useMainStore } from '../../store/mainStore';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import { APIDataStatus } from '../../typings/api';
interface Indicator {
// status: Status.Data;
message: string;
lights: {
greenLight: boolean;
greenBlinkLight: boolean;
redTopLight: boolean;
orangeLight: boolean;
redBottomLight: boolean;
};
}
export default defineComponent({ export default defineComponent({
data() { data() {
return { return {
tooltipActive: false, tooltipActive: false,
indicator: { apiStore: useApiStore()
offline: false,
status: Status.Data.Loading,
message: 'data-status.S3'
},
greenLight: false,
greenBlinkLight: false,
redTopLight: false,
orangeLight: false,
redBottomLight: false
}; };
}, },
mounted() {
this.setSignalStatus(Status.Data.Loading);
},
setup() {
const store = useMainStore();
const apiStore = useApiStore();
return {
dataStatus: apiStore.dataStatuses,
store
};
},
watch: {
dataStatus: {
deep: true,
handler(statuses: any) {
const connectionStatus = statuses.connection;
const sceneryDataStatus = statuses.sceneries;
const trainsDataStatus = statuses.trains;
const dispatcherDataStatus = statuses.dispatchers;
if (connectionStatus == Status.Data.Offline) {
this.setSignalStatus(Status.Data.Offline);
this.indicator.status = Status.Data.Offline;
this.indicator.message = 'data-status.S1-offline';
return;
}
if (connectionStatus == Status.Data.Error) {
this.setSignalStatus(connectionStatus);
this.indicator.status = connectionStatus;
this.indicator.message = 'data-status.S1a-connection';
return;
}
if (sceneryDataStatus == Status.Data.Error) {
this.setSignalStatus(sceneryDataStatus);
this.indicator.status = sceneryDataStatus;
this.indicator.message = 'data-status.S1a-sceneries';
return;
}
if (trainsDataStatus == Status.Data.Warning) {
this.setSignalStatus(trainsDataStatus);
this.indicator.status = trainsDataStatus;
this.indicator.message = 'data-status.S5-trains';
return;
}
if (dispatcherDataStatus == Status.Data.Warning) {
this.setSignalStatus(dispatcherDataStatus);
this.indicator.status = dispatcherDataStatus;
this.indicator.message = 'data-status.S5-dispatchers';
return;
}
if (sceneryDataStatus == Status.Data.Loaded) {
this.setSignalStatus(Status.Data.Loaded);
this.indicator.status = Status.Data.Loaded;
this.indicator.message = 'data-status.S2';
}
}
}
},
methods: { methods: {
setSignalStatus(status: Status.Data) { setLights(message: string) {
this.greenLight = false; let lights = {
this.greenBlinkLight = false; greenBlinkLight: false,
this.redTopLight = false; greenLight: false,
this.orangeLight = false; orangeLight: false,
this.redBottomLight = false; redBottomLight: false,
redTopLight: false
};
if (status == Status.Data.Initialized || status == Status.Data.Offline) { switch (message) {
this.redTopLight = true; case 'S3':
lights.greenBlinkLight = true;
break;
case 'S2':
lights.greenLight = true;
break;
case 'S1-offline':
lights.redTopLight = true;
break;
case 'S1a-connection':
case 'S1a-sceneries':
lights.redTopLight = true;
lights.redBottomLight = true;
break;
case 'S5-dispatchers':
case 'S5-trains':
lights.orangeLight = true;
break;
default:
break;
} }
if (status == Status.Data.Loaded) { return lights;
this.greenLight = true; }
},
computed: {
indicator(): Indicator {
const dataStatuses = this.apiStore.dataStatuses;
const swdrStatuses = this.apiStore.activeData?.apiStatuses;
let message = 'S3';
switch (dataStatuses.connection) {
case Status.Data.Loading:
message = 'S3';
break;
case Status.Data.Loaded:
message = 'S2';
break;
case Status.Data.Offline:
message = 'S1-offline';
break;
case Status.Data.Error:
message = 'S1a-connection';
break;
default:
break;
} }
if (status == Status.Data.Warning) { if (swdrStatuses?.dispatchersAPI == APIDataStatus.WARNING) {
this.orangeLight = true; message = 'S5-dispatchers';
} }
if (status == Status.Data.Error) { if (swdrStatuses?.trainsAPI == APIDataStatus.WARNING) {
this.redTopLight = true; message = 'S5-trains';
this.redBottomLight = true;
} }
if (status == Status.Data.Loading) { if (swdrStatuses?.stationsAPI == APIDataStatus.WARNING) {
this.greenBlinkLight = true; message = 'S1a-sceneries';
} }
return {
lights: this.setLights(message),
message
};
} }
} }
}); });
+1 -1
View File
@@ -85,7 +85,7 @@ export default defineComponent({
regionList() { regionList() {
return regionsJSON.map((region) => { return regionsJSON.map((region) => {
const regionStationCount = this.store.onlineSceneryList.filter( const regionStationCount = this.store.activeSceneryList.filter(
(scenery) => scenery.region == region.id (scenery) => scenery.region == region.id
).length; ).length;
@@ -61,6 +61,9 @@ export default defineComponent({
case Status.ActiveDispatcher.UNKNOWN: case Status.ActiveDispatcher.UNKNOWN:
return 'unknown'; return 'unknown';
case Status.ActiveDispatcher.FREE:
return 'free';
default: default:
if (this.dispatcherTimestamp != null && this.dispatcherStatus >= Date.now() + 25500000) if (this.dispatcherTimestamp != null && this.dispatcherStatus >= Date.now() + 25500000)
return 'no-limit'; return 'no-limit';
-123
View File
@@ -1,123 +0,0 @@
<template>
<span class="stop-date">
<span
class="date arrival"
v-if="!stop.beginsHere"
:class="{
delayed: stop.arrivalDelay > 0 && (stop.confirmed || stop.stopped),
preponed: stop.arrivalDelay < 0 && (stop.confirmed || stop.stopped),
'on-time': stop.arrivalDelay == 0 && stop.confirmed
}"
>
<span v-if="stop.arrivalDelay != 0 && (stop.confirmed || stop.stopped)">
<s>{{ timestampToString(stop.arrivalTimestamp) }}</s>
{{ timestampToString(stop.arrivalRealTimestamp) }}
({{ stop.arrivalDelay > 0 ? '+' : '' }}{{ stop.arrivalDelay }})
</span>
<span v-else>
{{ timestampToString(stop.arrivalTimestamp) }}
</span>
</span>
<span
class="date stop"
v-if="stop.stopTime || stop.stopped"
:class="stop.stopType.replace(', ', '-')"
>
{{ stop.stopTime }} {{ stop.stopType == '' ? 'pt' : stop.stopType }}
</span>
<span
class="date departure"
v-if="!stop.terminatesHere && (stop.stopTime != 0 || stop.stopped)"
:class="{
delayed: stop.departureDelay > 0 && stop.confirmed,
preponed: stop.departureDelay < 0 && stop.confirmed
}"
>
<span v-if="stop.departureDelay != 0 && stop.confirmed">
<s>{{ timestampToString(stop.departureTimestamp) }}</s>
{{ timestampToString(stop.departureRealTimestamp) }}
({{ stop.departureDelay > 0 ? '+' : '' }}{{ stop.departureDelay }})
</span>
<span v-else>
{{ timestampToString(stop.departureTimestamp) }}
</span>
</span>
</span>
</template>
<script lang="ts">
import { PropType, defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { TrainStop } from '../../store/typings';
export default defineComponent({
mixins: [dateMixin],
props: {
stop: {
type: Object as PropType<TrainStop>,
required: true
}
},
setup() {
return {};
}
});
</script>
<style lang="scss" scoped>
$preponedClr: lime;
$delayedClr: salmon;
$dateClr: #525151;
$stopExchangeClr: #db8e29;
$stopDefaultClr: #252525;
.stop-date {
display: flex;
align-items: center;
.date {
background: $dateClr;
padding: 0.3em 0.5em;
}
.stop {
&.ph,
&.ph-pm,
&.pm {
background: $stopExchangeClr;
}
background: $stopDefaultClr;
}
.arrival,
.departure {
&.delayed {
s {
color: #999;
}
span {
color: $delayedClr;
}
}
&.preponed {
s {
color: #999;
}
span {
color: $preponedClr;
}
}
}
}
</style>
@@ -76,7 +76,7 @@ import Station from '../../scripts/interfaces/Station';
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 { ActiveScenery } 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'; import http from '../../http';
@@ -90,7 +90,7 @@ export default defineComponent({
type: Object as PropType<Station> type: Object as PropType<Station>
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery> type: Object as PropType<ActiveScenery>
} }
}, },
+2 -2
View File
@@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { OnlineScenery } from '../../store/typings'; import { ActiveScenery } from '../../store/typings';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -29,7 +29,7 @@ export default defineComponent({
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery> type: Object as PropType<ActiveScenery>
} }
} }
}); });
+2 -2
View File
@@ -90,7 +90,7 @@ import SceneryInfoUserList from './SceneryInfo/SceneryInfoUserList.vue';
import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue'; import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue';
import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue'; import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
import { OnlineScenery } from '../../store/typings'; import { ActiveScenery } from '../../store/typings';
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -106,7 +106,7 @@ export default defineComponent({
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery> type: Object as PropType<ActiveScenery>
} }
} }
}); });
@@ -1,6 +1,6 @@
<template> <template>
<section class="info-dispatcher"> <section class="info-dispatcher">
<div class="dispatcher" v-if="onlineScenery"> <div class="dispatcher" v-if="onlineScenery && onlineScenery.dispatcherExp != -1">
<span <span
class="dispatcher_level" class="dispatcher_level"
:style="calculateExpStyle(onlineScenery.dispatcherExp, onlineScenery.dispatcherIsSupporter)" :style="calculateExpStyle(onlineScenery.dispatcherExp, onlineScenery.dispatcherIsSupporter)"
@@ -42,14 +42,14 @@ import dateMixin from '../../../mixins/dateMixin';
import routerMixin from '../../../mixins/routerMixin'; import routerMixin from '../../../mixins/routerMixin';
import styleMixin from '../../../mixins/styleMixin'; import styleMixin from '../../../mixins/styleMixin';
import StationStatusBadge from '../../Global/StationStatusBadge.vue'; import StationStatusBadge from '../../Global/StationStatusBadge.vue';
import { OnlineScenery } from '../../../store/typings'; import { ActiveScenery } from '../../../store/typings';
import donatorMixin from '../../../mixins/donatorMixin'; import donatorMixin from '../../../mixins/donatorMixin';
export default defineComponent({ export default defineComponent({
mixins: [styleMixin, dateMixin, routerMixin, donatorMixin], mixins: [styleMixin, dateMixin, routerMixin, donatorMixin],
props: { props: {
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<ActiveScenery>,
required: false required: false
} }
}, },
@@ -1,41 +1,49 @@
<template> <template>
<section class="info-routes" v-if="station.generalInfo"> <section class="info-routes" v-if="station.generalInfo">
<div class="routes one-way" v-if="station.generalInfo.routes.oneWay.length > 0"> <div class="routes one-way" v-if="filteredOneWayRoutes.length > 0">
<b>{{ $t('scenery.one-way-routes') }}</b> <b>{{ $t('scenery.one-way-routes') }}</b>
<ul class="routes-list"> <ul class="routes-list">
<li <li
v-for="route in station.generalInfo.routes.oneWay" v-for="route in filteredOneWayRoutes"
:key="route.name" :key="route.routeName"
@click="setActiveShowLength(route.name)" @click="setActiveShowLength(route.routeName)"
> >
<span :class="{ 'no-catenary': !route.catenary, internal: route.isInternal }"> <span :class="{ 'no-catenary': !route.isElectric, internal: route.isInternal }">
{{ route.name }}</span {{ route.routeName }}</span
> >
<span v-if="route.speed" class="speed"> <span v-if="route.routeSpeed" class="speed">
{{ activeShowLength.includes(route.name) ? route.length + 'm' : route.speed }} {{
activeShowLength.includes(route.routeName)
? route.routeLength + 'm'
: route.routeSpeed
}}
</span> </span>
<span v-if="route.SBL" class="sbl">SBL</span> <span v-if="route.isRouteSBL" class="sbl">SBL</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class="routes two-way" v-if="station.generalInfo.routes.twoWay.length > 0"> <div class="routes two-way" v-if="filteredTwoWayRoutes.length > 0">
<b>{{ $t('scenery.two-way-routes') }}</b> <b>{{ $t('scenery.two-way-routes') }}</b>
<ul class="routes-list"> <ul class="routes-list">
<li <li
v-for="route in station.generalInfo.routes.twoWay" v-for="route in filteredTwoWayRoutes"
:key="route.name" :key="route.routeName"
@click="setActiveShowLength(route.name)" @click="setActiveShowLength(route.routeName)"
> >
<span :class="{ 'no-catenary': !route.catenary, internal: route.isInternal }">{{ <span :class="{ 'no-catenary': !route.isElectric, internal: route.isInternal }">{{
route.name route.routeName
}}</span> }}</span>
<span v-if="route.speed" class="speed"> <span v-if="route.routeSpeed" class="speed">
{{ activeShowLength.includes(route.name) ? route.length + 'm' : route.speed }} {{
activeShowLength.includes(route.routeName)
? route.routeLength + 'm'
: route.routeSpeed
}}
</span> </span>
<span v-if="route.SBL" class="sbl">SBL</span> <span v-if="route.isRouteSBL" class="sbl">SBL</span>
</li> </li>
</ul> </ul>
</div> </div>
@@ -45,6 +53,9 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import Station from '../../../scripts/interfaces/Station'; import Station from '../../../scripts/interfaces/Station';
import { StationRoutesInfo } from '../../../store/typings';
const routeFilter = (route: StationRoutesInfo) => !route.hidden;
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -66,6 +77,16 @@ export default defineComponent({
return { return {
activeShowLength: [] as string[] activeShowLength: [] as string[]
}; };
},
computed: {
filteredOneWayRoutes() {
return this.station.generalInfo?.routes.oneWay.filter(routeFilter) || [];
},
filteredTwoWayRoutes() {
return this.station.generalInfo?.routes.twoWay.filter(routeFilter) || [];
}
} }
}); });
</script> </script>
@@ -30,12 +30,12 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import { OnlineScenery } from '../../../store/typings'; import { ActiveScenery } from '../../../store/typings';
export default defineComponent({ export default defineComponent({
props: { props: {
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<ActiveScenery>,
required: false required: false
} }
}, },
@@ -32,14 +32,14 @@
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import modalTrainMixin from '../../../mixins/modalTrainMixin'; import modalTrainMixin from '../../../mixins/modalTrainMixin';
import routerMixin from '../../../mixins/routerMixin'; import routerMixin from '../../../mixins/routerMixin';
import { OnlineScenery } from '../../../store/typings'; import { ActiveScenery } from '../../../store/typings';
export default defineComponent({ export default defineComponent({
mixins: [routerMixin, modalTrainMixin], mixins: [routerMixin, modalTrainMixin],
props: { props: {
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery>, type: Object as PropType<ActiveScenery>,
required: false required: false
} }
} }
+11 -12
View File
@@ -6,10 +6,10 @@
<span>{{ $t('scenery.timetables') }}</span> <span>{{ $t('scenery.timetables') }}</span>
<span> <span>
<span class="text--primary">{{ onlineScenery?.scheduledTrainCount.all || 0 }}</span> <span class="text--primary">{{ onlineScenery?.scheduledTrainCount.all ?? 0 }}</span>
<span> / </span> <span> / </span>
<span class="text--grayed"> <span class="text--grayed">
{{ onlineScenery?.scheduledTrainCount.confirmed || '0' }} {{ onlineScenery?.scheduledTrainCount.confirmed ?? 0 }}
</span> </span>
</span> </span>
@@ -33,12 +33,12 @@
{{ (i > 0 && '&bull;') || '' }} {{ (i > 0 && '&bull;') || '' }}
<button <button
:key="cp.checkpointName" :key="cp"
class="checkpoint_item" class="checkpoint_item"
:class="{ current: chosenCheckpoint === cp.checkpointName }" :class="{ current: chosenCheckpoint === cp }"
@click="setCheckpoint(cp)" @click="setCheckpoint(cp)"
> >
{{ cp.checkpointName }} {{ cp }}
</button> </button>
</span> </span>
</div> </div>
@@ -190,7 +190,7 @@ import Station from '../../scripts/interfaces/Station';
import { useMainStore } 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 { ActiveScenery } from '../../store/typings';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
@@ -205,7 +205,7 @@ export default defineComponent({
type: Object as PropType<Station> type: Object as PropType<Station>
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery> type: Object as PropType<ActiveScenery>
} }
}, },
@@ -231,7 +231,7 @@ export default defineComponent({
const chosenCheckpoint = ref( const chosenCheckpoint = ref(
props.station?.generalInfo?.checkpoints?.length == 0 props.station?.generalInfo?.checkpoints?.length == 0
? '' ? ''
: props.station?.generalInfo?.checkpoints[0].checkpointName || null : props.station?.generalInfo?.checkpoints[0] ?? null
); );
return { return {
@@ -278,12 +278,11 @@ export default defineComponent({
loadSelectedOption() { loadSelectedOption() {
if (!this.station) return; if (!this.station) return;
this.chosenCheckpoint = this.chosenCheckpoint = this.station.generalInfo?.checkpoints[0] ?? this.station.name;
this.station.generalInfo?.checkpoints[0]?.checkpointName || this.station.name;
}, },
setCheckpoint(cp: { checkpointName: string }) { setCheckpoint(cp: string) {
this.chosenCheckpoint = cp.checkpointName; this.chosenCheckpoint = cp;
} }
} }
}); });
@@ -74,7 +74,7 @@ import dateMixin from '../../mixins/dateMixin';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
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 { ActiveScenery } 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'; import http from '../../http';
@@ -87,7 +87,7 @@ export default defineComponent({
type: Object as PropType<Station> type: Object as PropType<Station>
}, },
onlineScenery: { onlineScenery: {
type: Object as PropType<OnlineScenery> type: Object as PropType<ActiveScenery>
} }
}, },
@@ -114,7 +114,7 @@ export default defineComponent({
const response: API.TimetableHistory.Response = await ( const response: API.TimetableHistory.Response = await (
await http.get('api/getTimetables', { await http.get('api/getTimetables', {
params: { params: {
issuedFrom: this.station?.name issuedFrom: this.station?.name || this.onlineScenery?.name
} }
}) })
).data; ).data;
+162 -134
View File
@@ -60,8 +60,9 @@
</div> </div>
</section> </section>
<section class="card_timestamp" style="text-align: center"> <section class="card_timestamp">
<div>{{ $t('filters.minimum-hours-title') }}</div> <h3 class="section-header">{{ $t('filters.minimum-hours-title') }}</h3>
<span class="clock"> <span class="clock">
<button class="btn--action" @click="subHour">-</button> <button class="btn--action" @click="subHour">-</button>
<span>{{ <span>{{
@@ -75,16 +76,27 @@
</span> </span>
</section> </section>
<datalist id="authors">
<option v-for="(author, i) in authors" :key="i" :value="author"></option>
</datalist>
<section class="card_authors-search"> <section class="card_authors-search">
<input <h3 class="section-header">{{ $t('filters.authors-search') }}</h3>
type="text"
:placeholder="$t('filters.authors-search')" <form action="javascript:void(0);" @submit="handleAuthorsInput">
name="authors" <input
v-model="authorsInputValue" type="text"
@input="handleAuthorsInput" id="author"
@focus="preventKeyDown = true" list="authors"
@blur="preventKeyDown = false" name="authors"
/> :placeholder="$t('filters.authors-placeholder')"
v-model="authorsInputValue"
@focus="preventKeyDown = true"
@blur="preventKeyDown = false"
/>
<button class="btn--action">{{ $t('filters.authors-button-title') }}</button>
</form>
</section> </section>
<section class="card_sliders"> <section class="card_sliders">
@@ -196,6 +208,19 @@ export default defineComponent({
currentOptionsActive() { currentOptionsActive() {
return true; return true;
},
authors() {
return this.store.stationList
.reduce((acc, station) => {
station.generalInfo?.authors?.forEach((author) => {
if (author.trim() != '' && !acc.includes(author.toLocaleLowerCase()))
acc.push(author.toLocaleLowerCase());
});
return acc;
}, [] as string[])
.sort((a, b) => a.localeCompare(b));
} }
}, },
@@ -230,12 +255,12 @@ export default defineComponent({
if (this.saveOptions) StorageManager.setStringValue(target.name, target.value); if (this.saveOptions) StorageManager.setStringValue(target.name, target.value);
}, },
handleAuthorsInput(e: Event) { handleAuthorsInput() {
clearTimeout(this.delayInputTimer); console.log(this.authorsInputValue);
this.delayInputTimer = window.setTimeout(() => { this.filterStore.changeFilterValue('authors', this.authorsInputValue);
this.handleInput(e);
}, 400); if (this.saveOptions) StorageManager.setStringValue('authors', this.authorsInputValue);
}, },
changeNumericFilterValue(name: string, value: number, saveToStorage = false) { changeNumericFilterValue(name: string, value: number, saveToStorage = false) {
@@ -297,136 +322,139 @@ export default defineComponent({
@import '../../styles/card.scss'; @import '../../styles/card.scss';
@import '../../styles/animations.scss'; @import '../../styles/animations.scss';
h3.section-header {
text-align: center;
margin: 0.5em 0;
}
.card { .card {
display: grid; display: grid;
grid-template-rows: 1fr auto; grid-template-rows: 1fr auto;
}
&_info { .card_info {
background-color: #111; background-color: #111;
padding: 0.5em; padding: 0.5em;
}
.card_controls {
display: flex;
gap: 0.5em;
input {
border-radius: 0.5em 0.5em 0 0;
height: 100%;
}
}
.card_content {
padding: 1em 0.5em;
display: flex;
flex-direction: column;
gap: 1em;
overflow: auto;
}
.card_title {
font-size: 2em;
font-weight: 700;
color: $accentCol;
text-align: center;
}
.card_regions {
display: flex;
justify-content: center;
label > input {
display: none;
} }
&_controls { label > span {
padding: 0.25em 0.5em;
margin: 0 0.25em;
cursor: pointer;
background-color: gray;
&.checked {
background-color: seagreen;
}
}
}
.card_timestamp {
display: flex;
flex-direction: column;
justify-content: center;
.clock {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2em;
text-align: center;
span {
min-width: 120px;
font-weight: bold;
color: $accentCol;
}
button {
padding: 0.2em 0.6em;
}
}
}
.card_authors-search {
margin: 1em 0;
form {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 0.5em;
width: 100%;
margin-top: 1em;
}
input {
width: 70%;
max-width: 400px;
padding: 0.5em;
outline: 1px solid white;
}
}
.card_actions {
width: 100%;
padding: 0.5em;
.filter-option {
max-width: 50%;
margin: 0 auto;
}
.action-buttons {
display: flex; display: flex;
gap: 0.5em; gap: 0.5em;
input {
border-radius: 0.5em 0.5em 0 0;
height: 100%;
}
}
&_content {
padding: 1em 0.5em;
display: flex;
flex-direction: column;
gap: 1em;
overflow: auto;
}
&_title {
font-size: 2em;
font-weight: 700;
color: $accentCol;
text-align: center;
}
&_regions {
display: flex;
justify-content: center;
label > input {
display: none;
}
label > span {
padding: 0.25em 0.5em;
margin: 0 0.25em;
cursor: pointer;
background-color: gray;
&.checked {
background-color: seagreen;
}
}
}
&_timestamp {
display: flex;
flex-direction: column;
justify-content: center;
.clock {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2em;
margin-top: 0.5em;
span {
min-width: 120px;
font-weight: bold;
color: $accentCol;
}
button {
padding: 0.2em 0.6em;
}
}
}
&_modes {
display: flex;
justify-content: center;
.option {
margin: 0 1em;
}
}
&_authors-search {
display: inline-block;
margin: 0 auto;
width: 60%;
min-width: 240px;
input {
width: 100%;
padding: 0.5em;
border: 1px solid white;
}
}
&_actions {
width: 100%; width: 100%;
padding: 0.5em;
.filter-option { margin-top: 0.5em;
max-width: 50%;
button {
width: 50%;
margin: 0 auto; margin: 0 auto;
} padding: 0.5em;
.action-buttons { &[data-selected='true'] {
display: flex; background-color: forestgreen;
gap: 0.5em;
width: 100%;
margin-top: 0.5em;
button {
width: 50%;
margin: 0 auto;
padding: 0.5em;
&[data-selected='true'] {
background-color: forestgreen;
}
} }
} }
} }
+1 -1
View File
@@ -132,7 +132,7 @@
<td class="station_dispatcher-exp"> <td class="station_dispatcher-exp">
<span <span
v-if="station.onlineInfo" v-if="station.onlineInfo && station.onlineInfo?.dispatcherExp != -1"
:style=" :style="
calculateExpStyle( calculateExpStyle(
station.onlineInfo.dispatcherExp, station.onlineInfo.dispatcherExp,
+2 -3
View File
@@ -42,14 +42,13 @@ export interface Filter {
nonPublic: boolean; nonPublic: boolean;
unavailable: boolean; unavailable: boolean;
abandoned: boolean; abandoned: boolean;
endingStatus: boolean; endingStatus: boolean;
afkStatus: boolean; afkStatus: boolean;
noSpaceStatus: boolean; noSpaceStatus: boolean;
unavailableStatus: boolean; unavailableStatus: boolean;
unsignedStatus: boolean; unsignedStatus: boolean;
authors: string; authors: string;
onlineFromHours: number; onlineFromHours: number;
withActiveTimetables: boolean;
withoutActiveTimetables: boolean;
} }
+172
View File
@@ -0,0 +1,172 @@
<template>
<span class="stop-label" :data-sbl="stop.isSBL">
<span class="name" v-html="stop.nameHtml"></span>
<span
v-if="stop.position != 'begin'"
class="date arrival"
:data-status="
stop.arrivalDelay > 0 && stop.status != 'unconfirmed'
? 'delayed'
: stop.arrivalDelay < 0 && stop.status != 'unconfirmed'
? 'preponed'
: stop.arrivalDelay == 0 && stop.status == 'confirmed'
? 'on-time'
: ''
"
>
<span v-if="stop.arrivalDelay != 0 && stop.status != 'unconfirmed'">
<s>{{ timestampToString(stop.arrivalScheduled) }}</s>
{{ timestampToString(stop.arrivalReal) }}
({{ stop.arrivalDelay > 0 ? '+' : '' }}{{ stop.arrivalDelay }})
</span>
<span v-else>
{{ timestampToString(stop.arrivalScheduled) }}
</span>
</span>
<span
v-if="
stop.duration ||
(stop.status == 'stopped' &&
stop.position != 'begin' &&
stop.departureDelay != stop.arrivalDelay)
"
class="date stop"
:data-stop-types="stop.type.replace(', ', '-')"
:data-stop-status="
stop.departureDelay - stop.arrivalDelay > 0 && !stop.duration ? 'delayed' : ''
"
>
{{ stop.duration || stop.departureDelay - stop.arrivalDelay }}
{{ stop.type == '' ? 'pt' : stop.type }}
</span>
<span
v-if="
stop.position != 'end' &&
(stop.duration != 0 || stop.status == 'stopped' || stop.departureDelay != stop.arrivalDelay)
"
class="date departure"
:data-status="
stop.departureDelay > 0 && stop.status == 'confirmed'
? 'delayed'
: stop.departureDelay < 0 && stop.status == 'confirmed'
? 'preponed'
: stop.departureDelay == 0 && stop.status == 'confirmed'
? 'on-time'
: ''
"
>
<span v-if="stop.departureDelay != 0 && stop.status == 'confirmed'">
<s>{{ timestampToString(stop.departureScheduled) }}</s>
{{ timestampToString(stop.departureReal) }}
({{ stop.departureDelay > 0 ? '+' : '' }}{{ stop.departureDelay }})
</span>
<span v-else>
{{ timestampToString(stop.departureScheduled) }}
</span>
</span>
</span>
</template>
<script lang="ts">
import { PropType, defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { TrainScheduleStop } from './TrainSchedule.vue';
export default defineComponent({
mixins: [dateMixin],
props: {
stop: {
type: Object as PropType<TrainScheduleStop>,
required: true
}
}
});
</script>
<style lang="scss" scoped>
$preponedClr: lime;
$delayedClr: salmon;
$dateClr: #525151;
$stopExchangeClr: #db8e29;
$stopDefaultClr: #252525;
$stopNameClr: #22a8d1;
.stop-label {
display: flex;
flex-wrap: wrap;
align-items: center;
&[data-sbl='true'] {
.date {
display: none;
}
.name {
background: none;
color: #aaa;
padding: 0;
}
}
.name {
background: $stopNameClr;
padding: 0.3em 0.5em;
display: flex;
align-items: center;
&.misc {
background: gray;
}
}
.date {
background: $dateClr;
padding: 0.3em 0.5em;
}
.stop {
&[data-stop-types='ph'],
&[data-stop-types='ph-pm'],
&[data-stop-types='pm'] {
background: $stopExchangeClr;
}
background: $stopDefaultClr;
&[data-stop-status='delayed'] {
color: $delayedClr;
}
}
.arrival,
.departure {
&[data-status='delayed'] {
s {
color: #999;
}
span {
color: $delayedClr;
}
}
&[data-status='preponed'] {
s {
color: #999;
}
span {
color: $preponedClr;
}
}
}
}
</style>
@@ -15,19 +15,12 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import trainInfoMixin from '../../mixins/trainInfoMixin'; import TrainInfo from './TrainInfo.vue';
import TrainInfo from '../TrainsView/TrainInfo.vue'; import TrainSchedule from './TrainSchedule.vue';
import TrainSchedule from '../TrainsView/TrainSchedule.vue';
export default defineComponent({ export default defineComponent({
components: { TrainInfo, TrainSchedule }, components: { TrainInfo, TrainSchedule },
mixins: [trainInfoMixin, modalTrainMixin], mixins: [modalTrainMixin],
data() {
return {
isTopBarVisible: false
};
},
activated() { activated() {
const contentEl = this.$refs['content'] as HTMLElement; const contentEl = this.$refs['content'] as HTMLElement;
+378 -270
View File
@@ -2,83 +2,126 @@
<div class="train-schedule" @click="toggleShowState"> <div class="train-schedule" @click="toggleShowState">
<StockList :trainStockList="train.stockList" /> <StockList :trainStockList="train.stockList" />
<!-- <div class="train-stock"> -->
<!-- <ul>
<li v-for="(stockName, i) in train.stockList" :key="i">
<p>{{ stockName.split(':')[0].split('_').splice(0, 2).join(' ') }} {{ stockName.split(':')[1] }}</p>
<TrainThumbnail :name="stockName" />
</li>
</ul> -->
<!-- </div> -->
<div class="schedule-wrapper" v-if="train.timetableData"> <div class="schedule-wrapper" v-if="train.timetableData">
<ul class="stop_list"> <div class="stops">
<li <div
v-for="(stop, i) in train.timetableData.followingStops" v-for="(stop, i) in scheduleStops"
:key="i" :key="i"
class="stop" class="stop"
:class="addClasses(stop, i)" :data-status="stop.status"
:data-position="stop.position"
:data-delayed="stop.departureDelay > 0"
:data-stop-type="stop.type"
:data-minor-stop-active="stop.isActive"
:data-last-confirmed="stop.isLastConfirmed"
x
> >
<span class="stop_info"> <span class="stop_info">
<div class="indicator"></div> <span class="distance">
{{ stop.distance ? stop.distance.toFixed(1) : '' }}
<div class="progress-bar"></div>
<div class="stop-bar"></div>
<span class="distance" v-if="stop.stopDistance">
{{ Math.floor(stop.stopDistance) }}
</span> </span>
<span class="stop-name" v-html="stop.stopName"> </span> <div class="progress">
<div class="line line_node line_node-top"></div>
<div class="node"></div>
<div class="line line_node line_node-bottom"></div>
</div>
<StopDate :stop="stop" /> <StopLabel :stop="stop" />
</span> </span>
<div class="stop_line" v-if="i < train.timetableData!.followingStops.length - 1"> <div class="stop_line">
<div class="progress-bar"></div> <!-- Grid placeholder -->
<div></div>
<div v-if="stop.comments" style="color: salmon"> <div class="progress">
<b>{{ stop.stopNameRAW }} </b>: <span v-html="stop.comments"></span> <div class="line line_connection" v-if="i < scheduleStops.length - 1"></div>
</div> </div>
<span <div class="bottom-line-info">
v-if=" <div class="info-comments" v-if="stop.comments" style="color: salmon">
stop.departureLine == train.timetableData!.followingStops[i + 1].arrivalLine && <img src="/images/icon-warning.svg" alt="icon-warning" width="20" />
!/sbl/gi.test(stop.departureLine!) <b v-html="stop.comments"></b>
" </div>
>
{{ stop.departureLine }}
</span>
<span v-else-if="!/sbl/gi.test(stop.departureLine!)"> <!-- Routes -->
{{ stop.departureLine }} / <span
{{ train.timetableData!.followingStops[i + 1].arrivalLine }} v-if="
</span> stop.departureLine &&
</div> stop.departureLine == scheduleStops[i + 1]?.arrivalLine &&
!/sbl/gi.test(stop.departureLine)
"
>
{{ stop.departureLine }}
</span>
<div class="stop_line" v-else> <span v-else-if="stop.departureLine && !/sbl/gi.test(stop.departureLine)">
<div v-if="stop.comments" style="color: salmon"> <div>{{ stop.departureLine }}</div>
<b>{{ stop.stopNameRAW }} </b>: <span v-html="stop.comments"></span> <div
class="scenery-change-name"
v-if="
i < scheduleStops.length - 1 &&
stop.sceneryName != scheduleStops[i + 1].sceneryName
"
>
{{ scheduleStops[i + 1].sceneryName }}
</div>
<div>
{{ scheduleStops[i + 1].arrivalLine }}
</div>
</span>
</div> </div>
</div> </div>
</li> </div>
</ul> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from 'vue'; import { 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 { useMainStore } from '../../store/mainStore'; import StopLabel from './StopLabel.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 { useMainStore } from '../../store/mainStore';
import { useApiStore } from '../../store/apiStore';
export interface TrainScheduleStop {
nameHtml: string;
nameRaw: string;
status: 'confirmed' | 'unconfirmed' | 'stopped';
type: string;
position: 'begin' | 'end' | 'en-route';
arrivalScheduled: number;
arrivalReal: number;
departureScheduled: number;
departureReal: number;
departureDelay: number;
arrivalDelay: number;
duration: number | null;
isActive: boolean;
isLastConfirmed: boolean;
isSBL: boolean;
sceneryName: string | null;
sceneryHash: string;
distance: number;
arrivalLine: string | null;
departureLine: string | null;
comments: string | null;
}
export default defineComponent({ export default defineComponent({
components: { StopDate, StockList }, components: { StopLabel, StockList },
props: { props: {
train: { train: {
type: Object as PropType<Train>, type: Object as PropType<Train>,
@@ -90,62 +133,95 @@ export default defineComponent({
emits: ['click'], emits: ['click'],
setup(props) { data() {
return { return {
store: useMainStore(), store: useMainStore(),
apiStore: useApiStore()
lastConfirmed: computed(() => {
return props.train.timetableData!.followingStops.findIndex(
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed && !stops[i + 1]?.stopped
);
}),
activeMinorStops: computed(() => {
const lastMajorConfirmed = props.train.timetableData!.followingStops.findIndex(
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed
);
const activeMinorStopList: number[] = [];
if (lastMajorConfirmed + 1 >= props.train.timetableData!.followingStops.length)
return activeMinorStopList;
for (
let i = lastMajorConfirmed + 1;
i < props.train.timetableData!.followingStops.length;
i++
) {
if (/po\.|sbl/gi.test(props.train.timetableData!.followingStops[i].stopNameRAW))
activeMinorStopList.push(i);
else break;
}
return activeMinorStopList;
})
}; };
}, },
computed: {
scheduleStops(): TrainScheduleStop[] {
let currentSceneryIndex = 0;
return (
this.train.timetableData?.followingStops.map((stop, i, arr) => {
if (
i > 0 &&
stop.arrivalLine &&
stop.arrivalLine != arr[i - 1].departureLine &&
!/sbl/gi.test(stop.arrivalLine)
)
currentSceneryIndex++;
return {
nameHtml: stop.stopName,
nameRaw: stop.stopNameRAW,
arrivalScheduled: stop.arrivalTimestamp,
arrivalReal: stop.arrivalRealTimestamp,
departureScheduled: stop.departureTimestamp,
departureReal: stop.departureRealTimestamp,
departureDelay: stop.departureDelay,
arrivalDelay: stop.arrivalDelay,
duration: stop.stopTime,
comments: stop.comments ?? null,
arrivalLine: stop.arrivalLine,
departureLine: stop.departureLine,
type: stop.stopType,
distance: stop.stopDistance,
isActive: this.activeMinorStops.includes(i),
isLastConfirmed: this.lastConfirmed === i && !stop.terminatesHere,
isSBL: /sbl/gi.test(stop.stopName),
position: stop.beginsHere ? 'begin' : stop.terminatesHere ? 'end' : 'en-route',
sceneryHash: '',
sceneryName: this.train.timetableData!.sceneryNames[currentSceneryIndex],
status: stop.confirmed ? 'confirmed' : stop.stopped ? 'stopped' : 'unconfirmed'
};
}) ?? []
);
},
lastConfirmed() {
return this.train.timetableData?.followingStops.findIndex(
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed && !stops[i + 1]?.stopped
);
},
activeMinorStops() {
if (!this.train.timetableData) return [];
const lastMajorConfirmed = this.train.timetableData.followingStops.findIndex(
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed
);
const activeMinorStopList: number[] = [];
if (lastMajorConfirmed + 1 >= this.train.timetableData.followingStops.length)
return activeMinorStopList;
for (
let i = lastMajorConfirmed + 1;
i < this.train.timetableData!.followingStops.length;
i++
) {
if (/po\.|sbl/gi.test(this.train.timetableData!.followingStops[i].stopNameRAW))
activeMinorStopList.push(i);
else break;
}
return activeMinorStopList;
}
},
methods: { methods: {
toggleShowState() { toggleShowState() {
this.$emit('click'); this.$emit('click');
},
addClasses(stop: TrainStop, index: number) {
return {
confirmed: stop.confirmed,
stopped: stop.stopped,
begin: stop.beginsHere,
end: stop.terminatesHere,
delayed: stop.departureDelay > 0,
sbl: /sbl/gi.test(stop.stopName),
[stop.stopType.replaceAll(', ', '-')]:
stop.stopType.match(new RegExp('ph|pm|pt')) && !stop.confirmed && !stop.beginsHere,
'minor-stop-active': this.activeMinorStops.includes(index),
'last-confirmed': index == this.lastConfirmed && !stop.terminatesHere
};
},
onImageError(e: Event) {
const imageEl = e.target as HTMLImageElement;
imageEl.src = '/images/icon-unknown.png';
} }
} }
}); });
@@ -155,17 +231,18 @@ export default defineComponent({
@import '../../styles/responsive.scss'; @import '../../styles/responsive.scss';
$barClr: #b1b1b1; $barClr: #b1b1b1;
$confirmedClr: #18d818; $confirmedClr: #4ae24a;
$stoppedClr: #f55f31; $stoppedClr: #f55f31;
$haltClr: #f8bb36; $haltClr: #f8bb36;
$stopNameClr: #22a8d1;
$blinkAnim: 0.5s ease-in-out alternate infinite blink;
@keyframes blink { @keyframes blink {
from { from {
background-color: $barClr; border-color: $barClr;
} }
to { to {
background-color: $confirmedClr; border-color: $confirmedClr;
} }
} }
@@ -181,216 +258,247 @@ $stopNameClr: #22a8d1;
margin-top: 1em; margin-top: 1em;
} }
.progress-bar { .stops {
position: absolute;
z-index: 10;
top: -1px;
left: -17px;
height: 100%;
width: 3px;
background-color: $barClr;
}
.stop-name {
background: $stopNameClr;
padding: 0.3em 0.5em;
display: flex;
align-items: center;
&.misc {
background: gray;
}
}
.stop-comment {
background: forestgreen;
padding: 0.3em 0.5em;
max-width: 250px;
overflow: hidden;
white-space: nowrap;
width: 2em;
cursor: pointer;
&:hover {
text-overflow: ellipsis;
width: 100%;
}
img {
width: 1em;
}
span {
font-size: 0.8em;
}
}
ul.stop_list {
margin-left: 2.5em;
}
ul.stop_list > li.stop {
position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-y: hidden;
gap: 5px;
padding: 0 0.5em; padding: 5px 0;
}
&.sbl { .stop {
.stop-date { // Begin stop
display: none; &[data-position='begin'] {
} .node {
.stop-name {
background: none;
color: #aaa;
padding: 0;
}
}
&[class*='ph'] > .stop_info > .indicator {
border-color: $stopNameClr;
}
&[class*='pt'] > .stop_info > .indicator {
border-color: #818181;
}
&.begin {
.stop_info > .indicator {
border-color: lightgreen; border-color: lightgreen;
} }
.stop_info > .progress-bar { .line_node-top {
background: lightgreen; display: none;
} }
} }
&.end { // End stop
.stop_info > .indicator { &[data-position='end'] {
.node {
border-color: salmon; border-color: salmon;
} }
.stop_info > .progress-bar { .line_node-bottom {
background: salmon; display: none;
} }
} }
&.minor-stop-active { // Stop types
.stop_info > .progress-bar { &[data-stop-type*='pt'] .node {
animation: 0.5s ease-in-out alternate infinite blink; border-color: #818181;
}
.stop_line > .progress-bar {
animation: 0.5s ease-in-out alternate infinite blink;
}
} }
&.last-confirmed { &[data-stop-type*='ph'] .node {
.stop_line > .progress-bar { border-color: $haltClr;
animation: 0.5s ease-in-out alternate infinite blink;
}
} }
&.confirmed { &[data-minor-stop-active='true'] {
.stop_info { .progress > .line {
> .progress-bar { animation: $blinkAnim;
background-color: $confirmedClr;
}
> .indicator {
border-color: $confirmedClr;
}
} }
.stop_line > .progress-bar { & + div {
background-color: $confirmedClr; .progress > .line_node-top {
} animation: $blinkAnim;
}
&.stopped {
.stop_info {
> .indicator {
border-color: $stoppedClr;
}
> .stop-bar {
background: $stoppedClr;
} }
} }
} }
.stop_line { // Last confirmed outpost / checkpoint
font-size: 0.8em; &[data-last-confirmed='true'] {
color: #ccc; .progress > .line_connection {
animation: $blinkAnim;
}
padding: 0.35em 0; .progress > .line_node-bottom {
animation: $blinkAnim;
}
position: relative; & + div {
.progress > .line_node-top {
.line-segment { animation: $blinkAnim;
color: $barClr; }
font-weight: 500;
} }
} }
.stop_info { // Confirmed status
display: flex; &[data-status='confirmed'] {
.progress > .node {
position: relative; border-color: $confirmedClr;
text-align: center; }
.progress > .line {
flex-wrap: wrap; border-left: 2px solid $confirmedClr;
border-right: 2px solid $confirmedClr;
}
} }
.stop-bar { // Stopped status
&[data-status='stopped'] {
.progress > .node {
border-color: $stoppedClr;
}
.progress > .line_node {
border-color: $stoppedClr;
}
}
// Unused so far
&[data-track-count-departure='2'] {
.progress > .line {
width: 6px;
}
}
&[data-track-count-arrival='2'] {
.progress > .line_node-top {
width: 6px;
}
}
&[data-track-count-arrival='1'] {
.progress > .line_node-top {
width: 4px;
}
}
&[data-electrified-departure] {
.stop_line > .line-speed > .speed-departure {
color: #00c1c7;
}
}
&[data-electrified-arrival] {
.stop_line > .line-speed > .speed-next-arrival {
color: #00c1c7;
}
}
}
.stop_info,
.stop_line {
display: grid;
grid-template-columns: 30px 40px auto 1fr;
}
.line-speed {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #9b9b9b;
gap: 10px;
}
.stop_info {
position: relative;
text-align: center;
}
.stop_line {
font-size: 0.8em;
color: #ccc;
margin-top: 5px;
}
.distance {
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75em;
}
.progress {
position: relative;
& > .node {
position: absolute; position: absolute;
top: 0;
left: -17px;
z-index: 10;
width: 3px;
height: 100%;
}
.distance {
position: absolute;
top: 50%; top: 50%;
transform: translate(-100%, -50%); left: 50%;
transform: translate(-50%, -50%);
margin-left: -1.75rem; z-index: 15;
font-size: 0.75em;
color: #d6d6d6;
}
.indicator {
position: absolute;
z-index: 11;
top: 50%;
left: -1rem;
transform: translate(-47%, -50%);
text-align: right; text-align: right;
width: 15px; width: 15px;
height: 15px; height: 15px;
background: var(--clr-secondary); background-color: var(--clr-secondary);
border: 3px solid $barClr; border: 4px solid $barClr;
border-radius: 100%; border-radius: 100%;
} }
& > .line {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0);
z-index: 10;
height: 100%;
// background-color: $barClr;
border-left: 2px solid $barClr;
border-right: 2px solid $barClr;
&.line_connection {
transform: translate(-50%, -6px);
height: calc(100% + 12px);
// height: calc(100% + 0.25em);
}
&.line_node-top {
top: 0;
height: 50%;
}
&.line_node-bottom {
top: 50%;
height: 50%;
}
&.line_stop {
border-color: $stoppedClr;
z-index: 11;
}
}
}
.info-comments {
display: flex;
align-items: center;
gap: 0.25em;
margin: 0.25em 0;
img {
height: 1.2em;
}
}
.bottom-line-info {
.scenery-change-name {
position: relative;
margin: 0.25em 0;
&::before {
content: '';
position: absolute;
height: 2px;
width: 30px;
background-color: #aaa;
top: 50%;
right: calc(100% + 5px);
transform: translate(0, -50%);
}
}
} }
</style> </style>
+14
View File
@@ -0,0 +1,14 @@
import { PropType, defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { TrainScheduleStop } from './TrainSchedule.vue';
export default defineComponent({
mixins: [dateMixin],
props: {
stop: {
type: Object as PropType<TrainScheduleStop>,
required: true
}
}
});
+2 -2
View File
@@ -8732,7 +8732,7 @@
"departureDelay": 0, "departureDelay": 0,
"beginsHere": true, "beginsHere": true,
"terminatesHere": false, "terminatesHere": false,
"confirmed": 0, "confirmed": 1,
"stopped": 0, "stopped": 0,
"stopTime": null "stopTime": null
}, },
@@ -9380,7 +9380,7 @@
"stopType": "", "stopType": "",
"stopDistance": 123.62, "stopDistance": 123.62,
"pointId": "1663532077406", "pointId": "1663532077406",
"comments": null, "comments": "test121",
"mainStop": true, "mainStop": true,
"arrivalLine": "Sk", "arrivalLine": "Sk",
"arrivalTimestamp": 1701889320000, "arrivalTimestamp": 1701889320000,
File diff suppressed because it is too large Load Diff
+16 -1
View File
@@ -7,7 +7,8 @@
"addons", "addons",
"blockades", "blockades",
"signals", "signals",
"status" "status",
"timetables"
], ],
"options": [ "options": [
@@ -228,6 +229,20 @@
"section": "status", "section": "status",
"value": true, "value": true,
"defaultValue": true "defaultValue": true
},
{
"id": "withActiveTimetables",
"name": "withActiveTimetables",
"section": "timetables",
"value": true,
"defaultValue": true
},
{
"id": "withoutActiveTimetables",
"name": "withoutActiveTimetables",
"section": "timetables",
"value": true,
"defaultValue": true
} }
], ],
"sliders": [ "sliders": [
+11 -3
View File
@@ -12,7 +12,7 @@
"p4": "Every person who decides to contribute at least {b1} (in case of PayPal it must be a payment including additional transaction fees) for the development of Stacjownik, will receive (upon a personal request) {img}{b2} of username in the app and on my Discord server (after verifying the payment author, preferably by providing the username directly with the payment).", "p4": "Every person who decides to contribute at least {b1} (in case of PayPal it must be a payment including additional transaction fees) for the development of Stacjownik, will receive (upon a personal request) {img}{b2} of username in the app and on my Discord server (after verifying the payment author, preferably by providing the username directly with the payment).",
"p4-b1": "5 PLN", "p4-b1": "5 PLN",
"p4-b2": "a symbolic highlight", "p4-b2": "a symbolic highlight",
"p5": "Thank you and enjoy the app!<br />~ Spythegre", "p5": "Thank you and enjoy the app!<br />~ Spythere",
"action-exit": "Maybe next time...", "action-exit": "Maybe next time...",
"action-paypal": "DONATE WITH PAYPAL", "action-paypal": "DONATE WITH PAYPAL",
"action-buycoffee": "BUY ME A COFFEE!", "action-buycoffee": "BUY ME A COFFEE!",
@@ -176,7 +176,8 @@
"signals": "SIGNALLING", "signals": "SIGNALLING",
"addons": "ADDITIONAL PROGRAMS", "addons": "ADDITIONAL PROGRAMS",
"blockades": "BLOCK SIGNALLING", "blockades": "BLOCK SIGNALLING",
"status": "ONLINE STATUS" "status": "ONLINE STATUS",
"timetables": "ACTIVE TIMETABLES"
}, },
"all-available": "ALL AVAILABLE", "all-available": "ALL AVAILABLE",
@@ -219,6 +220,10 @@
"historical": "HISTORICAL", "historical": "HISTORICAL",
"free": "FREE", "free": "FREE",
"occupied": "OCCUPIED", "occupied": "OCCUPIED",
"withActiveTimetables": "ACTIVE",
"withoutActiveTimetables": "NO ACTIVE",
"sliders": { "sliders": {
"min-lvl": "MIN. REQUIRED DISPATCHER LEVEL", "min-lvl": "MIN. REQUIRED DISPATCHER LEVEL",
"max-lvl": "MAX. REQUIRED DISPATCHER LEVEL", "max-lvl": "MAX. REQUIRED DISPATCHER LEVEL",
@@ -227,7 +232,10 @@
"routes-2t-cat": "MIN. CATENARY DOUBLE TRACK ROUTES", "routes-2t-cat": "MIN. CATENARY DOUBLE TRACK ROUTES",
"routes-2t-other": "MIN. OTHER DOUBLE TRACK ROUTES" "routes-2t-other": "MIN. OTHER DOUBLE TRACK ROUTES"
}, },
"authors-search": "Search by author (other filters apply)", "authors-search": "SEARCH BY AUTHOR NAME (other filters apply):",
"authors-placeholder": "Enter the author nickname...",
"authors-button-title": "Search",
"minimum-hours-title": "SHOW ONLY SCENERIES UNTIL:", "minimum-hours-title": "SHOW ONLY SCENERIES UNTIL:",
"now": "NOW", "now": "NOW",
"hour": "h", "hour": "h",
+8 -2
View File
@@ -165,7 +165,8 @@
"signals": "TYP SYGNALIZACJI", "signals": "TYP SYGNALIZACJI",
"addons": "DODATKOWE PROGRAMY", "addons": "DODATKOWE PROGRAMY",
"blockades": "BLOKADY LINIOWE", "blockades": "BLOKADY LINIOWE",
"status": "STATUS ONLINE" "status": "STATUS ONLINE",
"timetables": "AKTYWNE ROZKŁADY JAZDY"
}, },
"all-available": "WSZYSTKIE DOSTĘPNE", "all-available": "WSZYSTKIE DOSTĘPNE",
@@ -209,6 +210,9 @@
"free": "WOLNA", "free": "WOLNA",
"occupied": "ZAJĘTA", "occupied": "ZAJĘTA",
"withActiveTimetables": "AKTYWNE RJ",
"withoutActiveTimetables": "BEZ AKTYWNYCH RJ",
"sliders": { "sliders": {
"min-lvl": "MIN. WYMAGANY POZIOM DYŻURNEGO", "min-lvl": "MIN. WYMAGANY POZIOM DYŻURNEGO",
"max-lvl": "MAKS. WYMAGANY POZIOM DYŻURNEGO", "max-lvl": "MAKS. WYMAGANY POZIOM DYŻURNEGO",
@@ -218,7 +222,9 @@
"routes-2t-other": "SZLAKI DWUTOROWE NIEZELEKTR. (MINIMUM)" "routes-2t-other": "SZLAKI DWUTOROWE NIEZELEKTR. (MINIMUM)"
}, },
"authors-search": "Szukaj autora (uwzględnia inne filtry)", "authors-search": "SZUKAJ AUTORA (uwzględnia inne filtry):",
"authors-placeholder": "Wpisz nick autora...",
"authors-button-title": "Szukaj",
"minimum-hours-title": "POKAŻ TYLKO SCENERIE DOSTĘPNE MINIMUM DO:", "minimum-hours-title": "POKAŻ TYLKO SCENERIE DOSTĘPNE MINIMUM DO:",
"now": "TERAZ", "now": "TERAZ",
"hour": " godz.", "hour": " godz.",
+5 -7
View File
@@ -1,5 +1,5 @@
import { Availability, OnlineScenery, ScheduledTrain } from '../../store/typings'; import { Availability, ActiveScenery, ScheduledTrain } from '../../store/typings';
import StationRoutes from './StationRoutes'; import { StationRoutes } from './StationRoutes';
export default interface Station { export default interface Station {
name: string; name: string;
@@ -8,6 +8,7 @@ export default interface Station {
name: string; name: string;
url: string; url: string;
abbr: string; abbr: string;
hash?: string;
reqLevel: number; reqLevel: number;
// supportersOnly: boolean; // supportersOnly: boolean;
@@ -25,11 +26,8 @@ export default interface Station {
availability: Availability; availability: Availability;
routes: StationRoutes; routes: StationRoutes;
checkpoints: { checkpoints: string[];
checkpointName: string;
scheduledTrains: ScheduledTrain[];
}[];
}; };
onlineInfo?: OnlineScenery; onlineInfo?: ActiveScenery;
} }
+4 -21
View File
@@ -1,25 +1,8 @@
export default interface StationRoutes { import { StationRoutesInfo } from '../../store/typings';
oneWay: {
name: string;
catenary: boolean;
SBL: boolean;
TWB: boolean;
isInternal: boolean;
tracks: number;
speed: number;
length: number;
}[];
twoWay: { export interface StationRoutes {
name: string; oneWay: StationRoutesInfo[];
catenary: boolean; twoWay: StationRoutesInfo[];
SBL: boolean;
TWB: boolean;
isInternal: boolean;
tracks: number;
speed: number;
length: number;
}[];
/* [catenary, noCatenary] */ /* [catenary, noCatenary] */
oneWayCatenaryRouteNames: string[]; oneWayCatenaryRouteNames: string[];
+1
View File
@@ -33,5 +33,6 @@ export default interface Train {
SKR: boolean; SKR: boolean;
routeDistance: number; routeDistance: number;
sceneries: string[]; sceneries: string[];
sceneryNames: string[];
}; };
} }
+28 -7
View File
@@ -93,26 +93,41 @@ export const sortStations = (
}; };
export const filterStations = (station: Station, filters: Filter) => { export const filterStations = (station: Station, filters: Filter) => {
if (!station.onlineInfo && filters['free']) return false; if (filters['free'] && (!station.onlineInfo || station.onlineInfo.dispatcherId == -1))
return false;
if (station.onlineInfo) { if (station.onlineInfo) {
const { dispatcherStatus } = station.onlineInfo; const { dispatcherStatus } = station.onlineInfo;
const isEnding = dispatcherStatus == Status.ActiveDispatcher.ENDING && filters['endingStatus']; const excludeEnding =
dispatcherStatus == Status.ActiveDispatcher.ENDING && filters['endingStatus'];
const isNotSigned = const excludeNotSigned =
(dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN || (dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN ||
dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE) && dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE) &&
filters['unavailableStatus']; filters['unavailableStatus'];
const isAFK = dispatcherStatus == Status.ActiveDispatcher.AFK && filters['afkStatus']; const excludeAFK = dispatcherStatus == Status.ActiveDispatcher.AFK && filters['afkStatus'];
const isNoSpace = const excludeNoSpace =
dispatcherStatus == Status.ActiveDispatcher.NO_SPACE && filters['noSpaceStatus']; dispatcherStatus == Status.ActiveDispatcher.NO_SPACE && filters['noSpaceStatus'];
const isOccupied = station.onlineInfo && filters['occupied']; const excludeOccupied = filters['occupied'] && dispatcherStatus != Status.ActiveDispatcher.FREE;
if (isEnding || isNotSigned || isAFK || isNoSpace || isOccupied) return false; const excludeActiveTTs =
(dispatcherStatus == Status.ActiveDispatcher.FREE ||
station.onlineInfo.scheduledTrainCount.all != 0) &&
filters['withActiveTimetables'];
if (
excludeEnding ||
excludeAFK ||
excludeNoSpace ||
excludeNotSigned ||
excludeOccupied ||
excludeActiveTTs
)
return false;
if ( if (
filters['onlineFromHours'] > 0 && filters['onlineFromHours'] > 0 &&
@@ -121,6 +136,12 @@ export const filterStations = (station: Station, filters: Filter) => {
return false; return false;
} }
const excludeNoActiveTTs =
filters['withoutActiveTimetables'] &&
(!station.onlineInfo || station.onlineInfo.scheduledTrainCount.all == 0);
if (excludeNoActiveTTs) return false;
if ( if (
(station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && (station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) &&
filters['nonPublic'] filters['nonPublic']
+31 -66
View File
@@ -5,14 +5,14 @@ import axios from 'axios';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
import { StationJSONData } from './typings'; import { StationJSONData } from './typings';
// Update seconds cron for active data scheduler
const UPDATE_SECONDS = [3, 23, 43];
export const useApiStore = defineStore('apiStore', { export const useApiStore = defineStore('apiStore', {
state: () => ({ state: () => ({
dataStatuses: { dataStatuses: {
connection: Status.Data.Loading, connection: Status.Data.Loading,
sceneries: 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, activeData: undefined as API.ActiveData.Response | undefined,
@@ -20,42 +20,46 @@ export const useApiStore = defineStore('apiStore', {
donatorsData: [] as API.Donators.Response, donatorsData: [] as API.Donators.Response,
sceneryData: [] as StationJSONData[], sceneryData: [] as StationJSONData[],
activeDataTimeout: undefined as number | undefined activeDataScheduler: undefined as number | undefined
}), }),
actions: { actions: {
async setupAPI() { async setupAPIData() {
// Static data // Static data
this.fetchStockInfoData(); this.fetchStockInfoData();
this.fetchDonatorsData(); this.fetchDonatorsData();
this.fetchStationsGeneralInfo(); this.fetchStationsGeneralInfo();
if (this.activeDataTimeout === undefined) this.startActiveDataScheduler(); // Active data schedueler
this.fetchActiveData();
this.setupActiveDataFetcher();
}, },
// async setDataStatuses() { async setupActiveDataFetcher() {
// if (!window.navigator.onLine) { if (this.activeDataScheduler) return;
// this.dataStatuses.connection = Status.Data.Offline;
// this.dataStatuses.sceneries = Status.Data.Offline;
// this.dataStatuses.trains = Status.Data.Offline;
// this.dataStatuses.dispatchers = Status.Data.Offline;
// this.dataStatuses.timetables = Status.Data.Offline;
// }
// if (!this.activeData?.activeSceneries) { this.dataStatuses.connection = Status.Data.Loading;
// this.dataStatuses.connection = Status.Data.Loaded;
// this.dataStatuses.sceneries = Status.Data.Error;
// this.dataStatuses.trains = Status.Data.Error;
// this.dataStatuses.dispatchers = Status.Data.Error;
// return; this.activeDataScheduler = window.setInterval(() => {
// } if (UPDATE_SECONDS.includes(new Date().getSeconds())) {
this.fetchActiveData();
}
}, 1000);
},
// this.dataStatuses.connection = Status.Data.Loaded; async fetchActiveData() {
// this.dataStatuses.sceneries = Status.Data.Loaded; try {
// this.dataStatuses.trains = !this.activeData.trains ? Status.Data.Warning : Status.Data.Loaded; const response = await http.get<API.ActiveData.Response>('api/getActiveData');
// this.dataStatuses.dispatchers = Status.Data.Loaded;
// }, this.activeData = response.data;
this.dataStatuses.connection = Status.Data.Loaded;
console.log('Fetching active data at ' + new Date().toLocaleTimeString('pl-PL'));
} catch (error) {
this.dataStatuses.connection = Status.Data.Error;
console.error('Ups! Wystąpił błąd podczas pobierania danych online:', error);
}
},
async fetchDonatorsData() { async fetchDonatorsData() {
try { try {
@@ -79,45 +83,6 @@ export const useApiStore = defineStore('apiStore', {
} }
}, },
async startActiveDataScheduler() {
if (!window.navigator.onLine) {
this.dataStatuses.connection = Status.Data.Offline;
return;
}
if (import.meta.env.VITE_API_MODE === 'mock') {
const mockActiveData = await import('../data/mockActiveData.json');
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = mockActiveData;
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;
} catch (error) {
this.dataStatuses.connection = Status.Data.Error;
console.error('Wystąpił błąd podczas pobierania danych online z API!');
} finally {
this.activeDataTimeout = window.setTimeout(
() => {
this.startActiveDataScheduler();
},
~~(1000 * (Math.random() * (25 - 20) + 25))
);
}
},
async stopActiveDataScheduler() {
window.clearTimeout(this.activeDataTimeout);
this.activeDataTimeout = undefined;
},
async fetchStationsGeneralInfo() { async fetchStationsGeneralInfo() {
const sceneryData: StationJSONData[] = (await http.get<StationJSONData[]>('api/getSceneries')) const sceneryData: StationJSONData[] = (await http.get<StationJSONData[]>('api/getSceneries'))
.data; .data;
+123 -152
View File
@@ -1,14 +1,13 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import StationRoutes from '../scripts/interfaces/StationRoutes';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
import { parseSpawns, getScheduledTrains, getStationTrains } from './utils'; import { parseSpawns, getScheduledTrains, getStationTrains } from './utils';
import { OnlineScenery, ScheduledTrain, StoreState } from './typings'; import { ActiveScenery, ScheduledTrain, StoreState } from './typings';
import { Status } from '../typings/common'; import { Status } from '../typings/common';
import Station from '../scripts/interfaces/Station'; import Station from '../scripts/interfaces/Station';
import { useApiStore } from './apiStore'; import { useApiStore } from './apiStore';
import { API } from '../typings/api'; import { StationRoutes } from '../scripts/interfaces/StationRoutes';
export const useMainStore = defineStore('store', { export const useMainStore = defineStore('store', {
state: () => state: () =>
@@ -42,6 +41,14 @@ export const useMainStore = defineStore('store', {
const timetable = train.timetable; const timetable = train.timetable;
const sceneryNames =
train.timetable?.sceneries?.map(
(sceneryHash) =>
this.activeSceneryList.find((st) => st.hash === sceneryHash)?.name ??
apiStore.sceneryData.find((sd) => sd.hash === sceneryHash)?.name ??
sceneryHash
) ?? [];
return { return {
trainId: train.driverName + train.trainNo.toString(), trainId: train.driverName + train.trainNo.toString(),
@@ -77,43 +84,67 @@ export const useMainStore = defineStore('store', {
category: timetable.category, category: timetable.category,
followingStops: timetable.stopList, followingStops: timetable.stopList,
routeDistance: timetable.stopList[timetable.stopList.length - 1].stopDistance, routeDistance: timetable.stopList[timetable.stopList.length - 1].stopDistance,
sceneries: timetable.sceneries sceneries: timetable.sceneries,
sceneryNames: sceneryNames.reverse()
} }
: undefined : undefined
} as Train; } as Train;
}); });
}, },
onlineSceneryList(state): OnlineScenery[] { activeSceneryList(state): ActiveScenery[] {
const apiStore = useApiStore(); const apiStore = useApiStore();
if (state.isOffline) return []; if (state.isOffline) return [];
if (!apiStore.activeData?.activeSceneries) return []; if (!apiStore.activeData?.activeSceneries) return [];
return apiStore.activeData?.activeSceneries.reduce((list, scenery) => { const offlineActiveSceneries = this.trainList.reduce((acc, train) => {
if (!train.timetableData) return acc;
train.timetableData.sceneryNames.forEach((name) => {
if (
acc.findIndex((v) => v.name == name && v.region == train.region) != -1 ||
apiStore.activeData?.activeSceneries?.findIndex(
(sc) => sc.stationName === name && sc.region == train.region
) != -1
)
return acc;
acc.push({
name: name,
hash: '',
region: train.region,
maxUsers: 0,
currentUsers: 0,
spawns: [],
dispatcherName: '',
dispatcherRate: 0,
dispatcherId: -1,
dispatcherExp: -1,
dispatcherIsSupporter: false,
scheduledTrains: [],
stationTrains: [],
dispatcherStatus: Status.ActiveDispatcher.FREE,
dispatcherTimestamp: -1,
isOnline: false,
scheduledTrainCount: {
all: 0,
confirmed: 0,
unconfirmed: 0
}
});
});
return acc;
}, [] as ActiveScenery[]);
const onlineActiveSceneries = 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;
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 = const dispatcherTimestamp =
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT
? Date.now() + 25500000 ? Date.now() + 25500000
@@ -133,97 +164,42 @@ export const useMainStore = defineStore('store', {
dispatcherId: scenery.dispatcherId, dispatcherId: scenery.dispatcherId,
dispatcherExp: scenery.dispatcherExp, dispatcherExp: scenery.dispatcherExp,
dispatcherIsSupporter: scenery.dispatcherIsSupporter, dispatcherIsSupporter: scenery.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
dispatcherStatus: scenery.dispatcherStatus, dispatcherStatus: scenery.dispatcherStatus,
dispatcherTimestamp: dispatcherTimestamp, dispatcherTimestamp: dispatcherTimestamp,
isOnline: scenery.isOnline == 1, isOnline: scenery.isOnline == 1,
scheduledTrains: [],
stationTrains: [],
scheduledTrainCount: { scheduledTrainCount: {
all: uniqueScheduledTrains.length, all: 0,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length, confirmed: 0,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length unconfirmed: 0
} }
}); });
return list; return list;
}, [] as OnlineScenery[]); }, [] as ActiveScenery[]);
},
stationList(): Station[] { const allActiveSceneries = [...onlineActiveSceneries, ...offlineActiveSceneries];
const apiStore = useApiStore();
return apiStore.sceneryData.map((scenery) => { for (let i = 0, n = allActiveSceneries.length; i < n; i++) {
return { const scenery = allActiveSceneries[i];
name: scenery.name,
generalInfo: { const station = this.stationList.find((s) => s.name === scenery.name);
...scenery,
authors: scenery.authors?.split(',').map((a) => a.trim()),
routes:
scenery.routesInfo.reduce(
(acc, route) => {
const propName: keyof StationRoutes = `${
route.routeTracks == 2 ? 'twoWay' : 'oneWay'
}${route.isElectric ? '' : 'No'}CatenaryRouteNames`;
acc[route.routeTracks == 2 ? 'twoWay' : 'oneWay'].push({ const scheduledTrains = getScheduledTrains(
name: route.routeName, this.trainList,
SBL: route.isRouteSBL, station?.generalInfo,
TWB: false, scenery.name,
catenary: route.isElectric, scenery.region
isInternal: route.isInternal, );
tracks: route.routeTracks,
length: route.routeLength,
speed: route.routeSpeed
});
if (!route.isInternal) acc[propName].push(route.routeName);
if (route.isRouteSBL) acc['sblRouteNames'].push(route.routeName);
return acc;
},
{
oneWay: [],
twoWay: [],
sblRouteNames: [],
oneWayCatenaryRouteNames: [],
oneWayNoCatenaryRouteNames: [],
twoWayCatenaryRouteNames: [],
twoWayNoCatenaryRouteNames: []
} as StationRoutes
) || {},
checkpoints: scenery.checkpoints
? scenery.checkpoints
.split(';')
.map((sub) => ({ checkpointName: sub, scheduledTrains: [] }))
: []
}
};
});
}
},
actions: {
async processStationsOnlineInfo(activeData: API.ActiveData.Response) {
if (!activeData.activeSceneries) return;
const onlineSceneries = activeData.activeSceneries.reduce((acc, scenery) => {
const savedStation = this.stationList.find((st) => scenery.stationName === st.name);
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return acc;
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( const stationTrains = getStationTrains(
this.trainList, this.trainList,
scheduledTrains, scheduledTrains,
this.region.id, this.region.id,
scenery scenery.name
); );
// Remove checkpoint duplicates // Remove checkpoint duplicates
@@ -235,65 +211,60 @@ export const useMainStore = defineStore('store', {
[] as ScheduledTrain[] [] as ScheduledTrain[]
); );
const dispatcherTimestamp = scenery.scheduledTrains = scheduledTrains;
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT scenery.stationTrains = stationTrains;
? Date.now() + 25500000
: scenery.dispatcherStatus > 5
? scenery.dispatcherStatus
: null;
const onlineInfo = { scenery.scheduledTrainCount = {
name: scenery.stationName, all: uniqueScheduledTrains.length,
hash: scenery.stationHash, confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
region: scenery.region, unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length
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; return allActiveSceneries;
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']) { stationList(): Station[] {
this.region = region; const apiStore = useApiStore();
return apiStore.sceneryData.map((scenery) => {
const routes = scenery.routesInfo.reduce(
(acc, route) => {
const tracksKey = route.routeTracks == 2 ? 'twoWay' : 'oneWay';
const isElectric = route.isElectric;
const routesKey: keyof StationRoutes = `${tracksKey}${
!isElectric ? 'No' : ''
}CatenaryRouteNames`;
if (!route.isInternal) acc[routesKey].push(route.routeName);
if (route.isRouteSBL) acc['sblRouteNames'].push(route.routeName);
acc[tracksKey].push(route);
return acc;
},
{
oneWay: [],
oneWayCatenaryRouteNames: [],
oneWayNoCatenaryRouteNames: [],
twoWay: [],
twoWayCatenaryRouteNames: [],
twoWayNoCatenaryRouteNames: [],
sblRouteNames: []
} as StationRoutes
);
return {
name: scenery.name,
generalInfo: {
...scenery,
authors: scenery.authors?.split(',').map((a) => a.trim()),
routes: routes,
checkpoints: scenery.checkpoints?.split(';') ?? []
}
};
});
} }
} }
}); });
+5 -2
View File
@@ -48,6 +48,8 @@ const filterInitStates: Filter = {
noSpaceStatus: false, noSpaceStatus: false,
unavailableStatus: false, unavailableStatus: false,
unsignedStatus: false, unsignedStatus: false,
withActiveTimetables: false,
withoutActiveTimetables: false,
authors: '', authors: '',
@@ -73,7 +75,7 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
const store = useMainStore(); const store = useMainStore();
const savedStationNames = store.stationList.map((s) => s.name); const savedStationNames = store.stationList.map((s) => s.name);
const onlineUnsavedStations = store.onlineSceneryList const onlineUnsavedStations = store.activeSceneryList
.filter((os) => !savedStationNames.includes(os.name) && os.region == store.region.id) .filter((os) => !savedStationNames.includes(os.name) && os.region == store.region.id)
.map((os) => ({ .map((os) => ({
name: os.name, name: os.name,
@@ -85,7 +87,8 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
...onlineUnsavedStations, ...onlineUnsavedStations,
...store.stationList.map((station) => ({ ...store.stationList.map((station) => ({
...station, ...station,
onlineInfo: store.onlineSceneryList.find( // append to 'onlineInfo' object for filtering legacy reasons - to optimize later (hopefully)
onlineInfo: store.activeSceneryList.find(
(os) => os.name == station.name && os.region == store.region.id (os) => os.name == station.name && os.region == store.region.id
) )
})) }))
+3 -1
View File
@@ -35,6 +35,7 @@ export interface StationRoutesInfo {
routeLength: number; routeLength: number;
routeSpeed: number; routeSpeed: number;
routeTracks: number; routeTracks: number;
hidden?: boolean;
} }
export interface StationJSONData { export interface StationJSONData {
@@ -44,6 +45,7 @@ export interface StationJSONData {
lines: string; lines: string;
project: string; project: string;
projectUrl: string; projectUrl: string;
hash: string;
reqLevel: number; reqLevel: number;
@@ -61,7 +63,7 @@ export interface StationJSONData {
availability: Availability; availability: Availability;
} }
export interface OnlineScenery { export interface ActiveScenery {
name: string; name: string;
hash: string; hash: string;
region: string; region: string;
+37 -83
View File
@@ -1,6 +1,5 @@
import Station from '../scripts/interfaces/Station'; import Station from '../scripts/interfaces/Station';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
import { API } from '../typings/api';
import { ScheduledTrain, StationTrain, StopStatus, TrainStop } from './typings'; import { ScheduledTrain, StationTrain, StopStatus, TrainStop } from './typings';
export function getLocoURL(locoType: string): string { export function getLocoURL(locoType: string): string {
@@ -102,51 +101,33 @@ export function getCheckpointTrain(
let prevStationName = '', let prevStationName = '',
nextStationName = ''; nextStationName = '';
let prevDepartureLine: string | null = null,
nextArrivalLine: string | null = null;
for (let i = trainStopIndex - 1; i >= 0; i--) {
if (/strong|podg/g.test(followingStops[i].stopName)) {
prevStationName = followingStops[i].stopNameRAW.replace(/,.*/g, '');
break;
}
}
for (let i = trainStopIndex + 1; i < followingStops.length; i++) {
if (/strong|podg/g.test(followingStops[i].stopName)) {
nextStationName = followingStops[i].stopNameRAW.replace(/,.*/g, '');
break;
}
}
let departureLine: string | null = null; let departureLine: string | null = null;
let arrivingLine: string | null = null; let arrivingLine: string | null = null;
for (let i = trainStopIndex; i < followingStops.length; i++) { let prevDepartureLine: string | null = null,
const currentStop = followingStops[i]; nextArrivalLine: string | null = null;
if (currentStop.departureLine == null) continue; for (let i = trainStopIndex; i >= 0; i--) {
const stop = followingStops[i];
if (!/-|_|it|sbl/gi.test(currentStop.departureLine)) { if (/strong|podg\.|pe\./g.test(stop.stopName) && !prevStationName && i <= trainStopIndex - 1)
departureLine = currentStop.departureLine; prevStationName = stop.stopNameRAW.replace(/,.*/g, '');
nextArrivalLine = followingStops[i + 1]?.arrivalLine || null;
break; if (stop.arrivalLine != null && !arrivingLine && !/-|_|it|sbl/gi.test(stop.arrivalLine)) {
arrivingLine = stop.arrivalLine;
prevDepartureLine = followingStops[i - 1]?.departureLine || null;
} }
} }
for (let i = trainStopIndex; i >= 0; i--) { for (let i = trainStopIndex; i < followingStops.length; i++) {
const currentStop = followingStops[i]; const stop = followingStops[i];
if (currentStop.arrivalLine == null) continue; if (/strong|podg\.|pe\./g.test(stop.stopName) && !nextStationName && i > trainStopIndex)
nextStationName = stop.stopNameRAW.replace(/,.*/g, '');
if (!/-|_|it|sbl/gi.test(currentStop.arrivalLine)) { if (stop.departureLine && !departureLine && !/-|_|it|sbl/gi.test(stop.departureLine)) {
arrivingLine = currentStop.arrivalLine; departureLine = stop.departureLine;
prevDepartureLine = followingStops[i - 1]?.departureLine || null; nextArrivalLine = followingStops[i + 1]?.arrivalLine || null;
break;
} }
} }
@@ -177,8 +158,8 @@ export function getCheckpointTrain(
region: train.region, region: train.region,
arrivingLine, arrivingLine: arrivingLine,
departureLine, departureLine: departureLine,
nextArrivalLine, nextArrivalLine,
prevDepartureLine prevDepartureLine
@@ -187,58 +168,33 @@ export function getCheckpointTrain(
export function getScheduledTrains( export function getScheduledTrains(
trainList: Train[], trainList: Train[],
sceneryData: API.ActiveSceneries.Data, stationGeneralInfo: Station['generalInfo'],
stationGeneralInfo: Station['generalInfo'] stationName: string,
region: string
// sceneryData: API.ActiveSceneries.Data,
): ScheduledTrain[] { ): ScheduledTrain[] {
const stationNameLower = sceneryData.stationName.toLocaleLowerCase(); // stationGeneralInfo?.checkpoints.forEach((cp) => (cp.scheduledTrains.length = 0));
stationGeneralInfo?.checkpoints.forEach((cp) => (cp.scheduledTrains.length = 0));
return trainList.reduce((acc: ScheduledTrain[], train) => { return trainList.reduce((acc: ScheduledTrain[], train) => {
if (!train.timetableData) return acc; if (!train.timetableData) return acc;
if (train.region != region) return acc;
const timetable = train.timetableData; const timetable = train.timetableData;
if (!timetable.sceneries.includes(sceneryData.stationHash)) return acc; if (!timetable.sceneryNames.includes(stationName)) return acc;
const stopInfoIndex = timetable.followingStops.findIndex((stop) => { const checkpoints = [stationName];
const stopNameLower = stop.stopNameRAW.toLocaleLowerCase(); if (stationGeneralInfo?.checkpoints) checkpoints.push(...stationGeneralInfo.checkpoints);
return (
stationNameLower == stopNameLower ||
(!/(po\.|podg\.)/.test(stopNameLower) && stopNameLower.includes(stationNameLower)) ||
(!/(po\.|podg\.)/.test(stationNameLower) && stationNameLower.includes(stopNameLower)) ||
(stopNameLower.split(', podg.')[0] !== undefined &&
stationNameLower.startsWith(stopNameLower.split(', podg.')[0]))
);
});
const checkpointScheduledTrains: ScheduledTrain[] = []; const checkpointScheduledTrains: ScheduledTrain[] = [];
for (let i = 0; i < timetable.followingStops.length; i++) {
if (stopInfoIndex != -1) {
checkpointScheduledTrains.push(
getCheckpointTrain(train, stopInfoIndex, sceneryData.stationName)
);
}
stationGeneralInfo?.checkpoints?.forEach((checkpoint) => {
// if (checkpoint.checkpointName.toLocaleLowerCase() == stationNameLower) return;
if ( if (
checkpointScheduledTrains.findIndex( new RegExp(`^(${checkpoints.join('|')})$`, 'i').test(
(cpTrain) => timetable.followingStops[i].stopNameRAW
cpTrain.checkpointName.toLocaleLowerCase() == )
checkpoint.checkpointName.toLocaleLowerCase() ) {
) != -1 checkpointScheduledTrains.push(getCheckpointTrain(train, i, stationName));
) }
return; }
const index = timetable.followingStops.findIndex(
(stop) => stop.stopNameRAW.toLowerCase() == checkpoint.checkpointName.toLowerCase()
);
if (index > -1)
checkpointScheduledTrains.push(getCheckpointTrain(train, index, sceneryData.stationName));
});
acc.push(...checkpointScheduledTrains); acc.push(...checkpointScheduledTrains);
return acc; return acc;
@@ -249,14 +205,12 @@ export function getStationTrains(
trainList: Train[], trainList: Train[],
scheduledTrainList: ScheduledTrain[], scheduledTrainList: ScheduledTrain[],
region: string, region: string,
sceneryData: API.ActiveSceneries.Data stationName: string
): StationTrain[] { ): StationTrain[] {
return trainList return trainList
.filter( .filter(
(train) => (train) =>
train?.region === region && train?.region === region && train.online && train.currentStationName === stationName
train.online &&
train.currentStationName === sceneryData.stationName
) )
.map((train) => ({ .map((train) => ({
driverName: train.driverName, driverName: train.driverName,
+20
View File
@@ -1,10 +1,22 @@
import { Status } from './common'; import { Status } from './common';
export enum APIDataStatus {
OK = 'OK',
WARNING = 'WARNING'
}
export namespace API { export namespace API {
export namespace ActiveData { export namespace ActiveData {
export interface APIStatuses {
stationsAPI: APIDataStatus;
trainsAPI: APIDataStatus;
dispatchersAPI: APIDataStatus;
sceneryRequirementsAPI: APIDataStatus;
}
export interface Response { export interface Response {
activeSceneries?: API.ActiveSceneries.Response; activeSceneries?: API.ActiveSceneries.Response;
trains?: API.ActiveTrains.Response; trains?: API.ActiveTrains.Response;
apiStatuses?: APIStatuses;
} }
} }
export namespace DispatcherHistory { export namespace DispatcherHistory {
@@ -368,3 +380,11 @@ export namespace GithubAPI {
} }
} }
} }
export namespace Websocket {
export interface Payload {
activeSceneries: API.ActiveSceneries.Response;
activeTrains: API.ActiveTrains.Response;
connectedSocketCount: number;
}
}
+1
View File
@@ -1,5 +1,6 @@
export namespace Status { export namespace Status {
export enum ActiveDispatcher { export enum ActiveDispatcher {
FREE = -3,
INVALID = -2, INVALID = -2,
UNKNOWN = -1, UNKNOWN = -1,
NO_LIMIT = 0, NO_LIMIT = 0,
+2 -6
View File
@@ -147,7 +147,7 @@ export default defineComponent({
}, },
onlineSceneryInfo() { onlineSceneryInfo() {
return this.store.onlineSceneryList.find( return this.store.activeSceneryList.find(
(scenery) => (scenery) =>
scenery.name === this.station?.toString().replace(/_/g, ' ') && scenery.name === this.station?.toString().replace(/_/g, ' ') &&
scenery.region == this.store.region.id scenery.region == this.store.region.id
@@ -169,11 +169,7 @@ export default defineComponent({
loadSelectedCheckpoint() { loadSelectedCheckpoint() {
if (!this.stationInfo?.generalInfo?.checkpoints) return; if (!this.stationInfo?.generalInfo?.checkpoints) return;
if (this.stationInfo.generalInfo.checkpoints.length == 0) return; if (this.stationInfo.generalInfo.checkpoints.length == 0) return;
this.selectedCheckpoint = this.stationInfo.generalInfo.checkpoints[0].checkpointName; this.selectedCheckpoint = this.stationInfo.generalInfo.checkpoints[0];
},
selectCheckpoint(cp: { checkpointName: string }) {
this.selectedCheckpoint = cp.checkpointName;
} }
} }
}); });
+212 -92
View File
@@ -42,7 +42,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz"
integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.4.0-0": "@babel/core@^7.11.1":
version "7.20.7" version "7.20.7"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.7.tgz" resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.7.tgz"
integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw== integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw==
@@ -929,11 +929,116 @@
resolved "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz" resolved "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz"
integrity sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw== integrity sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==
"@esbuild/android-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
"@esbuild/android-arm@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
"@esbuild/android-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
"@esbuild/darwin-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
"@esbuild/darwin-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
"@esbuild/freebsd-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
"@esbuild/freebsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
"@esbuild/linux-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
"@esbuild/linux-arm@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
"@esbuild/linux-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
"@esbuild/linux-loong64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
"@esbuild/linux-mips64el@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
"@esbuild/linux-ppc64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
"@esbuild/linux-riscv64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
"@esbuild/linux-s390x@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
"@esbuild/linux-x64@0.18.20": "@esbuild/linux-x64@0.18.20":
version "0.18.20" version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz" resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz"
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
"@esbuild/netbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
"@esbuild/openbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
"@esbuild/sunos-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
"@esbuild/win32-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
"@esbuild/win32-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
"@esbuild/win32-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0" version "4.4.0"
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz"
@@ -1025,7 +1130,7 @@
"@firebase/util" "1.9.3" "@firebase/util" "1.9.3"
tslib "^2.1.0" tslib "^2.1.0"
"@firebase/app-compat@0.2.19", "@firebase/app-compat@0.x": "@firebase/app-compat@0.2.19":
version "0.2.19" version "0.2.19"
resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.19.tgz" resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.19.tgz"
integrity sha512-QkJDqYqjhvs4fTMcRVXQkP9hbo5yfoJXDWkhU4VA5Vzs8Qsp76VPzYbqx5SD5OmBy+bz/Ot1UV8qySPGI4aKuw== integrity sha512-QkJDqYqjhvs4fTMcRVXQkP9hbo5yfoJXDWkhU4VA5Vzs8Qsp76VPzYbqx5SD5OmBy+bz/Ot1UV8qySPGI4aKuw==
@@ -1036,12 +1141,12 @@
"@firebase/util" "1.9.3" "@firebase/util" "1.9.3"
tslib "^2.1.0" tslib "^2.1.0"
"@firebase/app-types@0.9.0", "@firebase/app-types@0.x": "@firebase/app-types@0.9.0":
version "0.9.0" version "0.9.0"
resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz" resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz"
integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==
"@firebase/app@0.9.19", "@firebase/app@0.x": "@firebase/app@0.9.19":
version "0.9.19" version "0.9.19"
resolved "https://registry.npmjs.org/@firebase/app/-/app-0.9.19.tgz" resolved "https://registry.npmjs.org/@firebase/app/-/app-0.9.19.tgz"
integrity sha512-t/SHyZ3xWkR77ZU9VMoobDNFLdDKQ5xqoCAn4o16gTsA1C8sJ6ZOMZ02neMOPxNHuQXVE4tA8ukilnDbnK7uJA== integrity sha512-t/SHyZ3xWkR77ZU9VMoobDNFLdDKQ5xqoCAn4o16gTsA1C8sJ6ZOMZ02neMOPxNHuQXVE4tA8ukilnDbnK7uJA==
@@ -1326,7 +1431,7 @@
node-fetch "2.6.7" node-fetch "2.6.7"
tslib "^2.1.0" tslib "^2.1.0"
"@firebase/util@1.9.3", "@firebase/util@1.x": "@firebase/util@1.9.3":
version "1.9.3" version "1.9.3"
resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz" resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz"
integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA== integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==
@@ -1431,7 +1536,7 @@
"@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/trace-mapping" "^0.3.9"
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14": "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
version "1.4.14" version "1.4.14"
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
@@ -1457,7 +1562,7 @@
"@nodelib/fs.stat" "2.0.5" "@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9" run-parallel "^1.1.9"
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5" version "2.0.5"
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@@ -1577,6 +1682,11 @@
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"
@@ -1597,26 +1707,16 @@
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz"
integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==
"@types/node@*": "@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
version "18.11.18" version "18.11.18"
resolved "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz" resolved "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz"
integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
"@types/node@^20.6.2", "@types/node@>= 14": "@types/node@^20.6.2":
version "20.6.2" version "20.6.2"
resolved "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz" resolved "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz"
integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw== integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
"@types/node@>=12.12.47":
version "18.11.18"
resolved "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz"
integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
"@types/node@>=13.7.0":
version "18.11.18"
resolved "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz"
integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
"@types/resolve@1.17.1": "@types/resolve@1.17.1":
version "1.17.1" version "1.17.1"
resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz" resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz"
@@ -1651,7 +1751,7 @@
semver "^7.5.4" semver "^7.5.4"
ts-api-utils "^1.0.1" ts-api-utils "^1.0.1"
"@typescript-eslint/parser@^6.0.0 || ^6.0.0-alpha", "@typescript-eslint/parser@^6.7.0": "@typescript-eslint/parser@^6.7.0":
version "6.9.1" version "6.9.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz"
integrity sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg== integrity sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==
@@ -1741,14 +1841,14 @@
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz" resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz"
integrity sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw== integrity sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==
"@volar/language-core@~1.10.0", "@volar/language-core@1.10.1": "@volar/language-core@1.10.1", "@volar/language-core@~1.10.0":
version "1.10.1" version "1.10.1"
resolved "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz" resolved "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz"
integrity sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA== integrity sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==
dependencies: dependencies:
"@volar/source-map" "1.10.1" "@volar/source-map" "1.10.1"
"@volar/source-map@~1.10.0", "@volar/source-map@1.10.1": "@volar/source-map@1.10.1", "@volar/source-map@~1.10.0":
version "1.10.1" version "1.10.1"
resolved "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz" resolved "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz"
integrity sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA== integrity sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==
@@ -1772,7 +1872,7 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
source-map-js "^1.0.2" source-map-js "^1.0.2"
"@vue/compiler-dom@^3.3.0", "@vue/compiler-dom@3.3.4": "@vue/compiler-dom@3.3.4", "@vue/compiler-dom@^3.3.0":
version "3.3.4" version "3.3.4"
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz" resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz"
integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w== integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==
@@ -1851,7 +1951,7 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
magic-string "^0.30.0" magic-string "^0.30.0"
"@vue/reactivity@^3.3.0", "@vue/reactivity@3.3.4": "@vue/reactivity@3.3.4", "@vue/reactivity@^3.3.0":
version "3.3.4" version "3.3.4"
resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz" resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz"
integrity sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ== integrity sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==
@@ -1883,7 +1983,7 @@
"@vue/compiler-ssr" "3.3.4" "@vue/compiler-ssr" "3.3.4"
"@vue/shared" "3.3.4" "@vue/shared" "3.3.4"
"@vue/shared@^3.3.0", "@vue/shared@3.3.4": "@vue/shared@3.3.4", "@vue/shared@^3.3.0":
version "3.3.4" version "3.3.4"
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz" resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz"
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ== integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
@@ -1906,7 +2006,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.10.0, acorn@^8.5.0, acorn@^8.9.0: acorn@^8.10.0, acorn@^8.5.0, acorn@^8.9.0:
version "8.10.0" version "8.10.0"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz"
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
@@ -1921,7 +2021,7 @@ ajv@^6.12.4:
json-schema-traverse "^0.4.1" json-schema-traverse "^0.4.1"
uri-js "^4.2.2" uri-js "^4.2.2"
ajv@^8.6.0, ajv@>=8: ajv@^8.6.0:
version "8.11.2" version "8.11.2"
resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz" resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz"
integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==
@@ -2084,7 +2184,7 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
browserslist@^4.21.3, browserslist@^4.21.4, "browserslist@>= 4.21.0": browserslist@^4.21.3, browserslist@^4.21.4:
version "4.21.4" version "4.21.4"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz"
integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
@@ -2151,15 +2251,7 @@ chalk@^2.4.2:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
supports-color "^5.3.0" supports-color "^5.3.0"
chalk@^4.0.0: chalk@^4.0.0, chalk@^4.0.2:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -2210,16 +2302,16 @@ color-convert@^2.0.1:
dependencies: dependencies:
color-name "~1.1.4" color-name "~1.1.4"
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-name@1.1.3: color-name@1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.9.0: color-string@^1.9.0:
version "1.9.1" version "1.9.1"
resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz"
@@ -2314,7 +2406,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.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
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==
@@ -2449,6 +2541,22 @@ 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.3"
resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz"
integrity sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==
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"
@@ -2545,7 +2653,7 @@ eslint-plugin-prettier@^5.0.0:
prettier-linter-helpers "^1.0.0" prettier-linter-helpers "^1.0.0"
synckit "^0.8.5" synckit "^0.8.5"
eslint-plugin-vue@^9.0.0, eslint-plugin-vue@^9.17.0: eslint-plugin-vue@^9.17.0:
version "9.18.1" version "9.18.1"
resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz" resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz"
integrity sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg== integrity sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==
@@ -2571,7 +2679,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0", "eslint@^7.0.0 || ^8.0.0", eslint@^8.49.0, "eslint@>= 8.0.0", eslint@>=6.0.0, eslint@>=7.0.0, eslint@>=8.0.0: eslint@^8.49.0:
version "8.52.0" version "8.52.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz" resolved "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz"
integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==
@@ -2819,9 +2927,9 @@ flatted@^3.2.9:
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
follow-redirects@^1.15.0: follow-redirects@^1.15.0:
version "1.15.2" version "1.15.5"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
form-data@^4.0.0: form-data@^4.0.0:
version "4.0.0" version "4.0.0"
@@ -2852,6 +2960,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.1: function-bind@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
@@ -3052,7 +3165,7 @@ ico-endec@*:
resolved "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz" resolved "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz"
integrity sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ== integrity sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==
idb@^7.0.1, idb@7.0.1: idb@7.0.1, idb@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz" resolved "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz"
integrity sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg== integrity sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==
@@ -3098,7 +3211,7 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@^2.0.3, inherits@^2.0.4, inherits@2: inherits@2, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -3826,7 +3939,7 @@ prettier-linter-helpers@^1.0.0:
dependencies: dependencies:
fast-diff "^1.1.2" fast-diff "^1.1.2"
prettier@^3.0.3, "prettier@>= 3.0.0", prettier@>=3.0.0: prettier@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz" resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz"
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
@@ -4023,7 +4136,7 @@ rollup-plugin-terser@^7.0.0:
serialize-javascript "^4.0.0" serialize-javascript "^4.0.0"
terser "^5.0.0" terser "^5.0.0"
"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.43.1: rollup@^2.43.1:
version "2.79.1" version "2.79.1"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz" resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz"
integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
@@ -4051,7 +4164,7 @@ run-parallel@^1.1.9:
dependencies: dependencies:
queue-microtask "^1.2.2" queue-microtask "^1.2.2"
safe-buffer@^5.0.1, safe-buffer@>=5.1.0, safe-buffer@~5.2.0: safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
version "5.2.1" version "5.2.1"
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -4070,7 +4183,7 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3" get-intrinsic "^1.1.3"
is-regex "^1.1.4" is-regex "^1.1.4"
sass@*, sass@^1.67.0: sass@^1.67.0:
version "1.67.0" version "1.67.0"
resolved "https://registry.npmjs.org/sass/-/sass-1.67.0.tgz" resolved "https://registry.npmjs.org/sass/-/sass-1.67.0.tgz"
integrity sha512-SVrO9ZeX/QQyEGtuZYCVxoeAL5vGlYjJ9p4i4HFuekWl8y/LtJ7tJc10Z+ck1c8xOuoBm2MYzcLfTAffD0pl/A== integrity sha512-SVrO9ZeX/QQyEGtuZYCVxoeAL5vGlYjJ9p4i4HFuekWl8y/LtJ7tJc10Z+ck1c8xOuoBm2MYzcLfTAffD0pl/A==
@@ -4084,28 +4197,7 @@ semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.3.5: semver@^7.3.5, semver@^7.3.6, semver@^7.3.8, semver@^7.5.4:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@^7.3.6:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@^7.3.8:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@^7.5.4:
version "7.5.4" version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
@@ -4194,7 +4286,25 @@ 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==
source-map-js@^1.0.2, "source-map-js@>=0.6.2 <2.0.0": socket.io-client@^4.7.4:
version "4.7.4"
resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz"
integrity sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==
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@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
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"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
@@ -4232,13 +4342,6 @@ streamx@^2.15.0:
fast-fifo "^1.1.0" fast-fifo "^1.1.0"
queue-tick "^1.0.1" queue-tick "^1.0.1"
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
@@ -4280,6 +4383,13 @@ string.prototype.trimstart@^1.0.6:
define-properties "^1.1.4" define-properties "^1.1.4"
es-abstract "^1.20.4" es-abstract "^1.20.4"
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
stringify-object@^3.3.0: stringify-object@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz"
@@ -4402,7 +4512,7 @@ tempy@^0.6.0:
type-fest "^0.16.0" type-fest "^0.16.0"
unique-string "^2.0.0" unique-string "^2.0.0"
terser@^5.0.0, terser@^5.4.0: terser@^5.0.0:
version "5.16.1" version "5.16.1"
resolved "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz" resolved "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz"
integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw== integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==
@@ -4485,7 +4595,7 @@ type-fest@^0.20.2:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
typescript@*, typescript@^5.2.2, typescript@>=4.2.0, typescript@>=4.4.4: typescript@^5.2.2:
version "5.2.2" version "5.2.2"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
@@ -4591,10 +4701,10 @@ vite-plugin-pwa@^0.16.5:
workbox-build "^7.0.0" workbox-build "^7.0.0"
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@^4.4.9:
version "4.5.1" version "4.5.2"
resolved "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz" resolved "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz"
integrity sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA== integrity sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==
dependencies: dependencies:
esbuild "^0.18.10" esbuild "^0.18.10"
postcss "^8.4.27" postcss "^8.4.27"
@@ -4653,7 +4763,7 @@ vue-tsc@^1.8.11:
"@vue/typescript" "1.8.11" "@vue/typescript" "1.8.11"
semver "^7.3.8" semver "^7.3.8"
"vue@^2.6.14 || ^3.3.0", vue@^3.0.0, "vue@^3.0.0-0 || ^2.6.0", vue@^3.2.0, vue@^3.2.25, vue@^3.3.4, vue@3.3.4: vue@^3.3.4:
version "3.3.4" version "3.3.4"
resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz" resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw== integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
@@ -4873,7 +4983,7 @@ workbox-sw@7.0.0:
resolved "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz" resolved "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz"
integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA== integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==
workbox-window@^7.0.0, workbox-window@7.0.0: workbox-window@7.0.0, workbox-window@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz" resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz"
integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA== integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==
@@ -4895,11 +5005,21 @@ 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"