poprawki do braku pokazywania się niezapisanych scenerii

This commit is contained in:
2023-12-07 16:16:06 +01:00
parent 188857d335
commit 0dc2c505db
14 changed files with 10678 additions and 85 deletions
-1
View File
@@ -74,7 +74,6 @@ export default defineComponent({
this.store.activeData.activeSceneries = [];
this.store.activeData.trains = [];
this.store.activeData.connectedSocketCount = 0;
this.store.setStatuses();
});
@@ -33,6 +33,8 @@
>
{{ historyItem.dispatcherLevel >= 2 ? historyItem.dispatcherLevel : 'L' }}
</b>
<b v-else>?</b>
</td>
<td class="text--primary">
<b>{{ historyItem.dispatcherRate }}</b>
@@ -84,12 +86,10 @@ export default defineComponent({
components: { Loading },
props: {
station: {
type: Object as PropType<Station>,
required: true
type: Object as PropType<Station>
},
onlineScenery: {
type: Object as PropType<OnlineScenery>,
required: false
type: Object as PropType<OnlineScenery>
}
},
@@ -113,10 +113,17 @@ export default defineComponent({
countFrom = 0,
countLimit = 30
): Promise<API.DispatcherHistory.Response | null> {
if (!this.station && !this.onlineScenery) {
this.dataStatus = Status.Data.Loaded;
return null;
}
try {
this.dataStatus = Status.Data.Loading;
const requestString = `${URLs.stacjownikAPI}/api/getDispatchers?stationName=${this.station.name}&countFrom=${countFrom}&countLimit=${countLimit}`;
const requestString = `${URLs.stacjownikAPI}/api/getDispatchers?stationName=${
this.station?.name || this.onlineScenery?.name
}&countFrom=${countFrom}&countLimit=${countLimit}`;
const historyAPIData: API.DispatcherHistory.Response = await (
await axios.get(requestString)
).data;
@@ -130,7 +137,9 @@ export default defineComponent({
}
},
navigateToHistory() {
this.$router.push(`/journal/dispatchers?sceneryName=${this.station.name}`);
this.$router.push(
`/journal/dispatchers?sceneryName=${this.station?.name || this.onlineScenery?.name}`
);
}
}
});
+10 -8
View File
@@ -1,11 +1,11 @@
<template>
<section class="info-header">
<a class="scenery-name" :href="station.generalInfo?.url" target="_blank">
{{ station.name }}
<a class="scenery-name" :href="station?.generalInfo?.url" target="_blank">
{{ stationName.replace(/_/g, ' ') }}
</a>
<div class="scenery-abbrev">
{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo?.abbr }}</b>
<div class="scenery-abbrev" v-if="station?.generalInfo?.abbr">
{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo.abbr }}</b>
</div>
<div class="scenery-hash" v-if="onlineScenery?.hash">#{{ onlineScenery.hash }}</div>
@@ -20,13 +20,16 @@ import { OnlineScenery } from '../../store/typings';
export default defineComponent({
props: {
station: {
type: Object as PropType<Station>,
type: Object as PropType<Station>
},
stationName: {
type: String,
required: true
},
onlineScenery: {
type: Object as PropType<OnlineScenery>,
required: false
type: Object as PropType<OnlineScenery>
}
}
});
@@ -58,4 +61,3 @@ export default defineComponent({
font-size: 1.2em;
}
</style>
../../store/storeTypes
+6 -8
View File
@@ -1,10 +1,10 @@
<template>
<div class="scenery-info">
<section>
<div class="scenery-info-general" v-if="station.generalInfo">
<div class="scenery-info-general">
<SceneryInfoIcons :station="station" />
<div class="scenery-general-list">
<div class="scenery-general-list" v-if="station?.generalInfo">
<span>
<b>{{ $t('availability.title') }}:</b>
{{ $t(`availability.${station.generalInfo.availability}`) }}
@@ -46,11 +46,11 @@
</span>
</div>
<SceneryInfoRoutes :station="station" />
<SceneryInfoRoutes v-if="station" :station="station" />
<div
class="scenery-authors"
v-if="station.generalInfo.authors && station.generalInfo.authors.length > 0"
v-if="station?.generalInfo?.authors && station.generalInfo.authors.length > 0"
>
<b>
{{
@@ -102,13 +102,11 @@ export default defineComponent({
},
props: {
station: {
type: Object as PropType<Station>,
required: true
type: Object as PropType<Station>
},
onlineScenery: {
type: Object as PropType<OnlineScenery>,
required: false
type: Object as PropType<OnlineScenery>
}
}
});
@@ -1,24 +1,33 @@
<template>
<section class="info-icons">
<span
v-if="station.generalInfo && station.generalInfo.reqLevel >= 0"
class="scenery-icon icon-info level"
:style="calculateExpStyle(station.generalInfo.reqLevel)"
>
{{ station.generalInfo.reqLevel >= 2 ? station.generalInfo.reqLevel : 'L' }}
<span v-if="!station || !station.generalInfo">
<img
class="icon-info"
src="/images/icon-unknown.svg"
alt="icon-unknown"
:title="$t('desc.unknown')"
/>
</span>
<span
v-if="station.generalInfo"
v-if="station?.generalInfo && station?.generalInfo.reqLevel >= 0"
class="scenery-icon icon-info level"
:style="calculateExpStyle(station?.generalInfo.reqLevel)"
>
{{ station?.generalInfo.reqLevel >= 2 ? station?.generalInfo.reqLevel : 'L' }}
</span>
<span
v-if="station?.generalInfo"
class="scenery-icon icon-info"
:class="station.generalInfo.controlType.replace('+', '-')"
:title="$t('desc.control-type') + $t(`controls.${station.generalInfo.controlType}`)"
v-html="getControlTypeAbbrev(station.generalInfo.controlType)"
:class="station?.generalInfo.controlType.replace('+', '-')"
:title="$t('desc.control-type') + $t(`controls.${station?.generalInfo.controlType}`)"
v-html="getControlTypeAbbrev(station?.generalInfo.controlType)"
>
</span>
<img
v-if="station.generalInfo?.SUP"
v-if="station?.generalInfo?.SUP"
class="icon-info"
src="/images/icon-SUP.svg"
alt="SUP (RASP-UZK)"
@@ -26,7 +35,7 @@
/>
<img
v-if="station.generalInfo?.signalType"
v-if="station?.generalInfo?.signalType"
class="icon-info"
:src="`/images/icon-${station.generalInfo.signalType}.svg`"
:alt="station.generalInfo.signalType"
@@ -34,7 +43,7 @@
/>
<img
v-if="station.generalInfo?.availability == 'nonPublic'"
v-if="station?.generalInfo?.availability == 'nonPublic'"
class="icon-info"
src="/images/icon-lock.svg"
alt="Non-public scenery"
@@ -42,7 +51,7 @@
/>
<img
v-if="station.generalInfo?.availability == 'unavailable'"
v-if="station?.generalInfo?.availability == 'unavailable'"
class="icon-info"
src="/images/icon-unavailable.svg"
alt="Unavailable scenery"
@@ -50,7 +59,7 @@
/>
<img
v-if="station.generalInfo?.availability == 'abandoned'"
v-if="station?.generalInfo?.availability == 'abandoned'"
class="icon-info"
src="/images/icon-abandoned.svg"
alt="Abandoned scenery"
@@ -58,20 +67,12 @@
/>
<img
v-if="station.generalInfo?.lines"
v-if="station?.generalInfo?.lines"
class="icon-info"
src="/images/icon-real.svg"
alt="real scenery"
:title="`${$t('desc.real')} ${station.generalInfo.lines}`"
/>
<img
v-if="!station.generalInfo"
class="icon-info"
src="/images/icon-unknown.svg"
alt="icon-unknown"
:title="$t('desc.unknown')"
/>
</section>
</template>
@@ -85,8 +86,7 @@ export default defineComponent({
mixins: [stationInfoMixin, styleMixin],
props: {
station: {
type: Object as PropType<Station>,
required: true
type: Object as PropType<Station>
}
}
});
@@ -13,7 +13,7 @@
</span>
</span>
<span class="header_links">
<span class="header_links" v-if="station">
<a
:href="`https://pragotron-td2.web.app/board?name=${station.name}`"
target="_blank"
@@ -201,12 +201,10 @@ export default defineComponent({
props: {
station: {
type: Object as PropType<Station>,
required: true
type: Object as PropType<Station>
},
onlineScenery: {
type: Object as PropType<OnlineScenery>,
required: false
type: Object as PropType<OnlineScenery>
}
},
@@ -243,19 +241,21 @@ export default defineComponent({
computed: {
tabliceZbiorczeHref() {
let url = `https://tablice-td2.web.app/?station=${this.station.name}`;
let url = `https://tablice-td2.web.app/?station=${this.station!.name}`;
if (this.chosenCheckpoint) url += `&checkpoint=${this.chosenCheckpoint}`;
return url;
},
computedScheduledTrains() {
if (!this.station) return [];
return (
this.onlineScenery?.scheduledTrains
?.filter(
(train) =>
train.checkpointName.toLocaleLowerCase() ==
(this.chosenCheckpoint || this.station.name).toLocaleLowerCase() &&
(this.chosenCheckpoint || this.station!.name).toLocaleLowerCase() &&
train.region == this.store.region.id
)
.sort((a, b) => {
@@ -273,6 +273,8 @@ export default defineComponent({
methods: {
loadSelectedOption() {
if (!this.station) return;
this.chosenCheckpoint =
this.station.generalInfo?.checkpoints[0]?.checkpointName || this.station.name;
},
@@ -80,12 +80,10 @@ export default defineComponent({
mixins: [dateMixin, listObserverMixin],
props: {
station: {
type: Object as PropType<Station>,
required: true
type: Object as PropType<Station>
},
onlineScenery: {
type: Object as PropType<OnlineScenery>,
required: false
type: Object as PropType<OnlineScenery>
}
},
@@ -103,8 +101,15 @@ export default defineComponent({
methods: {
async fetchAPIData(countFrom = 0, countLimit = 15) {
if (!this.station && !this.onlineScenery) {
this.dataStatus = Status.Data.Loaded;
return;
}
try {
const requestString = `${URLs.stacjownikAPI}/api/getTimetables?issuedFrom=${this.station.name}&countFrom=${countFrom}&countLimit=${countLimit}`;
const requestString = `${URLs.stacjownikAPI}/api/getTimetables?issuedFrom=${
this.station?.name || this.onlineScenery?.name
}&countFrom=${countFrom}&countLimit=${countLimit}`;
const response: API.TimetableHistory.Response = await (await axios.get(requestString)).data;
@@ -117,7 +122,9 @@ export default defineComponent({
},
navigateToHistory() {
this.$router.push(`/journal/timetables?issuedFrom=${this.station.name}`);
this.$router.push(
`/journal/timetables?issuedFrom=${this.station?.name || this.onlineScenery?.name}`
);
}
},
components: { Loading }
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -405,8 +405,8 @@
"two-way-routes": "Two way routes",
"option-active-timetables": "Active timetables",
"option-timetables-history": "Timetables history",
"option-dispatchers-history": "Dispatchers history",
"option-timetables-history": "Timetables history PL1",
"option-dispatchers-history": "Dispatchers history PL1",
"timetable-author-title": "Issued by",
"timetable-author-unknown": "Author unknown",
+2 -2
View File
@@ -386,8 +386,8 @@
"two-way-routes": "Szlaki dwutorowe",
"option-active-timetables": "Aktywne rozkłady jazdy",
"option-timetables-history": "Historia rozkładów",
"option-dispatchers-history": "Historia dyżurów",
"option-timetables-history": "Historia rozkładów PL1",
"option-dispatchers-history": "Historia dyżurów PL1",
"timetable-author-title": "Wydany przez",
"timetable-author-unknown": "Autor nieznany",
+90 -4
View File
@@ -86,7 +86,7 @@ export const useStore = defineStore('store', {
distance: train.distance,
signal: train.signal,
online: train.online,
online: Boolean(train.online),
driverId: train.driverId,
driverName: train.driverName,
currentStationName: train.currentStationName,
@@ -183,6 +183,91 @@ export const useStore = defineStore('store', {
}
},
actions: {
async processStationsOnlineInfo() {
if (!this.activeData.activeSceneries) return;
const onlineSceneries = this.activeData.activeSceneries.reduce((acc, scenery) => {
const savedStation = this.stationList.find((st) => scenery.stationName === st.name);
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 2) return acc;
if (scenery.dispatcherStatus == Status.ActiveDispatcher.UNKNOWN) return acc;
const station = this.stationList.find((s) => s.name === scenery.stationName);
const scheduledTrains = getScheduledTrains(this.trainList, scenery, station?.generalInfo);
const stationTrains = getStationTrains(
this.trainList,
scheduledTrains,
this.region.id,
scenery
);
// Remove checkpoint duplicates
const uniqueScheduledTrains = scheduledTrains.reduce(
(uniqueList, sTrain) =>
uniqueList.find((v) => v.trainId === sTrain.trainId)
? uniqueList
: [...uniqueList, sTrain],
[] as ScheduledTrain[]
);
const dispatcherTimestamp =
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT
? Date.now() + 25500000
: scenery.dispatcherStatus > 5
? scenery.dispatcherStatus
: null;
const onlineInfo = {
name: scenery.stationName,
hash: scenery.stationHash,
region: scenery.region,
maxUsers: scenery.maxUsers,
currentUsers: scenery.currentUsers,
spawns: parseSpawns(scenery.spawnString),
dispatcherName: scenery.dispatcherName,
dispatcherRate: scenery.dispatcherRate,
dispatcherId: scenery.dispatcherId,
dispatcherExp: scenery.dispatcherExp,
dispatcherIsSupporter: scenery.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
dispatcherStatus: scenery.dispatcherStatus,
dispatcherTimestamp: dispatcherTimestamp,
isOnline: scenery.isOnline == 1,
scheduledTrainCount: {
all: uniqueScheduledTrains.length,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length
}
};
if (savedStation) savedStation.onlineInfo = onlineInfo;
else
this.stationList.push({
name: onlineInfo.name,
onlineInfo: onlineInfo
});
acc.push(onlineInfo);
return acc;
}, [] as OnlineScenery[]);
// Reset online info of already offline sceneries
this.stationList
.filter(
(station) =>
station.onlineInfo &&
onlineSceneries.findIndex(
(os) => os.region == station.onlineInfo!.region && station.name == os.name
) != -1
)
.forEach((station) => (station.onlineInfo = undefined));
},
async fetchStationsGeneralInfo() {
const sceneryData: StationJSONData[] = await (
await axios.get(`${URLs.stacjownikAPI}/api/getSceneries`)
@@ -245,10 +330,10 @@ export const useStore = defineStore('store', {
},
async fetchActiveData() {
if (import.meta.env.VITE_APP_WS_DEV === '1') {
const mockWebsocketData = await import('../data/mockWebsocketData.json');
if (import.meta.env.VITE_APP_API_MODE === 'mock') {
const mockActiveData = await import('../data/mockActiveData.json');
this.dataStatuses.connection = Status.Data.Loaded;
this.activeData = mockWebsocketData as any;
this.activeData = mockActiveData;
this.setStatuses();
console.warn('Stacjownik działa w trybie mockowania danych z WS');
@@ -263,6 +348,7 @@ export const useStore = defineStore('store', {
this.activeData = data;
this.dataStatuses.connection = Status.Data.Loaded;
this.setStatuses();
} catch (error) {
this.dataStatuses.connection = Status.Data.Error;
+14 -2
View File
@@ -71,13 +71,25 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
filteredStationList: (state) => {
const store = useStore();
return store.stationList
.map((station) => ({
const savedStationNames = store.stationList.map((s) => s.name);
const onlineUnsavedStations = store.onlineSceneryList
.filter((os) => !savedStationNames.includes(os.name) && os.region == store.region.id)
.map((os) => ({
name: os.name,
generalInfo: undefined,
onlineInfo: os
}));
return [
...onlineUnsavedStations,
...store.stationList.map((station) => ({
...station,
onlineInfo: store.onlineSceneryList.find(
(os) => os.name == station.name && os.region == store.region.id
)
}))
]
.filter((station) => filterStations(station, state.filters))
.sort((a, b) => sortStations(a, b, state.sorterActive));
}
+8 -9
View File
@@ -5,7 +5,6 @@ export namespace API {
export interface Response {
activeSceneries?: API.ActiveSceneries.Response;
trains?: API.ActiveTrains.Response;
connectedSocketCount: number;
}
}
export namespace DispatcherHistory {
@@ -123,9 +122,9 @@ export namespace API {
driverLevel?: number;
currentStationName: string;
currentStationHash: string;
currentStationHash?: string;
online: boolean;
online: number;
lastSeen: number;
region: string;
@@ -139,16 +138,16 @@ export namespace API {
stopNameRAW: string;
stopType: string;
stopDistance: number;
pointId: number;
pointId: string;
mainStop: boolean;
arrivalLine: string;
arrivalLine: string | null;
arrivalTimestamp: number;
arrivalRealTimestamp: number;
arrivalDelay: number;
departureLine: string;
departureLine: string | null;
departureTimestamp: number;
departureRealTimestamp: number;
departureDelay: number;
@@ -157,9 +156,9 @@ export namespace API {
beginsHere: boolean;
terminatesHere: boolean;
confirmed: boolean;
stopped: boolean;
stopTime: number;
confirmed: number;
stopped: number;
stopTime: number | null;
}
export interface Timetable {
+11 -4
View File
@@ -1,14 +1,17 @@
<template>
<div class="scenery-view">
<div class="scenery-offline" v-if="!stationInfo && store.dataStatuses.sceneries == 2">
<!-- <div
class="scenery-offline"
v-if="!stationInfo && !onlineSceneryInfo && store.dataStatuses.sceneries == 2"
>
<div>{{ $t('scenery.no-scenery') }}</div>
<action-button>
<router-link to="/">{{ $t('scenery.return-btn') }}</router-link>
</action-button>
</div>
</div> -->
<div class="scenery-wrapper" v-if="stationInfo" ref="card-wrapper">
<div class="scenery-wrapper" ref="card-wrapper">
<div class="scenery-left">
<div class="scenery-actions">
<button class="back-btn btn" :title="$t('scenery.return-btn')" @click="navigateTo('/')">
@@ -16,7 +19,11 @@
</button>
</div>
<SceneryHeader :station="stationInfo" :onlineScenery="onlineSceneryInfo" />
<SceneryHeader
:stationName="station"
:station="stationInfo"
:onlineScenery="onlineSceneryInfo"
/>
<SceneryInfo :station="stationInfo" :onlineScenery="onlineSceneryInfo" />
</div>