mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af6eb35b67 | |||
| 1e6ab1c2d1 | |||
| fd4849bd5e | |||
| bc0f4c5d3f | |||
| 8909a0cd40 | |||
| a2602aeefe | |||
| 37ad9b2787 | |||
| 0b4ad679b3 | |||
| dd0d7897cf | |||
| 1453dbda01 | |||
| 4af856b833 | |||
| 182b46a377 | |||
| bb5fc395d2 | |||
| a91a00f88a | |||
| c8d481a952 | |||
| 03ff4d8648 | |||
| 23767801d5 | |||
| 310261fb59 | |||
| 742754ceef | |||
| b9bb9dc201 | |||
| 611927f96f | |||
| 2e191f355e | |||
| f974643e37 | |||
| 02afe2bf33 | |||
| ebdffc6241 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "stacjownik",
|
||||
"version": "1.30.1",
|
||||
"version": "1.30.3",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
+31
-5
@@ -5,9 +5,11 @@
|
||||
@toggle-card="() => (isUpdateCardOpen = false)"
|
||||
/>
|
||||
|
||||
<AppWelcomeCard :is-card-open="isWelcomeCardOpen" @toggle-card="closeWelcomeCard" />
|
||||
|
||||
<Tooltip />
|
||||
|
||||
<AppHeader :current-lang="currentLang" @change-lang="changeLang" />
|
||||
|
||||
<AppHeader :current-lang="store.currentLocale" @change-lang="changeLang" />
|
||||
|
||||
<main class="app_main">
|
||||
<router-view v-slot="{ Component }">
|
||||
@@ -44,8 +46,10 @@ import UpdateCard from './components/App/UpdateCard.vue';
|
||||
|
||||
import StorageManager from './managers/storageManager';
|
||||
import AppFooter from './components/App/AppFooter.vue';
|
||||
import AppWelcomeCard from './components/App/AppWelcomeCard.vue';
|
||||
|
||||
const STORAGE_VERSION_KEY = 'app_version';
|
||||
const WELCOME_CARD_SEEN_KEY = 'welcome_card_seen';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -54,6 +58,7 @@ export default defineComponent({
|
||||
AppHeader,
|
||||
AppFooter,
|
||||
UpdateCard,
|
||||
AppWelcomeCard,
|
||||
Tooltip
|
||||
},
|
||||
|
||||
@@ -64,8 +69,8 @@ export default defineComponent({
|
||||
tooltipStore: useTooltipStore(),
|
||||
|
||||
isUpdateCardOpen: false,
|
||||
isWelcomeCardOpen: false,
|
||||
|
||||
currentLang: 'pl',
|
||||
isOnProductionHost: location.hostname == 'stacjownik-td2.web.app'
|
||||
}),
|
||||
|
||||
@@ -85,13 +90,29 @@ export default defineComponent({
|
||||
this.loadLang();
|
||||
this.setupOfflineHandling();
|
||||
this.checkAppVersion();
|
||||
this.handleQueries();
|
||||
|
||||
this.apiStore.setupAPIData();
|
||||
},
|
||||
|
||||
handleQueries() {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
|
||||
if (query.get('welcomeCard') == '1') {
|
||||
this.isWelcomeCardOpen = true;
|
||||
}
|
||||
},
|
||||
|
||||
async checkAppVersion() {
|
||||
const isWelcomeCardSeen = StorageManager.getBooleanValue(WELCOME_CARD_SEEN_KEY);
|
||||
const storageVersion = StorageManager.getStringValue(STORAGE_VERSION_KEY);
|
||||
|
||||
if (isWelcomeCardSeen == false && storageVersion == '') {
|
||||
setTimeout(() => {
|
||||
this.isWelcomeCardOpen = true;
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
try {
|
||||
const releaseData = await (
|
||||
await axios.get('https://api.github.com/repos/Spythere/stacjownik/releases/latest')
|
||||
@@ -140,7 +161,7 @@ export default defineComponent({
|
||||
|
||||
changeLang(lang: string) {
|
||||
this.$i18n.locale = lang;
|
||||
this.currentLang = lang;
|
||||
this.store.currentLocale = lang;
|
||||
|
||||
StorageManager.setStringValue('lang', lang);
|
||||
},
|
||||
@@ -157,10 +178,15 @@ export default defineComponent({
|
||||
|
||||
const naviLanguage = window.navigator.language.toString();
|
||||
|
||||
if (naviLanguage.startsWith('en')) {
|
||||
if (!naviLanguage.startsWith('pl')) {
|
||||
this.changeLang('en');
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
closeWelcomeCard() {
|
||||
this.isWelcomeCardOpen = false;
|
||||
StorageManager.setBooleanValue(WELCOME_CARD_SEEN_KEY, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
<br />
|
||||
<a href="https://discord.gg/x2mpNN3svk">
|
||||
<img src="/images/icon-discord.png" alt="" /> <b>{{ $t('footer.discord') }}</b>
|
||||
<img src="/images/icon-discord.png" alt="discord logo icon" /> <b class="text--discord">
|
||||
{{ $t('footer.discord') }}
|
||||
</b>
|
||||
</a>
|
||||
|
||||
<div style="display: none">∫ ukryta taktyczna całka do programowania w HTMLu</div>
|
||||
@@ -36,4 +38,4 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<Card :is-open="props.isCardOpen">
|
||||
<div class="body-content">
|
||||
<h1>{{ $t('welcome.title') }}</h1>
|
||||
|
||||
<div class="language-select">
|
||||
<button :data-active="$i18n.locale == 'pl'" @click="changeLang('pl')">
|
||||
<img src="/images/icon-pl.svg" alt="" width="45" />
|
||||
</button>
|
||||
|
||||
<button :data-active="$i18n.locale == 'en'" @click="changeLang('en')">
|
||||
<img src="/images/icon-en.jpg" alt="" width="45" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<section class="app-description">
|
||||
<i18n-t keypath="welcome.app-desc" tag="p">
|
||||
<template v-slot:b1>
|
||||
<b>{{ $t('welcome.app-desc-b1') }}</b>
|
||||
</template>
|
||||
|
||||
<template v-slot:link>
|
||||
<a href="https://td2.info.pl/" class="link" target="_blank">Train Driver 2</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</section>
|
||||
|
||||
<section class="tabs">
|
||||
<div class="tab-description">
|
||||
<h2 class="text--primary">{{ $t('welcome.sceneries-header') }}</h2>
|
||||
<hr />
|
||||
<i18n-t keypath="welcome.sceneries-desc" tag="p">
|
||||
<template v-slot:b1>
|
||||
<b>{{ $t('welcome.sceneries-desc-b1') }}</b>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
|
||||
<div class="tab-description">
|
||||
<h2 class="text--primary">{{ $t('welcome.trains-header') }}</h2>
|
||||
<hr />
|
||||
<i18n-t keypath="welcome.trains-desc" tag="p">
|
||||
<template v-slot:b1>
|
||||
<b>{{ $t('welcome.trains-desc-b1') }}</b>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
|
||||
<div class="tab-description">
|
||||
<h2 class="text--primary">{{ $t('welcome.journal-header') }}</h2>
|
||||
<hr />
|
||||
<i18n-t keypath="welcome.journal-desc" tag="p">
|
||||
<template v-slot:b1>
|
||||
<b>{{ $t('welcome.journal-desc-b1') }}</b>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="other-apps">
|
||||
<b class="text--primary">
|
||||
{{ $t('welcome.other-apps') }}
|
||||
</b>
|
||||
|
||||
<div class="apps-grid">
|
||||
<a class="app-item" href="https://pojazdownik-td2.web.app/" target="_blank">
|
||||
<img src="/images/icon-pojazdownik.svg" alt="pojazdownik app logo" />
|
||||
<h3 class="text--primary">Pojazdownik</h3>
|
||||
<p>{{ $t('welcome.pojazdownik-desc') }}</p>
|
||||
</a>
|
||||
|
||||
<a class="app-item" href="https://generator-td2.web.app/" target="_blank">
|
||||
<img src="/images/icon-gnr.svg" alt="generator app logo" />
|
||||
<h3 class="text--primary">GeneraTOR</h3>
|
||||
<p>{{ $t('welcome.generator-desc') }}</p>
|
||||
</a>
|
||||
|
||||
<a class="app-item" href="https://srjp-td2.web.app/" target="_blank">
|
||||
<img src="/images/icon-srjp.svg" alt="srjp app logo" />
|
||||
<h3 class="text--primary">Rozkładownik</h3>
|
||||
<p>{{ $t('welcome.srjp-desc') }}</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="bottom-info">
|
||||
<i18n-t keypath="welcome.donation-info" tag="div" class="donation-info">
|
||||
<template v-slot:icon1>
|
||||
<img src="/images/icon-diamond.svg" alt="diamond icon" width="25" />
|
||||
<span class="text--donator"> {{ $t('welcome.donation-info-icon1-text') }}</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
|
||||
<i18n-t keypath="welcome.discord-info" tag="div" class="discord-info">
|
||||
<template v-slot:discord>
|
||||
<a href="https://discord.gg/x2mpNN3svk" class="link" target="_blank">
|
||||
<b class="text--discord">{{ $t('welcome.discord-info-link-text') }}</b>
|
||||
</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
|
||||
<div class="bottom-text">
|
||||
<i>{{ $t('welcome.bottom-text') }}</i>
|
||||
</div>
|
||||
|
||||
<div class="bottom-actions">
|
||||
<button class="btn btn--action" @click="toggleCard(false)">
|
||||
{{ $t('welcome.button-confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Card from '../Global/Card.vue';
|
||||
import { useMainStore } from '../../store/mainStore';
|
||||
import StorageManager from '../../managers/storageManager';
|
||||
|
||||
const i18n = useI18n();
|
||||
const store = useMainStore();
|
||||
|
||||
const emit = defineEmits(['toggleCard']);
|
||||
const props = defineProps({
|
||||
isCardOpen: Boolean
|
||||
});
|
||||
|
||||
function toggleCard(state: boolean) {
|
||||
emit('toggleCard', state);
|
||||
}
|
||||
|
||||
function changeLang(localeName: string) {
|
||||
i18n.locale.value = localeName;
|
||||
store.currentLocale = localeName;
|
||||
|
||||
StorageManager.setStringValue('lang', localeName);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.body-content {
|
||||
max-width: 800px;
|
||||
min-height: 900px;
|
||||
padding: 1em 0.5em;
|
||||
|
||||
text-align: center;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
a.link {
|
||||
text-decoration: underline;
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.language-select {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0.5em 0;
|
||||
|
||||
button[data-active='false'] img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.app-description {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.tab-description {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.other-apps {
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.apps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.apps-grid > a.app-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
padding: 1em;
|
||||
background-color: #2b2b2b;
|
||||
transition: background-color 100ms ease-in-out;
|
||||
border-radius: 0.5em;
|
||||
|
||||
&:hover {
|
||||
background-color: #3b3b3b;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 2.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.donation-info {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.discord-info {
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-text {
|
||||
margin: 1em 0;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 1em;
|
||||
|
||||
font-size: 1.25em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,13 @@
|
||||
<template>
|
||||
<section class="info-header">
|
||||
<button
|
||||
class="btn btn-return"
|
||||
:title="$t('scenery.return-btn')"
|
||||
@click="onReturnButtonClick"
|
||||
>
|
||||
<img src="/images/icon-back.svg" alt="return button" />
|
||||
</button>
|
||||
|
||||
<a class="scenery-name" :href="station?.generalInfo?.url" target="_blank">
|
||||
{{ stationName.replace(/_/g, ' ') }}
|
||||
</a>
|
||||
@@ -12,39 +20,64 @@
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { PropType, defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, PropType, ref } from 'vue';
|
||||
import { ActiveScenery, Station } from '../../typings/common';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
station: {
|
||||
type: Object as PropType<Station>
|
||||
},
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
stationName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
const prevPath = ref('/');
|
||||
|
||||
onlineScenery: {
|
||||
type: Object as PropType<ActiveScenery>
|
||||
}
|
||||
onMounted(() => {
|
||||
prevPath.value = (route.meta['prevPath'] as string) ?? '/';
|
||||
});
|
||||
|
||||
defineProps({
|
||||
station: {
|
||||
type: Object as PropType<Station>
|
||||
},
|
||||
|
||||
stationName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
|
||||
onlineScenery: {
|
||||
type: Object as PropType<ActiveScenery>
|
||||
}
|
||||
});
|
||||
|
||||
function onReturnButtonClick() {
|
||||
router.push(prevPath.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/responsive';
|
||||
@use 'sass:color';
|
||||
|
||||
.info-header {
|
||||
margin-top: 1em;
|
||||
.btn-return {
|
||||
$bgColor: #2b2b2b;
|
||||
background-color: $bgColor;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
img {
|
||||
width: 2em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: color.adjust($color: $bgColor, $lightness: 15%);
|
||||
}
|
||||
}
|
||||
|
||||
.scenery-name {
|
||||
font-weight: bold;
|
||||
font-size: 3em;
|
||||
|
||||
text-align: center;
|
||||
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@@ -58,4 +91,10 @@ export default defineComponent({
|
||||
color: #aaa;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
@include responsive.smallScreen {
|
||||
.scenery-name {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
{{ route.routeName }}
|
||||
</span>
|
||||
<span v-if="route.routeSpeed" class="speed">{{ route.routeSpeed }}</span>
|
||||
<span v-if="route.routeSpeedExit" class="speed">| {{ route.routeSpeedExit }}</span>
|
||||
<span v-if="route.routeLength" class="length">
|
||||
{{ (route.routeLength / 1000).toFixed(1) + 'km' }}
|
||||
</span>
|
||||
|
||||
@@ -93,18 +93,56 @@
|
||||
<span class="timetable-general">
|
||||
<span class="general-info">
|
||||
<div class="info-train">
|
||||
<b
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="getCategoryExplanation(row.train.timetableData!.category)"
|
||||
class="text--primary tooltip-help"
|
||||
>
|
||||
{{ row.train.timetableData!.category }}
|
||||
</b>
|
||||
<span> </span>
|
||||
<b>{{ row.train.trainNo }}</b>
|
||||
<span> • </span>
|
||||
<span>{{ row.train.driverName }}</span>
|
||||
<!-- Cargo warnings & details badges -->
|
||||
<span
|
||||
class="train-badge twr"
|
||||
v-if="row.train.timetableData!.twr"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="$t('warnings.TWR')"
|
||||
>
|
||||
TWR
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="train-badge tn"
|
||||
v-if="row.train.timetableData!.hasDangerousCargo"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="$t('warnings.TN')"
|
||||
>
|
||||
TN
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="train-badge pn"
|
||||
v-if="row.train.timetableData!.hasExtraDeliveries"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="$t('warnings.PN')"
|
||||
>
|
||||
PN
|
||||
</span>
|
||||
|
||||
<!-- Train info -->
|
||||
<span>
|
||||
<b
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="
|
||||
getCategoryExplanation(row.train.timetableData!.category)
|
||||
"
|
||||
class="text--primary tooltip-help"
|
||||
>
|
||||
{{ row.train.timetableData!.category }}
|
||||
</b>
|
||||
|
||||
<b> {{ row.train.trainNo }}</b>
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span>{{ row.train.driverName }}</span>
|
||||
<span>•</span>
|
||||
<b style="color: #ddd">{{ row.train.stockList[0] }}</b>
|
||||
|
||||
<!-- Train stop comments -->
|
||||
<span
|
||||
class="stop-comments-icon"
|
||||
v-if="row.checkpointStop.comments"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="row.checkpointStop.comments"
|
||||
@@ -352,6 +390,7 @@ export default defineComponent({
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/responsive';
|
||||
@use '../../styles/animations';
|
||||
@use '../../styles/badge';
|
||||
|
||||
.scenery-timetable {
|
||||
height: 100%;
|
||||
@@ -468,21 +507,31 @@ export default defineComponent({
|
||||
|
||||
.general-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.info-number {
|
||||
color: var(--clr-primary);
|
||||
}
|
||||
.info-train {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25em;
|
||||
}
|
||||
|
||||
.info-route {
|
||||
width: 100%;
|
||||
}
|
||||
.info-train > .train-badge {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 0.9em;
|
||||
vertical-align: middle;
|
||||
margin: 0 0.25em;
|
||||
}
|
||||
.info-number {
|
||||
color: var(--clr-primary);
|
||||
}
|
||||
|
||||
.info-route {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.stop-comments-icon > img {
|
||||
width: 1.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.schedule {
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
<div class="general-status">
|
||||
<span
|
||||
:class="computedScheduledTrain.status"
|
||||
data-tooltip-type="HtmlTooltip"
|
||||
:data-tooltip-content="computedScheduledTrain.stopStatusDescription"
|
||||
@click.prevent="() => {}"
|
||||
v-html="computedScheduledTrain.stopStatusIndicator"
|
||||
>
|
||||
{{ computedScheduledTrain.stopStatusIndicator }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -28,48 +26,37 @@ export default defineComponent({
|
||||
computedScheduledTrain() {
|
||||
const { status, prevElement, currentElement, nextElement } = this.sceneryTimetableRow;
|
||||
|
||||
const prevDepartureIndicator = prevElement?.departureRouteExt
|
||||
? `(${prevElement.departureRouteExt}) ${prevElement.stationName}`
|
||||
: '---';
|
||||
|
||||
const nextArrivalIndicator = nextElement?.arrivalRouteExt
|
||||
? `(${nextElement.arrivalRouteExt}) ${nextElement.stationName}`
|
||||
: `${currentElement.stationName}`;
|
||||
|
||||
let stopStatusDescription = '',
|
||||
stopStatusIndicator = '';
|
||||
let stopStatusIndicator = '';
|
||||
|
||||
switch (status) {
|
||||
case StopStatus.ARRIVING:
|
||||
stopStatusIndicator = `${this.$t('timetables.from')}: ${prevDepartureIndicator}`;
|
||||
stopStatusDescription = this.$t('timetables.desc-arriving', {
|
||||
prevStationName: prevElement?.stationName ?? '',
|
||||
prevDepartureLine: prevElement?.departureRouteExt ?? ''
|
||||
});
|
||||
if (prevElement) {
|
||||
stopStatusIndicator = this.$t('timetables.desc-arriving', {
|
||||
prevStationName: prevElement?.stationName ?? '',
|
||||
prevDepartureLine: prevElement?.departureRouteExt ?? ''
|
||||
});
|
||||
} else {
|
||||
stopStatusIndicator = this.$t('timetables.desc-beginning');
|
||||
}
|
||||
break;
|
||||
|
||||
case StopStatus.ONLINE:
|
||||
case StopStatus.STOPPED:
|
||||
stopStatusIndicator = nextElement?.arrivalRouteExt
|
||||
? `${this.$t('timetables.to')}: ${nextArrivalIndicator}`
|
||||
: `${this.$t('timetables.desc-end')}`;
|
||||
stopStatusDescription = nextElement?.arrivalRouteExt
|
||||
? this.$t(`timetables.desc-${status}`, {
|
||||
nextStationName: nextElement?.stationName,
|
||||
nextArrivalLine: nextElement?.arrivalRouteExt
|
||||
})
|
||||
: '';
|
||||
: this.$t(`timetables.desc-end`);
|
||||
break;
|
||||
|
||||
case StopStatus.DEPARTED:
|
||||
stopStatusIndicator = `${this.$t('timetables.to')}: ${nextArrivalIndicator}`;
|
||||
|
||||
if (!nextElement?.stationName) {
|
||||
stopStatusDescription = this.$t('timetables.desc-departed-ends', {
|
||||
stopStatusIndicator = this.$t('timetables.desc-departed-ends', {
|
||||
nextStationName: currentElement.stationName
|
||||
});
|
||||
} else {
|
||||
stopStatusDescription = this.$t('timetables.desc-departed', {
|
||||
stopStatusIndicator = this.$t('timetables.desc-departed', {
|
||||
nextStationName: nextElement?.stationName ?? currentElement.stationName,
|
||||
nextArrivalLine: nextElement?.arrivalRouteExt
|
||||
});
|
||||
@@ -78,16 +65,14 @@ export default defineComponent({
|
||||
break;
|
||||
|
||||
case StopStatus.DEPARTED_AWAY:
|
||||
stopStatusIndicator = `${this.$t('timetables.to')}: ${nextArrivalIndicator}`;
|
||||
stopStatusDescription = this.$t('timetables.desc-departed-away', {
|
||||
stopStatusIndicator = this.$t('timetables.desc-departed-away', {
|
||||
nextStationName: nextElement?.stationName,
|
||||
nextArrivalLine: nextElement?.arrivalRouteExt
|
||||
});
|
||||
break;
|
||||
|
||||
case StopStatus.TERMINATED:
|
||||
stopStatusIndicator = `X ${this.$t('timetables.desc-terminated')}`;
|
||||
stopStatusDescription = this.$t('timetables.desc-terminated');
|
||||
stopStatusIndicator = this.$t('timetables.desc-terminated');
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -95,7 +80,6 @@ export default defineComponent({
|
||||
}
|
||||
return {
|
||||
...this.sceneryTimetableRow,
|
||||
stopStatusDescription,
|
||||
stopStatusIndicator
|
||||
};
|
||||
}
|
||||
@@ -106,7 +90,6 @@ export default defineComponent({
|
||||
<style lang="scss" scoped>
|
||||
.general-status {
|
||||
margin-top: 0.5em;
|
||||
cursor: help;
|
||||
|
||||
span.arriving {
|
||||
color: #ccc;
|
||||
@@ -114,17 +97,14 @@ export default defineComponent({
|
||||
|
||||
span.departed {
|
||||
color: lime;
|
||||
font-weight: bold;
|
||||
|
||||
&-away {
|
||||
font-weight: bold;
|
||||
color: #5ecc5e;
|
||||
}
|
||||
}
|
||||
|
||||
span.stopped {
|
||||
color: #ffa600;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.online {
|
||||
@@ -133,7 +113,6 @@ export default defineComponent({
|
||||
|
||||
span.terminated {
|
||||
color: salmon;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<span
|
||||
class="train-badge twr"
|
||||
v-if="train.timetableData?.TWR"
|
||||
v-if="train.timetableData?.twr"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="$t('warnings.TWR')"
|
||||
>
|
||||
@@ -156,7 +156,7 @@
|
||||
v-if="extended && train.timetableData && train.timetableData.warningNotes"
|
||||
>
|
||||
<div class="dangers-badges">
|
||||
<div v-if="train.timetableData?.TWR">
|
||||
<div v-if="train.timetableData?.twr">
|
||||
<div class="train-badge twr">TWR</div>
|
||||
- {{ $t('warnings.TWR') }}
|
||||
</div>
|
||||
|
||||
@@ -57,7 +57,14 @@
|
||||
<span>{{ stop.departureLine }}</span>
|
||||
|
||||
<span v-if="stop.departureLineInfo">
|
||||
<span> | {{ stop.departureLineInfo.routeSpeed }}</span>
|
||||
<span>
|
||||
|
|
||||
{{
|
||||
stop.departureLineInfo.routeSpeedExit
|
||||
? `${stop.departureLineInfo.routeSpeedExit} (${stop.departureLineInfo.routeSpeed})`
|
||||
: stop.departureLineInfo.routeSpeed
|
||||
}}</span
|
||||
>
|
||||
|
||||
<img
|
||||
:src="
|
||||
@@ -85,13 +92,13 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="stop.sceneryName != scheduleStops[i + 1]?.sceneryName"
|
||||
v-if="stop.nextPointRef && stop.sceneryName != stop.nextPointRef.sceneryName"
|
||||
class="scenery-change-name"
|
||||
>
|
||||
<span>{{ scheduleStops[i + 1].sceneryName }}</span>
|
||||
<span>{{ stop.nextPointRef.sceneryName }}</span>
|
||||
|
||||
<i
|
||||
v-if="!scheduleStops[i + 1].isSceneryOnline"
|
||||
v-if="!stop.nextPointRef.isSceneryOnline"
|
||||
class="fa-solid fa-ban fa-sm"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="$t('app.tooltip-scenery-offline')"
|
||||
@@ -101,30 +108,33 @@
|
||||
|
||||
<div
|
||||
class="scenery-route"
|
||||
v-if="stop.sceneryName != scheduleStops[i + 1]?.sceneryName"
|
||||
v-if="stop.nextPointRef && stop.sceneryName != stop.nextPointRef.sceneryName"
|
||||
>
|
||||
<span> {{ scheduleStops[i + 1].arrivalLine }}</span>
|
||||
<span> {{ stop.nextPointRef.arrivalLine }}</span>
|
||||
|
||||
<span v-if="scheduleStops[i + 1].arrivalLineInfo">
|
||||
<span> | {{ scheduleStops[i + 1].arrivalLineInfo!.routeSpeed }} </span>
|
||||
<span v-if="stop.nextPointRef.arrivalLineInfo">
|
||||
<span> | {{ stop.nextPointRef.arrivalLineInfo!.routeSpeed }}</span>
|
||||
<span v-if="stop.nextPointRef.arrivalLineInfo!.routeSpeedExit"
|
||||
>({{ stop.nextPointRef.arrivalLineInfo!.routeSpeedExit }})</span
|
||||
>
|
||||
|
||||
<img
|
||||
:src="
|
||||
scheduleStops[i + 1].arrivalLineInfo?.isElectric
|
||||
stop.nextPointRef.arrivalLineInfo?.isElectric
|
||||
? '/images/icon-catenary.svg'
|
||||
: '/images/icon-we4a.png'
|
||||
"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
:data-tooltip-content="
|
||||
$t(
|
||||
`trains.${!scheduleStops[i + 1].arrivalLineInfo?.isElectric ? 'no-' : ''}catenary-tooltip`
|
||||
`trains.${!stop.nextPointRef.arrivalLineInfo?.isElectric ? 'no-' : ''}catenary-tooltip`
|
||||
)
|
||||
"
|
||||
width="14"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="scheduleStops[i + 1].arrivalLineInfo!.isRouteSBL"
|
||||
v-if="stop.nextPointRef.arrivalLineInfo!.isRouteSBL"
|
||||
src="/images/icon-sbl-transparent.svg"
|
||||
width="14"
|
||||
data-tooltip-type="BaseTooltip"
|
||||
@@ -228,7 +238,7 @@ export default defineComponent({
|
||||
departureLineInfo = pathData.departureLineData;
|
||||
}
|
||||
|
||||
for (const stop of followingStops) {
|
||||
followingStops.forEach((stop, i) => {
|
||||
let isExternal = false;
|
||||
|
||||
if (stop.arrivalLine === currentPath.arrivalRouteExt) {
|
||||
@@ -287,7 +297,9 @@ export default defineComponent({
|
||||
status: stop.confirmed ? 'confirmed' : stop.stopped ? 'stopped' : 'unconfirmed',
|
||||
|
||||
sceneryName: currentPath.stationName,
|
||||
isSceneryOnline: pathData?.isOnline ?? false
|
||||
isSceneryOnline: pathData?.isOnline ?? false,
|
||||
|
||||
nextPointRef: null
|
||||
};
|
||||
|
||||
if (internalRouteInfo) {
|
||||
@@ -309,6 +321,11 @@ export default defineComponent({
|
||||
|
||||
stopRows.push(rowData);
|
||||
|
||||
// Assign this row data object to the last one as reference
|
||||
if (i != 0) {
|
||||
stopRows[i - 1].nextPointRef = rowData;
|
||||
}
|
||||
|
||||
if (stop.departureLine === currentPath.departureRouteExt) {
|
||||
// Reverse search for last scenery checkpoint
|
||||
if (pathData?.departureLineData) {
|
||||
@@ -328,7 +345,7 @@ export default defineComponent({
|
||||
currentPath = timetablePath[++currentPathIndex];
|
||||
pathData = this.getPathSceneryData(currentPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return stopRows;
|
||||
},
|
||||
|
||||
@@ -196,4 +196,6 @@ export interface TrainSchedulePoint {
|
||||
isSBL: boolean;
|
||||
sceneryName: string | null;
|
||||
isSceneryOnline: boolean;
|
||||
|
||||
nextPointRef: TrainSchedulePoint | null;
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
"TRE", "TRS",
|
||||
"TSE", "TSS",
|
||||
"THE", "THS",
|
||||
"LPE",
|
||||
"LPE", "LPS",
|
||||
"LTE", "LTS",
|
||||
"LSS",
|
||||
"LZE", "LZS",
|
||||
|
||||
+37
-12
@@ -1,4 +1,28 @@
|
||||
{
|
||||
"welcome": {
|
||||
"title": "Welcome to Stacjownik!",
|
||||
"app-desc": "{b1} is a web tool made for {link}, which main goal is to assist in-game dispatchers and drivers on their duties. Here you can find who is currently online and on what scenery, find a train driver or browse the journal, which contains a history of past timetables and dispatcher duty.",
|
||||
"app-desc-b1": "Stacjownik",
|
||||
"sceneries-header": "Sceneries",
|
||||
"sceneries-desc": "Under the {b1} tab, you will find information about the dispatchers and sceneries they currently occupy. You can also browse all available sceneries in the simulator (in the filters, check the “Free” option to show the rest of the unoccupied ones) and filter them by various aspects, such as control types, additional software, signaling types, required duty level or types of routes. Click on the corresponding scenery in the table to show its details.",
|
||||
"sceneries-desc-b1": "Sceneries",
|
||||
"trains-header": "Trains",
|
||||
"trains-desc": "The {b1} tab contains a list of active drivers and timetables that are currently realized on the selected server (server selection is at the top of the page, next to the counters). The list can be filtered and sorted, taking into account the most important criteria, such as driver name, train number or timetable details. You can also click on the train to show additional information.",
|
||||
"trains-desc-b1": "Trains",
|
||||
"journal-header": "Journal",
|
||||
"journal-desc": "The {b1} is a tab where you can find dispatcher duty and timetables history (currently only from the main PL1 game server). You can also search for a particular player's history using additional filters.",
|
||||
"journal-desc-b1": "Journal",
|
||||
"other-apps": "Also check out other apps designed to make TD2 gameplay easier:",
|
||||
"pojazdownik-desc": "online rolling stock editor",
|
||||
"generator-desc": "graphical manager of train orders",
|
||||
"srjp-desc": "Polish working train timetable",
|
||||
"donation-info": "If you appreciate the Stacjownik project as well as other applications, please consider supporting it financially - click the button with {icon1} to learn more!",
|
||||
"donation-info-icon1-text": "the diamond icon",
|
||||
"discord-info": "I also invite you to the official {discord}, where you will find a dedicated Stacjobot, with which you can search for additional data from the simulator, unavailable on this site!",
|
||||
"discord-info-link-text": "Stacjownik Discord server",
|
||||
"bottom-text": "Enjoy!\n~Spythere",
|
||||
"button-confirm": "Start using the app!"
|
||||
},
|
||||
"donations": {
|
||||
"button-title": "TOSS A COIN",
|
||||
"header": "Toss a coin to Stacjownik!",
|
||||
@@ -60,7 +84,7 @@
|
||||
"categories": {
|
||||
"EI": "domestic express",
|
||||
"EC": "international express",
|
||||
"EN": "domestic night express",
|
||||
"EN": "international night express",
|
||||
"MP": "intervoivodeship bullet",
|
||||
"MO": "intervoivodeship regio",
|
||||
"MM": "international bullet",
|
||||
@@ -519,7 +543,7 @@
|
||||
"no-users": "NO ACTIVE PLAYERS",
|
||||
"no-spawns": "NO OPEN SPAWNS",
|
||||
"no-scenery": "Oops! This scenery doesn't exist!",
|
||||
"return-btn": "Return",
|
||||
"return-btn": "BACK TO THE LAST SITE",
|
||||
"history-btn": "View the dispatcher history",
|
||||
"info-btn": "Return to the scenery view",
|
||||
"authors-title": "Scenery author | Scenery authors",
|
||||
@@ -527,7 +551,7 @@
|
||||
"lines-title": "Real lines",
|
||||
"project-title": "Project name",
|
||||
"additional-tools-title": "Additional tools",
|
||||
"one-way-routes": "Signle track routes",
|
||||
"one-way-routes": "Single track routes",
|
||||
"two-way-routes": "Double track routes",
|
||||
"no-data": "No available data about this scenery",
|
||||
"option-active-timetables": "Active timetables",
|
||||
@@ -565,15 +589,16 @@
|
||||
"terminated": "Timetable terminated",
|
||||
"begins": "BEGINS HERE",
|
||||
"terminates": "TERMINATES\nHERE",
|
||||
"from": "FROM",
|
||||
"to": "TO",
|
||||
"desc-arriving": "The train is not here yet.\nIt's going to come from: <b>{prevStationName} (route {prevDepartureLine})</b>",
|
||||
"desc-online": "The train is at the station.\nIt's going to leave to: <b>{nextStationName} (route {nextArrivalLine})</b>",
|
||||
"desc-stopped": "The train is at the station and is stopped.\nIt's going to leave towards: <b>{nextStationName} (route {nextArrivalLine})</b>",
|
||||
"desc-next-arrival": "Leaves towards: <b>{nextStationName} (route {nextArrivalLine})</b>",
|
||||
"desc-departed": "The train is at the station and it's been departed.\nLeaves towards: <b>{nextStationName} (route {nextArrivalLine})</b>",
|
||||
"desc-departed-ends": "The train is at the station and it's been departed.\nLeaves towards station: <b>{nextStationName}</b>",
|
||||
"desc-departed-away": "The train has been departed to:\n<b>{nextStationName} (route {nextArrivalLine})</b>",
|
||||
"from": "Arrives from",
|
||||
"to": "Departs to",
|
||||
"desc-beginning": "The train begins here",
|
||||
"desc-arriving": "<i>Arrives from: <b>{prevStationName} ({prevDepartureLine})</b></i>",
|
||||
"desc-online": "On scenery / <i>direction: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-stopped": "On scenery - stopped / <i>direction: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-next-arrival": "On scenery / <i>direction: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-departed": "On scenery / <i>departed to: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-departed-ends": "On scenery / <i>departed to: <b>{nextStationName}</b></i>",
|
||||
"desc-departed-away": "<i>Departed to: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-end": "The train terminates here",
|
||||
"desc-terminated": "The train has been terminated"
|
||||
},
|
||||
|
||||
+38
-13
@@ -1,4 +1,28 @@
|
||||
{
|
||||
"welcome": {
|
||||
"title": "Witaj na Stacjowniku!",
|
||||
"app-desc": "{b1} to aplikacja stworzona dla symulatora {link}, której celem jest wspomaganie dyżurnego ruchu i maszynisty. Możesz sprawdzić tutaj kto i na jakiej scenerii obecnie pełni służbę, znaleźć maszynistę lub przejrzeć dziennik, który zawiera historię przeszłych dyżurów i rozkładów jazdy.",
|
||||
"app-desc-b1": "Stacjownik",
|
||||
"sceneries-header": "Scenerie",
|
||||
"sceneries-desc": "W zakładce {b1} znajdziesz informacje o dyżurnych ruchu pełniących służby na wybranych sceneriach. Możesz również przeglądać wszystkie dostępne scenerie w symulatorze (w filtrach należy zaznaczyć opcję \"Wolna\", aby pokazać resztę niezajętych) i filtrować je pod względem wielu kryteriów, takich jak sterowanie, dodatkowe oprogramowanie, sygnalizacja, wymagany poziom dyżurnego czy szlaki. Aby wyświetlić detale danej scenerii, kliknij na nią w tabelce.",
|
||||
"sceneries-desc-b1": "Scenerie",
|
||||
"trains-header": "Pociągi",
|
||||
"trains-desc": " Zakładka {b1} zawiera listę aktywnych maszynistów i rozkładów jazdy, które są obecnie realizowane na wybranym serwerze (wybór serwera znajduje się na górze strony). Listę można filtrować i sortować uwzględniając najważniejsze kryteria, takie jak nazwa maszynisty, numer pociągu lub detale rozkładu jazdy. Możesz również kliknąć na dany pociąg, aby wyświetlić dodatkowe informacje.",
|
||||
"trains-desc-b1": "Pociągi",
|
||||
"journal-header": "Dziennik",
|
||||
"journal-desc": "{b1} to zakładka, w której znajdziesz historię dyżurów i rozkładów jazdy, obecnie jedynie z głównego serwera rozgrywki PL1. Możesz także wyszukać historię danego użytkownika używając dodatkowych filtrów.",
|
||||
"journal-desc-b1": "Dziennik",
|
||||
"other-apps": "Sprawdź także inne aplikacje stworzone z myślą ułatwienia rozgrywki w TD2:",
|
||||
"pojazdownik-desc": "edytor składów online",
|
||||
"generator-desc": "graficzny menadżer rozkazów pisemnych",
|
||||
"srjp-desc": "służbowy rozkład jazdy pociągu",
|
||||
"donation-info": "Jeśli doceniasz projekt Stacjownika jak i inne aplikacje mojego autorstwa, rozważ jego wsparcie finansowe - kliknij przycisk z {icon1}, aby dowiedzieć się więcej!",
|
||||
"donation-info-icon1-text": "ikoną diamentu",
|
||||
"discord-info": "Zapraszam także na oficjalnego {discord}, gdzie znajdziesz dedykowanego Stacjobota, za pomocą którego możesz wyszukiwać dodatkowe dane z symulatora niedostępne na tej stronie",
|
||||
"discord-info-link-text": "Discorda Stacjownika",
|
||||
"bottom-text": "Miłego korzystania\n~Spythere",
|
||||
"button-confirm": "Zacznij korzystać z aplikacji!"
|
||||
},
|
||||
"donations": {
|
||||
"button-title": "GROSZA DAJ",
|
||||
"header": "Grosza daj Stacjownikowi!",
|
||||
@@ -57,7 +81,7 @@
|
||||
"categories": {
|
||||
"EI": "ekspres krajowy",
|
||||
"EC": "ekspres międzynarodowy",
|
||||
"EN": "ekspres krajowy nocny",
|
||||
"EN": "ekspres międzynarodowy nocny",
|
||||
"MP": "międzywojewódzki pospieszny",
|
||||
"MO": "międzywojewódzki osobowy",
|
||||
"MM": "międzynarodowy pospieszny",
|
||||
@@ -505,7 +529,7 @@
|
||||
"no-users": "BRAK AKTYWNYCH GRACZY",
|
||||
"no-spawns": "BRAK OTWARTYCH SPAWNÓW",
|
||||
"no-scenery": "Ups! Ta sceneria nie istnieje!",
|
||||
"return-btn": "Powrót",
|
||||
"return-btn": "POWRÓT DO POPRZEDNIEJ STRONY",
|
||||
"history-btn": "Przejdź do widoku historii dyżurnych ruchu",
|
||||
"info-btn": "Wróć do widoku scenerii",
|
||||
"authors-title": "Autor scenerii | Autorzy scenerii",
|
||||
@@ -551,19 +575,20 @@
|
||||
"terminated": "Rozkład jazdy zakończony",
|
||||
"begins": "ROZPOCZYNA\nBIEG",
|
||||
"terminates": "KOŃCZY BIEG",
|
||||
"from": "Z",
|
||||
"to": "DO",
|
||||
"desc-arriving": "Pociągu nie ma jeszcze na tej scenerii.\nPrzyjedzie z: <b>{prevStationName} (szlak {prevDepartureLine})</b>",
|
||||
"desc-online": "Pociąg jest na tej scenerii.\nOdjedzie w kierunku: <b>{nextStationName} (szlak {nextArrivalLine})</b>",
|
||||
"desc-stopped": "Pociąg jest na tej scenerii i odbywa postój.\nOdjedzie w kierunku: <b>{nextStationName} (szlak {nextArrivalLine})</b>",
|
||||
"desc-next-arrival": "Odjeżdża do:\n<b>{nextStationName} (szlak {nextArrivalLine})</b>",
|
||||
"desc-departed": "Pociąg jest na tej scenerii i został odprawiony.\nOdjeżdża w kierunku: <b>{nextStationName} (szlak {nextArrivalLine})</b>",
|
||||
"desc-departed-ends": "Pociąg jest na tej scenerii i został odprawiony.\nOdjechał w kierunku stacji: <b>{nextStationName}</b>",
|
||||
"desc-departed-away": "Pociąg został odprawiony i odjechał do:\n<b>{nextStationName} (szlak {nextArrivalLine})</b>",
|
||||
"from": "Przyjedzie z",
|
||||
"to": "Odjeżdża do",
|
||||
"desc-beginning": "Pociąg rozpoczyna bieg",
|
||||
"desc-arriving": "<i>Przyjedzie z: <b>{prevStationName} ({prevDepartureLine})</b></i>",
|
||||
"desc-online": "Na scenerii / <i>kierunek: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-stopped": "Na scenerii - postój / <i>kierunek: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-next-arrival": "Na scenerii / <i>kierunek: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-departed": "Na scenerii / <i>odprawiony do: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-departed-ends": "Na scenerii / <i>odprawiony do: <b>{nextStationName}</b></i>",
|
||||
"desc-departed-away": "<i>Odprawiony do: <b>{nextStationName} ({nextArrivalLine})</b></i>",
|
||||
"desc-end": "Pociąg kończy bieg",
|
||||
"desc-terminated": "Pociąg skończył bieg"
|
||||
"desc-terminated": "Pociąg zakończył bieg"
|
||||
},
|
||||
"history": {
|
||||
"title": "DZIENNIK ROZKŁADÓW JAZDY"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ function filterTrainList(
|
||||
return train.timetableData?.followingStops.some((stop) => stop.comments);
|
||||
|
||||
case TrainFilterId.twr:
|
||||
return !train.timetableData?.TWR;
|
||||
return !train.timetableData?.twr;
|
||||
|
||||
case TrainFilterId.pn:
|
||||
return !train.timetableData?.hasExtraDeliveries;
|
||||
@@ -52,7 +52,7 @@ function filterTrainList(
|
||||
return !train.timetableData?.hasDangerousCargo;
|
||||
|
||||
case TrainFilterId.common:
|
||||
return train.timetableData?.SKR || train.timetableData?.TWR;
|
||||
return train.timetableData?.twr;
|
||||
|
||||
case TrainFilterId.passenger:
|
||||
return !/^[AMRE]\D{2}$/.test(train.timetableData?.category || '');
|
||||
|
||||
+5
-2
@@ -36,7 +36,10 @@ const routes: Array<RouteRecordRaw> = [
|
||||
props: (route) => ({
|
||||
region: route.query.region,
|
||||
station: route.query.station
|
||||
})
|
||||
}),
|
||||
beforeEnter: (to, from) => {
|
||||
to.meta['prevPath'] = from.fullPath;
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/journal',
|
||||
@@ -72,7 +75,7 @@ const router = createRouter({
|
||||
from.query['view'] === undefined &&
|
||||
!savedPosition
|
||||
)
|
||||
return { el: `.scenery-left`, behavior: 'instant', top: 3 };
|
||||
return { el: `.app_main`, behavior: 'instant', top: -13 };
|
||||
|
||||
if (savedPosition) return savedPosition;
|
||||
},
|
||||
|
||||
@@ -32,7 +32,8 @@ export const useMainStore = defineStore('mainStore', {
|
||||
|
||||
chosenModalTrainId: undefined,
|
||||
|
||||
modalLastClickedTarget: null
|
||||
modalLastClickedTarget: null,
|
||||
currentLocale: 'pl'
|
||||
}) as MainStoreState,
|
||||
|
||||
getters: {
|
||||
@@ -97,8 +98,7 @@ export const useMainStore = defineStore('mainStore', {
|
||||
followingStops: timetable.stopList,
|
||||
routeDistance: timetable.stopList[timetable.stopList.length - 1].stopDistance,
|
||||
sceneries: timetable.sceneries,
|
||||
TWR: timetable.TWR,
|
||||
SKR: timetable.SKR,
|
||||
twr: timetable.twr,
|
||||
warningNotes: timetable.warningNotes,
|
||||
hasDangerousCargo: timetable.hasDangerousCargo,
|
||||
hasExtraDeliveries: timetable.hasExtraDeliveries,
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface MainStoreState {
|
||||
driverStatsStatus: Status.Data;
|
||||
chosenModalTrainId?: string;
|
||||
modalLastClickedTarget: EventTarget | null;
|
||||
currentLocale: string;
|
||||
}
|
||||
|
||||
export interface StationJSONData {
|
||||
|
||||
+14
-44
@@ -23,7 +23,6 @@
|
||||
|
||||
--clr-donator: #f7a4ff;
|
||||
|
||||
|
||||
--no-scroll-padding: 17px;
|
||||
--max-container-width: 1700px;
|
||||
|
||||
@@ -207,10 +206,23 @@ ul {
|
||||
background: linear-gradient(90deg, #ff88db 30%, #ffffff 70%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
-webkit-text-fill-color: transparent;
|
||||
|
||||
text-shadow: #f050ff 0 0 10px;
|
||||
}
|
||||
|
||||
&--discord {
|
||||
color: var(--clr-donator);
|
||||
color: transparent;
|
||||
|
||||
background: var(--clr-donator);
|
||||
background: linear-gradient(90deg, #7fb6ff 0%, #60ecff 70%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
|
||||
text-shadow: #88ddff 0 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
button,
|
||||
@@ -285,48 +297,6 @@ a.a-button {
|
||||
}
|
||||
}
|
||||
|
||||
.return-btn {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
position: fixed;
|
||||
right: 2.5rem;
|
||||
bottom: 4rem;
|
||||
|
||||
z-index: 100;
|
||||
|
||||
width: 3.5rem;
|
||||
|
||||
font-size: 3rem;
|
||||
|
||||
background-color: #555;
|
||||
outline: 3px solid #222;
|
||||
color: white;
|
||||
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #3c3c3c;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 1.3em;
|
||||
}
|
||||
|
||||
@include responsive.smallScreen {
|
||||
bottom: 1em;
|
||||
right: 0;
|
||||
left: 50%;
|
||||
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
// Basic tooltip
|
||||
[data-tooltip] {
|
||||
cursor: help;
|
||||
|
||||
+1
-2
@@ -197,8 +197,7 @@ export namespace API {
|
||||
category: string;
|
||||
route: string;
|
||||
stopList: TimetableStop[];
|
||||
TWR: boolean;
|
||||
SKR: boolean;
|
||||
twr: boolean;
|
||||
hasDangerousCargo: boolean;
|
||||
hasExtraDeliveries: boolean;
|
||||
warningNotes: string | null;
|
||||
|
||||
@@ -83,8 +83,7 @@ export interface TrainTimetableData {
|
||||
category: string;
|
||||
route: string;
|
||||
followingStops: TrainStop[];
|
||||
TWR: boolean;
|
||||
SKR: boolean;
|
||||
twr: boolean;
|
||||
hasDangerousCargo: boolean;
|
||||
hasExtraDeliveries: boolean;
|
||||
warningNotes: string | null;
|
||||
@@ -143,6 +142,7 @@ export interface StationRoutesInfo {
|
||||
isRouteSBL: boolean;
|
||||
routeLength: number;
|
||||
routeSpeed: number;
|
||||
routeSpeedExit?: number;
|
||||
routeTracks: number;
|
||||
hidden?: boolean;
|
||||
realLineNo?: number;
|
||||
|
||||
+74
-128
@@ -2,12 +2,6 @@
|
||||
<div class="scenery-view">
|
||||
<div class="scenery-wrapper" ref="card-wrapper">
|
||||
<div class="scenery-left">
|
||||
<div class="scenery-actions">
|
||||
<button class="back-btn" :title="$t('scenery.return-btn')" @click="onReturnButtonClick">
|
||||
<img src="/images/icon-back.svg" alt="return button" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<SceneryHeader
|
||||
:stationName="station"
|
||||
:station="stationInfo"
|
||||
@@ -23,8 +17,8 @@
|
||||
v-for="(viewMode, i) in viewModes"
|
||||
:key="i"
|
||||
class="btn btn--option"
|
||||
:class="{ checked: currentMode == viewMode.component }"
|
||||
@click="setViewMode(viewMode.component)"
|
||||
:class="{ checked: currentMode == viewMode.component.name }"
|
||||
@click="setViewMode(viewMode.component.name!)"
|
||||
>
|
||||
{{ $t(viewMode.id) }}
|
||||
</button>
|
||||
@@ -32,17 +26,17 @@
|
||||
|
||||
<div
|
||||
v-if="
|
||||
apiStore.dataStatuses.sceneries == Status.Loading ||
|
||||
apiStore.dataStatuses.connection == Status.Loading
|
||||
apiStore.dataStatuses.sceneries == Status.Data.Loading ||
|
||||
apiStore.dataStatuses.connection == Status.Data.Loading
|
||||
"
|
||||
></div>
|
||||
|
||||
<keep-alive v-else>
|
||||
<component
|
||||
:is="currentMode"
|
||||
:is="currentViewComponent"
|
||||
:onlineScenery="onlineSceneryInfo"
|
||||
:station="stationInfo"
|
||||
:key="currentMode"
|
||||
:key="currentViewComponent.name"
|
||||
></component>
|
||||
</keep-alive>
|
||||
</div>
|
||||
@@ -50,141 +44,93 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import routerMixin from '../mixins/routerMixin';
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useMainStore } from '../store/mainStore';
|
||||
|
||||
import SceneryInfo from '../components/SceneryView/SceneryInfo.vue';
|
||||
import SceneryHeader from '../components/SceneryView/SceneryHeader.vue';
|
||||
|
||||
import SceneryTimetable from '../components/SceneryView/SceneryTimetable.vue';
|
||||
import SceneryTimetablesHistory from '../components/SceneryView/SceneryTimetablesHistory.vue';
|
||||
import SceneryDispatchersHistory from '../components/SceneryView/SceneryDispatchersHistory.vue';
|
||||
import ActionButton from '../components/Global/ActionButton.vue';
|
||||
import { Status } from '../typings/common';
|
||||
|
||||
import { useApiStore } from '../store/apiStore';
|
||||
import { Status } from '../typings/common';
|
||||
|
||||
enum SceneryViewMode {
|
||||
'TIMETABLES_ACTIVE',
|
||||
'TIMETABLES_HISTORY',
|
||||
'SCENERY_HISTORY'
|
||||
}
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SceneryView',
|
||||
|
||||
components: {
|
||||
SceneryInfo,
|
||||
SceneryTimetable,
|
||||
ActionButton,
|
||||
SceneryHeader,
|
||||
SceneryTimetablesHistory,
|
||||
SceneryDispatchersHistory
|
||||
const props = defineProps({
|
||||
region: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
|
||||
props: {
|
||||
region: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
|
||||
station: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
mixins: [routerMixin],
|
||||
|
||||
data: () => ({
|
||||
store: useMainStore(),
|
||||
apiStore: useApiStore(),
|
||||
|
||||
viewModes: [
|
||||
{
|
||||
id: 'scenery.option-active-timetables',
|
||||
component: 'SceneryTimetable'
|
||||
},
|
||||
{
|
||||
id: 'scenery.option-timetables-history',
|
||||
component: 'SceneryTimetablesHistory'
|
||||
},
|
||||
{
|
||||
id: 'scenery.option-dispatchers-history',
|
||||
component: 'SceneryDispatchersHistory'
|
||||
}
|
||||
],
|
||||
sceneryViewMode: SceneryViewMode,
|
||||
selectedCheckpoint: '',
|
||||
currentViewCompontent: 'SceneryTimetable',
|
||||
onlineFrom: -1,
|
||||
Status: Status.Data
|
||||
}),
|
||||
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
|
||||
const isComponentVisible = computed(() => route.path === '/scenery');
|
||||
|
||||
return {
|
||||
isComponentVisible
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentMode() {
|
||||
return this.$route.query.view?.toString() ?? 'SceneryTimetable';
|
||||
},
|
||||
|
||||
stationInfo() {
|
||||
return this.store.stationList.find(
|
||||
(station) => station.name === this.station?.toString().replace(/_/g, ' ')
|
||||
);
|
||||
},
|
||||
|
||||
onlineSceneryInfo() {
|
||||
return this.store.activeSceneryList.find(
|
||||
(scenery) =>
|
||||
scenery.name === this.station?.toString().replace(/_/g, ' ') &&
|
||||
scenery.region == this.store.region.id
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
setViewMode(componentName: string) {
|
||||
this.$router.push({
|
||||
path: this.$route.path,
|
||||
query: {
|
||||
...this.$route.query,
|
||||
view: componentName
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadSelectedCheckpoint() {
|
||||
if (!this.stationInfo?.generalInfo?.checkpoints) return;
|
||||
if (this.stationInfo.generalInfo.checkpoints.length == 0) return;
|
||||
this.selectedCheckpoint = this.stationInfo.generalInfo.checkpoints[0];
|
||||
},
|
||||
|
||||
onReturnButtonClick() {
|
||||
this.$router.back();
|
||||
}
|
||||
station: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const store = useMainStore();
|
||||
const apiStore = useApiStore();
|
||||
|
||||
const viewModes = [
|
||||
{
|
||||
id: 'scenery.option-active-timetables',
|
||||
component: SceneryTimetable
|
||||
},
|
||||
{
|
||||
id: 'scenery.option-timetables-history',
|
||||
component: SceneryTimetablesHistory
|
||||
},
|
||||
{
|
||||
id: 'scenery.option-dispatchers-history',
|
||||
component: SceneryDispatchersHistory
|
||||
}
|
||||
];
|
||||
|
||||
const currentMode = computed(() => {
|
||||
return route.query.view?.toString() ?? 'SceneryTimetable';
|
||||
});
|
||||
|
||||
const currentViewComponent = computed(() => {
|
||||
return (
|
||||
viewModes.find((mode) => mode.component.name == currentMode.value)?.component ??
|
||||
SceneryTimetable
|
||||
);
|
||||
});
|
||||
|
||||
const stationInfo = computed(() => {
|
||||
return store.stationList.find(
|
||||
(station) => station.name === props.station?.toString().replace(/_/g, ' ')
|
||||
);
|
||||
});
|
||||
|
||||
const onlineSceneryInfo = computed(() => {
|
||||
return store.activeSceneryList.find(
|
||||
(scenery) =>
|
||||
scenery.name === props.station?.toString().replace(/_/g, ' ') &&
|
||||
scenery.region == store.region.id
|
||||
);
|
||||
});
|
||||
|
||||
function setViewMode(componentName: string) {
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
view: componentName
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../styles/responsive';
|
||||
|
||||
button.back-btn {
|
||||
img {
|
||||
width: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.scenery {
|
||||
&-view {
|
||||
display: flex;
|
||||
|
||||
@@ -3202,7 +3202,7 @@ sharp@*, sharp@^0.33.5:
|
||||
|
||||
showdown@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/showdown/-/showdown-2.1.0.tgz#1251f5ed8f773f0c0c7bfc8e6fd23581f9e545c5"
|
||||
integrity sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==
|
||||
dependencies:
|
||||
commander "^9.0.0"
|
||||
|
||||
Reference in New Issue
Block a user