mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Zamiana karty stacji na zakładkę stacji [W.I.P.]
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 15C13.625 15 12.5 13.875 12.5 12.5C12.5 11.125 13.625 10 15 10C16.375 10 17.5 11.125 17.5 12.5C17.5 13.875 16.375 15 15 15ZM22.5 12.75C22.5 8.2125 19.1875 5 15 5C10.8125 5 7.5 8.2125 7.5 12.75C7.5 15.675 9.9375 19.55 15 24.175C20.0625 19.55 22.5 15.675 22.5 12.75ZM15 2.5C20.25 2.5 25 6.525 25 12.75C25 16.9 21.6625 21.8125 15 27.5C8.3375 21.8125 5 16.9 5 12.75C5 6.525 9.75 2.5 15 2.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 519 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.75 3.75H22.5V1.25H20V3.75H10V1.25H7.5V3.75H6.25C4.875 3.75 3.75 4.875 3.75 6.25V23.75C3.75 25.125 4.875 26.25 6.25 26.25H23.75C25.125 26.25 26.25 25.125 26.25 23.75V6.25C26.25 4.875 25.125 3.75 23.75 3.75ZM23.75 23.75H6.25V11.25H23.75V23.75ZM6.25 8.75V6.25H23.75V8.75H6.25ZM8.75 13.75H21.25V16.25H8.75V13.75ZM8.75 18.75H17.5V21.25H8.75V18.75Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 475 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 15C17.7625 15 20 12.7625 20 10C20 7.2375 17.7625 5 15 5C12.2375 5 10 7.2375 10 10C10 12.7625 12.2375 15 15 15ZM15 17.5C11.6625 17.5 5 19.175 5 22.5V25H25V22.5C25 19.175 18.3375 17.5 15 17.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
@@ -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="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg>
|
||||
|
After Width: | Height: | Size: 285 B |
@@ -7,19 +7,17 @@
|
||||
alt="schedule-icon"
|
||||
@click="() => (cardMode = cardMode == 0 ? 1 : 0)"
|
||||
/>
|
||||
<img
|
||||
:src="require('@/assets/icon-exit.svg')"
|
||||
alt="exit-icon"
|
||||
@click="exit"
|
||||
/>
|
||||
<img :src="require('@/assets/icon-exit.svg')" alt="exit-icon" @click="exit" />
|
||||
</div>
|
||||
|
||||
<div class="card-content" :class="{ offline: !stationInfo.online }">
|
||||
<div class="main">
|
||||
<div class="main-content">
|
||||
<span class="main-level flex" v-if="stationInfo.reqLevel > -1">{{
|
||||
<span class="main-level flex" v-if="stationInfo.reqLevel > -1">
|
||||
{{
|
||||
2 > parseInt(stationInfo.reqLevel) ? "L" : stationInfo.reqLevel
|
||||
}}</span>
|
||||
}}
|
||||
</span>
|
||||
<span class="main-general">
|
||||
<div class="main-name">
|
||||
<a
|
||||
@@ -27,8 +25,7 @@
|
||||
:href="stationInfo.stationURL"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>{{ stationInfo.stationName }}</a
|
||||
>
|
||||
>{{ stationInfo.stationName }}</a>
|
||||
|
||||
<span v-else>{{ stationInfo.stationName }}</span>
|
||||
</div>
|
||||
@@ -90,9 +87,7 @@
|
||||
stationInfo.dispatcherIsSupporter
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ stationInfo.online ? computedDispatcherExp : "" }}
|
||||
</div>
|
||||
>{{ stationInfo.online ? computedDispatcherExp : "" }}</div>
|
||||
<div class="dispatcher-info">
|
||||
<div class="dispatcher-name">
|
||||
<a
|
||||
@@ -101,8 +96,7 @@
|
||||
"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>{{ stationInfo.dispatcherName || "---" }}</a
|
||||
>
|
||||
>{{ stationInfo.dispatcherName || "---" }}</a>
|
||||
</div>
|
||||
|
||||
<div class="dispatcher-rate">
|
||||
@@ -114,9 +108,11 @@
|
||||
|
||||
<div class="hours">
|
||||
<div class="hours-title title">STATUS</div>
|
||||
<span class="status" :class="statusClasses(stationInfo.occupiedTo)">{{
|
||||
<span class="status" :class="statusClasses(stationInfo.occupiedTo)">
|
||||
{{
|
||||
stationInfo.occupiedTo
|
||||
}}</span>
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="spawns flex flex-column">
|
||||
@@ -126,8 +122,7 @@
|
||||
class="spawn"
|
||||
v-for="(spawn, i) in stationInfo.spawnString"
|
||||
:key="spawn + stationInfo.dispatcherName + i"
|
||||
>{{ spawn }}</span
|
||||
>
|
||||
>{{ spawn }}</span>
|
||||
|
||||
<span class="spawn" v-if="!stationInfo.spawnString">BRAK</span>
|
||||
</div>
|
||||
@@ -160,8 +155,7 @@
|
||||
!stationInfo.stationTrains ||
|
||||
stationInfo.stationTrains.length == 0
|
||||
"
|
||||
>BRAK</span
|
||||
>
|
||||
>BRAK</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
<table class="table">
|
||||
<thead class="table-head">
|
||||
<tr>
|
||||
<th
|
||||
v-for="(head, i) in headTitles"
|
||||
:key="i"
|
||||
@click="() => changeSorter(i)"
|
||||
>
|
||||
<th v-for="(head, i) in headTitles" :key="i" @click="() => changeSorter(i)">
|
||||
<span>
|
||||
<div>
|
||||
<div>{{ head[0] }}</div>
|
||||
@@ -30,11 +26,7 @@
|
||||
class="table-item"
|
||||
v-for="(station, i) in stations"
|
||||
:key="i + station.stationHash"
|
||||
@click="
|
||||
() => {
|
||||
setFocusedStation(station.stationName);
|
||||
}
|
||||
"
|
||||
@click="setScenery(station.stationHash)"
|
||||
>
|
||||
<td
|
||||
class="item-station-name"
|
||||
@@ -43,49 +35,43 @@
|
||||
online: station.online,
|
||||
'station-unavailable': station.unavailable,
|
||||
}"
|
||||
>
|
||||
{{ station.stationName }}
|
||||
</td>
|
||||
>{{ station.stationName }}</td>
|
||||
|
||||
<td class="item-station-level">
|
||||
<span
|
||||
v-if="station.reqLevel"
|
||||
:style="calculateExpStyle(station.reqLevel)"
|
||||
>{{
|
||||
station.reqLevel && station.reqLevel > -1
|
||||
? parseInt(station.reqLevel) >= 2
|
||||
? station.reqLevel
|
||||
: "L"
|
||||
: "?"
|
||||
}}</span
|
||||
>
|
||||
<span v-if="station.reqLevel" :style="calculateExpStyle(station.reqLevel)">
|
||||
{{
|
||||
station.reqLevel && station.reqLevel > -1
|
||||
? parseInt(station.reqLevel) >= 2
|
||||
? station.reqLevel
|
||||
: "L"
|
||||
: "?"
|
||||
}}
|
||||
</span>
|
||||
|
||||
<span v-else>?</span>
|
||||
</td>
|
||||
|
||||
<td class="item-station-status">
|
||||
<span class="status" :class="statusClasses(station.occupiedTo)">{{
|
||||
<span class="status" :class="statusClasses(station.occupiedTo)">
|
||||
{{
|
||||
station.occupiedTo
|
||||
}}</span>
|
||||
}}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="item-dispatcher-name">
|
||||
{{ station.online ? station.dispatcherName : "" }}
|
||||
</td>
|
||||
<td class="item-dispatcher-name">{{ station.online ? station.dispatcherName : "" }}</td>
|
||||
<td class="item-dispatcher-exp">
|
||||
<span
|
||||
v-if="station.online"
|
||||
:style="calculateExpStyle(station.dispatcherExp)"
|
||||
>{{
|
||||
2 > station.dispatcherExp ? "L" : station.dispatcherExp
|
||||
}}</span
|
||||
>
|
||||
<span v-if="station.online" :style="calculateExpStyle(station.dispatcherExp)">
|
||||
{{
|
||||
2 > station.dispatcherExp ? "L" : station.dispatcherExp
|
||||
}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="item-users">
|
||||
{{
|
||||
station.online
|
||||
? station.currentUsers + "/" + station.maxUsers
|
||||
: ""
|
||||
station.online
|
||||
? station.currentUsers + "/" + station.maxUsers
|
||||
: ""
|
||||
}}
|
||||
</td>
|
||||
<td class="item-info">
|
||||
@@ -130,8 +116,7 @@
|
||||
'Liczba zelektryfikowanych szlaków dwutorowych: ' +
|
||||
station.routes.twoWay.catenary
|
||||
"
|
||||
>{{ station.routes.twoWay.catenary }}</span
|
||||
>
|
||||
>{{ station.routes.twoWay.catenary }}</span>
|
||||
|
||||
<span
|
||||
v-if="station.routes && station.routes.twoWay.noCatenary > 0"
|
||||
@@ -140,8 +125,7 @@
|
||||
'Liczba niezelektryfikowanych szlaków dwutorowych: ' +
|
||||
station.routes.twoWay.noCatenary
|
||||
"
|
||||
>{{ station.routes.twoWay.noCatenary }}</span
|
||||
>
|
||||
>{{ station.routes.twoWay.noCatenary }}</span>
|
||||
|
||||
<span class="separator"></span>
|
||||
|
||||
@@ -152,8 +136,7 @@
|
||||
'Liczba zelektryfikowanych szlaków jednotorowych: ' +
|
||||
station.routes.oneWay.catenary
|
||||
"
|
||||
>{{ station.routes.oneWay.catenary }}</span
|
||||
>
|
||||
>{{ station.routes.oneWay.catenary }}</span>
|
||||
|
||||
<span
|
||||
v-if="station.routes && station.routes.oneWay.noCatenary > 0"
|
||||
@@ -162,23 +145,26 @@
|
||||
'Liczba niezelektryfikowanych szlaków jednotorowych: ' +
|
||||
station.routes.oneWay.noCatenary
|
||||
"
|
||||
>{{ station.routes.oneWay.noCatenary }}</span
|
||||
>
|
||||
>{{ station.routes.oneWay.noCatenary }}</span>
|
||||
</td>
|
||||
|
||||
<td class="active-timetables">
|
||||
<transition name="change-anim" mode="out-in">
|
||||
<span :key="station.scheduledTrains.length">
|
||||
<span v-if="station.scheduledTrains">
|
||||
<span style="color: #eee">{{
|
||||
<span style="color: #eee">
|
||||
{{
|
||||
station.scheduledTrains.length
|
||||
}}</span>
|
||||
}}
|
||||
</span>
|
||||
/
|
||||
<span style="color: #bbb">{{
|
||||
<span style="color: #bbb">
|
||||
{{
|
||||
station.scheduledTrains.filter(
|
||||
(train) => train.stopInfo.confirmed
|
||||
(train) => train.stopInfo.confirmed
|
||||
).length
|
||||
}}</span>
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span v-else>...</span>
|
||||
@@ -188,9 +174,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="no-stations" v-if="stations.length == 0">
|
||||
Ups! Brak stacji do wyświetlenia!
|
||||
</div>
|
||||
<div class="no-stations" v-if="stations.length == 0">Ups! Brak stacji do wyświetlenia!</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -217,6 +201,10 @@ export default class StationTable extends styleMixin {
|
||||
@Prop() readonly setFocusedStation!: () => void;
|
||||
@Prop() readonly changeSorter!: () => void;
|
||||
|
||||
setScenery(sceneryHash: string) {
|
||||
this.$router.push({ name: "SceneryView", query: { hash: sceneryHash } })
|
||||
}
|
||||
|
||||
icons: { ascSVG; descSVG } = { ascSVG, descSVG };
|
||||
|
||||
headTitles: string[][] = [
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"default": false,
|
||||
"nonPublic": false,
|
||||
"stops": ["Borowe, podg.", "Wysoka, podg.", "Naprawa, podg."]
|
||||
"stops": ["Borowe, podg.", "Wysoka, podg.", "Naprawa, podg.", "Borowe Towarowe"]
|
||||
},
|
||||
{
|
||||
"stationName": "LCS Gdańsk",
|
||||
|
||||
@@ -4,6 +4,7 @@ import VueRouter, { RouteConfig } from 'vue-router';
|
||||
import StationsView from '../views/StationsView.vue';
|
||||
import TrainsView from '../views/TrainsView.vue';
|
||||
import TimetableView from '../views/TimetableView.vue';
|
||||
import SceneryView from '../views/SceneryView.vue';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
@@ -24,6 +25,12 @@ const routes: Array<RouteConfig> = [
|
||||
name: 'TimetableView',
|
||||
component: TimetableView,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: '/scenery',
|
||||
name: "SceneryView",
|
||||
component: SceneryView,
|
||||
props: true
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import TrainStop from "./TrainStop";
|
||||
|
||||
export default interface ScheduledTrain {
|
||||
trainNo: number;
|
||||
driverName: string;
|
||||
driverId: number;
|
||||
currentStationName: string;
|
||||
currentStationHash: string;
|
||||
category: string;
|
||||
stopInfo: TrainStop;
|
||||
|
||||
terminatesAt: string;
|
||||
beginsAt: string;
|
||||
nearestStop: string;
|
||||
|
||||
stopLabel: string;
|
||||
stopStatus: string;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import Train from '@/scripts/interfaces/Train';
|
||||
import TrainStop from '@/scripts/interfaces/TrainStop';
|
||||
import Train from './Train';
|
||||
import ScheduledTrain from './ScheduledTrain';
|
||||
|
||||
export default interface Station {
|
||||
stationName: string;
|
||||
@@ -24,24 +24,12 @@ export default interface Station {
|
||||
oneWay: { catenary: number; noCatenary: number };
|
||||
twoWay: { catenary: number; noCatenary: number };
|
||||
};
|
||||
subStations: {
|
||||
scheduledTrains: ScheduledTrain[],
|
||||
}[];
|
||||
online: boolean;
|
||||
occupiedTo: string;
|
||||
statusTimestamp: number;
|
||||
stationTrains: Train[];
|
||||
scheduledTrains: {
|
||||
trainNo: number;
|
||||
driverName: string;
|
||||
driverId: number;
|
||||
currentStationName: string;
|
||||
currentStationHash: string;
|
||||
category: string;
|
||||
stopInfo: TrainStop;
|
||||
|
||||
terminatesAt: string;
|
||||
beginsAt: string;
|
||||
nearestStop: string;
|
||||
|
||||
stopLabel: string;
|
||||
stopStatus: string;
|
||||
}[];
|
||||
scheduledTrains: ScheduledTrain[];
|
||||
}
|
||||
|
||||
+38
-7
@@ -13,6 +13,21 @@ enum Status {
|
||||
Loaded = 2,
|
||||
}
|
||||
|
||||
interface TimetableData {
|
||||
trainNo: number;
|
||||
driverName: string;
|
||||
driverId: number;
|
||||
currentStationName: string;
|
||||
currentStationHash: string;
|
||||
timetableId: number;
|
||||
category: string;
|
||||
route: string;
|
||||
TWR: boolean;
|
||||
SKR: boolean;
|
||||
routeDistance: number;
|
||||
followingStops: TrainStop[];
|
||||
}
|
||||
|
||||
const URLs = {
|
||||
stations: 'https://api.td2.info.pl:9640/?method=getStationsOnline',
|
||||
trains: 'https://api.td2.info.pl:9640/?method=getTrainsOnline',
|
||||
@@ -96,6 +111,7 @@ export default class Store extends VuexModule {
|
||||
// private dataConnectionStatus: Status = Status.Loading;
|
||||
|
||||
private dataConnectionStatus: Status = Status.Loading;
|
||||
private timetableLoaded: Status = Status.Loading;
|
||||
|
||||
private stationList: Station[] = [];
|
||||
private trainList: Train[] = [];
|
||||
@@ -119,6 +135,14 @@ export default class Store extends VuexModule {
|
||||
return this.trainList;
|
||||
}
|
||||
|
||||
get getTimetableDataStatus() {
|
||||
return this.timetableLoaded;
|
||||
}
|
||||
|
||||
get getDataStatus() {
|
||||
return this.dataConnectionStatus;
|
||||
}
|
||||
|
||||
//ACTIONS
|
||||
@Action
|
||||
async synchronizeData() {
|
||||
@@ -135,10 +159,9 @@ export default class Store extends VuexModule {
|
||||
const timetable = await (await axios.get(timetableURL(train.trainNo))).data.message;
|
||||
const trainInfo = timetable.trainInfo;
|
||||
|
||||
let timetableData;
|
||||
|
||||
|
||||
if (timetable && trainInfo) {
|
||||
timetableData = {};
|
||||
let timetableData!: TimetableData;
|
||||
|
||||
const followingStops: TrainStop[] = timetable.stopPoints.reduce((acc: TrainStop[], point) => {
|
||||
const arrivalTimestamp = getTimestamp(point.arrivalTime);
|
||||
@@ -192,9 +215,11 @@ export default class Store extends VuexModule {
|
||||
routeDistance: timetable.stopPoints[timetable.stopPoints.length - 1].pointDistance,
|
||||
followingStops,
|
||||
};
|
||||
|
||||
return timetableData;
|
||||
}
|
||||
|
||||
return timetableData;
|
||||
return null;
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -295,6 +320,7 @@ export default class Store extends VuexModule {
|
||||
statusTimestamp: -3,
|
||||
stationTrains: [],
|
||||
scheduledTrains: [],
|
||||
subStations: [],
|
||||
...stationData,
|
||||
}));
|
||||
}
|
||||
@@ -303,15 +329,17 @@ export default class Store extends VuexModule {
|
||||
private updateOnlineStations(updatedStationList: any[]) {
|
||||
this.stationList = this.stationList.reduce((acc, station) => {
|
||||
const onlineStationData = updatedStationList.find(updatedStation => updatedStation.stationName === station.stationName);
|
||||
const isRegistered = JSONStationData.some(data => data.stationName === station.stationName);
|
||||
const registeredStation = JSONStationData.find(data => data.stationName === station.stationName);
|
||||
const subStations = registeredStation?.stops && registeredStation.stops;
|
||||
|
||||
if (onlineStationData)
|
||||
acc.push({
|
||||
...station,
|
||||
...onlineStationData,
|
||||
subStations,
|
||||
online: true,
|
||||
});
|
||||
else if (isRegistered)
|
||||
else if (registeredStation)
|
||||
acc.push({
|
||||
...station,
|
||||
stationProject: '',
|
||||
@@ -329,6 +357,7 @@ export default class Store extends VuexModule {
|
||||
statusTimestamp: -3,
|
||||
stationTrains: [],
|
||||
scheduledTrains: [],
|
||||
subStations: []
|
||||
});
|
||||
|
||||
return acc;
|
||||
@@ -370,7 +399,7 @@ export default class Store extends VuexModule {
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private updateTimetableData(timetableList: any[]) {
|
||||
private updateTimetableData(timetableList: TimetableData[]) {
|
||||
this.stationList = this.stationList.map(station => {
|
||||
const scheduledTrains: Station['scheduledTrains'] = timetableList.reduce((acc: Station['scheduledTrains'], timetableData: any, index) => {
|
||||
const scheduledIndex = timetableData
|
||||
@@ -447,5 +476,7 @@ export default class Store extends VuexModule {
|
||||
|
||||
return acc;
|
||||
}, [] as Train[]);
|
||||
|
||||
this.timetableLoaded = Status.Loaded;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ $secondaryCol: #01e733;
|
||||
$bgCol: #505050;
|
||||
|
||||
$errorCol: #ff1919;
|
||||
$warningCol: #ff975b;
|
||||
$warningCol: #ffe15b;
|
||||
|
||||
$accentCol: #ffc014;
|
||||
$accent2Col: #ff3d5d;
|
||||
|
||||
@@ -0,0 +1,678 @@
|
||||
<template>
|
||||
<div class="scenery-view">
|
||||
<div class="scenery-offline" v-if="!stationInfo && dataStatus == 2">
|
||||
Ups! Nie znaleziono danej stacji bądź jest ona offline!
|
||||
<button class="button">
|
||||
<a href="https://stacjownik-td2.web.app">Wróć na stronę główną</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="scenery-wrapper" v-if="stationInfo">
|
||||
<div class="scenery-header">
|
||||
<div class="station-name">{{ stationInfo.stationName }}</div>
|
||||
<div class="station-hash">#{{ stationInfo.stationHash }}</div>
|
||||
</div>
|
||||
|
||||
<section v-if="!timetableOnly">
|
||||
<div class="scenery-stats">
|
||||
<span class="likes">
|
||||
<img :src="likeIcon" alt="icon-like" />
|
||||
<span>{{ stationInfo.dispatcherRate }}</span>
|
||||
</span>
|
||||
<span class="users">
|
||||
<img :src="userIcon" alt="icon-user" />
|
||||
<span>{{ stationInfo.currentUsers }}</span>
|
||||
/
|
||||
<span>{{ stationInfo.maxUsers }}</span>
|
||||
</span>
|
||||
<span class="spawns">
|
||||
<img :src="spawnIcon" alt="icon-spawn" />
|
||||
<span>{{ stationInfo.spawnString.length }}</span>
|
||||
</span>
|
||||
<span class="schedules">
|
||||
<img :src="timetableIcon" alt="icon-timetable" />
|
||||
<span v-if="stationInfo.scheduledTrains">
|
||||
<span style="color: #eee">{{stationInfo.scheduledTrains.length}}</span>
|
||||
/
|
||||
<span
|
||||
style="color: #bbb"
|
||||
>{{ stationInfo.scheduledTrains.filter(train => train.stopInfo.confirmed).length }}</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="scenery-brief">
|
||||
<img
|
||||
v-if="stationInfo.controlType"
|
||||
:src="require(`@/assets/icon-${stationInfo.controlType}.svg`)"
|
||||
:alt="stationInfo.controlType"
|
||||
:title="'Sterowanie ' + stationInfo.controlType"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="stationInfo.signalType"
|
||||
:src="require(`@/assets/icon-${stationInfo.signalType}.svg`)"
|
||||
:alt="stationInfo.signalType"
|
||||
:title="'Sygnalizacja ' + stationInfo.signalType"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="stationInfo.SBL && stationInfo.SBL !== ''"
|
||||
:src="require(`@/assets/icon-SBL.svg`)"
|
||||
alt="SBL"
|
||||
title="Sceneria posiada SBL na przynajmniej jednym ze szlaków"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="stationInfo.default"
|
||||
:src="require(`@/assets/icon-td2.svg`)"
|
||||
alt="default-pack"
|
||||
title="Sceneria domyślnie dostępna w grze"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="stationInfo.nonPublic || !stationInfo.reqLevel"
|
||||
:src="require(`@/assets/icon-lock.svg`)"
|
||||
alt="non-public"
|
||||
title="Sceneria niepubliczna"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="stationInfo.unavailable"
|
||||
:src="require(`@/assets/icon-unavailable.svg`)"
|
||||
alt="icon-unavailable"
|
||||
title="Sceneria niedostępna"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="scenery-dispatcher">
|
||||
<div>
|
||||
<span
|
||||
class="level"
|
||||
:style="calculateExpStyle(stationInfo.dispatcherExp, stationInfo.dispatcherIsSupporter)"
|
||||
>{{ stationInfo.dispatcherExp > 1 ? stationInfo.dispatcherExp : "L"}}</span>
|
||||
|
||||
<span class="name">{{ stationInfo.dispatcherName }}</span>
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="status"
|
||||
:class="statusClasses(stationInfo.occupiedTo)"
|
||||
>{{ stationInfo.occupiedTo }}</span>
|
||||
</div>
|
||||
|
||||
<div class="scenery-info">
|
||||
<div class="user-list">
|
||||
<h3 class="user-header">
|
||||
GRACZE ONLINE
|
||||
<img :src="userIcon" alt="icon-user" />
|
||||
</h3>
|
||||
<ul>
|
||||
<li
|
||||
class="user user-badge"
|
||||
:class="train.stopStatus"
|
||||
v-for="train in computedStationTrains"
|
||||
:key="train.trainNo + train.driverName"
|
||||
>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'TrainsView',
|
||||
params: { passedSearchedTrain: train.trainNo.toString() },
|
||||
}"
|
||||
>
|
||||
<span>{{ train.trainNo }}</span>
|
||||
|
|
||||
<span>{{ train.driverName }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<span
|
||||
class="user offline"
|
||||
v-if="
|
||||
!stationInfo.stationTrains ||
|
||||
stationInfo.stationTrains.length == 0
|
||||
"
|
||||
>BRAK</span>
|
||||
</div>
|
||||
<div class="spawn-list">
|
||||
<h3 class="spawn-header">
|
||||
OTWARTE SPAWNY
|
||||
<img :src="spawnIcon" alt="icon-spawn" />
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<span
|
||||
class="spawn"
|
||||
v-for="(spawn, i) in stationInfo.spawnString"
|
||||
:key="spawn + stationInfo.dispatcherName + i"
|
||||
>{{ spawn }}</span>
|
||||
</div>
|
||||
<span class="spawn" v-if="!stationInfo.spawnString">BRAK</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="scenery-timetables">
|
||||
<h3 class="timetable-header">
|
||||
<span>AKTYWNE ROZKŁADY JAZDY</span>
|
||||
<a v-if="!timetableOnly" :href="currentURL + '&timetable_only=1'" target="_blank">
|
||||
<img :src="viewIcon" alt="icon-view" title="Wyodrębnij rozkłady jazdy" />
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<span class="timetable-item loading" v-if="timetableDataStatus == 0">Ładowanie...</span>
|
||||
|
||||
<span
|
||||
class="timetable-item empty"
|
||||
v-else-if="computedScheduledTrains.length == 0"
|
||||
>Brak aktywnych rozkładów!</span>
|
||||
|
||||
<div class="timetable-item" v-for="(scheduledTrain, i) in computedScheduledTrains" :key="i">
|
||||
<span class="timetable-general">
|
||||
<span class="general-info">
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'TrainsView',
|
||||
params: {
|
||||
passedSearchedTrain: scheduledTrain.trainNo.toString(),
|
||||
},
|
||||
}"
|
||||
>
|
||||
<span>
|
||||
<strong>{{ scheduledTrain.category }}</strong>
|
||||
{{ scheduledTrain.trainNo }}
|
||||
</span>
|
||||
</router-link>|
|
||||
<span>
|
||||
<a
|
||||
:href="
|
||||
'https://td2.info.pl/profile/?u=' + scheduledTrain.driverId
|
||||
"
|
||||
target="_blank"
|
||||
>{{ scheduledTrain.driverName }}</a>
|
||||
</span>
|
||||
|
||||
<div class="info-route">
|
||||
<strong>{{ scheduledTrain.beginsAt }} - {{ scheduledTrain.terminatesAt }}</strong>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="general-status">
|
||||
<span :class="scheduledTrain.stopStatus">{{scheduledTrain.stopLabel}}</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="timetable-schedule">
|
||||
<span class="schedule-arrival">
|
||||
<span class="arrival-time begins" v-if="scheduledTrain.stopInfo.beginsHere">
|
||||
ROZPOCZYNA
|
||||
<div>BIEG</div>
|
||||
</span>
|
||||
<span class="arrival-time" v-else>
|
||||
{{ scheduledTrain.stopInfo.arrivalTimeString }} ({{
|
||||
scheduledTrain.stopInfo.arrivalDelay
|
||||
}})
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="schedule-stop">
|
||||
<span class="stop-time" v-if="scheduledTrain.stopInfo.stopTime">
|
||||
{{ scheduledTrain.stopInfo.stopTime }}
|
||||
{{ scheduledTrain.stopInfo.stopType }}
|
||||
</span>
|
||||
<span class="stop-arrow arrow"></span>
|
||||
</span>
|
||||
<span class="schedule-departure">
|
||||
<span
|
||||
class="departure-time terminates"
|
||||
v-if="scheduledTrain.stopInfo.terminatesHere"
|
||||
>KOŃCZY BIEG</span>
|
||||
<span class="departure-time" v-else>
|
||||
{{ scheduledTrain.stopInfo.departureTimeString }} ({{
|
||||
scheduledTrain.stopInfo.departureDelay
|
||||
}})
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Watch } from "vue-property-decorator";
|
||||
|
||||
import { Getter } from "vuex-class";
|
||||
|
||||
import styleMixin from "@/mixins/styleMixin";
|
||||
|
||||
import Station from "@/scripts/interfaces/Station";
|
||||
import Train from "@/scripts/interfaces/Train";
|
||||
|
||||
import StationTimetable from "@/components/StationsView/StationTimetable.vue";
|
||||
|
||||
|
||||
@Component
|
||||
export default class SceneryView extends styleMixin {
|
||||
@Getter('getStationList') storeStationList!: Station[];
|
||||
@Getter('getTimetableDataStatus') timetableDataStatus!: number;
|
||||
@Getter('getDataStatus') dataStatus!: number;
|
||||
|
||||
likeIcon: string = require('@/assets/icon-like.svg');
|
||||
spawnIcon: string = require("@/assets/icon-spawn.svg")
|
||||
timetableIcon: string = require("@/assets/icon-timetable.svg")
|
||||
userIcon: string = require("@/assets/icon-user.svg")
|
||||
|
||||
viewIcon: string = require("@/assets/icon-view.svg");
|
||||
|
||||
timetableOnly: boolean = false;
|
||||
|
||||
activated() {
|
||||
this.timetableOnly = this.$route.query['timetable_only'] == "1" ? true : false;
|
||||
}
|
||||
|
||||
get dataLoaded() {
|
||||
return this.storeStationList ? true : false;
|
||||
}
|
||||
|
||||
get currentURL() {
|
||||
return `${location.origin}/scenery?hash=${this.stationInfo?.stationHash}`;
|
||||
}
|
||||
|
||||
get stationInfo(): Station | null {
|
||||
if (!this.$route.query.hash || !this.storeStationList) return null;
|
||||
|
||||
return this.storeStationList.find(station => station.stationHash === this.$route.query.hash.toString()) || null;
|
||||
}
|
||||
|
||||
get computedDispatcherExp(): string {
|
||||
if (!this.stationInfo) return "";
|
||||
|
||||
|
||||
return this.stationInfo.dispatcherExp < 2
|
||||
? "L"
|
||||
: `${this.stationInfo.dispatcherExp}`;
|
||||
}
|
||||
|
||||
get computedStationTrains() {
|
||||
if (!this.stationInfo) return null;
|
||||
|
||||
return this.stationInfo.stationTrains.map(stationTrain => {
|
||||
const scheduledData = this.stationInfo?.scheduledTrains.find(scheduledTrain => scheduledTrain.trainNo === stationTrain.trainNo);
|
||||
|
||||
return {
|
||||
...stationTrain,
|
||||
stopStatus: scheduledData?.stopStatus || "no-timetable"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
get computedScheduledTrains() {
|
||||
return this.stationInfo?.scheduledTrains.sort((a, b) => {
|
||||
if (a.stopInfo.arrivalTimestamp > b.stopInfo.arrivalTimestamp) return 1;
|
||||
else if ((a.stopInfo.arrivalTimestamp < b.stopInfo.arrivalTimestamp)) return -1;
|
||||
|
||||
return a.stopInfo.departureTimestamp > b.stopInfo.departureTimestamp ? 1 : -1;
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../styles/responsive.scss";
|
||||
@import "../styles/variables.scss";
|
||||
@import "../styles/user_badge.scss";
|
||||
|
||||
h3 {
|
||||
margin: 0.5em 0;
|
||||
padding: 0.3em;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-size: 1.2em;
|
||||
|
||||
img {
|
||||
width: 1.1em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.scenery {
|
||||
&-offline {
|
||||
align-self: center;
|
||||
font-size: 2em;
|
||||
text-align: center;
|
||||
|
||||
color: $warningCol;
|
||||
|
||||
button {
|
||||
margin: 1em auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-view {
|
||||
min-height: 100%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
font-size: calc(0.5rem + 0.65vw);
|
||||
|
||||
@include bigScreen() {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
@include smallScreen {
|
||||
font-size: calc(0.5rem + 1vw);
|
||||
}
|
||||
}
|
||||
|
||||
&-wrapper {
|
||||
// background: #555;
|
||||
max-width: 950px;
|
||||
width: 75%;
|
||||
|
||||
@include smallScreen {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
// max-height: 100vh;
|
||||
// overflow: auto;
|
||||
|
||||
background: #333;
|
||||
padding: 1em;
|
||||
margin: 1rem 0;
|
||||
|
||||
border-radius: 1.5em;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-header {
|
||||
padding: 1rem;
|
||||
|
||||
& > .station-name {
|
||||
font-size: 3em;
|
||||
font-weight: bold;
|
||||
color: $accentCol;
|
||||
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
& > .station-hash {
|
||||
font-size: 1em;
|
||||
line-height: 0.8em;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
&-stats {
|
||||
font-size: 1.3em;
|
||||
padding: 1rem 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
& > span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
margin: 0 0.6em;
|
||||
}
|
||||
|
||||
.likes,
|
||||
.spawns {
|
||||
color: $accentCol;
|
||||
}
|
||||
|
||||
span > img {
|
||||
width: 1.2em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
&-brief {
|
||||
padding: 1rem 0;
|
||||
|
||||
img {
|
||||
width: 2.5em;
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-dispatcher {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.level {
|
||||
display: inline-block;
|
||||
margin-right: 0.3em;
|
||||
background: firebrick;
|
||||
|
||||
border-radius: 0.1em;
|
||||
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
line-height: 1.5em;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 1.6em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 1em;
|
||||
border-radius: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
& > .user-list {
|
||||
ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-timetables {
|
||||
margin: 1em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.user {
|
||||
font-size: 0.85em;
|
||||
|
||||
@include smallScreen() {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.spawn,
|
||||
.user.offline {
|
||||
padding: 0.3em 0.4em;
|
||||
background: #585858;
|
||||
|
||||
margin-right: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
|
||||
@include smallScreen() {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.timetable {
|
||||
&-header {
|
||||
a {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
margin: 1em auto;
|
||||
font-size: 0.8em;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
|
||||
|
||||
padding: 0 0.5rem;
|
||||
|
||||
background: #555;
|
||||
|
||||
@include smallScreen() {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.loading,
|
||||
&.empty {
|
||||
padding: 1rem;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
&.empty {
|
||||
color: $accentCol;
|
||||
}
|
||||
}
|
||||
|
||||
&-general {
|
||||
padding: 0.5rem 0.3rem;
|
||||
border-radius: 10px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
text-align: left;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
@include smallScreen() {
|
||||
width: 95%;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
&-schedule {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(50px, 1fr));
|
||||
font-size: 1.2em;
|
||||
|
||||
@include smallScreen() {
|
||||
width: 100%;
|
||||
margin: 0.7em 0;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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-info {
|
||||
span {
|
||||
color: $accentCol;
|
||||
}
|
||||
|
||||
.info-route {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.general-status {
|
||||
span.arriving {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
span.departed {
|
||||
color: lime;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.stopped {
|
||||
color: #ffa600;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.online {
|
||||
color: gold;
|
||||
}
|
||||
|
||||
span.terminated {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.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>
|
||||
Reference in New Issue
Block a user