Wygląd i podstawowe funkcjonalności widoku składów online

This commit is contained in:
2020-08-04 18:10:23 +02:00
parent ca2eea15e4
commit e22115844a
7 changed files with 297 additions and 37 deletions
+3 -1
View File
@@ -30,7 +30,9 @@
<main class="app-main">
<Loading v-if="connectionState == 0" />
<Error v-else-if="connectionState == 1" :error="errorMessage" />
<router-view v-else />
<keep-alive v-else>
<router-view />
</keep-alive>
</main>
<footer class="app-footer flex">&copy; Spythere 2020</footer>
+4
View File
@@ -0,0 +1,4 @@
<svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30.3072" height="30" rx="6" fill="#7B7B7B"/>
<path d="M26.7965 15.5303C27.0894 15.2374 27.0894 14.7626 26.7965 14.4697L22.0236 9.6967C21.7307 9.40381 21.2558 9.40381 20.9629 9.6967C20.67 9.98959 20.67 10.4645 20.9629 10.7574L25.2056 15L20.9629 19.2426C20.67 19.5355 20.67 20.0104 20.9629 20.3033C21.2558 20.5962 21.7307 20.5962 22.0236 20.3033L26.7965 15.5303ZM3.51062 14.4697C3.21773 14.7626 3.21773 15.2374 3.51062 15.5303L8.2836 20.3033C8.57649 20.5962 9.05136 20.5962 9.34426 20.3033C9.63715 20.0104 9.63715 19.5355 9.34426 19.2426L5.10161 15L9.34426 10.7574C9.63715 10.4645 9.63715 9.98959 9.34426 9.6967C9.05136 9.40381 8.57649 9.40381 8.2836 9.6967L3.51062 14.4697ZM4.92996 15.75H25.3772V14.25H4.92996V15.75ZM25.3772 15.75H26.2662V14.25H25.3772V15.75ZM4.92996 14.25H4.04095V15.75H4.92996V14.25Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 934 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30.3072" height="30" rx="6" fill="#7B7B7B"/>
<path d="M11.8852 9.32496C12.5388 3.65327 17.7683 3.4642 18.422 9.32496M21.9331 9.70309L26.2662 24.0714H4.04095L8.54741 9.70309H15.1536H21.9331Z" stroke="white" stroke-width="2" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 365 B

