Poprawki kod

u. Dodano widok z rozkładami w karcie stacji
This commit is contained in:
2020-09-06 02:29:37 +02:00
parent 3febe562bf
commit 33b3837bd8
11 changed files with 358 additions and 88 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
<title>Stacjownik</title>
</head>
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg>

After

Width:  |  Height:  |  Size: 350 B

+1 -3
View File
@@ -1,3 +1 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 2L32 32M32 2L2 32" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 256 B

+1 -1
View File
@@ -166,7 +166,7 @@ export default class FilterCard extends Vue {
@include smallScreen() {
width: 85vw;
font-size: 1em;
font-size: 0.45em;
}
}
+228 -24
View File
@@ -1,7 +1,13 @@
<template>
<section class="card station-card">
<div class="card-exit" @click="exit">
<img :src="require('@/assets/icon-exit.svg')" alt="exit icon" />
<div class="card-exit">
<img
class="schedule-icon"
:src="require('@/assets/icon-clock.svg')"
alt="schedule-icon"
@click="() => cardMode = cardMode == 0 ? 1 : 0"
/>
<img :src="require('@/assets/icon-exit.svg')" alt="exit-icon" @click="exit" />
</div>
<div class="card-content" :class="{'offline': !stationInfo.online}">
@@ -133,13 +139,63 @@
</div>
</div>
<!-- <div class="card-timetables">
<div class="title">AKTYWNE ROZKŁADY JAZDY</div>
<div class="content">
<ul>
</ul>
<div class="card-timetables" id="card-timetables" :class="{show: cardMode == 1}">
<div class="timetables-wrapper">
<div class="timetables-title title">
<div style="font-size: 1.2em;">{{stationInfo.stationName.toUpperCase()}}</div>
<div>AKTYWNE ROZKŁADY JAZDY</div>
</div>
<div class="timetables-content">
<div class="timetable" v-for="(timetable, i) in computedScheduledTrains" :key="i">
<span class="timetable-general">
<span class="general-category">
<span>{{timetable.category}}</span>
{{timetable.trainNo}}
</span>
<span class="general-driver">{{timetable.driverName}}</span>
<span class="general-confirmed">
<span
style="color: gold"
v-if="timetable.stopped || (timetable.beginsHere && !timetable.confirmed)"
>Na stacji</span>
<span style="color: #aaa" v-else-if="!timetable.confirmed">W drodze</span>
<span
style="color: red"
v-else-if="(timetable.terminatesHere && timetable.confirmed)"
>Skończył bieg</span>
<span style="color: lime" v-else>Odprawiony</span>
</span>
</span>
<span class="timetable-schedule">
<span class="schedule-arrival">
<span class="arrival-time begins" v-if="timetable.beginsHere">ROZPOCZYNA BIEG</span>
<span
class="arrival-time"
v-else
>{{timestampToTime(timetable.arrivalTime)}} ({{timetable.arrivalDelay}})</span>
</span>
<span class="schedule-stop">
<span
class="stop-time"
v-if="timetable.stopTime"
>{{timetable.stopTime}} {{timetable.stopType}}</span>
<span class="stop-arrow arrow"></span>
</span>
<span class="schedule-departure">
<span class="departure-time terminates" v-if="timetable.terminatesHere">KOŃCZY BIEG</span>
<span
class="departure-time"
v-else
>{{timestampToTime(timetable.departureTime)}} ({{timetable.departureDelay}})</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>-->
</section>
</template>
@@ -147,32 +203,55 @@
import { Component, Prop, Watch } from "vue-property-decorator";
import styleMixin from "@/mixins/styleMixin";
import Station from "@/scripts/interfaces/Station";
@Component
export default class StationCard extends styleMixin {
@Prop() stationInfo;
@Prop() dispatcherHistory;
@Prop() stationInfo!: Station;
@Prop() exit!: void;
history: any[] = [];
cardMode: number = 0;
get computedExp(): string {
console.log(this.stationInfo.scheduledTrains);
return this.stationInfo.dispatcherExp < 2
? "L"
: `${this.stationInfo.dispatcherExp}`;
}
get computedScheduledTrains() {
return this.stationInfo.scheduledTrains.sort((a, b) => {
if (a.arrivalTime > b.arrivalTime) return 1;
else if ((a.arrivalTime < b.arrivalTime)) return -1;
return a.departureTime > b.departureTime ? 1 : -1;
})
}
timestampToTime(timestamp: number) {
return new Date(timestamp).toLocaleTimeString('pl-PL', {
hour: '2-digit',
minute: '2-digit',
})
}
}
</script>
<style lang="scss">
@import "../../styles/variables.scss";
@import "../../styles/responsive.scss";
.title {
color: $accentCol;
font-weight: 600;
margin: 0.5em 0;
}
.station-card {
scroll-behavior: smooth;
}
.card {
padding: 2em;
text-align: center;
@@ -182,18 +261,26 @@ export default class StationCard extends styleMixin {
-webkit-user-select: none;
&-exit {
z-index: 3;
img {
width: 1.5em;
margin: 0 0.3em;
font-size: 1.6em;
}
cursor: pointer;
}
&-content {
position: relative;
display: grid;
grid-template-areas: "main main" "icons icons" "dispatcher hours" "users spawns" "history history";
grid-template-columns: repeat(2, minmax(0, 1fr));
min-width: 200px;
max-height: 500px;
transform: translateY(0%);
gap: 1.5em;
@@ -367,21 +454,138 @@ export default class StationCard extends styleMixin {
.card-timetables {
position: absolute;
width: 100%;
height: 90%;
background: #333;
overflow: hidden;
bottom: 0;
left: 0;
top: 0;
width: 100%;
min-height: 100%;
.content {
position: absolute;
transform: translateY(-100%);
-webikit-transform: translateY(-100%);
&.show {
transform: translateY(0);
-webkit-transform: translateY(0);
}
// transform: translateY(80%);
transition: transform 150ms ease-out;
overflow: auto;
background: #333;
}
.timetables {
&-content {
width: 100%;
height: 100%;
padding: 25px 0;
}
&-title {
padding-top: 1rem;
font-size: 1.3em;
}
}
.timetable {
position: relative;
// margin: 0.rem auto;
margin: 1em auto;
max-width: 600px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
gap: 0 1rem;
@include smallScreen() {
display: flex;
flex-direction: column;
align-items: center;
}
&-general {
padding: 0.3rem 0.5rem;
border: 1px solid white;
display: flex;
justify-content: space-between;
@include smallScreen() {
width: 75%;
}
}
&-schedule {
@include smallScreen() {
width: 70%;
margin: 0.7em 0;
}
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
font-size: 1.2em;
}
}
.arrow {
border: solid white;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 2px;
margin-left: 50px;
position: relative;
transform: rotate(-45deg);
&::before {
content: "";
position: absolute;
display: block;
width: 55px;
height: 3px;
top: 4px;
left: 4px;
transform: translate(-100%, -1px) rotate(45deg);
transform-origin: right bottom;
background: white;
}
}
.general-category {
span {
color: $accentCol;
}
}
.schedule {
&-arrival,
&-stop,
&-departure {
display: flex;
justify-content: center;
align-items: center;
margin: 0 0.3rem;
}
&-stop {
display: flex;
flex-direction: column;
.stop-time {
font-size: 0.7em;
}
}
}
.arrival-time.begins,
.departure-time.terminates {
font-size: 0.75em;
}
</style>
+13 -7
View File
@@ -30,9 +30,9 @@
</div>
<div class="info-stations">
<span v-if="train.sceneries.length > 2">
<span v-if="train.followingStops.length > 2">
Przez:
<span v-html="mapTimetableSceneries(train.sceneries)"></span>
<span v-html="generateStopList(train.followingStops)"></span>
</span>
</div>
</div>
@@ -140,12 +140,18 @@ export default class TrainTable extends Vue {
(e.target as HTMLImageElement).src = unknownTrainImage;
}
mapTimetableSceneries(sceneries: string[]): string {
if (sceneries.length < 1) return "";
generateStopList(stops: any): string | undefined {
if (!stops) return "";
return stops.reduce((acc, stop, i) => {
if (i < 2 || i > stops.length - 2) return acc;
return sceneries
.filter((scenery, i) => i > 0 && i < sceneries.length - 1)
.join(" * ");
if (stop.stopType.includes("ph")) acc.push(`<strong>${stop.stopName}</strong>`);
if (stop.stopType == "") acc.push(`<span style='color: #ccc;'>${stop.stopName}</span>`);
if (stop.stopType == "podg.") acc.push(`<span style='color: #ccc;'>${stop.stopName
}</span>`);
return acc;
}, []).join(" * ");
}
}
</script>
+13 -3
View File
@@ -25,8 +25,18 @@ export default interface Station {
statusTimestamp: number;
scheduledTrains: {
trainNo: number;
trainCategory: string;
arrivalTime: string;
departureTime: string;
driverName: string;
category: string;
stopName: string;
stopType: string;
arrivalTime: number;
arrivalDelay: number;
departureTime: number;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
beginsHere: boolean;
terminatesHere: boolean;
}[];
}
+19 -10
View File
@@ -12,7 +12,25 @@ export default interface Train {
route: string | null;
timetableId: number | null;
category: string | null;
sceneries: string[] | null;
followingStops: {
stopName: string;
stopType: string;
arrivalLine?: string;
arrivalTime: number;
arrivalDelay: number;
departureLine?: string;
departureTime: number;
beginsHere: boolean;
terminatesHere: boolean;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
arrivalScenery?: string;
departureScenery?: string;
}[];
TWR: boolean | null;
SKR: boolean | null;
noTimetable: boolean;
@@ -20,13 +38,4 @@ export default interface Train {
locoType: string;
routeDistance: number;
online: boolean;
stopPoints: {
arrivalTime: string;
arrivalDelay: number;
departureTime: string;
departureDelay: number;
pointNameRAW: string;
pointStopType: string;
confirmed: boolean;
}[];
}
+64 -26
View File
@@ -1,9 +1,9 @@
import { Module, VuexModule, Mutation, Action } from "vuex-module-decorators";
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators';
import Train from "@/scripts/interfaces/Train";
import Train from '@/scripts/interfaces/Train';
import axios from "axios";
const API_URL = "https://api.td2.info.pl:9640/?method=getTrainsOnline";
import axios from 'axios';
const API_URL = 'https://api.td2.info.pl:9640/?method=getTrainsOnline';
enum ConnState {
Loading = 0,
@@ -32,6 +32,15 @@ interface TimetableResponseData {
pointNameRAW: string;
pointName: string;
pointStopType: string;
arrivalLine: string;
departureLine: string;
arrivalTime: string;
arrivalDelay: number;
departureTime: string;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
pointStopTime: number;
}[];
trainInfo: {
timetableId: number;
@@ -54,12 +63,14 @@ interface TimetableData {
stopPoints?: {}[];
}
const getTimestamp = (date: string) => (date ? new Date(date).getTime() : 0);
const getTimetableURL = (trainNo: number) =>
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`;
const getLocoURL = (locoType: string) =>
`https://rj.td2.info.pl/dist/img/thumbnails/${
locoType.includes("EN") ? locoType + "rb" : locoType
locoType.includes('EN') ? locoType + 'rb' : locoType
}.png`;
@Module
@@ -67,21 +78,21 @@ export default class TrainsModule extends VuexModule {
onlineTrainsData: Train[] = [];
onlineTrainsState: ConnState = ConnState.Loading;
@Action({ commit: "loadTrainsData" })
@Action({ commit: 'loadTrainsData' })
async fetchTrainsData() {
let trainDataResponse;
try {
trainDataResponse = await axios.get(API_URL);
} catch (error) {
this.context.commit("setConnectionState", ConnState.Error);
this.context.commit('setConnectionState', ConnState.Error);
return null;
}
let onlineTrainsData: TrainData[] = trainDataResponse.data.message;
return await Promise.all(
onlineTrainsData.map(async (train) => {
onlineTrainsData.map(async train => {
const timetableResponseData: TimetableResponseData | null = (
await axios.get(getTimetableURL(train.trainNo))
).data.message;
@@ -101,29 +112,57 @@ export default class TrainsModule extends VuexModule {
};
}
const locoType = train.dataCon.split(";")
? train.dataCon.split(";")[0]
const locoType = train.dataCon.split(';')
? train.dataCon.split(';')[0]
: train.dataCon;
const stopPoints = timetableResponseData?.stopPoints.reduce(
const followingStops = timetableResponseData?.stopPoints.reduce(
(acc, point) => {
if (point.pointName.includes("strong"))
acc.push(
point.pointStopType.includes("ph")
? `<strong>${point.pointNameRAW}</strong>`
: `<span style='color: #ccc;'>${point.pointNameRAW}</span>`
);
const stopObj: any = {};
if (
!point.pointName.includes('Południowy') &&
(point.pointName.includes('strong') ||
point.pointName.includes('podg.'))
) {
if (point.pointName.includes('strong')) {
stopObj.stopName = point.pointNameRAW;
if (point.pointName.includes("podg."))
acc.push(
`<span style='color: #ccc;'>${
point.pointNameRAW.split(",")[0]
}</span>`
);
stopObj.stopType = point.pointStopType;
} else {
stopObj.stopName = point.pointNameRAW.split(',')[0];
stopObj.stopType = 'podg.';
}
stopObj.arrivalTime = getTimestamp(point.arrivalTime);
stopObj.departureTime = getTimestamp(point.departureTime);
stopObj.arrivalDelay = point.arrivalDelay;
stopObj.departureDelay = point.departureDelay;
stopObj.beginsHere =
getTimestamp(point.arrivalTime) == 0 ? true : false;
stopObj.terminatesHere =
getTimestamp(point.departureTime) == 0 ? true : false;
stopObj.confirmed = point.confirmed;
stopObj.stopped = point.stopped;
stopObj.stopTime = point.pointStopTime;
acc.push(stopObj);
}
return acc;
},
[] as string[]
[] as {
stopName: string;
stopType: string;
arrivalTime: number;
arrivalDelay: number;
departureTime: number;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
beginsHere: boolean;
terminatesHere: boolean;
}[]
);
return {
@@ -145,8 +184,7 @@ export default class TrainsModule extends VuexModule {
timetableId: timetableData?.timetableId,
category: timetableData?.trainCategoryCode,
routeDistance: timetableData?.routeDistance || 0,
sceneries: stopPoints,
stopPoints: timetableData?.stopPoints,
followingStops,
TWR: timetableData?.twr,
SKR: timetableData?.skr,
};
+4 -2
View File
@@ -23,7 +23,8 @@ html {
body {
width: 100%;
margin: 0;
font-family: "Open Sans", sans-serif;
// font-family: "Open Sans", sans-serif;
font-family: "Quicksand", sans-serif;
overflow-x: hidden;
}
@@ -31,7 +32,8 @@ body {
button,
input,
select {
font-family: "Open Sans", sans-serif;
// font-family: "Open Sans", sans-serif;
font-family: "Quicksand", sans-serif;
}
input {
+13 -11
View File
@@ -127,28 +127,30 @@ export default class StationsView extends Vue {
this.trains
.filter((train) => !train.noTimetable)
.forEach((train) => {
const found = train.stopPoints!.find(
(sp) =>
const foundIndex = train.followingStops.findIndex(
(stop) =>
(station.stationName
.toLowerCase()
.includes(sp.pointNameRAW.toLowerCase()) ||
.includes(stop.stopName) ||
station.stationName
.toLowerCase()
.includes(sp.pointNameRAW.toLowerCase().split(",")[0]) ||
.includes(stop.stopName.toLowerCase().split(",")[0]) ||
(station.stationName
.toLowerCase()
.includes(sp.pointNameRAW.toLowerCase().split(" ")[0]) &&
.includes(stop.stopName.toLowerCase().split(" ")[0]) &&
station.stationName.toLowerCase().includes("lcs"))) &&
!acc[station.stationName].find((t) => t.trainNo === train.trainNo)
);
if (!found) return acc;
if (foundIndex < 0) return acc;
const foundStop = train.followingStops[foundIndex];
acc[station.stationName].push({
trainNo: train.trainNo,
driverName: train.driverName,
category: train.category,
...found,
...foundStop
});
});
@@ -244,8 +246,8 @@ export default class StationsView extends Vue {
break;
case 3:
if (a.dispatcherName > b.dispatcherName) return dir;
if (a.dispatcherName < b.dispatcherName) return -dir;
if (a.dispatcherName.toLowerCase() > b.dispatcherName.toLowerCase()) return dir;
if (a.dispatcherName.toLowerCase() < b.dispatcherName.toLowerCase()) return -dir;
break;
case 4:
@@ -264,7 +266,7 @@ export default class StationsView extends Vue {
break;
}
if (a.stationName >= b.stationName) return dir;
if (a.stationName.toLowerCase() >= b.stationName.toLowerCase()) return dir;
return -dir;
})
.map((station) => ({
@@ -307,7 +309,7 @@ export default class StationsView extends Vue {
}
get focusedStationInfo() {
return this.stations.find(
return this.computedStations.find(
(station) => station.stationName === this.focusedStationName
);
}