mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-04 05:48:11 +00:00
rework reaktywności danych z API i WS
This commit is contained in:
+6
-32
@@ -32,20 +32,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, provide, ref, watch } from 'vue';
|
import { defineComponent, watch } from 'vue';
|
||||||
|
|
||||||
import Clock from './components/App/Clock.vue';
|
import Clock from './components/App/Clock.vue';
|
||||||
|
|
||||||
import packageInfo from '.././package.json';
|
import packageInfo from '.././package.json';
|
||||||
|
|
||||||
|
import { useStore } from './store/store';
|
||||||
import StatusIndicator from './components/App/StatusIndicator.vue';
|
import StatusIndicator from './components/App/StatusIndicator.vue';
|
||||||
import SelectBox from './components/Global/SelectBox.vue';
|
import SelectBox from './components/Global/SelectBox.vue';
|
||||||
import { useStore } from './store/store';
|
|
||||||
import TrainModal from './components/Global/TrainModal.vue';
|
import TrainModal from './components/Global/TrainModal.vue';
|
||||||
import StorageManager from './scripts/managers/storageManager';
|
import StorageManager from './scripts/managers/storageManager';
|
||||||
import AppHeader from './components/App/AppHeader.vue';
|
import AppHeader from './components/App/AppHeader.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useCustomSW from './mixins/useCustomSW';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@@ -56,31 +55,9 @@ export default defineComponent({
|
|||||||
AppHeader
|
AppHeader
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
|
||||||
const store = useStore();
|
|
||||||
store.connectToAPI();
|
|
||||||
|
|
||||||
useCustomSW();
|
|
||||||
|
|
||||||
const isFilterCardVisible = ref(false);
|
|
||||||
|
|
||||||
provide('isFilterCardVisible', isFilterCardVisible);
|
|
||||||
|
|
||||||
return {
|
|
||||||
store,
|
|
||||||
isFilterCardVisible,
|
|
||||||
onlineDispatchers: computed(() =>
|
|
||||||
store.stationList.filter(
|
|
||||||
(station) => station.onlineInfo && station.onlineInfo.region == store.region.id
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
dispatcherDataStatus: store.dataStatuses.dispatchers
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
VERSION: packageInfo.version,
|
VERSION: packageInfo.version,
|
||||||
|
store: useStore(),
|
||||||
|
|
||||||
currentLang: 'pl',
|
currentLang: 'pl',
|
||||||
releaseURL: '',
|
releaseURL: '',
|
||||||
@@ -89,6 +66,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.loadLang();
|
this.loadLang();
|
||||||
|
this.store.connectToAPI();
|
||||||
|
|
||||||
this.store.isOffline = !window.navigator.onLine;
|
this.store.isOffline = !window.navigator.onLine;
|
||||||
|
|
||||||
@@ -116,12 +94,8 @@ export default defineComponent({
|
|||||||
watch(
|
watch(
|
||||||
() => this.store.blockScroll,
|
() => this.store.blockScroll,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value) {
|
if (value) document.body.classList.add('no-scroll');
|
||||||
document.body.classList.add('no-scroll');
|
else document.body.classList.remove('no-scroll');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.body.classList.remove('no-scroll');
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -82,28 +82,30 @@ export default defineComponent({
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
store: useStore()
|
store: useStore()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
changeRegion(region: { id: string; value: string }) {
|
changeRegion(region: { id: string; value: string }) {
|
||||||
this.store.changeRegion(region);
|
this.store.changeRegion(region);
|
||||||
},
|
},
|
||||||
|
|
||||||
changeLang(lang: string) {
|
changeLang(lang: string) {
|
||||||
this.$emit('changeLang', lang);
|
this.$emit('changeLang', lang);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
onlineTrainsCount() {
|
onlineTrainsCount() {
|
||||||
return this.store.trainList.filter((train) => train.online).length;
|
return this.store.trainList.filter((train) => train.online).length;
|
||||||
},
|
},
|
||||||
|
|
||||||
onlineDispatchersCount() {
|
onlineDispatchersCount() {
|
||||||
return this.store.stationList.filter(
|
return this.store.onlineSceneryList.length;
|
||||||
(station) => station.onlineInfo && station.onlineInfo.region == this.store.region.id
|
|
||||||
).length;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
factorU() {
|
factorU() {
|
||||||
|
|||||||
@@ -87,6 +87,19 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
'$route.query': {
|
||||||
|
immediate: true,
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal.region) {
|
||||||
|
const item = this.itemList.find((it) => it.id == newVal.region);
|
||||||
|
|
||||||
|
if (item) this.selectedItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
selectOption(item: Item) {
|
selectOption(item: Item) {
|
||||||
this.selectedItem = item;
|
this.selectedItem = item;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ import { URLs } from '../../scripts/utils/apiURLs';
|
|||||||
import Loading from '../Global/Loading.vue';
|
import Loading from '../Global/Loading.vue';
|
||||||
import styleMixin from '../../mixins/styleMixin';
|
import styleMixin from '../../mixins/styleMixin';
|
||||||
import listObserverMixin from '../../mixins/listObserverMixin';
|
import listObserverMixin from '../../mixins/listObserverMixin';
|
||||||
|
import { OnlineScenery } from '../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SceneryDispatchersHistory',
|
name: 'SceneryDispatchersHistory',
|
||||||
@@ -85,6 +86,10 @@ export default defineComponent({
|
|||||||
station: {
|
station: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<Station>,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
onlineScenery: {
|
||||||
|
type: Object as PropType<OnlineScenery>,
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -8,19 +8,25 @@
|
|||||||
{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo?.abbr }}</b>
|
{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo?.abbr }}</b>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="scenery-hash" v-if="station.onlineInfo?.hash">#{{ station.onlineInfo.hash }}</div>
|
<div class="scenery-hash" v-if="onlineScenery?.hash">#{{ onlineScenery.hash }}</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PropType, defineComponent } from 'vue';
|
import { PropType, defineComponent } from 'vue';
|
||||||
import Station from '../../scripts/interfaces/Station';
|
import Station from '../../scripts/interfaces/Station';
|
||||||
|
import { OnlineScenery } from '../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
station: {
|
station: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<Station>,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
onlineScenery: {
|
||||||
|
type: Object as PropType<OnlineScenery>,
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="scenery-info">
|
<div class="scenery-info">
|
||||||
<section v-if="!timetableOnly">
|
<section>
|
||||||
<div class="scenery-info-general" v-if="station.generalInfo">
|
<div class="scenery-info-general" v-if="station.generalInfo">
|
||||||
<SceneryInfoIcons :station="station" />
|
<SceneryInfoIcons :station="station" />
|
||||||
|
|
||||||
@@ -68,14 +68,14 @@
|
|||||||
<div style="margin: 2em 0; height: 2px; background-color: white"></div>
|
<div style="margin: 2em 0; height: 2px; background-color: white"></div>
|
||||||
|
|
||||||
<!-- info dispatcher -->
|
<!-- info dispatcher -->
|
||||||
<SceneryInfoDispatcher :station="station" :onlineFrom="onlineFrom" />
|
<SceneryInfoDispatcher :onlineScenery="onlineScenery" />
|
||||||
|
|
||||||
<div class="info-lists">
|
<div class="info-lists">
|
||||||
<!-- user list -->
|
<!-- user list -->
|
||||||
<SceneryInfoUserList :station="station" />
|
<SceneryInfoUserList :onlineScenery="onlineScenery" />
|
||||||
|
|
||||||
<!-- spawn list -->
|
<!-- spawn list -->
|
||||||
<SceneryInfoSpawnList :station="station" />
|
<SceneryInfoSpawnList :onlineScenery="onlineScenery" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,6 +90,7 @@ import SceneryInfoUserList from './SceneryInfo/SceneryInfoUserList.vue';
|
|||||||
import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue';
|
import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue';
|
||||||
import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue';
|
import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue';
|
||||||
import Station from '../../scripts/interfaces/Station';
|
import Station from '../../scripts/interfaces/Station';
|
||||||
|
import { OnlineScenery } from '../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@@ -105,12 +106,11 @@ export default defineComponent({
|
|||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
|
||||||
timetableOnly: Boolean
|
onlineScenery: {
|
||||||
|
type: Object as PropType<OnlineScenery>,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
|
||||||
onlineFrom: -1
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="info-dispatcher">
|
<section class="info-dispatcher">
|
||||||
<div class="dispatcher" v-if="station.onlineInfo">
|
<div class="dispatcher" v-if="onlineScenery">
|
||||||
<span
|
<span
|
||||||
class="dispatcher_level"
|
class="dispatcher_level"
|
||||||
:style="
|
:style="calculateExpStyle(onlineScenery.dispatcherExp, onlineScenery.dispatcherIsSupporter)"
|
||||||
calculateExpStyle(
|
|
||||||
station.onlineInfo.dispatcherExp,
|
|
||||||
station.onlineInfo.dispatcherIsSupporter
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ station.onlineInfo.dispatcherExp > 1 ? station.onlineInfo.dispatcherExp : 'L' }}
|
{{ onlineScenery.dispatcherExp > 1 ? onlineScenery.dispatcherExp : 'L' }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
class="dispatcher_name"
|
class="dispatcher_name"
|
||||||
:to="`/journal/dispatchers?dispatcherName=${station.onlineInfo.dispatcherName}`"
|
:to="`/journal/dispatchers?dispatcherName=${onlineScenery.dispatcherName}`"
|
||||||
>
|
>
|
||||||
{{ station.onlineInfo.dispatcherName }}
|
{{ onlineScenery.dispatcherName }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<span class="dispatcher_likes text--primary">
|
<span class="dispatcher_likes text--primary">
|
||||||
<img src="/images/icon-like.svg" alt="Likes count icon" />
|
<img src="/images/icon-like.svg" alt="Likes count icon" />
|
||||||
<span>{{ station.onlineInfo?.dispatcherRate || '0' }}</span>
|
<span>{{ onlineScenery?.dispatcherRate || '0' }}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StationStatusBadge
|
<StationStatusBadge
|
||||||
:statusID="station.onlineInfo?.statusID"
|
:statusID="onlineScenery?.statusID"
|
||||||
:isOnline="station.onlineInfo ? true : false"
|
:isOnline="onlineScenery ? true : false"
|
||||||
:statusTimestamp="station.onlineInfo?.statusTimestamp"
|
:statusTimestamp="onlineScenery?.statusTimestamp"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -39,19 +34,15 @@ import { PropType, defineComponent } from 'vue';
|
|||||||
import dateMixin from '../../../mixins/dateMixin';
|
import dateMixin from '../../../mixins/dateMixin';
|
||||||
import routerMixin from '../../../mixins/routerMixin';
|
import routerMixin from '../../../mixins/routerMixin';
|
||||||
import styleMixin from '../../../mixins/styleMixin';
|
import styleMixin from '../../../mixins/styleMixin';
|
||||||
import Station from '../../../scripts/interfaces/Station';
|
|
||||||
import StationStatusBadge from '../../Global/StationStatusBadge.vue';
|
import StationStatusBadge from '../../Global/StationStatusBadge.vue';
|
||||||
|
import { OnlineScenery } from '../../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
mixins: [styleMixin, dateMixin, routerMixin],
|
mixins: [styleMixin, dateMixin, routerMixin],
|
||||||
props: {
|
props: {
|
||||||
station: {
|
onlineScenery: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<OnlineScenery>,
|
||||||
required: true
|
required: false
|
||||||
},
|
|
||||||
onlineFrom: {
|
|
||||||
type: Number,
|
|
||||||
default: -1
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { StationStatusBadge }
|
components: { StationStatusBadge }
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<h3 class="spawn-header section-header">
|
<h3 class="spawn-header section-header">
|
||||||
<img src="/images/icon-spawn.svg" alt="Open spawns icon" />
|
<img src="/images/icon-spawn.svg" alt="Open spawns icon" />
|
||||||
{{ $t('scenery.spawns') }}
|
{{ $t('scenery.spawns') }}
|
||||||
<span class="text--primary">{{ station.onlineInfo?.spawns.length || '0' }}</span>
|
<span class="text--primary">{{ onlineScenery?.spawns.length || '0' }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span v-if="station.onlineInfo">
|
<span v-if="onlineScenery">
|
||||||
<span
|
<span
|
||||||
class="badge spawn"
|
class="badge spawn"
|
||||||
v-for="(spawn, i) in sortedSpawns"
|
v-for="(spawn, i) in sortedSpawns"
|
||||||
:key="spawn.spawnName + station.onlineInfo?.dispatcherName + i"
|
:key="spawn.spawnName + onlineScenery?.dispatcherName + i"
|
||||||
:data-electrified="spawn.isElectrified"
|
:data-electrified="spawn.isElectrified"
|
||||||
>
|
>
|
||||||
<span class="spawn_name">{{ spawn.spawnName }}</span>
|
<span class="spawn_name">{{ spawn.spawnName }}</span>
|
||||||
@@ -18,9 +18,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span class="badge spawn badge-none" v-if="!onlineScenery || onlineScenery.spawns.length == 0"
|
||||||
class="badge spawn badge-none"
|
|
||||||
v-if="!station.onlineInfo || station.onlineInfo.spawns.length == 0"
|
|
||||||
>{{ $t('scenery.no-spawns') }}
|
>{{ $t('scenery.no-spawns') }}
|
||||||
</span>
|
</span>
|
||||||
</section>
|
</section>
|
||||||
@@ -28,21 +26,21 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PropType, defineComponent } from 'vue';
|
import { PropType, defineComponent } from 'vue';
|
||||||
import Station from '../../../scripts/interfaces/Station';
|
import { OnlineScenery } from '../../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
station: {
|
onlineScenery: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<OnlineScenery>,
|
||||||
required: true
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
sortedSpawns() {
|
sortedSpawns() {
|
||||||
if (!this.station.onlineInfo) return [];
|
if (!this.onlineScenery) return [];
|
||||||
|
|
||||||
return [...this.station.onlineInfo.spawns].sort((s1, s2) =>
|
return [...this.onlineScenery.spawns].sort((s1, s2) =>
|
||||||
s1.spawnLength < s2.spawnLength ? 1 : -1
|
s1.spawnLength < s2.spawnLength ? 1 : -1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
<h3 class="user-header section-header">
|
<h3 class="user-header section-header">
|
||||||
<img src="/images/icon-user.svg" alt="Users icon" />
|
<img src="/images/icon-user.svg" alt="Users icon" />
|
||||||
{{ $t('scenery.users') }}
|
{{ $t('scenery.users') }}
|
||||||
<span class="text--primary">{{ station.onlineInfo?.currentUsers || '0' }}</span
|
<span class="text--primary">{{ onlineScenery?.currentUsers || 0 }}</span
|
||||||
> / <span class="text--primary">{{ station.onlineInfo?.maxUsers || '0' }}</span>
|
> / <span class="text--primary">{{ onlineScenery?.maxUsers || 0 }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="train in computedStationTrains"
|
v-for="train in onlineScenery?.stationTrains"
|
||||||
class="badge user"
|
class="badge user"
|
||||||
:class="train.stopStatus"
|
:class="train.stopStatus"
|
||||||
:key="train.trainId"
|
:key="train.trainId"
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="badge user badge-none"
|
class="badge user badge-none"
|
||||||
v-if="!computedStationTrains || computedStationTrains.length == 0"
|
v-if="!onlineScenery?.scheduledTrains || onlineScenery.scheduledTrains.length == 0"
|
||||||
>
|
>
|
||||||
{{ $t('scenery.no-users') }}
|
{{ $t('scenery.no-users') }}
|
||||||
</div>
|
</div>
|
||||||
@@ -30,45 +30,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PropType, computed, defineComponent } from 'vue';
|
import { PropType, defineComponent } from 'vue';
|
||||||
import modalTrainMixin from '../../../mixins/modalTrainMixin';
|
import modalTrainMixin from '../../../mixins/modalTrainMixin';
|
||||||
import routerMixin from '../../../mixins/routerMixin';
|
import routerMixin from '../../../mixins/routerMixin';
|
||||||
import Station from '../../../scripts/interfaces/Station';
|
import { OnlineScenery } from '../../../scripts/interfaces/store/storeTypes';
|
||||||
import { useStore } from '../../../store/store';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
mixins: [routerMixin, modalTrainMixin],
|
mixins: [routerMixin, modalTrainMixin],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
station: {
|
onlineScenery: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<OnlineScenery>,
|
||||||
required: true
|
required: false
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
const computedStationTrains = computed(() => {
|
|
||||||
if (!props.station) return [];
|
|
||||||
|
|
||||||
const station = props.station as Station;
|
|
||||||
if (!station.onlineInfo) return [];
|
|
||||||
if (!station.onlineInfo.stationTrains) return [];
|
|
||||||
|
|
||||||
return station.onlineInfo.stationTrains.map((train) => {
|
|
||||||
const scheduledTrainStatus = station.onlineInfo?.scheduledTrains?.find(
|
|
||||||
(st) => st.trainNo === train.trainNo
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...train,
|
|
||||||
stopStatus: scheduledTrainStatus?.stopStatus || 'no-timetable'
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return { computedStationTrains, store };
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,14 +6,12 @@
|
|||||||
<span>{{ $t('scenery.timetables') }}</span>
|
<span>{{ $t('scenery.timetables') }}</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<span class="text--primary">{{
|
<span class="text--primary">{{ onlineScenery?.scheduledTrains?.length || '0' }}</span>
|
||||||
station.onlineInfo?.scheduledTrains?.length || '0'
|
|
||||||
}}</span>
|
|
||||||
<span> / </span>
|
<span> / </span>
|
||||||
<span class="text--grayed">
|
<span class="text--grayed">
|
||||||
{{
|
{{
|
||||||
station.onlineInfo?.scheduledTrains?.filter((train) => train.stopInfo.confirmed)
|
onlineScenery?.scheduledTrains?.filter((train) => train.stopInfo.confirmed).length ||
|
||||||
.length || '0'
|
'0'
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -59,7 +57,7 @@
|
|||||||
|
|
||||||
<span
|
<span
|
||||||
class="timetable-item empty"
|
class="timetable-item empty"
|
||||||
v-else-if="computedScheduledTrains.length == 0 && !station.onlineInfo"
|
v-else-if="computedScheduledTrains.length == 0 && !onlineScenery"
|
||||||
>
|
>
|
||||||
{{ $t('scenery.offline') }}
|
{{ $t('scenery.offline') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -186,6 +184,7 @@ import Station from '../../scripts/interfaces/Station';
|
|||||||
import { useStore } from '../../store/store';
|
import { useStore } from '../../store/store';
|
||||||
import modalTrainMixin from '../../mixins/modalTrainMixin';
|
import modalTrainMixin from '../../mixins/modalTrainMixin';
|
||||||
import ScheduledTrainStatus from './ScheduledTrainStatus.vue';
|
import ScheduledTrainStatus from './ScheduledTrainStatus.vue';
|
||||||
|
import { OnlineScenery } from '../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SceneryTimetable',
|
name: 'SceneryTimetable',
|
||||||
@@ -199,9 +198,9 @@ export default defineComponent({
|
|||||||
type: Object as PropType<Station>,
|
type: Object as PropType<Station>,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
onlineScenery: {
|
||||||
timetableOnly: {
|
type: Object as PropType<OnlineScenery>,
|
||||||
type: Boolean
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -229,36 +228,9 @@ export default defineComponent({
|
|||||||
: props.station?.generalInfo?.checkpoints[0].checkpointName || null
|
: props.station?.generalInfo?.checkpoints[0].checkpointName || null
|
||||||
);
|
);
|
||||||
|
|
||||||
const computedScheduledTrains = computed(() => {
|
|
||||||
if (!props.station) return [];
|
|
||||||
|
|
||||||
const station = props.station as Station;
|
|
||||||
|
|
||||||
let scheduledTrains =
|
|
||||||
station.generalInfo?.checkpoints.find((cp) => cp.checkpointName === chosenCheckpoint.value)
|
|
||||||
?.scheduledTrains ||
|
|
||||||
station.onlineInfo?.scheduledTrains ||
|
|
||||||
[];
|
|
||||||
|
|
||||||
if (!scheduledTrains) return [];
|
|
||||||
|
|
||||||
return (
|
|
||||||
scheduledTrains.sort((a, b) => {
|
|
||||||
if (a.stopStatusID > b.stopStatusID) return 1;
|
|
||||||
if (a.stopStatusID < b.stopStatusID) return -1;
|
|
||||||
|
|
||||||
if (a.stopInfo.arrivalTimestamp > b.stopInfo.arrivalTimestamp) return 1;
|
|
||||||
if (a.stopInfo.arrivalTimestamp < b.stopInfo.arrivalTimestamp) return -1;
|
|
||||||
|
|
||||||
return a.stopInfo.departureTimestamp > b.stopInfo.departureTimestamp ? 1 : -1;
|
|
||||||
}) || []
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentURL,
|
currentURL,
|
||||||
chosenCheckpoint,
|
chosenCheckpoint,
|
||||||
computedScheduledTrains,
|
|
||||||
store
|
store
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -269,27 +241,37 @@ export default defineComponent({
|
|||||||
if (this.chosenCheckpoint) url += `&checkpoint=${this.chosenCheckpoint}`;
|
if (this.chosenCheckpoint) url += `&checkpoint=${this.chosenCheckpoint}`;
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
|
},
|
||||||
|
|
||||||
|
computedScheduledTrains() {
|
||||||
|
return (
|
||||||
|
this.onlineScenery?.scheduledTrains
|
||||||
|
?.filter(
|
||||||
|
(train) =>
|
||||||
|
train.checkpointName.toLocaleLowerCase() ==
|
||||||
|
(this.chosenCheckpoint || this.station.name).toLocaleLowerCase()
|
||||||
|
)
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.stopStatusID > b.stopStatusID) return 1;
|
||||||
|
if (a.stopStatusID < b.stopStatusID) return -1;
|
||||||
|
|
||||||
|
if (a.stopInfo.arrivalTimestamp > b.stopInfo.arrivalTimestamp) return 1;
|
||||||
|
if (a.stopInfo.arrivalTimestamp < b.stopInfo.arrivalTimestamp) return -1;
|
||||||
|
|
||||||
|
return a.stopInfo.departureTimestamp > b.stopInfo.departureTimestamp ? 1 : -1;
|
||||||
|
}) || []
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
loadSelectedOption() {
|
loadSelectedOption() {
|
||||||
if (!this.station) return;
|
this.chosenCheckpoint =
|
||||||
if (!this.station.generalInfo) return;
|
this.station.generalInfo?.checkpoints[0]?.checkpointName || this.station.name;
|
||||||
if (!this.station.generalInfo.checkpoints) return;
|
|
||||||
if (this.station.generalInfo.checkpoints.length == 0) return;
|
|
||||||
|
|
||||||
if (this.chosenCheckpoint != '') return;
|
|
||||||
|
|
||||||
this.chosenCheckpoint = this.station.generalInfo.checkpoints[0].checkpointName;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setCheckpoint(cp: { checkpointName: string }) {
|
setCheckpoint(cp: { checkpointName: string }) {
|
||||||
this.chosenCheckpoint = cp.checkpointName;
|
this.chosenCheckpoint = cp.checkpointName;
|
||||||
},
|
|
||||||
|
|
||||||
showTimetableOnlyView() {
|
|
||||||
this.$router.push(`${this.$route.fullPath}&timetableOnly=1`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import Station from '../../scripts/interfaces/Station';
|
|||||||
import { URLs } from '../../scripts/utils/apiURLs';
|
import { URLs } from '../../scripts/utils/apiURLs';
|
||||||
import Loading from '../Global/Loading.vue';
|
import Loading from '../Global/Loading.vue';
|
||||||
import listObserverMixin from '../../mixins/listObserverMixin';
|
import listObserverMixin from '../../mixins/listObserverMixin';
|
||||||
|
import { OnlineScenery } from '../../scripts/interfaces/store/storeTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SceneryTimetablesHistory',
|
name: 'SceneryTimetablesHistory',
|
||||||
@@ -73,6 +74,10 @@ export default defineComponent({
|
|||||||
station: {
|
station: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<Station>,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
onlineScenery: {
|
||||||
|
type: Object as PropType<OnlineScenery>,
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<label @dblclick="handleDbClick">
|
<label @dblclick="handleDbClick">
|
||||||
<input
|
<input
|
||||||
:value="optionValue"
|
:checked="optionValue"
|
||||||
@input="$emit('update:optionValue', ($event.target as HTMLInputElement).value)"
|
@input="$emit('update:optionValue', ($event.target as HTMLInputElement).checked)"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:class="option.section"
|
:class="option.section"
|
||||||
:name="option.id"
|
:name="option.id"
|
||||||
|
|||||||
@@ -79,11 +79,19 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-else-if="station.generalInfo.availability == 'abandoned'">
|
<span v-else-if="station.generalInfo.availability == 'abandoned'">
|
||||||
<img src="/images/icon-abandoned.svg" alt="non-public" :title="$t('desc.abandoned')" />
|
<img
|
||||||
|
src="/images/icon-abandoned.svg"
|
||||||
|
alt="non-public"
|
||||||
|
:title="$t('desc.abandoned')"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-else-if="station.generalInfo.availability == 'nonPublic'">
|
<span v-else-if="station.generalInfo.availability == 'nonPublic'">
|
||||||
<img src="/images/icon-lock.svg" alt="non-public" :title="$t('desc.non-public')" />
|
<img
|
||||||
|
src="/images/icon-lock.svg"
|
||||||
|
alt="non-public"
|
||||||
|
:title="$t('desc.non-public')"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-else>
|
<span v-else>
|
||||||
@@ -234,7 +242,7 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="station_schedules"
|
class="station_schedules all"
|
||||||
style="width: 30px"
|
style="width: 30px"
|
||||||
:class="{ inactive: !station.onlineInfo }"
|
:class="{ inactive: !station.onlineInfo }"
|
||||||
>
|
>
|
||||||
@@ -244,20 +252,23 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="station_schedules"
|
class="station_schedules unconfirmed"
|
||||||
style="width: 30px"
|
style="width: 30px"
|
||||||
:class="{ inactive: !station.onlineInfo }"
|
:class="{ inactive: !station.onlineInfo }"
|
||||||
>
|
>
|
||||||
<span style="color: #ccc">
|
<span style="color: #ccc">
|
||||||
{{
|
{{
|
||||||
station.onlineInfo?.scheduledTrains?.filter((train) => !train.stopInfo.confirmed)
|
new Set([
|
||||||
.length || 0
|
...(station.onlineInfo?.scheduledTrains
|
||||||
|
?.filter((train) => !train.stopInfo.confirmed)
|
||||||
|
.map((train) => train.checkpointName) || [])
|
||||||
|
]).size || 0
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="station_schedules"
|
class="station_schedules confirmed"
|
||||||
style="width: 30px"
|
style="width: 30px"
|
||||||
:class="{ inactive: !station.onlineInfo }"
|
:class="{ inactive: !station.onlineInfo }"
|
||||||
>
|
>
|
||||||
@@ -336,9 +347,13 @@ export default defineComponent({
|
|||||||
if (!station) return;
|
if (!station) return;
|
||||||
|
|
||||||
this.lastSelectedStationName = station.name;
|
this.lastSelectedStationName = station.name;
|
||||||
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'SceneryView',
|
name: 'SceneryView',
|
||||||
query: { station: station.name.replaceAll(' ', '_') }
|
query: {
|
||||||
|
station: station.name.replaceAll(' ', '_'),
|
||||||
|
region: this.$route.query.region || undefined
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import plLang from './locales/pl.json';
|
|||||||
|
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from 'vue-i18n';
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
|
import useCustomSW from './mixins/useCustomSW';
|
||||||
|
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
locale: 'pl',
|
locale: 'pl',
|
||||||
@@ -20,6 +21,9 @@ const i18n = createI18n({
|
|||||||
enableLegacy: false
|
enableLegacy: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// SW
|
||||||
|
useCustomSW();
|
||||||
|
|
||||||
const clickOutsideDirective: Directive = {
|
const clickOutsideDirective: Directive = {
|
||||||
mounted(el, binding) {
|
mounted(el, binding) {
|
||||||
el.clickOutsideEvent = (event: Event) => {
|
el.clickOutsideEvent = (event: Event) => {
|
||||||
|
|||||||
+12
-3
@@ -6,7 +6,10 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'StationsView',
|
name: 'StationsView',
|
||||||
component: () => import('../views/StationsView.vue')
|
component: () => import('../views/StationsView.vue'),
|
||||||
|
props: (route) => ({
|
||||||
|
region: route.query.region
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/trains',
|
path: '/trains',
|
||||||
@@ -21,7 +24,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: '/scenery',
|
path: '/scenery',
|
||||||
name: 'SceneryView',
|
name: 'SceneryView',
|
||||||
component: () => import('../views/SceneryView.vue')
|
component: () => import('../views/SceneryView.vue'),
|
||||||
|
props: (route) => ({
|
||||||
|
region: route.query.region,
|
||||||
|
station: route.query.station
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/journal',
|
path: '/journal',
|
||||||
@@ -53,9 +60,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
scrollBehavior(to, from) {
|
scrollBehavior(to, from, savedPosition) {
|
||||||
if (to.name == 'SceneryView' && from.name) return { el: `.app_main` };
|
if (to.name == 'SceneryView' && from.name) return { el: `.app_main` };
|
||||||
|
|
||||||
|
if (savedPosition) return savedPosition;
|
||||||
|
|
||||||
// if (from.name == 'SceneryView' && to.name == 'StationsView') return { el: `.last-selected`, top: 20 };
|
// if (from.name == 'SceneryView' && to.name == 'StationsView') return { el: `.last-selected`, top: 20 };
|
||||||
},
|
},
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ export enum StopStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ScheduledTrain {
|
export interface ScheduledTrain {
|
||||||
|
checkpointName: string;
|
||||||
|
|
||||||
trainId: string;
|
trainId: string;
|
||||||
trainNo: number;
|
trainNo: number;
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,16 @@ import { Socket } from 'socket.io-client';
|
|||||||
import { DataStatus } from '../../enums/DataStatus';
|
import { DataStatus } from '../../enums/DataStatus';
|
||||||
import StationAPIData from '../api/StationAPIData';
|
import StationAPIData from '../api/StationAPIData';
|
||||||
import { TrainAPIData } from '../api/TrainAPIData';
|
import { TrainAPIData } from '../api/TrainAPIData';
|
||||||
import Station from '../Station';
|
|
||||||
import Train from '../Train';
|
|
||||||
import { DispatcherStatsAPIData } from '../api/DispatcherStatsAPIData';
|
import { DispatcherStatsAPIData } from '../api/DispatcherStatsAPIData';
|
||||||
import { DriverStatsAPIData } from '../api/DriverStatsAPIData';
|
import { DriverStatsAPIData } from '../api/DriverStatsAPIData';
|
||||||
import { RollingStockGithubData } from '../github_api/StockInfoGithubData';
|
import { RollingStockGithubData } from '../github_api/StockInfoGithubData';
|
||||||
|
import Station from '../Station';
|
||||||
|
import { ScheduledTrain } from '../ScheduledTrain';
|
||||||
|
|
||||||
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
|
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
|
||||||
|
|
||||||
export interface StoreState {
|
export interface StoreState {
|
||||||
stationList: Station[];
|
stationList: Station[];
|
||||||
trainList: Train[];
|
|
||||||
apiData: APIData;
|
apiData: APIData;
|
||||||
rollingStockData?: RollingStockGithubData;
|
rollingStockData?: RollingStockGithubData;
|
||||||
|
|
||||||
@@ -91,3 +90,31 @@ export interface StationJSONData {
|
|||||||
|
|
||||||
availability: Availability;
|
availability: Availability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StationTrain {
|
||||||
|
driverName: string;
|
||||||
|
driverId: number;
|
||||||
|
trainNo: number;
|
||||||
|
trainId: string;
|
||||||
|
stopStatus: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OnlineScenery {
|
||||||
|
name: string;
|
||||||
|
hash: string;
|
||||||
|
region: string;
|
||||||
|
maxUsers: number;
|
||||||
|
currentUsers: number;
|
||||||
|
spawns: { spawnName: string; spawnLength: number; isElectrified: boolean }[];
|
||||||
|
dispatcherName: string;
|
||||||
|
dispatcherRate: number;
|
||||||
|
dispatcherId: number;
|
||||||
|
dispatcherExp: number;
|
||||||
|
dispatcherIsSupporter: boolean;
|
||||||
|
|
||||||
|
statusTimestamp: number;
|
||||||
|
statusID: string;
|
||||||
|
|
||||||
|
stationTrains?: StationTrain[];
|
||||||
|
scheduledTrains?: ScheduledTrain[];
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { ScheduledTrain, StopStatus } from '../interfaces/ScheduledTrain';
|
import { ScheduledTrain, StopStatus } from '../interfaces/ScheduledTrain';
|
||||||
|
import Station from '../interfaces/Station';
|
||||||
import Train from '../interfaces/Train';
|
import Train from '../interfaces/Train';
|
||||||
import TrainStop from '../interfaces/TrainStop';
|
import TrainStop from '../interfaces/TrainStop';
|
||||||
|
import StationAPIData from '../interfaces/api/StationAPIData';
|
||||||
|
import { StationTrain, StoreState } from '../interfaces/store/storeTypes';
|
||||||
|
|
||||||
export const getLocoURL = (locoType: string): string =>
|
export const getLocoURL = (locoType: string): string =>
|
||||||
`https://rj.td2.info.pl/dist/img/thumbnails/${
|
`https://rj.td2.info.pl/dist/img/thumbnails/${
|
||||||
@@ -79,7 +82,7 @@ export const getTimestamp = (date: string | null): number => (date ? new Date(da
|
|||||||
export const getTrainStopStatus = (
|
export const getTrainStopStatus = (
|
||||||
stopInfo: TrainStop,
|
stopInfo: TrainStop,
|
||||||
currentStationName: string,
|
currentStationName: string,
|
||||||
stationName: string
|
sceneryName: string
|
||||||
) => {
|
) => {
|
||||||
let stopStatus = StopStatus['arriving'],
|
let stopStatus = StopStatus['arriving'],
|
||||||
stopLabel = '',
|
stopLabel = '',
|
||||||
@@ -89,23 +92,23 @@ export const getTrainStopStatus = (
|
|||||||
stopStatus = StopStatus['terminated'];
|
stopStatus = StopStatus['terminated'];
|
||||||
stopLabel = 'Skończył bieg';
|
stopLabel = 'Skończył bieg';
|
||||||
stopStatusID = 5;
|
stopStatusID = 5;
|
||||||
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName == stationName) {
|
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName == sceneryName) {
|
||||||
stopStatus = StopStatus['departed'];
|
stopStatus = StopStatus['departed'];
|
||||||
stopLabel = 'Odprawiony';
|
stopLabel = 'Odprawiony';
|
||||||
stopStatusID = 2;
|
stopStatusID = 2;
|
||||||
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName != stationName) {
|
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName != sceneryName) {
|
||||||
stopStatus = StopStatus['departed-away'];
|
stopStatus = StopStatus['departed-away'];
|
||||||
stopLabel = 'Odjechał';
|
stopLabel = 'Odjechał';
|
||||||
stopStatusID = 4;
|
stopStatusID = 4;
|
||||||
} else if (currentStationName == stationName && !stopInfo.stopped) {
|
} else if (currentStationName == sceneryName && !stopInfo.stopped) {
|
||||||
stopStatus = StopStatus['online'];
|
stopStatus = StopStatus['online'];
|
||||||
stopLabel = 'Na stacji';
|
stopLabel = 'Na stacji';
|
||||||
stopStatusID = 0;
|
stopStatusID = 0;
|
||||||
} else if (currentStationName == stationName && stopInfo.stopped) {
|
} else if (currentStationName == sceneryName && stopInfo.stopped) {
|
||||||
stopStatus = StopStatus['stopped'];
|
stopStatus = StopStatus['stopped'];
|
||||||
stopLabel = 'Postój';
|
stopLabel = 'Postój';
|
||||||
stopStatusID = 1;
|
stopStatusID = 1;
|
||||||
} else if (currentStationName != stationName) {
|
} else if (currentStationName != sceneryName) {
|
||||||
stopStatus = StopStatus['arriving'];
|
stopStatus = StopStatus['arriving'];
|
||||||
stopLabel = 'W drodze';
|
stopLabel = 'W drodze';
|
||||||
stopStatusID = 3;
|
stopStatusID = 3;
|
||||||
@@ -114,16 +117,16 @@ export const getTrainStopStatus = (
|
|||||||
return { stopStatus, stopLabel, stopStatusID };
|
return { stopStatus, stopLabel, stopStatusID };
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getScheduledTrain(
|
export function getCheckpointTrain(
|
||||||
train: Train,
|
train: Train,
|
||||||
trainStopIndex: number,
|
trainStopIndex: number,
|
||||||
stationName: string
|
sceneryName: string
|
||||||
): ScheduledTrain {
|
): ScheduledTrain {
|
||||||
const timetable = train.timetableData!;
|
const timetable = train.timetableData!;
|
||||||
const followingStops = timetable.followingStops;
|
const followingStops = timetable.followingStops;
|
||||||
const trainStop = followingStops[trainStopIndex];
|
const trainStop = followingStops[trainStopIndex];
|
||||||
|
|
||||||
const trainStopStatus = getTrainStopStatus(trainStop, train.currentStationName, stationName);
|
const trainStopStatus = getTrainStopStatus(trainStop, train.currentStationName, sceneryName);
|
||||||
|
|
||||||
let prevStationName = '',
|
let prevStationName = '',
|
||||||
nextStationName = '';
|
nextStationName = '';
|
||||||
@@ -177,6 +180,8 @@ export function getScheduledTrain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
checkpointName: trainStop.stopNameRAW,
|
||||||
|
|
||||||
trainNo: train.trainNo,
|
trainNo: train.trainNo,
|
||||||
trainId: train.trainId,
|
trainId: train.trainId,
|
||||||
|
|
||||||
@@ -206,3 +211,119 @@ export function getScheduledTrain(
|
|||||||
prevDepartureLine
|
prevDepartureLine
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDispatcherStatus(state: StoreState, onlineStationData: StationAPIData) {
|
||||||
|
const { dispatchers } = state.apiData;
|
||||||
|
|
||||||
|
const prevDispatcherStatus = state.lastDispatcherStatuses.find(
|
||||||
|
(dispatcher) => dispatcher.hash === onlineStationData.stationHash
|
||||||
|
);
|
||||||
|
|
||||||
|
const stationStatus = !dispatchers
|
||||||
|
? undefined
|
||||||
|
: dispatchers.find(
|
||||||
|
(status: string[]) =>
|
||||||
|
status[0] == onlineStationData.stationHash && status[1] == state.region.id
|
||||||
|
) || -1;
|
||||||
|
|
||||||
|
const statusTimestamp =
|
||||||
|
prevDispatcherStatus && !dispatchers
|
||||||
|
? prevDispatcherStatus.statusTimestamp
|
||||||
|
: getStatusTimestamp(stationStatus);
|
||||||
|
|
||||||
|
const statusID =
|
||||||
|
prevDispatcherStatus && !dispatchers
|
||||||
|
? prevDispatcherStatus.statusID
|
||||||
|
: getStatusID(stationStatus);
|
||||||
|
|
||||||
|
return {
|
||||||
|
hash: onlineStationData.stationHash,
|
||||||
|
statusID,
|
||||||
|
statusTimestamp
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getScheduledTrains(
|
||||||
|
trainList: Train[],
|
||||||
|
stationAPIData: StationAPIData,
|
||||||
|
stationGeneralInfo: Station['generalInfo']
|
||||||
|
): ScheduledTrain[] {
|
||||||
|
const stationName = stationAPIData.stationName.toLocaleLowerCase();
|
||||||
|
|
||||||
|
stationGeneralInfo?.checkpoints.forEach((cp) => (cp.scheduledTrains.length = 0));
|
||||||
|
|
||||||
|
return trainList.reduce((acc: ScheduledTrain[], train) => {
|
||||||
|
if (!train.timetableData) return acc;
|
||||||
|
|
||||||
|
const timetable = train.timetableData;
|
||||||
|
if (!timetable.sceneries.includes(stationAPIData.stationHash)) return acc;
|
||||||
|
|
||||||
|
const stopInfoIndex = timetable.followingStops.findIndex((stop) => {
|
||||||
|
const stopName = stop.stopNameRAW.toLowerCase();
|
||||||
|
|
||||||
|
return (
|
||||||
|
stationName == stopName ||
|
||||||
|
(!/(po\.|podg\.)/.test(stationName) && stopName.includes(stationName)) ||
|
||||||
|
(!/(po\.|podg\.)/.test(stopName) && stationName.includes(stopName)) ||
|
||||||
|
(stopName.split(', podg.')[0] !== undefined &&
|
||||||
|
stationName.startsWith(stopName.split(', podg.')[0]))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const checkpointScheduledTrains: ScheduledTrain[] = [];
|
||||||
|
|
||||||
|
if (stopInfoIndex != -1) {
|
||||||
|
checkpointScheduledTrains.push(
|
||||||
|
getCheckpointTrain(train, stopInfoIndex, stationAPIData.stationName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
stationGeneralInfo?.checkpoints?.forEach((checkpoint) => {
|
||||||
|
if (checkpoint.checkpointName.toLocaleLowerCase() == stationName) return;
|
||||||
|
|
||||||
|
if (
|
||||||
|
checkpointScheduledTrains.findIndex(
|
||||||
|
(cpTrain) =>
|
||||||
|
cpTrain.checkpointName.toLocaleLowerCase() ==
|
||||||
|
checkpoint.checkpointName.toLocaleLowerCase()
|
||||||
|
) != -1
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const index = timetable.followingStops.findIndex(
|
||||||
|
(stop) => stop.stopNameRAW.toLowerCase() == checkpoint.checkpointName.toLowerCase()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (index > -1)
|
||||||
|
checkpointScheduledTrains.push(
|
||||||
|
getCheckpointTrain(train, index, stationAPIData.stationName)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
acc.push(...checkpointScheduledTrains);
|
||||||
|
return acc;
|
||||||
|
}, []) as ScheduledTrain[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStationTrains(
|
||||||
|
trainList: Train[],
|
||||||
|
scheduledTrainList: ScheduledTrain[],
|
||||||
|
region: string,
|
||||||
|
apiStation: StationAPIData
|
||||||
|
): StationTrain[] {
|
||||||
|
return trainList
|
||||||
|
.filter(
|
||||||
|
(train) =>
|
||||||
|
train?.region === region &&
|
||||||
|
train.online &&
|
||||||
|
train.currentStationName === apiStation.stationName
|
||||||
|
)
|
||||||
|
.map((train) => ({
|
||||||
|
driverName: train.driverName,
|
||||||
|
driverId: train.driverId,
|
||||||
|
trainNo: train.trainNo,
|
||||||
|
trainId: train.trainId,
|
||||||
|
stopStatus:
|
||||||
|
scheduledTrainList.find((st) => st.trainNo === train.trainNo)?.stopStatus || 'no-timetable'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import inputData from '../data/options.json';
|
import inputData from '../data/options.json';
|
||||||
import Station from '../scripts/interfaces/Station';
|
|
||||||
import StorageManager from '../scripts/managers/storageManager';
|
import StorageManager from '../scripts/managers/storageManager';
|
||||||
import { useStore } from './store';
|
import { useStore } from './store';
|
||||||
import { filterInitStates } from '../scripts/constants/stores/initFilterStates';
|
import { filterInitStates } from '../scripts/constants/stores/initFilterStates';
|
||||||
@@ -13,31 +12,28 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
|
|||||||
inputs: inputData,
|
inputs: inputData,
|
||||||
filters: { ...filterInitStates },
|
filters: { ...filterInitStates },
|
||||||
sorterActive: { headerName: 'station' as HeadIdsTypes, dir: 1 },
|
sorterActive: { headerName: 'station' as HeadIdsTypes, dir: 1 },
|
||||||
store: useStore(),
|
|
||||||
lastClickedFilterId: ''
|
lastClickedFilterId: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
areFiltersAtDefault(state) {
|
areFiltersAtDefault: (state) => {
|
||||||
return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]);
|
return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]);
|
||||||
|
},
|
||||||
|
|
||||||
|
filteredStationList: (state) => {
|
||||||
|
const store = useStore();
|
||||||
|
return store.stationList
|
||||||
|
.map((station) => ({
|
||||||
|
...station,
|
||||||
|
onlineInfo: store.onlineSceneryList.find((os) => os.name == station.name)
|
||||||
|
}))
|
||||||
|
.filter((station) => filterStations(station, state.filters))
|
||||||
|
.sort((a, b) => sortStations(a, b, state.sorterActive));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
getFilteredStationList(stationList: Station[], region: string): Station[] {
|
|
||||||
return stationList
|
|
||||||
.map((station) => {
|
|
||||||
if (station.onlineInfo && station.onlineInfo.region != region) {
|
|
||||||
delete station.onlineInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return station;
|
|
||||||
})
|
|
||||||
.filter((station) => filterStations(station, this.filters))
|
|
||||||
.sort((a, b) => sortStations(a, b, this.sorterActive));
|
|
||||||
},
|
|
||||||
|
|
||||||
setupFilters() {
|
setupFilters() {
|
||||||
if (!StorageManager.isRegistered('options_saved')) return;
|
if (!StorageManager.isRegistered('options_saved')) return;
|
||||||
|
|
||||||
|
|||||||
+108
-189
@@ -9,12 +9,18 @@ import StationRoutes from '../scripts/interfaces/StationRoutes';
|
|||||||
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 {
|
||||||
getStatusTimestamp,
|
getDispatcherStatus,
|
||||||
getStatusID,
|
getCheckpointTrain,
|
||||||
getScheduledTrain,
|
parseSpawns,
|
||||||
parseSpawns
|
getScheduledTrains,
|
||||||
|
getStationTrains
|
||||||
} from '../scripts/utils/storeUtils';
|
} from '../scripts/utils/storeUtils';
|
||||||
import { APIData, StationJSONData, StoreState } from '../scripts/interfaces/store/storeTypes';
|
import {
|
||||||
|
APIData,
|
||||||
|
OnlineScenery,
|
||||||
|
StationJSONData,
|
||||||
|
StoreState
|
||||||
|
} from '../scripts/interfaces/store/storeTypes';
|
||||||
import packageInfo from '../../package.json';
|
import packageInfo from '../../package.json';
|
||||||
import { RollingStockGithubData } from '../scripts/interfaces/github_api/StockInfoGithubData';
|
import { RollingStockGithubData } from '../scripts/interfaces/github_api/StockInfoGithubData';
|
||||||
|
|
||||||
@@ -25,7 +31,7 @@ export const useStore = defineStore('store', {
|
|||||||
rollingStockData: undefined,
|
rollingStockData: undefined,
|
||||||
|
|
||||||
stationList: [],
|
stationList: [],
|
||||||
trainList: [],
|
|
||||||
routesList: [],
|
routesList: [],
|
||||||
|
|
||||||
sceneryData: [],
|
sceneryData: [],
|
||||||
@@ -63,13 +69,9 @@ export const useStore = defineStore('store', {
|
|||||||
modalLastClickedTarget: null
|
modalLastClickedTarget: null
|
||||||
}) as StoreState,
|
}) as StoreState,
|
||||||
|
|
||||||
actions: {
|
getters: {
|
||||||
setTrainsOnlineData() {
|
trainList(): Train[] {
|
||||||
const { trains } = this.apiData;
|
return (this.apiData?.trains ?? [])
|
||||||
|
|
||||||
if (!trains) return [];
|
|
||||||
|
|
||||||
this.trainList = trains
|
|
||||||
.filter(
|
.filter(
|
||||||
(train) =>
|
(train) =>
|
||||||
train.region === this.region.id &&
|
train.region === this.region.id &&
|
||||||
@@ -123,193 +125,113 @@ export const useStore = defineStore('store', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDispatcherStatus(onlineStationData: StationAPIData) {
|
onlineSceneryList(state): OnlineScenery[] {
|
||||||
const { dispatchers } = this.apiData;
|
if (state.isOffline) return [];
|
||||||
|
if (!state.apiData?.stations) return [];
|
||||||
|
|
||||||
const prevDispatcherStatus = this.lastDispatcherStatuses.find(
|
return state.apiData?.stations
|
||||||
(dispatcher) => dispatcher.hash === onlineStationData.stationHash
|
?.filter((apiStation) => apiStation.region == state.region.id && apiStation.isOnline)
|
||||||
);
|
.map((apiStation) => {
|
||||||
|
const dispatcherStatus = getDispatcherStatus(state as StoreState, apiStation);
|
||||||
|
const station = this.stationList.find((s) => s.name === apiStation.stationName);
|
||||||
|
|
||||||
const stationStatus = !dispatchers
|
const scheduledTrains = getScheduledTrains(
|
||||||
? undefined
|
this.trainList,
|
||||||
: dispatchers.find(
|
apiStation,
|
||||||
(status: string[]) =>
|
station?.generalInfo
|
||||||
status[0] == onlineStationData.stationHash && status[1] == this.region.id
|
);
|
||||||
) || -1;
|
|
||||||
|
|
||||||
const statusTimestamp =
|
const stationTrains = getStationTrains(
|
||||||
prevDispatcherStatus && !dispatchers
|
this.trainList,
|
||||||
? prevDispatcherStatus.statusTimestamp
|
scheduledTrains,
|
||||||
: getStatusTimestamp(stationStatus);
|
this.region.id,
|
||||||
const statusID =
|
apiStation
|
||||||
prevDispatcherStatus && !dispatchers
|
);
|
||||||
? prevDispatcherStatus.statusID
|
|
||||||
: getStatusID(stationStatus);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hash: onlineStationData.stationHash,
|
name: apiStation.stationName,
|
||||||
statusID,
|
hash: apiStation.stationHash,
|
||||||
statusTimestamp
|
region: apiStation.region,
|
||||||
};
|
maxUsers: apiStation.maxUsers,
|
||||||
},
|
currentUsers: apiStation.currentUsers,
|
||||||
|
spawns: parseSpawns(apiStation.spawnString),
|
||||||
getScheduledTrains(stationGeneralInfo: Station['generalInfo'], stationAPIData: StationAPIData) {
|
dispatcherName: apiStation.dispatcherName,
|
||||||
const stationName = stationAPIData.stationName.toLowerCase();
|
dispatcherRate: apiStation.dispatcherRate,
|
||||||
|
dispatcherId: apiStation.dispatcherId,
|
||||||
stationGeneralInfo?.checkpoints.forEach((cp) => (cp.scheduledTrains.length = 0));
|
dispatcherExp: apiStation.dispatcherExp,
|
||||||
|
dispatcherIsSupporter: apiStation.dispatcherIsSupporter,
|
||||||
return this.trainList.reduce((acc: ScheduledTrain[], train) => {
|
scheduledTrains: scheduledTrains,
|
||||||
if (!train.timetableData) return acc;
|
stationTrains: stationTrains,
|
||||||
|
statusTimestamp: dispatcherStatus.statusTimestamp,
|
||||||
const timetable = train.timetableData;
|
statusID: dispatcherStatus.statusID
|
||||||
if (!timetable.sceneries.includes(stationAPIData.stationHash)) return acc;
|
};
|
||||||
|
|
||||||
const stopInfoIndex = timetable.followingStops.findIndex((stop) => {
|
|
||||||
const stopName = stop.stopNameRAW.toLowerCase();
|
|
||||||
|
|
||||||
if (stationName === stopName) return true;
|
|
||||||
if (
|
|
||||||
stopName.includes(stationName) &&
|
|
||||||
!stop.stopName.includes('po.') &&
|
|
||||||
!stop.stopName.includes('podg.')
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (
|
|
||||||
stationName.includes(stopName) &&
|
|
||||||
!stop.stopName.includes('po.') &&
|
|
||||||
!stop.stopName.includes('podg.')
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (
|
|
||||||
stopName.includes('podg.') &&
|
|
||||||
stopName.split(', podg.')[0] &&
|
|
||||||
stationName.includes(stopName.split(', podg.')[0])
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (
|
|
||||||
stationGeneralInfo &&
|
|
||||||
stationGeneralInfo.checkpoints &&
|
|
||||||
stationGeneralInfo.checkpoints.length > 0 &&
|
|
||||||
stationGeneralInfo.checkpoints.some((cp) =>
|
|
||||||
cp.checkpointName.toLowerCase().includes(stop.stopNameRAW.toLowerCase())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
// setStationsOnlineInfo() {
|
||||||
|
// const onlineStationNames: string[] = [];
|
||||||
|
// const prevDispatcherStatuses: StoreState['lastDispatcherStatuses'] = [];
|
||||||
|
|
||||||
if (stopInfoIndex == -1) return acc;
|
// if (this.isOffline) {
|
||||||
|
// this.stationList.forEach((station) => {
|
||||||
|
// station.onlineInfo = undefined;
|
||||||
|
// });
|
||||||
|
|
||||||
const scheduledStopTrain = getScheduledTrain(
|
// return;
|
||||||
train,
|
// }
|
||||||
stopInfoIndex,
|
|
||||||
stationAPIData.stationName
|
|
||||||
);
|
|
||||||
|
|
||||||
if (stationGeneralInfo?.checkpoints) {
|
// this.apiData.stations?.forEach((stationAPIData) => {
|
||||||
for (const checkpoint of stationGeneralInfo.checkpoints) {
|
// if (stationAPIData.region !== this.region.id || !stationAPIData.isOnline) return;
|
||||||
const index = timetable.followingStops.findIndex(
|
|
||||||
(stop) => stop.stopNameRAW.toLowerCase() == checkpoint.checkpointName.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index == -1) continue;
|
// const station = this.stationList.find((s) => s.name === stationAPIData.stationName);
|
||||||
|
|
||||||
const scheduledCheckpointTrain = getScheduledTrain(
|
// onlineStationNames.push(stationAPIData.stationName);
|
||||||
train,
|
|
||||||
index,
|
|
||||||
stationAPIData.stationName
|
|
||||||
);
|
|
||||||
checkpoint.scheduledTrains.push(scheduledCheckpointTrain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acc.push(scheduledStopTrain);
|
// const dispatcherStatus = this.getDispatcherStatus(stationAPIData);
|
||||||
return acc;
|
// prevDispatcherStatuses.push(dispatcherStatus);
|
||||||
}, []) as ScheduledTrain[];
|
|
||||||
},
|
|
||||||
|
|
||||||
getStationTrains(stationAPIData: StationAPIData) {
|
// const stationTrains = this.getStationTrains(stationAPIData);
|
||||||
return this.trainList
|
// const scheduledTrains = this.getScheduledTrains(station?.generalInfo, stationAPIData);
|
||||||
.filter(
|
|
||||||
(train) =>
|
|
||||||
train?.region === this.region.id &&
|
|
||||||
train.online &&
|
|
||||||
train.currentStationName === stationAPIData.stationName
|
|
||||||
)
|
|
||||||
.map((train) => ({
|
|
||||||
driverName: train.driverName,
|
|
||||||
driverId: train.driverId,
|
|
||||||
trainNo: train.trainNo,
|
|
||||||
trainId: train.trainId
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
setStationsOnlineInfo() {
|
// const onlineInfo = {
|
||||||
const onlineStationNames: string[] = [];
|
// name: stationAPIData.stationName,
|
||||||
const prevDispatcherStatuses: StoreState['lastDispatcherStatuses'] = [];
|
// hash: stationAPIData.stationHash,
|
||||||
|
// region: stationAPIData.region,
|
||||||
|
// maxUsers: stationAPIData.maxUsers,
|
||||||
|
// currentUsers: stationAPIData.currentUsers,
|
||||||
|
// spawns: parseSpawns(stationAPIData.spawnString),
|
||||||
|
// dispatcherName: stationAPIData.dispatcherName,
|
||||||
|
// dispatcherRate: stationAPIData.dispatcherRate,
|
||||||
|
// dispatcherId: stationAPIData.dispatcherId,
|
||||||
|
// dispatcherExp: stationAPIData.dispatcherExp,
|
||||||
|
// dispatcherIsSupporter: stationAPIData.dispatcherIsSupporter,
|
||||||
|
// stationTrains,
|
||||||
|
// statusTimestamp: dispatcherStatus.statusTimestamp,
|
||||||
|
// statusID: dispatcherStatus.statusID,
|
||||||
|
// scheduledTrains
|
||||||
|
// };
|
||||||
|
|
||||||
if (this.isOffline) {
|
// if (!station) {
|
||||||
this.stationList.forEach((station) => {
|
// this.stationList.push({
|
||||||
station.onlineInfo = undefined;
|
// name: stationAPIData.stationName,
|
||||||
});
|
// onlineInfo
|
||||||
|
// });
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.apiData.stations?.forEach((stationAPIData) => {
|
// station.onlineInfo = { ...onlineInfo };
|
||||||
if (stationAPIData.region !== this.region.id || !stationAPIData.isOnline) return;
|
// });
|
||||||
const station = this.stationList.find((s) => s.name === stationAPIData.stationName);
|
|
||||||
|
|
||||||
onlineStationNames.push(stationAPIData.stationName);
|
// this.stationList
|
||||||
|
// .filter((station) => !onlineStationNames.includes(station.name) && station.onlineInfo)
|
||||||
|
// .forEach((offlineStation) => {
|
||||||
|
// offlineStation.onlineInfo = undefined;
|
||||||
|
// });
|
||||||
|
|
||||||
const dispatcherStatus = this.getDispatcherStatus(stationAPIData);
|
// if (this.apiData.dispatchers != null) this.lastDispatcherStatuses = prevDispatcherStatuses;
|
||||||
prevDispatcherStatuses.push(dispatcherStatus);
|
// },
|
||||||
|
|
||||||
const stationTrains = this.getStationTrains(stationAPIData);
|
|
||||||
const scheduledTrains = this.getScheduledTrains(station?.generalInfo, stationAPIData);
|
|
||||||
|
|
||||||
const onlineInfo = {
|
|
||||||
name: stationAPIData.stationName,
|
|
||||||
hash: stationAPIData.stationHash,
|
|
||||||
region: stationAPIData.region,
|
|
||||||
maxUsers: stationAPIData.maxUsers,
|
|
||||||
currentUsers: stationAPIData.currentUsers,
|
|
||||||
spawns: parseSpawns(stationAPIData.spawnString),
|
|
||||||
dispatcherName: stationAPIData.dispatcherName,
|
|
||||||
dispatcherRate: stationAPIData.dispatcherRate,
|
|
||||||
dispatcherId: stationAPIData.dispatcherId,
|
|
||||||
dispatcherExp: stationAPIData.dispatcherExp,
|
|
||||||
dispatcherIsSupporter: stationAPIData.dispatcherIsSupporter,
|
|
||||||
stationTrains,
|
|
||||||
statusTimestamp: dispatcherStatus.statusTimestamp,
|
|
||||||
statusID: dispatcherStatus.statusID,
|
|
||||||
scheduledTrains
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!station) {
|
|
||||||
this.stationList.push({
|
|
||||||
name: stationAPIData.stationName,
|
|
||||||
onlineInfo
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
station.onlineInfo = { ...onlineInfo };
|
|
||||||
|
|
||||||
this.stationList
|
|
||||||
.filter((station) => !onlineStationNames.includes(station.name) && station.onlineInfo)
|
|
||||||
.forEach((offlineStation) => {
|
|
||||||
offlineStation.onlineInfo = undefined;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.apiData.dispatchers != null) this.lastDispatcherStatuses = prevDispatcherStatuses;
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchStationsGeneralInfo() {
|
async fetchStationsGeneralInfo() {
|
||||||
const sceneryData: StationJSONData[] = await (
|
const sceneryData: StationJSONData[] = await (
|
||||||
@@ -385,7 +307,7 @@ export const useStore = defineStore('store', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const socket = io(URLs.stacjownikAPI, {
|
const socket = io(URLs.stacjownikAPI, {
|
||||||
// transports: ['websocket', 'polling'],
|
transports: ['websocket', 'polling'],
|
||||||
rememberUpgrade: true,
|
rememberUpgrade: true,
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
extraHeaders: {
|
extraHeaders: {
|
||||||
@@ -405,7 +327,6 @@ export const useStore = defineStore('store', {
|
|||||||
|
|
||||||
socket.emit('FETCH_DATA', { version: packageInfo.version }, (data: APIData) => {
|
socket.emit('FETCH_DATA', { version: packageInfo.version }, (data: APIData) => {
|
||||||
this.dataStatuses.connection = DataStatus.Loaded;
|
this.dataStatuses.connection = DataStatus.Loaded;
|
||||||
|
|
||||||
this.apiData = data;
|
this.apiData = data;
|
||||||
this.setOnlineData();
|
this.setOnlineData();
|
||||||
});
|
});
|
||||||
@@ -414,10 +335,9 @@ export const useStore = defineStore('store', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async connectToAPI() {
|
async connectToAPI() {
|
||||||
await this.fetchStationsGeneralInfo();
|
|
||||||
await this.fetchStockInfoData();
|
|
||||||
|
|
||||||
this.connectToWebsocket();
|
this.connectToWebsocket();
|
||||||
|
this.fetchStockInfoData();
|
||||||
|
this.fetchStationsGeneralInfo();
|
||||||
},
|
},
|
||||||
|
|
||||||
async changeRegion(region: StoreState['region']) {
|
async changeRegion(region: StoreState['region']) {
|
||||||
@@ -453,8 +373,7 @@ export const useStore = defineStore('store', {
|
|||||||
? DataStatus.Warning
|
? DataStatus.Warning
|
||||||
: DataStatus.Loaded;
|
: DataStatus.Loaded;
|
||||||
|
|
||||||
this.setTrainsOnlineData();
|
// this.setStationsOnlineInfo();
|
||||||
this.setStationsOnlineInfo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,10 +35,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--clr-bg);
|
background: var(--clr-bg);
|
||||||
|
|
||||||
|
|||||||
+35
-25
@@ -1,9 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="scenery-view">
|
<div class="scenery-view">
|
||||||
<div
|
<div class="scenery-offline" v-if="!stationInfo && store.dataStatuses.sceneries == 2">
|
||||||
class="scenery-offline"
|
|
||||||
v-if="!stationInfo && isComponentVisible && store.dataStatuses.sceneries == 2"
|
|
||||||
>
|
|
||||||
<div>{{ $t('scenery.no-scenery') }}</div>
|
<div>{{ $t('scenery.no-scenery') }}</div>
|
||||||
|
|
||||||
<action-button>
|
<action-button>
|
||||||
@@ -11,21 +8,16 @@
|
|||||||
</action-button>
|
</action-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="scenery-wrapper" v-if="stationInfo" ref="card-wrapper">
|
||||||
class="scenery-wrapper"
|
<div class="scenery-left">
|
||||||
v-if="stationInfo"
|
|
||||||
ref="card-wrapper"
|
|
||||||
:data-timetable-only="timetableOnly"
|
|
||||||
>
|
|
||||||
<div class="scenery-left" v-if="!timetableOnly">
|
|
||||||
<div class="scenery-actions">
|
<div class="scenery-actions">
|
||||||
<button class="back-btn btn" :title="$t('scenery.return-btn')" @click="navigateTo('/')">
|
<button class="back-btn btn" :title="$t('scenery.return-btn')" @click="navigateTo('/')">
|
||||||
<img src="/images/icon-back.svg" alt="Back to scenery" />
|
<img src="/images/icon-back.svg" alt="Back to scenery" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SceneryHeader :station="stationInfo" />
|
<SceneryHeader :station="stationInfo" :onlineScenery="onlineSceneryInfo" />
|
||||||
<SceneryInfo :station="stationInfo" />
|
<SceneryInfo :station="stationInfo" :onlineScenery="onlineSceneryInfo" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="scenery-right">
|
<div class="scenery-right">
|
||||||
@@ -44,6 +36,7 @@
|
|||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component
|
<component
|
||||||
:is="currentViewCompontent"
|
:is="currentViewCompontent"
|
||||||
|
:onlineScenery="onlineSceneryInfo"
|
||||||
:station="stationInfo"
|
:station="stationInfo"
|
||||||
:key="currentViewCompontent"
|
:key="currentViewCompontent"
|
||||||
></component>
|
></component>
|
||||||
@@ -82,9 +75,22 @@ export default defineComponent({
|
|||||||
SceneryDispatchersHistory
|
SceneryDispatchersHistory
|
||||||
},
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
region: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
|
||||||
|
station: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
mixins: [routerMixin],
|
mixins: [routerMixin],
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
store: useStore(),
|
||||||
viewModes: [
|
viewModes: [
|
||||||
{
|
{
|
||||||
id: 'scenery.option-active-timetables',
|
id: 'scenery.option-active-timetables',
|
||||||
@@ -111,24 +117,28 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
const timetableOnly = computed(() => (route.query['timetableOnly'] == '1' ? true : false));
|
|
||||||
const isComponentVisible = computed(() => route.path === '/scenery');
|
const isComponentVisible = computed(() => route.path === '/scenery');
|
||||||
|
|
||||||
const stationInfo = computed(() => {
|
|
||||||
return store.stationList.find(
|
|
||||||
(station) => station.name === route.query.station?.toString().replace(/_/g, ' ')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timetableOnly,
|
isComponentVisible
|
||||||
isComponentVisible,
|
|
||||||
stationInfo,
|
|
||||||
store
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
stationInfo() {
|
||||||
|
return this.store.stationList.find(
|
||||||
|
(station) => station.name === this.station?.toString().replace(/_/g, ' ')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
onlineSceneryInfo() {
|
||||||
|
return this.store.onlineSceneryList.find(
|
||||||
|
(scenery) => scenery.name === this.station?.toString().replace(/_/g, ' ')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
setViewMode(componentName: string) {
|
setViewMode(componentName: string) {
|
||||||
this.currentViewCompontent = componentName;
|
this.currentViewCompontent = componentName;
|
||||||
|
|||||||
@@ -33,19 +33,15 @@ export default defineComponent({
|
|||||||
filterCardOpen: false,
|
filterCardOpen: false,
|
||||||
modalHidden: true,
|
modalHidden: true,
|
||||||
STORAGE_KEY: 'options_saved',
|
STORAGE_KEY: 'options_saved',
|
||||||
focusedStationName: ''
|
focusedStationName: '',
|
||||||
|
filterStore: useStationFiltersStore(),
|
||||||
|
store: useStore()
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
filterStore: useStationFiltersStore(),
|
|
||||||
store: useStore()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
computedStationList() {
|
computedStationList() {
|
||||||
return this.filterStore.getFilteredStationList(this.store.stationList, this.store.region.id);
|
return this.filterStore.filteredStationList;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+27
-17
@@ -4,7 +4,7 @@ import { VitePWA } from 'vite-plugin-pwa';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
port: 5001,
|
port: 5001
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
@@ -20,13 +20,25 @@ export default defineConfig({
|
|||||||
options: {
|
options: {
|
||||||
cacheName: 'sceneries-cache',
|
cacheName: 'sceneries-cache',
|
||||||
expiration: {
|
expiration: {
|
||||||
maxEntries: 1,
|
maxAgeSeconds: 60 * 60 * 24 * 7 // <== 7 days
|
||||||
maxAgeSeconds: 60 * 60 * 24 * 7, // <== 7 days
|
|
||||||
},
|
},
|
||||||
cacheableResponse: {
|
cacheableResponse: {
|
||||||
statuses: [0, 200],
|
statuses: [0, 200]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: new RegExp('^https://raw.githubusercontent.com/Spythere/api/*', 'i'),
|
||||||
|
handler: 'NetworkFirst',
|
||||||
|
options: {
|
||||||
|
cacheName: 'github-api-cache',
|
||||||
|
expiration: {
|
||||||
|
maxAgeSeconds: 60 * 60 * 24 * 7 // <== 7 days
|
||||||
},
|
},
|
||||||
},
|
cacheableResponse: {
|
||||||
|
statuses: [0, 200]
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
urlPattern: /^https:\/\/rj.td2.info.pl\/dist\/img\/thumbnails\/.*/i,
|
urlPattern: /^https:\/\/rj.td2.info.pl\/dist\/img\/thumbnails\/.*/i,
|
||||||
@@ -35,21 +47,19 @@ export default defineConfig({
|
|||||||
cacheName: 'images-cache',
|
cacheName: 'images-cache',
|
||||||
expiration: {
|
expiration: {
|
||||||
maxEntries: 100,
|
maxEntries: 100,
|
||||||
maxAgeSeconds: 60 * 60 * 24 * 60,
|
maxAgeSeconds: 60 * 60 * 24 * 7 // <== 7 days
|
||||||
},
|
},
|
||||||
cacheableResponse: {
|
cacheableResponse: {
|
||||||
statuses: [0, 200, 404],
|
statuses: [0, 200, 404]
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
devOptions: {
|
devOptions: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
suppressWarnings: true
|
||||||
}),
|
}
|
||||||
],
|
})
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user