Dodano informacje o poc. offline

This commit is contained in:
2022-06-29 00:19:17 +02:00
parent 4e80e73949
commit 01a03622fb
8 changed files with 147 additions and 119 deletions
+7 -1
View File
@@ -37,7 +37,7 @@
<img src="@/assets/icon-dispatcher.svg" alt="icon dispatcher" /> <img src="@/assets/icon-dispatcher.svg" alt="icon dispatcher" />
<span class="text--primary">{{ onlineDispatchers.length }}</span> <span class="text--primary">{{ onlineDispatchers.length }}</span>
<span class="text--grayed"> / </span> <span class="text--grayed"> / </span>
<span class="text--primary">{{ store.trainList.length }}</span> <span class="text--primary">{{ trainList.length }}</span>
<img src="@/assets/icon-train.svg" alt="icon train" /> <img src="@/assets/icon-train.svg" alt="icon train" />
</div> </div>
@@ -125,6 +125,12 @@ export default defineComponent({
}; };
}, },
computed: {
trainList() {
return this.store.trainList.filter(train => train.online);
}
},
data: () => ({ data: () => ({
VERSION: packageInfo.version, VERSION: packageInfo.version,
updateModalVisible: false, updateModalVisible: false,
@@ -3,7 +3,8 @@
<h3 class="user-header section-header"> <h3 class="user-header section-header">
<img :src="icons.user" alt="icon-user" /> <img :src="icons.user" alt="icon-user" />
&nbsp;{{ $t('scenery.users') }} &nbsp; &nbsp;{{ $t('scenery.users') }} &nbsp;
<span class="text--primary">{{ station.onlineInfo?.currentUsers || '0' }}</span>&nbsp;/&nbsp;<span class="text--primary">{{ station.onlineInfo?.maxUsers || '0' }}</span> <span class="text--primary">{{ station.onlineInfo?.currentUsers || '0' }}</span
>&nbsp;/&nbsp;<span class="text--primary">{{ station.onlineInfo?.maxUsers || '0' }}</span>
</h3> </h3>
<div <div
@@ -41,7 +42,7 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const computedStationTrains= computed(() => { const computedStationTrains = computed(() => {
if (!props.station) return []; if (!props.station) return [];
const station = props.station as Station; const station = props.station as Station;
@@ -49,9 +50,7 @@ export default defineComponent({
if (!station.onlineInfo.stationTrains) return []; if (!station.onlineInfo.stationTrains) return [];
return station.onlineInfo.stationTrains.map((train) => { return station.onlineInfo.stationTrains.map((train) => {
const scheduledTrainStatus = station.onlineInfo?.scheduledTrains?.find( const scheduledTrainStatus = station.onlineInfo?.scheduledTrains?.find((st) => st.trainNo === train.trainNo);
(st) => st.trainNo === train.trainNo
);
return { return {
...train, ...train,
+4
View File
@@ -61,6 +61,10 @@
</span> </span>
</div> </div>
<div v-if="!train.online" style="color: salmon">
Offline - {{ lastSeenMessage(train.lastSeen) }}
</div>
<div class="driver_position text--grayed" style="margin-top: 0.25em"> <div class="driver_position text--grayed" style="margin-top: 0.25em">
<span v-if="train.currentStationHash"> <span v-if="train.currentStationHash">
{{ $t('trains.current-scenery') }} <span>{{ train['currentStationName'] }}&nbsp;</span> {{ $t('trains.current-scenery') }} <span>{{ train['currentStationName'] }}&nbsp;</span>
+5 -1
View File
@@ -181,7 +181,11 @@
"loco-diesel": "Diesel locomotive", "loco-diesel": "Diesel locomotive",
"timetable-comments": "Exploitation comments available for this train", "timetable-comments": "Exploitation comments available for this train",
"comment": "Exploitation comments for: ", "comment": "Exploitation comments for: ",
"table-limit": "For performance reasons there's a limit of 10 trains shown at the same time." "table-limit": "For performance reasons there's a limit of 10 trains shown at the same time.",
"last-seen-now": "last seen: just now",
"last-seen-min": "last seen: one minute ago",
"last-seen-ago": "last seen: {minutes} mins ago"
}, },
"journal": { "journal": {
"title": "DISPATCHER HISTORY", "title": "DISPATCHER HISTORY",
+5 -2
View File
@@ -161,7 +161,6 @@
"filter-noTimetable": "bez RJ", "filter-noTimetable": "bez RJ",
"filter-reset": "X RESETUJ", "filter-reset": "X RESETUJ",
"sorter-prefix": "Sortuj: ", "sorter-prefix": "Sortuj: ",
"search-train": "Numer pociągu", "search-train": "Numer pociągu",
"search-driver": "Nick maszynisty", "search-driver": "Nick maszynisty",
@@ -183,7 +182,11 @@
"loco-diesel": "Spalinowóz", "loco-diesel": "Spalinowóz",
"timetable-comments": "Pociąg z uwagami eksploatacyjnymi", "timetable-comments": "Pociąg z uwagami eksploatacyjnymi",
"comment": "Uwagi eksploatacyjne dla: ", "comment": "Uwagi eksploatacyjne dla: ",
"table-limit": "Dla płynności działania strony pokazanych jest tylko 10 pociągów zgodnie z wybranymi filtrami." "table-limit": "Dla płynności działania strony pokazanych jest tylko 10 pociągów zgodnie z wybranymi filtrami.",
"last-seen-now": "ostatnio widziany: przed chwilą",
"last-seen-min": "ostatnio widziany: minutę temu",
"last-seen-ago": "ostatnio widziany: {minutes} min. temu"
}, },
"journal": { "journal": {
"title": "HISTORIA DYŻURÓW", "title": "HISTORIA DYŻURÓW",
+115 -104
View File
@@ -1,117 +1,128 @@
import Train from "@/scripts/interfaces/Train"; import Train from '@/scripts/interfaces/Train';
import TrainStop from "@/scripts/interfaces/TrainStop"; import TrainStop from '@/scripts/interfaces/TrainStop';
import { defineComponent } from "vue"; import { defineComponent } from 'vue';
export default defineComponent({ export default defineComponent({
data: () => ({ data: () => ({
STATS: { STATS: {
main: [ main: [
{ {
name: 'speed', name: 'speed',
unit: 'km/h', unit: 'km/h',
},
{
name: 'length',
unit: 'm',
},
{
name: 'mass',
unit: 't',
multiplier: 0.001,
},
],
position: [
{
name: 'scenery',
prop: 'currentStationName',
},
{
name: 'route',
prop: 'connectedTrack',
},
{
name: 'signal',
prop: 'signal',
},
{
name: 'distance',
prop: 'distance',
unit: 'm',
},
],
}, },
}), {
name: 'length',
methods: { unit: 'm',
displayStopList(stops: TrainStop[]): string | undefined {
if (!stops) return '';
return stops
.reduce((acc: string[], stop: TrainStop, i: number) => {
if (stop.stopType.includes('ph') && !stop.stopNameRAW.includes('po.'))
acc.push(`<strong style='color:${stop.confirmed ? 'springgreen' : 'white'}'>${stop.stopName}</strong>`);
else if (
i > 0 &&
i < stops.length - 1 &&
!stop.stopNameRAW.includes('po.') &&
!stop.stopNameRAW.includes('SBL')
)
acc.push(`<span style='color:${stop.confirmed ? 'springgreen' : 'lightgray'}'>${stop.stopName}</span>`);
return acc;
}, [])
.join(' > ');
}, },
{
currentDistance(stops: TrainStop[]) { name: 'mass',
return stops.filter(stop => stop.confirmed).slice(-1)[0]?.stopDistance || 0; unit: 't',
multiplier: 0.001,
}, },
],
confirmedPercentage(stops: TrainStop[]) { position: [
return Number(((stops.filter((stop) => stop.confirmed).length / stops.length) * 100).toFixed(0)); {
name: 'scenery',
prop: 'currentStationName',
}, },
{
currentDelay(stops: TrainStop[]) { name: 'route',
const delay = prop: 'connectedTrack',
stops.find((stop, i) => (i == 0 && !stop.confirmed) || (i > 0 && stops[i - 1].confirmed && !stop.confirmed))
?.departureDelay || 0;
if (delay > 0) return `<span style='color: salmon'>${this.$t('trains.delayed')} ${delay} min</span>`;
else if (delay < 0) return `<span style='color: lightgreen'>${this.$t('trains.preponed')} ${delay} min</span>`;
else return this.$t('trains.on-time');
}, },
{
displayLocoInfo(locoType: string) { name: 'signal',
if (locoType.includes('EN')) return `${this.$t('trains.EZT')}`; prop: 'signal',
if (locoType.includes('SN')) return `${this.$t('trains.SZT')}`;
if (locoType.startsWith('E')) return `${this.$t('trains.loco-electric')}`;
if (locoType.startsWith('S')) return `${this.$t('trains.loco-diesel')}`;
return '';
}, },
{
getSceneriesWithComments(timetableData: Train['timetableData']) { name: 'distance',
const commentList = timetableData?.followingStops.reduce((acc, stop, i) => { prop: 'distance',
if (stop.comments) acc.push(stop.stopNameRAW); unit: 'm',
return acc;
}, [] as string[]) || []
const moreCount = commentList.length - 10;
return commentList.slice(0, 10).join(", ") + (moreCount > 0 ? `... (+${moreCount})` : '');
}, },
],
},
}),
displayDistance(distance: number) { methods: {
if (distance < 1000) return `${distance}m`; lastSeenMessage(timestamp: number) {
const diff = Date.now() - timestamp;
const diffMins = Math.floor(diff / 60000);
return `${(distance / 1000).toPrecision(2)}km`; return diffMins < 1
}, ? this.$t('trains.last-seen-now')
: diffMins < 2
? this.$t('trains.last-seen-min')
: this.$t('trains.last-seen-ago', { minutes: diffMins });
},
onImageError(e: Event) { displayStopList(stops: TrainStop[]): string | undefined {
const imageEl = e.target as HTMLImageElement; if (!stops) return '';
imageEl.src = require('@/assets/unknown.png');
} return stops
} .reduce((acc: string[], stop: TrainStop, i: number) => {
}) if (stop.stopType.includes('ph') && !stop.stopNameRAW.includes('po.'))
acc.push(`<strong style='color:${stop.confirmed ? 'springgreen' : 'white'}'>${stop.stopName}</strong>`);
else if (
i > 0 &&
i < stops.length - 1 &&
!stop.stopNameRAW.includes('po.') &&
!stop.stopNameRAW.includes('SBL')
)
acc.push(`<span style='color:${stop.confirmed ? 'springgreen' : 'lightgray'}'>${stop.stopName}</span>`);
return acc;
}, [])
.join(' > ');
},
currentDistance(stops: TrainStop[]) {
return stops.filter((stop) => stop.confirmed).slice(-1)[0]?.stopDistance || 0;
},
confirmedPercentage(stops: TrainStop[]) {
return Number(((stops.filter((stop) => stop.confirmed).length / stops.length) * 100).toFixed(0));
},
currentDelay(stops: TrainStop[]) {
const delay =
stops.find((stop, i) => (i == 0 && !stop.confirmed) || (i > 0 && stops[i - 1].confirmed && !stop.confirmed))
?.departureDelay || 0;
if (delay > 0) return `<span style='color: salmon'>${this.$t('trains.delayed')} ${delay} min</span>`;
else if (delay < 0) return `<span style='color: lightgreen'>${this.$t('trains.preponed')} ${delay} min</span>`;
else return this.$t('trains.on-time');
},
displayLocoInfo(locoType: string) {
if (locoType.includes('EN')) return `${this.$t('trains.EZT')}`;
if (locoType.includes('SN')) return `${this.$t('trains.SZT')}`;
if (locoType.startsWith('E')) return `${this.$t('trains.loco-electric')}`;
if (locoType.startsWith('S')) return `${this.$t('trains.loco-diesel')}`;
return '';
},
getSceneriesWithComments(timetableData: Train['timetableData']) {
const commentList =
timetableData?.followingStops.reduce((acc, stop, i) => {
if (stop.comments) acc.push(stop.stopNameRAW);
return acc;
}, [] as string[]) || [];
const moreCount = commentList.length - 10;
return commentList.slice(0, 10).join(', ') + (moreCount > 0 ? `... (+${moreCount})` : '');
},
displayDistance(distance: number) {
if (distance < 1000) return `${distance}m`;
return `${(distance / 1000).toPrecision(2)}km`;
},
onImageError(e: Event) {
const imageEl = e.target as HTMLImageElement;
imageEl.src = require('@/assets/unknown.png');
},
},
});
+1
View File
@@ -15,6 +15,7 @@ export default interface Train {
locoURL: string; locoURL: string;
locoType: string; locoType: string;
online: boolean; online: boolean;
lastSeen: number;
region: string; region: string;
cars: string[]; cars: string[];
+6 -6
View File
@@ -1,11 +1,8 @@
import { DataStatus } from '@/scripts/enums/DataStatus'; import { DataStatus } from '@/scripts/enums/DataStatus';
import { DispatcherStatsAPIData } from '@/scripts/interfaces/api/DispatcherStatsAPIData';
import StationAPIData from '@/scripts/interfaces/api/StationAPIData'; import StationAPIData from '@/scripts/interfaces/api/StationAPIData';
import TrainAPIData from '@/scripts/interfaces/api/TrainAPIData';
import ScheduledTrain from '@/scripts/interfaces/ScheduledTrain'; import ScheduledTrain from '@/scripts/interfaces/ScheduledTrain';
import Station from '@/scripts/interfaces/Station'; import Station from '@/scripts/interfaces/Station';
import StationRoutes from '@/scripts/interfaces/StationRoutes'; import StationRoutes from '@/scripts/interfaces/StationRoutes';
import { StoreData } from '@/scripts/interfaces/StoreData';
import Train from '@/scripts/interfaces/Train'; import Train from '@/scripts/interfaces/Train';
import { URLs } from '@/scripts/utils/apiURLs'; import { URLs } from '@/scripts/utils/apiURLs';
import { import {
@@ -62,7 +59,10 @@ export const useStore = defineStore('store', {
if (!trains) return []; if (!trains) return [];
this.trainList = trains this.trainList = trains
.filter((train) => train.region === this.region.id) .filter(
(train) =>
train.region === this.region.id && (train.online || train.timetable || train.lastSeen > Date.now() - 180000)
)
.map((train) => { .map((train) => {
const stock = train.stockString.split(';'); const stock = train.stockString.split(';');
const locoType = stock ? stock[0] : train.stockString; const locoType = stock ? stock[0] : train.stockString;
@@ -88,6 +88,8 @@ export const useStore = defineStore('store', {
locoURL: getLocoURL(locoType), locoURL: getLocoURL(locoType),
cars: stock.slice(1), cars: stock.slice(1),
lastSeen: train.lastSeen,
timetableData: timetable timetableData: timetable
? { ? {
timetableId: timetable.timetableId, timetableId: timetable.timetableId,
@@ -206,7 +208,6 @@ export const useStore = defineStore('store', {
const prevDispatcherStatuses: StoreState['lastDispatcherStatuses'] = []; const prevDispatcherStatuses: StoreState['lastDispatcherStatuses'] = [];
this.apiData.stations?.forEach((stationAPIData) => { this.apiData.stations?.forEach((stationAPIData) => {
if (stationAPIData.region !== this.region.id || !stationAPIData.isOnline) return; if (stationAPIData.region !== this.region.id || !stationAPIData.isOnline) return;
const station = this.stationList.find((s) => s.name === stationAPIData.stationName); const station = this.stationList.find((s) => s.name === stationAPIData.stationName);
@@ -345,7 +346,6 @@ export const useStore = defineStore('store', {
this.setOnlineData(); this.setOnlineData();
console.log(data); console.log(data);
}); });
socket.emit('FETCH_DATA', {}, (data: APIData) => { socket.emit('FETCH_DATA', {}, (data: APIData) => {