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
+44 -6
View File
@@ -21,7 +21,7 @@
</span>
<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>
</span>
</div>
@@ -30,12 +30,17 @@
<main class="app-main">
<Loading v-if="connectionState == 0" />
<Error v-else-if="connectionState == 1" :error="errorMessage" />
<keep-alive v-else>
<router-view />
</keep-alive>
<transition name="view-anim" mode="out-in" v-else>
<keep-alive>
<router-view />
</keep-alive>
</transition>
</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>
</template>
@@ -86,6 +91,23 @@ export default class App extends Vue {
@import "./styles/variables.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 {
margin: 0 0.2em;
@@ -100,6 +122,10 @@ export default class App extends Vue {
color: white;
font-size: calc(1rem + 2.1vw);
@include smallScreen() {
font-size: 2rem;
}
}
.container {
@@ -115,6 +141,8 @@ export default class App extends Vue {
background: #333;
padding: 0.15em;
border-radius: 0 0 0.7em 0.7em;
display: flex;
justify-content: center;
@@ -142,7 +170,6 @@ export default class App extends Vue {
display: flex;
justify-content: center;
background-color: #222;
border-radius: 0.7em;
padding: 0.2em;
@@ -172,5 +199,16 @@ footer {
color: white;
max-width: 100%;
font-size: calc(0.5rem + 0.5vw);
flex-direction: column;
span {
margin: 0.2rem;
&:nth-child(2) {
color: #888;
font-size: 0.95em;
}
}
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="loading">Pobieranie danych o sceneriach...</div>
<div class="loading">Stój, pobieranie danych...</div>
</template>
<script lang="ts">
-1
View File
@@ -297,7 +297,6 @@ export default class List extends styleMixin {
}
.list-body {
max-height: calc(100vh - 4.5em);
overflow: auto;
display: flex;
flex-direction: column;
+11 -6
View File
@@ -46,8 +46,9 @@
</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="exit">ZAMKNIJ FILTRY</button>
</div>
</section>
</template>
@@ -74,7 +75,7 @@ export default class OptionCard extends Vue {
this.setFilter({
filterName: target.name,
value: !target.checked
value: !target.checked,
});
}
@@ -83,16 +84,16 @@ export default class OptionCard extends Vue {
this.setFilter({
filterName: target.name,
value: parseInt(target.value)
value: parseInt(target.value),
});
}
reset(): void {
this.inputs.options.forEach(option => {
this.inputs.options.forEach((option) => {
option.value = option.defaultValue;
});
this.inputs.sliders.forEach(slider => {
this.inputs.sliders.forEach((slider) => {
slider.value = slider.defaultValue;
});
@@ -168,8 +169,12 @@ export default class OptionCard extends Vue {
margin-top: 1em;
}
&-reset {
&-actions {
margin-top: 0.7em;
button {
margin: 0 0.3em;
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ const routes: Array<RouteConfig> = [
},
{
path: "/trains",
name: "TrainsView",
name: "TrainsView",
component: TrainsView
}
]
+140 -138
View File
@@ -1,211 +1,213 @@
:root {
font-size: 16px;
font-size: 16px;
}
::-webkit-scrollbar {
width: 0.5rem;
height: 0.5rem;
width: 0.5rem;
height: 0.5rem;
&-track {
background: #222;
}
&-track {
background: #222;
}
&-thumb {
border-radius: 1rem;
background: #777;
}
&-thumb {
border-radius: 1rem;
background: #777;
}
}
html {
scroll-behavior: smooth;
scroll-behavior: smooth;
}
body {
width: 100%;
margin: 0;
font-family: "Muli", sans-serif;
width: 100%;
margin: 0;
font-family: "Lato", sans-serif;
overflow-x: hidden;
}
button,
input {
font-family: "Muli", sans-serif;
font-family: "Lato", sans-serif;
}
input {
border: 1px solid white;
background: none;
color: white;
font-size: 1em;
border: 1px solid white;
background: none;
color: white;
font-size: 1em;
padding: 0.15em;
margin: 0.2em;
padding: 0.15em;
margin: 0.2em;
max-width: 55px;
max-width: 55px;
&::placeholder {
color: #bebebe;
}
&::placeholder {
color: #bebebe;
}
}
*,
*::before,
*::after {
box-sizing: border-box;
padding: 0;
margin: 0;
box-sizing: border-box;
padding: 0;
margin: 0;
}
.status {
border-radius: 1.3rem;
font-weight: 500;
border-radius: 1.3rem;
font-weight: 500;
font-size: 0.95em;
padding: 0.25em 0.4em;
background-color: #00be19;
&.free {
background-color: #8a8a8a;
font-size: 0.95em;
padding: 0.25em 0.4em;
}
background-color: #00be19;
&.ending {
background-color: $accentCol;
color: black;
font-size: 0.9em;
}
&.free {
background-color: #8a8a8a;
font-size: 0.95em;
}
&.no-limit {
background-color: #0077ae;
font-size: 0.85em;
}
&.ending {
background-color: $accentCol;
color: black;
font-size: 0.9em;
}
&.not-signed,
&.unavailable {
background-color: $accent2Col;
font-size: 0.8em;
}
&.no-limit {
background-color: #0077ae;
font-size: 0.85em;
}
&.brb {
background-color: $accentCol;
color: black;
font-size: 0.95em;
}
&.not-signed,
&.unavailable {
background-color: $accent2Col;
font-size: 0.8em;
}
&.brb {
background-color: $accentCol;
color: black;
font-size: 0.95em;
}
&.no-space {
background-color: #222;
color: white;
font-size: 0.85em;
}
&.no-space {
background-color: #222;
color: white;
font-size: 0.85em;
}
}
.default-station {
font-weight: bold;
color: $accentCol;
font-weight: bold;
color: $accentCol;
}
.card {
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 4;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 4;
overflow: auto;
// background: #474747;
background: #262a2e;
overflow: auto;
// background: #474747;
background: #262a2e;
box-shadow: 0 0 15px 5px #474747;
box-shadow: 0 0 15px 5px #474747;
width: 75%;
max-width: 750px;
max-height: 95%;
width: 75%;
max-width: 750px;
max-height: 95%;
// font-size: calc(0.6rem + 0.5vw);
font-size: calc(0.45rem + 0.35vw);
// font-size: calc(0.6rem + 0.5vw);
font-size: calc(0.45rem + 0.35vw);
@include smallScreen {
width: 95%;
@include smallScreen {
width: 95%;
}
&-exit {
position: absolute;
top: 0;
right: 0;
margin: 0.8em;
img {
width: 1.5em;
}
&-exit {
position: absolute;
top: 0;
right: 0;
margin: 0.8em;
img {
width: 1.5em;
}
cursor: pointer;
}
cursor: pointer;
}
}
.button {
display: flex;
align-items: center;
display: flex;
align-items: center;
background: #333;
background: #333;
border: none;
color: #e0e0e0;
font-size: 0.9em;
outline: none;
padding: 0.35em;
cursor: pointer;
transition: all 0.3s;
&.open {
color: $accentCol;
border: none;
}
color: #e0e0e0;
font-size: 0.9em;
outline: none;
padding: 0.35em;
cursor: pointer;
transition: all 0.3s;
&.open {
color: $accentCol;
border: none;
}
&:hover {
background: rgba(#e0e0e0, 0.4);
}
&:hover {
background: rgba(#e0e0e0, 0.4);
}
}
a {
color: white;
text-decoration: none;
color: white;
text-decoration: none;
transition: color 0.3s;
transition: color 0.3s;
&:hover,
&:focus {
color: $accentCol;
border: none;
outline: none;
}
&:hover,
&:focus {
color: $accentCol;
border: none;
outline: none;
}
&:focus {
text-decoration: underline;
}
&:focus {
// text-decoration: underline;
}
}
ul {
padding: 0;
list-style: none;
padding: 0;
list-style: none;
}
.flex {
display: flex;
align-items: center;
justify-content: center;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
width: 100%;
&-spaced {
justify-content: space-between;
}
&-spaced {
justify-content: space-between;
}
&-column {
flex-direction: column;
}
&-column {
flex-direction: column;
}
}
+3
View File
@@ -8,3 +8,6 @@ $warningCol: #ff975b;
$accentCol: #ffc014;
$accent2Col: #ff3d5d;
$animDuration: 200ms;
$animType: ease-out;
+104 -33
View File
@@ -2,32 +2,41 @@
<section class="trains-view">
<ul class="list" v-if="listLoaded">
<li class="item" v-for="train in computedTrains" :key="train.timetableId">
<span class="info">
<div class="info-category">
<strong>{{train.category}}</strong>
{{train.trainNo}}
</div>
<a :href="'https://rj.td2.info.pl/train#' + train.trainNo + ';eu'" target="_blank">
<span class="info">
<div class="info-category">
<span>
<strong>{{train.category}}</strong>
{{train.trainNo}} |
</span>
<span style=" color: gold;">{{train.routeDistance}} km</span>
</div>
<div class="info-warnings">
<span class="warning twr" v-if="train.TWR">TWR</span>
<span class="warning skr" v-if="train.SKR">SKR</span>
</div>
<div class="info-warnings">
<span class="warning twr" v-if="train.TWR">TWR</span>
<span class="warning skr" v-if="train.SKR">SKR</span>
</div>
<div class="info-route">
<strong>{{train.route && train.route.replace("|", " -> ")}}</strong>
</div>
<div class="info-route">
<strong>{{train.route && train.route.replace("|", " - ")}}</strong>
</div>
<div class="info-stations">
<i v-if="train.sceneries.length > 0">Przez: {{train.sceneries}}</i>
</div>
</span>
<div class="info-stations">
<i v-if="train.sceneries.length > 0">Przez: {{train.sceneries}}</i>
</div>
</span>
</a>
<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">
<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 class="stats">
<div class="stats-general">
<span class="mass">
@@ -81,6 +90,8 @@ import Station from "@/scripts/interfaces/Station";
import axios from "axios";
const unknownTrainImage = require("@/assets/unknown.png");
@Component
export default class TrainsView extends Vue {
speedIcon: string = require("@/assets/icon-speed.svg");
@@ -95,7 +106,6 @@ export default class TrainsView extends Vue {
speed: number;
signal: string;
distance: number;
imageURL: string;
connectedTrack: string;
driverId: number;
trainNo: number;
@@ -108,6 +118,9 @@ export default class TrainsView extends Vue {
TWR: boolean | null;
SKR: boolean | null;
noTimetable: boolean;
locoURL: string;
locoType: string;
routeDistance: number;
}[] = [];
listLoaded: boolean = false;
@@ -138,6 +151,14 @@ export default class TrainsView extends Vue {
.map(async (train) => {
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 {
driverId: train.driverId,
driverName: train.driverName,
@@ -148,12 +169,14 @@ export default class TrainsView extends Vue {
speed: train.dataSpeed,
distance: train.dataDistance,
signal: train.dataSignal,
imageURL: train.dataCon,
connectedTrack: train.dataSceneryConnection,
locoURL,
locoType,
noTimetable: timetableData == null,
route: timetableData && timetableData.route,
timetableId: timetableData && timetableData.timetableId,
category: timetableData && timetableData.trainCategoryCode,
routeDistance: (timetableData && timetableData.routeDistance) || 0,
sceneries:
timetableData &&
(await this.mapSceneries(timetableData.sceneries)),
@@ -167,20 +190,45 @@ export default class TrainsView extends Vue {
}
async getTimetableData(trainNo: number) {
const response = await axios.get(
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`
);
const responseDataMessage: {
stopPoints: { pointDistance: number }[] | [];
trainInfo: {
timetableId: number;
trainCategoryCode: string;
route: string;
twr: boolean;
skr: boolean;
sceneries: string[];
} | null;
} = (
await axios.get(
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`
)
).data.message;
const timetableData: {
let result: {
timetableId: number;
trainCategoryCode: string;
route: string;
twr: boolean;
skr: boolean;
sceneries: string[];
} | null = response.data.message.trainInfo;
routeDistance: number;
} | null = null;
return timetableData;
if (responseDataMessage.trainInfo) {
const routeDistance: number =
responseDataMessage.stopPoints[
responseDataMessage.stopPoints.length - 1
].pointDistance;
result = {
...responseDataMessage.trainInfo,
routeDistance,
};
}
return result;
}
mapSceneries(sceneries: string[]): string {
@@ -200,17 +248,25 @@ export default class TrainsView extends Vue {
return text;
}
onImageError(e: Event) {
(e.target as HTMLImageElement).src = unknownTrainImage;
}
get computedTrains() {
return this.onlineTrainsList.filter((train) => !train.noTimetable);
}
mounted() {
this.getTrainData();
setInterval(this.getTrainData, 5000);
}
}
</script>
<style lang="scss" scoped>
@import "../styles/responsive.scss";
.trains-view {
display: flex;
align-items: center;
@@ -218,25 +274,35 @@ export default class TrainsView extends Vue {
}
.list {
font-size: calc(0.5rem + 0.5vw);
margin-top: 2rem;
max-height: calc(100vh - 14em);
margin: 2rem 0;
overflow: auto;
max-width: 1300px;
max-width: 2000px;
}
.item {
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;
padding: 1rem;
margin: 1rem 0;
&:nth-child(even) {
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 {
@@ -284,16 +350,19 @@ export default class TrainsView extends Vue {
}
&-loco img {
max-width: 15em;
max-width: 12em;
}
}
.stats {
width: 100%;
&-general {
display: flex;
span {
display: flex;
justify-content: center;
width: 100%;
align-items: center;
@@ -306,7 +375,9 @@ export default class TrainsView extends Vue {
&-position {
display: flex;
margin-top: 1em;
text-align: center;
span {
width: 100%;