+18
View File
@@ -0,0 +1,18 @@
<svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30.3072" height="30" rx="6" fill="#7B7B7B"/>
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="5" y="8" width="21" height="12">
<rect x="5.05118" y="8" width="20.2048" height="11.5" fill="#C4C4C4"/>
</mask>
<g mask="url(#mask0)">
<ellipse cx="15.1536" cy="19" rx="10.1024" ry="10" fill="white"/>
<rect width="3.02307" height="1.00257" transform="matrix(0.868217 -0.496185 -0.503825 -0.863806 21.5304 15.933)" fill="#4A4A4A"/>
<rect x="5.05118" y="18.5" width="3.03072" height="1" fill="#4A4A4A"/>
<rect width="3.03072" height="1" transform="matrix(1 0 0 -1 22.2253 19.5)" fill="#4A4A4A"/>
<rect width="3.00771" height="1.00769" transform="matrix(-0.503825 -0.863806 -0.868217 0.496185 12.0552 12.6879)" fill="#4A4A4A"/>
<rect width="3.00771" height="1.00769" transform="matrix(-0.503825 0.863806 -0.868217 -0.496185 20.6422 10.5897)" fill="#4A4A4A"/>
<rect width="3" height="1.01024" transform="matrix(-4.41589e-08 -1 -1 4.32684e-08 15.6587 12)" fill="#4A4A4A"/>
<rect width="3.02307" height="1.00257" transform="matrix(0.868217 0.496185 -0.503825 0.863806 6.6572 13.567)" fill="#4A4A4A"/>
<ellipse cx="15.1536" cy="19.5" rx="1.01024" ry="1" fill="#474747"/>
<path d="M18.4254 13.9298C18.3862 13.798 18.2465 13.7226 18.1134 13.7614L15.9439 14.393C15.8107 14.4318 15.7345 14.57 15.7737 14.7018C15.8129 14.8336 15.9525 14.909 16.0857 14.8702L18.0141 14.3088L18.5813 16.2177C18.6205 16.3495 18.7602 16.4249 18.8933 16.3862C19.0264 16.3474 19.1026 16.2092 19.0635 16.0774L18.4254 13.9298ZM15.3742 19.6191L18.4049 14.1191L17.9637 13.8809L14.933 19.3809L15.3742 19.6191Z" fill="#474747"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1 -1
View File
@@ -297,7 +297,7 @@ export default class List extends styleMixin {
}
.list-body {
max-height: calc(100vh - 4em);
max-height: calc(100vh - 4.5em);
overflow: auto;
display: flex;
flex-direction: column;
+4
View File
@@ -65,6 +65,10 @@ class Store extends VuexModule {
return this.filteredStations;
}
get getAllStations() {
return this.stations;
}
get getFilters() {
return this.filters;
}
+263 -35
View File
@@ -1,36 +1,113 @@
<template>
<section class="trains-view">
<div class="list" v-if="listLoaded">
<div v-for="train in onlineTrainsList" :key="train.timetableId">{{ train.route }}</div>
</div>
<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>
<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-stations">
<i v-if="train.sceneries.length > 0">Przez: {{train.sceneries}}</i>
</div>
</span>
<span class="driver">
<span class="driver-name">{{train.driverName}}</span>
<span class="driver-loco">
<img src="https://rj.td2.info.pl/dist/img/thumbnails/ET41-144.png" alt="icon-train" />
</span>
</span>
<span class="stats">
<div class="stats-general">
<span class="mass">
<img :src="massIcon" alt="icon-mass" />
{{train.mass/1000}}t
</span>
<span class="speed">
<img :src="speedIcon" alt="icon-speed" />
{{train.speed}} km/h
</span>
<span class="length">
<img :src="lengthIcon" alt="icon-length" />
{{train.length}}m
</span>
</div>
<div class="stats-position">
<span class="station">
<p>
<strong>SCENERIA</strong>
</p>
{{train.currentStationName}}
</span>
<span class="track">
<p>
<strong>SZLAK</strong>
</p>
{{train.connectedTrack || "---"}}
</span>
<span class="signal">
<p>
<strong>SEMAFOR</strong>
</p>
{{train.signal || "---"}}
</span>
</div>
</span>
</li>
</ul>
</section>
</template>
<script lang="ts">
import Vue from "vue";
import { Component } from "vue-property-decorator";
import { Getter } from "vuex-class";
import Station from "@/scripts/interfaces/Station";
import axios from "axios";
@Component
export default class TrainsView extends Vue {
speedIcon: string = require("@/assets/icon-speed.svg");
massIcon: string = require("@/assets/icon-mass.svg");
lengthIcon: string = require("@/assets/icon-length.svg");
@Getter("getAllStations") stations!: Station[];
onlineTrainsList: {
mass: number;
length: number;
speed: number;
signal: string;
distance: number;
imageURL: string;
connectedTrack: string;
route?: string;
driverId: number;
trainNo: number;
timetableId?: number;
driverName: string;
currentStationName: string;
category: string;
sceneries: string[];
TWR: boolean;
SKR: boolean;
route: string | null;
timetableId: number | null;
category: string | null;
sceneries: string | null;
TWR: boolean | null;
SKR: boolean | null;
noTimetable: boolean;
}[] = [];
listLoaded: boolean = false;
@@ -50,35 +127,43 @@ export default class TrainsView extends Vue {
dataSpeed: number;
dataDistance: number;
dataSignal: string;
dataCon: string;
dataSceneryConnection: string;
isOnline: boolean;
}[] = response.data.message;
onlineTrainsData = onlineTrainsData.filter((train) => train.isOnline);
this.onlineTrainsList = await Promise.all(
onlineTrainsData
.filter((train) => train.isOnline)
.map(async (train) => {
const timetableData = await this.getTimetableData(train.trainNo);
onlineTrainsData.forEach(async (train) => {
const timetableData = await this.getTimetableData(train.trainNo);
return {
driverId: train.driverId,
driverName: train.driverName,
trainNo: train.trainNo,
currentStationName: train.station.stationName,
mass: train.dataMass,
length: train.dataLength,
speed: train.dataSpeed,
distance: train.dataDistance,
signal: train.dataSignal,
imageURL: train.dataCon,
connectedTrack: train.dataSceneryConnection,
noTimetable: timetableData == null,
route: timetableData && timetableData.route,
timetableId: timetableData && timetableData.timetableId,
category: timetableData && timetableData.trainCategoryCode,
sceneries:
timetableData &&
(await this.mapSceneries(timetableData.sceneries)),
TWR: timetableData && timetableData.twr,
SKR: timetableData && timetableData.skr,
};
})
);
if (timetableData)
this.onlineTrainsList.push({
driverId: train.driverId,
driverName: train.driverName,
trainNo: train.trainNo,
currentStationName: train.station.stationName,
mass: train.dataMass,
length: train.dataLength,
speed: train.dataSpeed,
distance: train.dataDistance,
signal: train.dataSignal,
connectedTrack: train.dataSceneryConnection,
route: timetableData.route || "",
timetableId: timetableData.timetableId,
category: timetableData.trainCategoryCode,
sceneries: timetableData.sceneries,
TWR: timetableData.twr,
SKR: timetableData.skr,
});
});
this.listLoaded = true;
}
async getTimetableData(trainNo: number) {
@@ -98,14 +183,157 @@ export default class TrainsView extends Vue {
return timetableData;
}
mapSceneries(sceneries: string[]): string {
let text = "";
for (let i = sceneries.length - 1; i >= 0; i--) {
const station = this.stations.find(
(station) => station.stationHash == sceneries[i]
);
if (!station) continue;
if (i == sceneries.length - 1 || i == 0) continue;
text += `${station.stationName}${i > 1 ? ", " : ""}`;
}
return text;
}
get computedTrains() {
return this.onlineTrainsList.filter((train) => !train.noTimetable);
}
mounted() {
this.getTrainData().then(() => (this.listLoaded = true));
this.getTrainData();
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.trains-view {
display: flex;
align-items: center;
flex-direction: column;
}
.list {
font-size: 1.2rem;
font-size: calc(0.5rem + 0.5vw);
margin-top: 2rem;
max-height: calc(100vh - 14em);
overflow: auto;
max-width: 1300px;
}
.item {
display: grid;
grid-template-columns: repeat(3, 1fr);
background-color: #444;
padding: 1rem;
&:nth-child(even) {
background-color: #666;
}
}
.info {
display: flex;
flex-wrap: wrap;
&-category {
flex-grow: 2;
font-size: 1.05em;
}
&-route {
width: 100%;
font-size: 1.2em;
}
&-stations {
margin-top: 0.35em;
font-size: 0.75em;
}
}
.driver {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
&-exp {
font-size: 1.4em;
padding: 0.3em 0.6em;
border-radius: 0.4em;
background-color: red;
}
&-name {
margin: 0 0.3em;
}
&-loco {
width: 100%;
text-align: center;
}
&-loco img {
max-width: 15em;
}
}
.stats {
&-general {
display: flex;
span {
display: flex;
width: 100%;
align-items: center;
}
img {
margin: 0 0.3em;
}
}
&-position {
display: flex;
margin-top: 1em;
span {
width: 100%;
font-size: 300;
}
p {
color: #00cff3;
}
}
}
.warning {
border-radius: 1em;
padding: 0.1em 1.2em;
margin: 0 0.2em;
color: black;
font-weight: bold;
font-size: 0.85em;
&.twr {
background-color: #ffc700;
}
&.skr {
background-color: #ff4646;
}
}
</style>