Dokończony widok pociągów, zmiany w wyglądzie

This commit is contained in:
2020-08-08 23:16:53 +02:00
parent e22115844a
commit 1a9e23f5c9
12 changed files with 363 additions and 206 deletions
+35
View File
@@ -2466,6 +2466,41 @@
"integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==",
"dev": true "dev": true
}, },
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"dev": true,
"requires": {
"follow-redirects": "1.5.10"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"dev": true,
"requires": {
"debug": "=3.1.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}
}
},
"babel-code-frame": { "babel-code-frame": {
"version": "6.26.0", "version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+1
View File
@@ -22,6 +22,7 @@
"@vue/cli-plugin-typescript": "~4.4.0", "@vue/cli-plugin-typescript": "~4.4.0",
"@vue/cli-plugin-vuex": "~4.4.0", "@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0", "@vue/cli-service": "~4.4.0",
"axios": "^0.19.2",
"sass": "^1.26.5", "sass": "^1.26.5",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"typescript": "~3.9.3", "typescript": "~3.9.3",
+17 -14
View File
@@ -1,23 +1,26 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head> <meta charset="utf-8" />
<meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0" />
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap"
<link href="https://fonts.googleapis.com/css2?family=Muli:wght@400;500;700&display=swap" rel="stylesheet"> rel="stylesheet"
/>
<title>Stacjownik</title> <title>Stacjownik</title>
</head> </head>
<body> <body>
<noscript> <noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. <strong
Please enable it to continue.</strong> >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
</body> </body>
</html> </html>
+42 -4
View File
@@ -21,7 +21,7 @@
</span> </span>
<span class="header-links"> <span class="header-links">
<router-link class="route" active-class="route-active" to="/" exact>SCENERIE</router-link>* <router-link class="route" active-class="route-active" to="/" exact>SCENERIE</router-link>/
<router-link class="route" active-class="route-active" to="/trains">POCIĄGI</router-link> <router-link class="route" active-class="route-active" to="/trains">POCIĄGI</router-link>
</span> </span>
</div> </div>
@@ -30,12 +30,17 @@
<main class="app-main"> <main class="app-main">
<Loading v-if="connectionState == 0" /> <Loading v-if="connectionState == 0" />
<Error v-else-if="connectionState == 1" :error="errorMessage" /> <Error v-else-if="connectionState == 1" :error="errorMessage" />
<keep-alive v-else> <transition name="view-anim" mode="out-in" v-else>
<keep-alive>
<router-view /> <router-view />
</keep-alive> </keep-alive>
</transition>
</main> </main>
<footer class="app-footer flex">&copy; Spythere 2020</footer> <footer class="app-footer flex">
<span>&copy; Spythere 2020</span>
<span>Sprawdź, co nowego w Stacjowniku!</span>
</footer>
</div> </div>
</div> </div>
</template> </template>
@@ -86,6 +91,23 @@ export default class App extends Vue {
@import "./styles/variables.scss"; @import "./styles/variables.scss";
@import "./styles/global.scss"; @import "./styles/global.scss";
.view-anim {
&-enter {
transform: translateX(-10%);
opacity: 0;
}
&-leave-to {
transform: translateX(10%);
opacity: 0;
}
&-enter-active,
&-leave-active {
transition: all $animDuration $animType;
}
}
.route { .route {
margin: 0 0.2em; margin: 0 0.2em;
@@ -100,6 +122,10 @@ export default class App extends Vue {
color: white; color: white;
font-size: calc(1rem + 2.1vw); font-size: calc(1rem + 2.1vw);
@include smallScreen() {
font-size: 2rem;
}
} }
.container { .container {
@@ -115,6 +141,8 @@ export default class App extends Vue {
background: #333; background: #333;
padding: 0.15em; padding: 0.15em;
border-radius: 0 0 0.7em 0.7em;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -142,7 +170,6 @@ export default class App extends Vue {
display: flex; display: flex;
justify-content: center; justify-content: center;
background-color: #222;
border-radius: 0.7em; border-radius: 0.7em;
padding: 0.2em; padding: 0.2em;
@@ -172,5 +199,16 @@ footer {
color: white; color: white;
max-width: 100%; max-width: 100%;
font-size: calc(0.5rem + 0.5vw); font-size: calc(0.5rem + 0.5vw);
flex-direction: column;
span {
margin: 0.2rem;
&:nth-child(2) {
color: #888;
font-size: 0.95em;
}
}
} }
</style> </style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+1 -1
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="loading">Pobieranie danych o sceneriach...</div> <div class="loading">Stój, pobieranie danych...</div>
</template> </template>
<script lang="ts"> <script lang="ts">
-1
View File
@@ -297,7 +297,6 @@ export default class List extends styleMixin {
} }
.list-body { .list-body {
max-height: calc(100vh - 4.5em);
overflow: auto; overflow: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
+11 -6
View File
@@ -46,8 +46,9 @@
</div> </div>
</div> </div>
<div class="card-reset flex"> <div class="card-actions flex">
<button class="button" @click="reset">RESET FILTRÓW</button> <button class="button" @click="reset">RESET FILTRÓW</button>
<button class="button" @click="exit">ZAMKNIJ FILTRY</button>
</div> </div>
</section> </section>
</template> </template>
@@ -74,7 +75,7 @@ export default class OptionCard extends Vue {
this.setFilter({ this.setFilter({
filterName: target.name, filterName: target.name,
value: !target.checked value: !target.checked,
}); });
} }
@@ -83,16 +84,16 @@ export default class OptionCard extends Vue {
this.setFilter({ this.setFilter({
filterName: target.name, filterName: target.name,
value: parseInt(target.value) value: parseInt(target.value),
}); });
} }
reset(): void { reset(): void {
this.inputs.options.forEach(option => { this.inputs.options.forEach((option) => {
option.value = option.defaultValue; option.value = option.defaultValue;
}); });
this.inputs.sliders.forEach(slider => { this.inputs.sliders.forEach((slider) => {
slider.value = slider.defaultValue; slider.value = slider.defaultValue;
}); });
@@ -168,8 +169,12 @@ export default class OptionCard extends Vue {
margin-top: 1em; margin-top: 1em;
} }
&-reset { &-actions {
margin-top: 0.7em; margin-top: 0.7em;
button {
margin: 0 0.3em;
}
} }
} }
+5 -3
View File
@@ -23,12 +23,14 @@ html {
body { body {
width: 100%; width: 100%;
margin: 0; margin: 0;
font-family: "Muli", sans-serif; font-family: "Lato", sans-serif;
overflow-x: hidden;
} }
button, button,
input { input {
font-family: "Muli", sans-serif; font-family: "Lato", sans-serif;
} }
input { input {
@@ -185,7 +187,7 @@ a {
} }
&:focus { &:focus {
text-decoration: underline; // text-decoration: underline;
} }
} }
+3
View File
@@ -8,3 +8,6 @@ $warningCol: #ff975b;
$accentCol: #ffc014; $accentCol: #ffc014;
$accent2Col: #ff3d5d; $accent2Col: #ff3d5d;
$animDuration: 200ms;
$animType: ease-out;
+91 -20
View File
@@ -2,10 +2,14 @@
<section class="trains-view"> <section class="trains-view">
<ul class="list" v-if="listLoaded"> <ul class="list" v-if="listLoaded">
<li class="item" v-for="train in computedTrains" :key="train.timetableId"> <li class="item" v-for="train in computedTrains" :key="train.timetableId">
<a :href="'https://rj.td2.info.pl/train#' + train.trainNo + ';eu'" target="_blank">
<span class="info"> <span class="info">
<div class="info-category"> <div class="info-category">
<span>
<strong>{{train.category}}</strong> <strong>{{train.category}}</strong>
{{train.trainNo}} {{train.trainNo}} |
</span>
<span style=" color: gold;">{{train.routeDistance}} km</span>
</div> </div>
<div class="info-warnings"> <div class="info-warnings">
@@ -14,20 +18,25 @@
</div> </div>
<div class="info-route"> <div class="info-route">
<strong>{{train.route && train.route.replace("|", " -> ")}}</strong> <strong>{{train.route && train.route.replace("|", " - ")}}</strong>
</div> </div>
<div class="info-stations"> <div class="info-stations">
<i v-if="train.sceneries.length > 0">Przez: {{train.sceneries}}</i> <i v-if="train.sceneries.length > 0">Przez: {{train.sceneries}}</i>
</div> </div>
</span> </span>
</a>
<span class="driver"> <span class="driver">
<span class="driver-name">{{train.driverName}}</span> <span class="driver-name">
{{train.driverName}}
<span style="color: #bbb; margin-left: 1em;">{{train.locoType}}</span>
</span>
<span class="driver-loco"> <span class="driver-loco">
<img src="https://rj.td2.info.pl/dist/img/thumbnails/ET41-144.png" alt="icon-train" /> <img :src="train.locoURL" @error="onImageError" />
</span> </span>
</span> </span>
<span class="stats"> <span class="stats">
<div class="stats-general"> <div class="stats-general">
<span class="mass"> <span class="mass">
@@ -81,6 +90,8 @@ import Station from "@/scripts/interfaces/Station";
import axios from "axios"; import axios from "axios";
const unknownTrainImage = require("@/assets/unknown.png");
@Component @Component
export default class TrainsView extends Vue { export default class TrainsView extends Vue {
speedIcon: string = require("@/assets/icon-speed.svg"); speedIcon: string = require("@/assets/icon-speed.svg");
@@ -95,7 +106,6 @@ export default class TrainsView extends Vue {
speed: number; speed: number;
signal: string; signal: string;
distance: number; distance: number;
imageURL: string;
connectedTrack: string; connectedTrack: string;
driverId: number; driverId: number;
trainNo: number; trainNo: number;
@@ -108,6 +118,9 @@ export default class TrainsView extends Vue {
TWR: boolean | null; TWR: boolean | null;
SKR: boolean | null; SKR: boolean | null;
noTimetable: boolean; noTimetable: boolean;
locoURL: string;
locoType: string;
routeDistance: number;
}[] = []; }[] = [];
listLoaded: boolean = false; listLoaded: boolean = false;
@@ -138,6 +151,14 @@ export default class TrainsView extends Vue {
.map(async (train) => { .map(async (train) => {
const timetableData = await this.getTimetableData(train.trainNo); const timetableData = await this.getTimetableData(train.trainNo);
let locoType = train.dataCon.split(";")
? train.dataCon.split(";")[0]
: train.dataCon;
const locoURL = `https://rj.td2.info.pl/dist/img/thumbnails/${
locoType.includes("EN") ? locoType + "rb" : locoType
}.png`;
return { return {
driverId: train.driverId, driverId: train.driverId,
driverName: train.driverName, driverName: train.driverName,
@@ -148,12 +169,14 @@ export default class TrainsView extends Vue {
speed: train.dataSpeed, speed: train.dataSpeed,
distance: train.dataDistance, distance: train.dataDistance,
signal: train.dataSignal, signal: train.dataSignal,
imageURL: train.dataCon,
connectedTrack: train.dataSceneryConnection, connectedTrack: train.dataSceneryConnection,
locoURL,
locoType,
noTimetable: timetableData == null, noTimetable: timetableData == null,
route: timetableData && timetableData.route, route: timetableData && timetableData.route,
timetableId: timetableData && timetableData.timetableId, timetableId: timetableData && timetableData.timetableId,
category: timetableData && timetableData.trainCategoryCode, category: timetableData && timetableData.trainCategoryCode,
routeDistance: (timetableData && timetableData.routeDistance) || 0,
sceneries: sceneries:
timetableData && timetableData &&
(await this.mapSceneries(timetableData.sceneries)), (await this.mapSceneries(timetableData.sceneries)),
@@ -167,20 +190,45 @@ export default class TrainsView extends Vue {
} }
async getTimetableData(trainNo: number) { async getTimetableData(trainNo: number) {
const response = await axios.get( const responseDataMessage: {
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu` stopPoints: { pointDistance: number }[] | [];
); trainInfo: {
const timetableData: {
timetableId: number; timetableId: number;
trainCategoryCode: string; trainCategoryCode: string;
route: string; route: string;
twr: boolean; twr: boolean;
skr: boolean; skr: boolean;
sceneries: string[]; sceneries: string[];
} | null = response.data.message.trainInfo; } | null;
} = (
await axios.get(
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`
)
).data.message;
return timetableData; let result: {
timetableId: number;
trainCategoryCode: string;
route: string;
twr: boolean;
skr: boolean;
sceneries: string[];
routeDistance: number;
} | null = null;
if (responseDataMessage.trainInfo) {
const routeDistance: number =
responseDataMessage.stopPoints[
responseDataMessage.stopPoints.length - 1
].pointDistance;
result = {
...responseDataMessage.trainInfo,
routeDistance,
};
}
return result;
} }
mapSceneries(sceneries: string[]): string { mapSceneries(sceneries: string[]): string {
@@ -200,17 +248,25 @@ export default class TrainsView extends Vue {
return text; return text;
} }
onImageError(e: Event) {
(e.target as HTMLImageElement).src = unknownTrainImage;
}
get computedTrains() { get computedTrains() {
return this.onlineTrainsList.filter((train) => !train.noTimetable); return this.onlineTrainsList.filter((train) => !train.noTimetable);
} }
mounted() { mounted() {
this.getTrainData(); this.getTrainData();
setInterval(this.getTrainData, 5000);
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../styles/responsive.scss";
.trains-view { .trains-view {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -218,25 +274,35 @@ export default class TrainsView extends Vue {
} }
.list { .list {
font-size: calc(0.5rem + 0.5vw); margin: 2rem 0;
margin-top: 2rem;
max-height: calc(100vh - 14em);
overflow: auto; overflow: auto;
max-width: 1300px; max-width: 2000px;
} }
.item { .item {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
font-size: calc(0.5rem + 0.5vw);
background-color: #444; background-color: #444;
padding: 1rem; padding: 1rem;
margin: 1rem 0;
&:nth-child(even) { &:nth-child(even) {
background-color: #666; background-color: #666;
} }
@include smallScreen() {
grid-template-columns: 1fr;
grid-template-rows: repeat(3, 1fr);
font-size: 0.9rem;
gap: 0.2em 0;
// grid-template-columns: repeat(3, 1fr);
}
} }
.info { .info {
@@ -284,16 +350,19 @@ export default class TrainsView extends Vue {
} }
&-loco img { &-loco img {
max-width: 15em; max-width: 12em;
} }
} }
.stats { .stats {
width: 100%;
&-general { &-general {
display: flex; display: flex;
span { span {
display: flex; display: flex;
justify-content: center;
width: 100%; width: 100%;
align-items: center; align-items: center;
@@ -306,7 +375,9 @@ export default class TrainsView extends Vue {
&-position { &-position {
display: flex; display: flex;
margin-top: 1em; margin-top: 1em;
text-align: center;
span { span {
width: 100%; width: 100%;