Compare commits

..

3 Commits

Author SHA1 Message Date
Spythere 3be964ec99 Merge pull request #152 from Spythere/development-old
Migration info for the old version of the app
2026-01-01 21:17:17 +01:00
Spythere caf6137ca3 chore: removed new vps settings for old branch 2026-01-01 21:14:55 +01:00
Spythere 0f2e5e084b chore(app): added info about migration to the new domain for the old version of the app 2026-01-01 21:10:28 +01:00
51 changed files with 334 additions and 833 deletions
@@ -1,17 +0,0 @@
on:
release:
types: [published]
jobs:
github-releases-to-discord:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Github Releases To Discord
uses: SethCohen/github-releases-to-discord@v1.13.1
with:
webhook_url: ${{ secrets.WEBHOOK_URL }}
color: "15844367"
footer_title: "Changelog - Stacjownik"
footer_timestamp: true
-23
View File
@@ -1,23 +0,0 @@
name: Build & Deploy to VPS
on:
push:
branches:
- main
env:
PROJECT_NAME: stacjownik-td2
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the app
run: yarn && yarn build
- name: Setup SSH key for connection with the server
run: |
mkdir -p ~/.ssh
echo "${{ secrets.VPS_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
- name: Send new files
run: rsync -avP -e "ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa -p 2022" ./dist/ ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}:/var/www/$PROJECT_NAME --delete
+2 -2
View File
@@ -15,8 +15,8 @@ app.get('/api/getSceneries', (_, res) => {
res.sendFile(path.join(cwd(), 'endpoints', 'getSceneries.json')); res.sendFile(path.join(cwd(), 'endpoints', 'getSceneries.json'));
}); });
app.get('/api/getVehiclesData', (_, res) => { app.get('/api/getVehicles', (_, res) => {
res.sendFile(path.join(cwd(), 'endpoints', 'getVehiclesData.json')); res.sendFile(path.join(cwd(), 'endpoints', 'getVehicles.json'));
}); });
app.get('/api/getDonators', (_, res) => { app.get('/api/getDonators', (_, res) => {
+6 -6
View File
@@ -62,24 +62,24 @@
crossorigin crossorigin
/> />
<link rel="preload" as="image" href="/images/icon-pl.svg" />
<link rel="preload" as="image" href="/images/stacjownik-header-logo.svg" /> <link rel="preload" as="image" href="/images/stacjownik-header-logo.svg" />
<link rel="preload" as="image" href="/images/icon-dispatcher.svg" /> <link rel="preload" as="image" href="/images/icon-dispatcher.svg" />
<link rel="preload" as="image" href="/images/icon-train.svg" /> <link rel="preload" as="image" href="/images/icon-train.svg" />
<link rel="preload" as="image" href="/images/icon-arrow-asc.svg" />
<link rel="preload" as="image" href="/images/icon-arrow-desc.svg" /> <link rel="preload" as="image" href="/images/icon-arrow-desc.svg" />
<link rel="preload" as="image" href="/images/icon-pojazdownik.svg" />
<link rel="preload" as="image" href="/images/icon-stats.svg" />
<link rel="preload" as="image" href="/images/icon-filter2.svg" /> <link rel="preload" as="image" href="/images/icon-filter2.svg" />
<link rel="preload" as="image" href="/images/icon-stats.svg" />
<link rel="preload" as="image" href="/images/icon-gnr.svg" />
<link rel="preload" as="image" href="/images/icon-pojazdownik.svg" />
<link rel="preload" as="image" href="/images/icon-diamond.svg" />
<link rel="preload" as="image" href="/images/icon-user.svg" /> <link rel="preload" as="image" href="/images/icon-user.svg" />
<link rel="preload" as="image" href="/images/icon-like.svg" /> <link rel="preload" as="image" href="/images/icon-like.svg" />
<link rel="preload" as="image" href="/images/icon-gnr.svg" />
<link rel="preload" as="image" href="/images/icon-spawn.svg" /> <link rel="preload" as="image" href="/images/icon-spawn.svg" />
<link rel="preload" as="image" href="/images/icon-timetableAll.svg" /> <link rel="preload" as="image" href="/images/icon-timetableAll.svg" />
<link rel="preload" as="image" href="/images/icon-timetableUnconfirmed.svg" /> <link rel="preload" as="image" href="/images/icon-timetableUnconfirmed.svg" />
<link rel="preload" as="image" href="/images/icon-timetableConfirmed.svg" /> <link rel="preload" as="image" href="/images/icon-timetableConfirmed.svg" />
<link rel="preload" as="image" href="/images/icon-discord.png" /> <link rel="preload" as="image" href="/images/icon-discord.png" />
<link rel="prefetch" as="image" href="/images/icon-arrow-asc.svg" />
<link rel="prefetch" as="image" href="/images/icon-diamond.svg" />
<!-- Static OpenGraph meta --> <!-- Static OpenGraph meta -->
<meta name="description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" /> <meta name="description" content="Pomocnik maszynisty i dyżurnego symulatora Train Driver 2" />
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.31.1", "version": "1.30.7",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
-5
View File
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-cz" viewBox="0 0 640 480">
<path fill="#fff" d="M0 0h640v240H0z"/>
<path fill="#d7141a" d="M0 240h640v240H0z"/>
<path fill="#11457e" d="M360 240 0 0v480z"/>
</svg>

Before

Width:  |  Height:  |  Size: 225 B

-5
View File
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-de" viewBox="0 0 640 480">
<path fill="#fc0" d="M0 320h640v160H0z"/>
<path fill="#000001" d="M0 0h640v160H0z"/>
<path fill="red" d="M0 160h640v160H0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 221 B

-7
View File
@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-it" viewBox="0 0 640 480">
<g fill-rule="evenodd" stroke-width="1pt">
<path fill="#fff" d="M0 0h640v480H0z"/>
<path fill="#009246" d="M0 0h213.3v480H0z"/>
<path fill="#ce2b37" d="M426.7 0H640v480H426.7z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 289 B

-5
View File
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ru" viewBox="0 0 640 480">
<path fill="#fff" d="M0 0h640v160H0z"/>
<path fill="#0039a6" d="M0 160h640v160H0z"/>
<path fill="#d52b1e" d="M0 320h640v160H0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 225 B

-4
View File
@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-se" viewBox="0 0 640 480">
<path fill="#005293" d="M0 0h640v480H0z"/>
<path fill="#fecb00" d="M176 0v192H0v96h176v192h96V288h368v-96H272V0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 209 B

-9
View File
@@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-sk" viewBox="0 0 640 480">
<path fill="#ee1c25" d="M0 0h640v480H0z"/>
<path fill="#0b4ea2" d="M0 0h640v320H0z"/>
<path fill="#fff" d="M0 0h640v160H0z"/>
<path fill="#fff" d="M233 370.8c-43-20.7-104.6-61.9-104.6-143.2 0-81.4 4-118.4 4-118.4h201.3s3.9 37 3.9 118.4S276 350 233 370.8"/>
<path fill="#ee1c25" d="M233 360c-39.5-19-96-56.8-96-131.4s3.6-108.6 3.6-108.6h184.8s3.5 34 3.5 108.6C329 303.3 272.5 341 233 360"/>
<path fill="#fff" d="M241.4 209c10.7.2 31.6.6 50.1-5.6 0 0-.4 6.7-.4 14.4s.5 14.4.5 14.4c-17-5.7-38.1-5.8-50.2-5.7v41.2h-16.8v-41.2c-12-.1-33.1 0-50.1 5.7 0 0 .5-6.7.5-14.4s-.5-14.4-.5-14.4c18.5 6.2 39.4 5.8 50 5.6v-25.9c-9.7 0-23.7.4-39.6 5.7 0 0 .5-6.6.5-14.4 0-7.7-.5-14.4-.5-14.4 15.9 5.3 29.9 5.8 39.6 5.7-.5-16.4-5.3-37-5.3-37s9.9.7 13.8.7 13.8-.7 13.8-.7-4.8 20.6-5.3 37c9.7.1 23.7-.4 39.6-5.7 0 0-.5 6.7-.5 14.4s.5 14.4.5 14.4a119 119 0 0 0-39.7-5.7v26z"/>
<path fill="#0b4ea2" d="M233 263.3c-19.9 0-30.5 27.5-30.5 27.5s-6-13-22.2-13c-11 0-19 9.7-24.2 18.8 20 31.7 51.9 51.3 76.9 63.4 25-12 57-31.7 76.9-63.4-5.2-9-13.2-18.8-24.2-18.8-16.2 0-22.2 13-22.2 13S253 263.3 233 263.3"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ua" viewBox="0 0 640 480">
<g fill-rule="evenodd" stroke-width="1pt">
<path fill="gold" d="M0 0h640v480H0z"/>
<path fill="#0057b8" d="M0 0h640v240H0z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Before

Width:  |  Height:  |  Size: 504 B

After

Width:  |  Height:  |  Size: 504 B

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 219 B

+3 -239
View File
@@ -1,213 +1,11 @@
<template> <template>
<div class="app_container"> <div class="app_container">
<UpdateCard <AppNewDomainInfo />
:is-update-card-open="isUpdateCardOpen"
@toggle-card="() => (isUpdateCardOpen = false)"
/>
<AppWelcomeCard :is-card-open="isWelcomeCardOpen" @toggle-card="closeWelcomeCard" />
<MigrateInfoCard
:is-open="store.isMigrateInfoCardOpen"
@toggle-card="closeMigrateInfoCard"
></MigrateInfoCard>
<Tooltip />
<AppHeader />
<main class="app_main">
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" :key="$route.name" />
</keep-alive>
</router-view>
</main>
<AppFooter
:version="VERSION"
:is-on-production-host="isOnProductionHost"
:is-update-card-open="isUpdateCardOpen"
@open-update-card="() => (isUpdateCardOpen = true)"
/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import AppNewDomainInfo from './components/App/AppNewDomainInfo.vue';
import axios from 'axios';
import { version } from '../package.json';
import { Status } from './typings/common';
import { useMainStore } from './store/mainStore';
import { useApiStore } from './store/apiStore';
import { useTooltipStore } from './store/tooltipStore';
import Clock from './components/App/Clock.vue';
import StatusIndicator from './components/App/StatusIndicator.vue';
import AppHeader from './components/App/AppHeader.vue';
import Tooltip from './components/Tooltip/Tooltip.vue';
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';
import MigrateInfoCard from './components/App/MigrateInfoCard.vue';
const STORAGE_VERSION_KEY = 'app_version';
const WELCOME_CARD_SEEN_KEY = 'welcome_card_seen';
const MIGRATE_INFO_CARD_SEEN_KEY = 'migrate_info_card_seen';
export default defineComponent({
components: {
Clock,
StatusIndicator,
AppHeader,
AppFooter,
UpdateCard,
AppWelcomeCard,
MigrateInfoCard,
Tooltip
},
data: () => ({
VERSION: version,
store: useMainStore(),
apiStore: useApiStore(),
tooltipStore: useTooltipStore(),
isUpdateCardOpen: false,
isWelcomeCardOpen: false,
isOnProductionHost: /(stacjownik-td2)(\.web\.app|\.spythere\.eu)/.test(location.hostname)
}),
created() {
this.init();
},
async mounted() {
window.addEventListener('mousemove', (e: MouseEvent) => this.tooltipStore.handle(e));
window.addEventListener('mousedown', () => this.tooltipStore.hide());
},
methods: {
init() {
if (!this.isOnProductionHost) document.title = 'Stacjownik Dev';
this.loadLang();
this.setupOfflineHandling();
this.checkAppVersion();
this.handleQueries();
this.handleMigrateInfo();
this.apiStore.setupAPIData();
},
handleQueries() {
const query = new URLSearchParams(window.location.search);
if (query.get('welcomeCard') == '1') {
this.isWelcomeCardOpen = true;
}
if (query.get('migrateCard') == '1') {
this.store.isMigrateInfoCardOpen = 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')
).data;
if (!releaseData) return;
this.store.appUpdate = {
version,
changelog: releaseData.body,
releaseURL: releaseData.html_url
};
this.isUpdateCardOpen =
(storageVersion != '' && storageVersion != version && this.isOnProductionHost) ||
import.meta.env.VITE_UPDATE_TEST === 'test';
} catch (error) {
console.error(`Wystąpił błąd podczas pobierania danych z API GitHuba: ${error}`);
}
StorageManager.setStringValue(STORAGE_VERSION_KEY, version);
},
setupOfflineHandling() {
this.store.isOffline = !window.navigator.onLine;
if (this.store.isOffline) this.handleOfflineMode();
window.addEventListener('offline', this.handleOfflineMode);
window.addEventListener('online', this.handleOnlineMode);
},
handleOfflineMode() {
this.store.isOffline = true;
this.apiStore.activeData = undefined;
this.apiStore.dataStatuses.connection = Status.Data.Offline;
},
handleOnlineMode() {
this.store.isOffline = false;
this.apiStore.dataStatuses.connection = Status.Data.Loading;
this.apiStore.connectToAPI();
},
handleMigrateInfo() {
if (location.hostname != 'stacjownik-td2.web.app') return;
if (StorageManager.getBooleanValue(MIGRATE_INFO_CARD_SEEN_KEY) === true) return;
this.store.isMigrateInfoCardOpen = true;
},
loadLang() {
const storageLang = StorageManager.getStringValue('lang');
if (storageLang) {
this.store.changeLocale(storageLang);
return;
}
if (!window.navigator.language) return;
const naviLanguage = window.navigator.language.toString();
if (!naviLanguage.startsWith('pl')) {
this.store.changeLocale('en');
return;
}
},
closeWelcomeCard() {
this.isWelcomeCardOpen = false;
StorageManager.setBooleanValue(WELCOME_CARD_SEEN_KEY, true);
},
closeMigrateInfoCard() {
this.store.isMigrateInfoCardOpen = false;
StorageManager.setBooleanValue(MIGRATE_INFO_CARD_SEEN_KEY, true);
}
}
});
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -234,38 +32,4 @@ export default defineComponent({
.app_main { .app_main {
padding: 0 0.5em; padding: 0 0.5em;
} }
.warning {
background-color: firebrick;
text-align: center;
padding: 0.5em 0.4em;
max-width: 1100px;
margin: 0 auto;
border-radius: 0 0 1em 1em;
}
// FOOTER
.app_footer {
max-width: 100%;
padding: 0.5em;
button {
display: inline-block;
padding: 0.1em;
}
img {
width: 1.1em;
vertical-align: text-bottom;
}
z-index: 10;
background: #111;
color: white;
text-align: center;
vertical-align: middle;
}
</style> </style>
+37
View File
@@ -0,0 +1,37 @@
<template>
<div class="app-domain-info">
<div>
<img src="/images/icon-loading.svg" alt="loading" height="200" />
<h1><span class="text--primary">Aplikacja</span> została przeniesiona na nową domenę!</h1>
<h1><span class="text--primary">This app</span> has been moved to a new domain!</h1>
<div style="margin-top: 1em">
<a :href="newLink">Nowy link dla obecnego adresu / New link to the current address</a>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const newLink = computed(() => {
return 'https://stacjownik-td2.spythere.eu' + location.pathname + location.search;
});
</script>
<style lang="scss" scoped>
.app-domain-info {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
min-height: 100vh;
color: white;
}
a {
font-size: 1.35em;
text-decoration: underline;
}
</style>
+3 -4
View File
@@ -5,11 +5,11 @@
<div class="language-select"> <div class="language-select">
<button :data-active="$i18n.locale == 'pl'" @click="store.changeLocale('pl')"> <button :data-active="$i18n.locale == 'pl'" @click="store.changeLocale('pl')">
<FlagIcon :language-id="0" width="2.5em" /> <img src="/images/icon-pl.svg" alt="" width="45" />
</button> </button>
<button :data-active="$i18n.locale == 'en'" @click="store.changeLocale('en')"> <button :data-active="$i18n.locale == 'en'" @click="store.changeLocale('en')">
<FlagIcon :language-id="1" width="2.5em" /> <img src="/images/icon-en.svg" alt="" width="45" />
</button> </button>
</div> </div>
@@ -116,7 +116,6 @@
<script setup lang="ts"> <script setup lang="ts">
import Card from '../Global/Card.vue'; import Card from '../Global/Card.vue';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import FlagIcon from '../Global/FlagIcon.vue';
const store = useMainStore(); const store = useMainStore();
@@ -158,7 +157,7 @@ a.link {
justify-content: center; justify-content: center;
margin: 0.5em 0; margin: 0.5em 0;
button[data-active='false'] ::v-deep(img) { button[data-active='false'] img {
opacity: 0.5; opacity: 0.5;
} }
} }
+7 -20
View File
@@ -1,6 +1,6 @@
<template> <template>
<Card :is-open="isUpdateCardOpen" @toggle-card="toggleCard(false)"> <Card :is-open="isUpdateCardOpen" @toggle-card="toggleCard(false)">
<div class="content" tabindex="0" ref="content"> <div class="content">
<h1 style="margin-bottom: 0.5em">🚀 {{ $t('update.title') }}</h1> <h1 style="margin-bottom: 0.5em">🚀 {{ $t('update.title') }}</h1>
<div class="features-body" v-if="htmlChangelog != ''" v-html="htmlChangelog"></div> <div class="features-body" v-if="htmlChangelog != ''" v-html="htmlChangelog"></div>
@@ -13,14 +13,7 @@
<p class="bottom-info"> <p class="bottom-info">
{{ $t('update.info-1') }} {{ $t('update.info-1') }}
<br /> <br />
<span v-html="$t('update.info-2')"></span>
<i18n-t keypath="update.info-2">
<template v-slot:link>
<a href="https://github.com/Spythere/stacjownik" target="_blank">{{
$t('update.info-2-link-text')
}}</a>
</template>
</i18n-t>
</p> </p>
</div> </div>
</Card> </Card>
@@ -58,7 +51,7 @@ export default defineComponent({
watch: { watch: {
isUpdateCardOpen(val: boolean) { isUpdateCardOpen(val: boolean) {
this.$nextTick(() => { this.$nextTick(() => {
if (val) (this.$refs['content'] as HTMLElement).focus(); if (val) (this.$refs['confirm-btn'] as HTMLElement).focus();
}); });
} }
}, },
@@ -86,18 +79,13 @@ export default defineComponent({
} }
::v-deep(h2) { ::v-deep(h2) {
margin-top: 1em; padding: 0.25em 0;
padding: 0.5em 0;
border-bottom: 1px solid #aaa; border-bottom: 1px solid #aaa;
} }
::v-deep(h3) {
padding: 0.5em 0;
}
::v-deep(ul) { ::v-deep(ul) {
list-style: disc; list-style: initial;
padding: 0 1.5em; padding: 1em;
line-height: 1.5em; line-height: 1.5em;
} }
@@ -117,7 +105,7 @@ export default defineComponent({
} }
button { button {
margin: 0.5em auto; margin: 0 auto;
padding: 0.5em 0.75em; padding: 0.5em 0.75em;
font-size: 1.1em; font-size: 1.1em;
} }
@@ -129,6 +117,5 @@ p.bottom-info {
a { a {
text-decoration: underline; text-decoration: underline;
color: white;
} }
</style> </style>
@@ -205,7 +205,7 @@ const availableCategories = computed(() => {
for (const stockName of stockList) { for (const stockName of stockList) {
const [vehicleName, ...cargoList] = stockName.split(':'); const [vehicleName, ...cargoList] = stockName.split(':');
const vehicleData = apiStore.vehiclesData?.vehicles.find((v) => v.name == vehicleName); const vehicleData = apiStore.vehiclesData?.find((v) => v.name == vehicleName);
if (!vehicleData) continue; if (!vehicleData) continue;
+23
View File
@@ -0,0 +1,23 @@
<template>
<button class="action-btn btn--filled">
<div class="button_content">
<slot></slot>
</div>
</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({});
</script>
<style lang="scss">
@use '../../styles/responsive';
.button_content {
display: flex;
justify-content: center;
align-items: center;
}
</style>
-43
View File
@@ -1,43 +0,0 @@
<template>
<div class="flag-icon">
<img
:src="languageFlagSrc"
alt="language flag"
:style="{
width: width
}"
/>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { getLanguageNameById } from '../../utils/languageUtils';
const props = defineProps({
languageId: {
type: Number,
required: true
},
width: {
type: String
}
});
const languageFlagSrc = computed(
() => `/images/flags/${getLanguageNameById(props.languageId)}.svg`
);
</script>
<style scoped>
.flag-icon {
display: flex;
justify-content: center;
align-items: center;
}
.flag-icon img {
vertical-align: middle;
}
</style>
@@ -1,22 +1,23 @@
<template> <template>
<li class="dispatcher-history-entry"> <li class="dispatcher-history-entry">
<div class="entry-info"> <div class="entry-info">
<span class="entry-info-left"> <span>
<div class="station-info"> <span>
<router-link :to="`/journal/dispatchers?search-station=${entry.stationName}`"> <router-link :to="`/journal/dispatchers?search-station=${entry.stationName}`">
<b>{{ entry.stationName }}</b> <b>{{ entry.stationName }}</b>
</router-link> </router-link>
<b class="text--grayed"> #{{ entry.stationHash }}</b> <b class="text--grayed"> #{{ entry.stationHash }}</b>
&bull; </span>
<b &bull;
v-if="entry.dispatcherLevel !== null" <b
class="level-badge dispatcher" v-if="entry.dispatcherLevel !== null"
:style="calculateExpStyle(entry.dispatcherLevel, entry.dispatcherIsSupporter)" class="level-badge dispatcher"
> :style="calculateExpStyle(entry.dispatcherLevel, entry.dispatcherIsSupporter)"
{{ entry.dispatcherLevel >= 2 ? entry.dispatcherLevel : 'L' }} >
</b> {{ entry.dispatcherLevel >= 2 ? entry.dispatcherLevel : 'L' }}
</b>
<b style="margin-left: 5px">
<span <span
v-if="apiStore.donatorsData.includes(entry.dispatcherName)" v-if="apiStore.donatorsData.includes(entry.dispatcherName)"
data-tooltip-type="DonatorTooltip" data-tooltip-type="DonatorTooltip"
@@ -36,11 +37,7 @@
> >
{{ entry.dispatcherName }} {{ entry.dispatcherName }}
</router-link> </router-link>
</b>
<span class="dispatcher-language" v-if="entry.dispatcherLanguageId != null">
<FlagIcon :language-id="entry.dispatcherLanguageId" width="1.75em" />
</span>
</div>
<div> <div>
<span v-if="entry.timestampTo"> <span v-if="entry.timestampTo">
@@ -121,7 +118,6 @@ import dateMixin from '../../../mixins/dateMixin';
import styleMixin from '../../../mixins/styleMixin'; import styleMixin from '../../../mixins/styleMixin';
import { useApiStore } from '../../../store/apiStore'; import { useApiStore } from '../../../store/apiStore';
import StationStatusBadge from '../../Global/StationStatusBadge.vue'; import StationStatusBadge from '../../Global/StationStatusBadge.vue';
import FlagIcon from '../../Global/FlagIcon.vue';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -129,7 +125,7 @@ export default defineComponent({
showExtraInfo: { type: Boolean, required: true } showExtraInfo: { type: Boolean, required: true }
}, },
components: { StationStatusBadge, FlagIcon }, components: { StationStatusBadge },
mixins: [dateMixin, styleMixin], mixins: [dateMixin, styleMixin],
emits: ['toggleShowExtraInfo'], emits: ['toggleShowExtraInfo'],
@@ -168,11 +164,6 @@ export default defineComponent({
padding: 1em; padding: 1em;
} }
.dispatcher-language {
display: inline-block;
vertical-align: middle;
}
.entry-info { .entry-info {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -194,15 +185,6 @@ export default defineComponent({
margin-top: 1em; margin-top: 1em;
} }
.station-info {
display: flex;
flex-wrap: wrap;
text-align: center;
align-items: center;
gap: 0.25em;
font-weight: bold;
}
.status-list { .status-list {
display: flex; display: flex;
overflow: auto; overflow: auto;
@@ -216,15 +198,11 @@ export default defineComponent({
border-radius: 1em; border-radius: 1em;
} }
@include responsive.smallScreen { @include responsive.smallScreen{
.entry-info { .entry-info {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
} }
.station-info {
justify-content: center;
}
} }
</style> </style>
@@ -71,10 +71,6 @@
<router-link v-else :to="`/journal/timetables?search-driver=${timetable.driverName}`"> <router-link v-else :to="`/journal/timetables?search-driver=${timetable.driverName}`">
<strong>{{ timetable.driverName }}</strong> <strong>{{ timetable.driverName }}</strong>
</router-link> </router-link>
<div v-if="timetable.driverLanguageId != null">
<FlagIcon :language-id="timetable.driverLanguageId" width="1.75em" />
</div>
</span> </span>
<span class="general-time"> <span class="general-time">
@@ -114,10 +110,8 @@ import dateMixin from '../../../mixins/dateMixin';
import styleMixin from '../../../mixins/styleMixin'; import styleMixin from '../../../mixins/styleMixin';
import { useApiStore } from '../../../store/apiStore'; import { useApiStore } from '../../../store/apiStore';
import trainCategoryMixin from '../../../mixins/trainCategoryMixin'; import trainCategoryMixin from '../../../mixins/trainCategoryMixin';
import FlagIcon from '../../Global/FlagIcon.vue';
export default defineComponent({ export default defineComponent({
components: { FlagIcon },
mixins: [dateMixin, styleMixin, trainCategoryMixin], mixins: [dateMixin, styleMixin, trainCategoryMixin],
data() { data() {
@@ -197,7 +191,7 @@ export default defineComponent({
} }
} }
@include responsive.smallScreen { @include responsive.smallScreen{
.item-general { .item-general {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
-1
View File
@@ -10,7 +10,6 @@ export namespace Journal {
| 'search-train' | 'search-train'
| 'search-date-from' | 'search-date-from'
| 'search-dispatcher' | 'search-dispatcher'
| 'search-includesScenery'
| 'search-issuedFrom' | 'search-issuedFrom'
| 'search-terminatingAt' | 'search-terminatingAt'
| 'search-via' | 'search-via'
@@ -151,7 +151,6 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
@use '../../styles/responsive'; @use '../../styles/responsive';
@use '../../styles/scenery-history-table'; @use '../../styles/scenery-history-table';
@use '../../styles/badge';
.scenery-dispatchers-history { .scenery-dispatchers-history {
height: 100%; height: 100%;
+13 -1
View File
@@ -57,8 +57,20 @@ export default defineComponent({
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss">
@use '../../styles/responsive'; @use '../../styles/responsive';
@use '../../styles/badge';
h3.section-header {
margin: 0.5em 0;
padding: 0.3em;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
.info-lists { .info-lists {
display: flex; display: flex;
@@ -21,8 +21,6 @@
</span> </span>
<span v-else>{{ onlineScenery.dispatcherName }}</span> <span v-else>{{ onlineScenery.dispatcherName }}</span>
</router-link> </router-link>
<FlagIcon :languageId="onlineScenery.dispatcherLanguageId" width="1.25em" />
</div> </div>
<div class="info-bottom"> <div class="info-bottom">
@@ -53,11 +51,9 @@ import styleMixin from '../../../mixins/styleMixin';
import StationStatusBadge from '../../Global/StationStatusBadge.vue'; import StationStatusBadge from '../../Global/StationStatusBadge.vue';
import { ActiveScenery } from '../../../typings/common'; import { ActiveScenery } from '../../../typings/common';
import { useApiStore } from '../../../store/apiStore'; import { useApiStore } from '../../../store/apiStore';
import FlagIcon from '../../Global/FlagIcon.vue';
export default defineComponent({ export default defineComponent({
mixins: [styleMixin, dateMixin, routerMixin], mixins: [styleMixin, dateMixin, routerMixin],
components: { StationStatusBadge, FlagIcon },
data() { data() {
return { return {
@@ -70,7 +66,8 @@ export default defineComponent({
type: Object as PropType<ActiveScenery>, type: Object as PropType<ActiveScenery>,
required: false required: false
} }
} },
components: { StationStatusBadge }
}); });
</script> </script>
@@ -1,6 +1,6 @@
<template> <template>
<section class="info-spawn-list"> <section class="info-spawn-list">
<h3 class="spawn-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" />
&nbsp;{{ $t('scenery.spawns') }} &nbsp; &nbsp;{{ $t('scenery.spawns') }} &nbsp;
<span class="text--primary">{{ onlineScenery?.spawns.length || '0' }}</span> <span class="text--primary">{{ onlineScenery?.spawns.length || '0' }}</span>
@@ -53,23 +53,10 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@use '../../../styles/badge';
ul { ul {
position: relative; position: relative;
} }
h3.spawn-header {
margin: 0.5em 0;
padding: 0.3em;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
.spawns-anim { .spawns-anim {
&-move, &-move,
&-enter-active, &-enter-active,
@@ -1,6 +1,6 @@
<template> <template>
<section class="info-user-list"> <section class="info-user-list">
<h3 class="user-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" />
&nbsp;{{ $t('scenery.users') }} &nbsp; &nbsp;{{ $t('scenery.users') }} &nbsp;
<span class="text--primary">{{ onlineScenery?.stationTrains?.length || 0 }}</span <span class="text--primary">{{ onlineScenery?.stationTrains?.length || 0 }}</span
@@ -111,8 +111,6 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@use '../../../styles/badge';
$no-timetable: #aaa; $no-timetable: #aaa;
$departed: springgreen; $departed: springgreen;
$stopped: #ffa600; $stopped: #ffa600;
@@ -120,17 +118,6 @@ $online: gold;
$terminated: salmon; $terminated: salmon;
$disconnected: slategray; $disconnected: slategray;
h3.user-header {
margin: 0.5em 0;
padding: 0.3em;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
.info-user-list { .info-user-list {
width: 100%; width: 100%;
} }
@@ -35,7 +35,6 @@
id="scenery-search" id="scenery-search"
list="sceneries" list="sceneries"
:placeholder="$t('filters.sceneries-placeholder')" :placeholder="$t('filters.sceneries-placeholder')"
@change="handleSceneriesInput"
@focus="preventKeyDown = true" @focus="preventKeyDown = true"
@blur="preventKeyDown = false" @blur="preventKeyDown = false"
/> />
@@ -45,40 +44,42 @@
</button> </button>
</section> </section>
<section class="card_input-search"> <section class="card_input-search authors">
<datalist id="authors" name="authors">
<option v-for="(author, i) in authorsOptions" :key="i" :value="author"></option>
</datalist>
<input <input
v-model="filters['lines']" type="text"
id="line-numbers-search" id="author"
:placeholder="$t('filters.line-numbers-placeholder')" list="authors"
name="authors"
v-model="filters['authors']"
:placeholder="$t('filters.authors-placeholder')"
@focus="preventKeyDown = true" @focus="preventKeyDown = true"
@blur="preventKeyDown = false" @blur="preventKeyDown = false"
/> />
<button class="btn--action btn--image" @click="resetLineNumbersInput">
<img src="/images/icon-exit.svg" alt="reset line numbers search" />
</button>
</section>
<section class="card_input-search">
<select id="author" name="authors" v-model="filters['authors']">
<option value="">{{ $t('filters.authors-placeholder') }}</option>
<option v-for="(author, i) in authorsOptions" :key="i" :value="author">
{{ author }}
</option>
</select>
<button class="btn--action btn--image" @click="resetAuthorsInput"> <button class="btn--action btn--image" @click="resetAuthorsInput">
<img src="/images/icon-exit.svg" alt="reset authors search" /> <img src="/images/icon-exit.svg" alt="reset authors search" />
</button> </button>
</section> </section>
<section class="card_input-search"> <section class="card_input-search">
<select id="projects" name="projects" v-model="filters['projects']"> <datalist id="projects" name="projects">
<option value="">{{ $t('filters.projects-placeholder') }}</option> <option v-for="(project, i) in projectsOptions" :key="i" :value="project"></option>
<option v-for="(project, i) in projectsOptions" :key="i" :value="project"> </datalist>
{{ project }}
</option> <input
</select> type="text"
id="projects"
list="projects"
name="projects"
v-model="filters['projects']"
:placeholder="$t('filters.projects-placeholder')"
@focus="preventKeyDown = true"
@blur="preventKeyDown = false"
/>
<button class="btn--action btn--image" @click="resetProjectsInput"> <button class="btn--action btn--image" @click="resetProjectsInput">
<img src="/images/icon-exit.svg" alt="reset projects search" /> <img src="/images/icon-exit.svg" alt="reset projects search" />
@@ -91,7 +92,7 @@
v-for="(sectionFilters, sectionKey) in filtersSections" v-for="(sectionFilters, sectionKey) in filtersSections"
:key="sectionKey" :key="sectionKey"
> >
<h3 class="section-header"> <h3 class="text--primary">
<span class="active-indicator" v-if="!areSectionFiltersDefault(sectionKey)"></span> <span class="active-indicator" v-if="!areSectionFiltersDefault(sectionKey)"></span>
{{ $t(`filters.sections.${sectionKey}`) }} {{ $t(`filters.sections.${sectionKey}`) }}
<button @click="resetSectionFilters(sectionKey)">RESET</button> <button @click="resetSectionFilters(sectionKey)">RESET</button>
@@ -121,7 +122,7 @@
</section> </section>
<section class="card_timestamp"> <section class="card_timestamp">
<h3 class="hours-section-header">{{ $t('filters.minimum-hours-title') }}</h3> <h3 class="section-header">{{ $t('filters.minimum-hours-title') }}</h3>
<span class="clock"> <span class="clock">
<button class="btn--action" @click="subHour">-</button> <button class="btn--action" @click="subHour">-</button>
@@ -216,6 +217,8 @@ export default defineComponent({
sliderStates, sliderStates,
minimumHours: 0, minimumHours: 0,
authorSearchFilter: '',
projectSearchFilter: '',
currentRegion: { id: '', value: '' }, currentRegion: { id: '', value: '' },
@@ -273,8 +276,6 @@ export default defineComponent({
authorsOptions() { authorsOptions() {
return this.store.stationList return this.store.stationList
.reduce((acc, station) => { .reduce((acc, station) => {
if (station.generalInfo?.hidden === true) return acc;
station.generalInfo?.authors?.forEach((author) => { station.generalInfo?.authors?.forEach((author) => {
if (author.trim() != '' && !acc.includes(author.toLocaleLowerCase())) if (author.trim() != '' && !acc.includes(author.toLocaleLowerCase()))
acc.push(author.toLocaleLowerCase()); acc.push(author.toLocaleLowerCase());
@@ -288,10 +289,8 @@ export default defineComponent({
projectsOptions() { projectsOptions() {
return this.store.stationList return this.store.stationList
.reduce((acc, station) => { .reduce((acc, station) => {
if (!station.generalInfo || !station.generalInfo.project || station.generalInfo.hidden) if (!station.generalInfo || !station.generalInfo.project || station.generalInfo.hidden) return acc;
return acc; if (!acc.includes(station.generalInfo.project.trim())) acc.push(station.generalInfo.project.trim());
if (!acc.includes(station.generalInfo.project.trim()))
acc.push(station.generalInfo.project.trim());
return acc; return acc;
}, [] as string[]) }, [] as string[])
@@ -321,15 +320,11 @@ export default defineComponent({
}, },
resetAuthorsInput() { resetAuthorsInput() {
this.filters['authors'] = ''; this.filters['authors'] = this.authorSearchFilter;
}, },
resetProjectsInput() { resetProjectsInput() {
this.filters['projects'] = ''; this.filters['projects'] = this.projectSearchFilter;
},
resetLineNumbersInput() {
this.filters['lines'] = '';
}, },
handleSceneriesInput() { handleSceneriesInput() {
@@ -374,6 +369,7 @@ export default defineComponent({
// Reset local model values // Reset local model values
this.minimumHours = 0; this.minimumHours = 0;
this.authorSearchFilter = '';
// Reset global filters // Reset global filters
Object.keys(this.filters).forEach((filterKey) => { Object.keys(this.filters).forEach((filterKey) => {
@@ -417,14 +413,6 @@ export default defineComponent({
@use '../../styles/animations'; @use '../../styles/animations';
h3.section-header { h3.section-header {
display: flex;
align-items: center;
margin-bottom: 0.25em;
gap: 0.5em;
color: var(--clr-primary);
}
h3.hours-section-header {
text-align: center; text-align: center;
margin: 0.5em 0; margin: 0.5em 0;
} }
@@ -506,12 +494,15 @@ h3.hours-section-header {
height: 100%; height: 100%;
} }
input, input {
select {
width: 100%; width: 100%;
padding: 0.5em; padding: 0.5em;
border: 1px solid #aaa; border: 1px solid #aaa;
} }
&.authors {
margin-top: 1em;
}
} }
.section-filters { .section-filters {
@@ -582,6 +573,12 @@ h3.hours-section-header {
} }
.option-section h3 { .option-section h3 {
display: flex;
align-items: center;
margin-bottom: 0.25em;
gap: 0.5em;
button { button {
padding: 0.15em; padding: 0.15em;
color: coral; color: coral;
+68 -81
View File
@@ -14,7 +14,7 @@
class="header-text" class="header-text"
:class="headerName" :class="headerName"
> >
<div class="header_wrapper"> <span class="header_wrapper">
<div v-html="$t(`sceneries.headers.${headerName}`)"></div> <div v-html="$t(`sceneries.headers.${headerName}`)"></div>
<img <img
@@ -23,7 +23,7 @@
:src="`/images/icon-arrow-${activeSorter.dir == 1 ? 'asc' : 'desc'}.svg`" :src="`/images/icon-arrow-${activeSorter.dir == 1 ? 'asc' : 'desc'}.svg`"
alt="sort icon" alt="sort icon"
/> />
</div> </span>
</th> </th>
<th <th
@@ -52,14 +52,14 @@
</thead> </thead>
<tbody> <tbody>
<tr <router-link
v-for="station in filteredStationList" v-for="station in filteredStationList"
class="a-row" class="a-row"
tabindex="0" role="row"
:key="station.name" :key="station.name"
@click.right.prevent="openForumSite($event, station.generalInfo?.url)" @click.right.prevent="openForumSite($event, station.generalInfo?.url)"
@click="getSceneryRoute(station)" @keydown.space.prevent="openForumSite($event, station.generalInfo?.url)"
@keydown.enter="getSceneryRoute(station)" :to="getSceneryRoute(station)"
> >
<td class="station-name" :class="station.generalInfo?.availability"> <td class="station-name" :class="station.generalInfo?.availability">
<b v-if="station.generalInfo?.project" style="color: salmon">{{ <b v-if="station.generalInfo?.project" style="color: salmon">{{
@@ -146,14 +146,6 @@
</span> </span>
</td> </td>
<td class="station-dispatcher-lang">
<FlagIcon
v-if="station.onlineInfo && station.onlineInfo.dispatcherLanguageId != -1"
:language-id="station.onlineInfo.dispatcherLanguageId"
width="2.25em"
/>
</td>
<td class="station-dispatcher-exp"> <td class="station-dispatcher-exp">
<span <span
v-if="station.onlineInfo && station.onlineInfo?.dispatcherExp != -1" v-if="station.onlineInfo && station.onlineInfo?.dispatcherExp != -1"
@@ -322,7 +314,7 @@
> >
{{ station.onlineInfo?.scheduledTrainCount.confirmed ?? '-' }} {{ station.onlineInfo?.scheduledTrainCount.confirmed ?? '-' }}
</td> </td>
</tr> </router-link>
</tbody> </tbody>
</table> </table>
@@ -352,13 +344,11 @@ import { useTooltipStore } from '../../store/tooltipStore';
import { getChangedFilters } from '../../managers/stationFilterManager'; import { getChangedFilters } from '../../managers/stationFilterManager';
import { ActiveSorter, HeadIdsType, headIconsIds, headIds } from './typings'; import { ActiveSorter, HeadIdsType, headIconsIds, headIds } from './typings';
import { filterStations, sortStations } from './utils'; import { filterStations, sortStations } from './utils';
import { getLanguageNameById } from '../../utils/languageUtils';
import FlagIcon from '../Global/FlagIcon.vue';
export default defineComponent({ export default defineComponent({
emits: ['toggleDonationCard'], emits: ['toggleDonationCard'],
components: { Loading, StationStatusBadge, FlagIcon }, components: { Loading, StationStatusBadge },
mixins: [styleMixin, dateMixin], mixins: [styleMixin, dateMixin],
data: () => ({ data: () => ({
@@ -394,13 +384,15 @@ export default defineComponent({
methods: { methods: {
getSceneryRoute(station: Station) { getSceneryRoute(station: Station) {
this.$router.push({ // TODO: Hide tooltips when navigating away
return {
name: 'SceneryView', name: 'SceneryView',
query: { query: {
station: station.name, station: station.name,
region: this.$route.query.region || undefined region: this.$route.query.region || undefined
} }
}); };
}, },
openDonationCard(e: Event) { openDonationCard(e: Event) {
@@ -467,82 +459,78 @@ table {
width: 100%; width: 100%;
min-width: 1250px; min-width: 1250px;
white-space: wrap; white-space: wrap;
}
thead { thead {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 50;
}
thead tr {
background-color: var(--clr-bg3);
}
thead th {
background-color: var(--clr-bg3);
white-space: pre-wrap;
padding: 0.5em 0.25em;
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
&.station {
width: 12em;
} }
&.min-lvl { thead tr {
width: 4em; background-color: var(--clr-bg3);
} }
&.status { thead th {
width: 10em; &.station {
} width: 12em;
}
&.dispatcher { &.min-lvl {
width: 12em; width: 4em;
} }
&.dispatcher-lang { &.status {
width: 6em; width: 10em;
} }
&.dispatcher-lvl { &.dispatcher {
width: 6em; width: 12em;
} }
&.routes-double, &.dispatcher-lvl {
&.routes-single { width: 6em;
width: 7em; }
}
&.general { &.routes-double,
width: 11em; &.routes-single {
} width: 7em;
}
&.header-image { &.general {
width: 3.5em; width: 11em;
}
&.user { &.header-image {
width: 5em; width: 3.5em;
&.user {
width: 5em;
}
}
padding: 0.5em 0.25em;
background-color: var(--clr-bg3);
white-space: pre-wrap;
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
span {
display: flex;
align-items: center;
justify-content: center;
img {
width: 1.5em;
vertical-align: middle;
}
} }
} }
} }
thead th .header_wrapper { tr,
display: flex; .a-row {
align-items: center;
justify-content: center;
img {
width: 1.5em;
vertical-align: middle;
}
}
tbody tr {
background-color: $rowCol; background-color: $rowCol;
vertical-align: middle; vertical-align: middle;
@@ -562,7 +550,6 @@ tbody tr {
cursor: pointer; cursor: pointer;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
height: 2.5em;
&.inactive { &.inactive {
opacity: 0.2; opacity: 0.2;
-1
View File
@@ -10,7 +10,6 @@ export const headIds = [
'min-lvl', 'min-lvl',
'status', 'status',
'dispatcher', 'dispatcher',
'dispatcher-lang',
'dispatcher-lvl', 'dispatcher-lvl',
'routes-single', 'routes-single',
'routes-double', 'routes-double',
+7 -32
View File
@@ -145,33 +145,13 @@ function filterSliderValues(filters: Record<string, any>, generalInfo: StationGe
} }
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) { function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
if ( return (
filters['authors'].length > 3 && (filters['authors'].length > 3 &&
generalInfo.authors && !generalInfo.authors
!generalInfo.authors.some( ?.map((a) => a.toLocaleLowerCase())
(a) => a.toLocaleLowerCase() == filters['authors'].toLocaleLowerCase() .includes(filters['authors'].toLocaleLowerCase())) ||
) (filters['projects'].length > 0 && generalInfo.project != filters['projects'])
) );
return true;
if (filters['projects'].length > 0 && generalInfo.project != filters['projects']) return true;
if (filters['lines'].length > 0) {
const linesNumbers = (filters['lines'] as string)
.split(',')
.map((l) => Number(l))
.filter((l) => !isNaN(l) && l != 0);
if (
!generalInfo.lines
?.split(',')
.map((l) => Number(l))
.some((l) => linesNumbers.includes(l))
)
return true;
}
return false;
} }
export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => { export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
@@ -210,11 +190,6 @@ export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0); diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0);
break; break;
case 'dispatcher-lang':
diff =
(a.onlineInfo?.dispatcherLanguageId ?? -1) - (b.onlineInfo?.dispatcherLanguageId ?? -1);
break;
case 'routes-single': case 'routes-single':
diff = diff =
(a.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1) - (a.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1) -
@@ -18,9 +18,9 @@
<span v-if="vehicleCargo">({{ vehicleCargo.id }})</span> <span v-if="vehicleCargo">({{ vehicleCargo.id }})</span>
</div> </div>
<div class="vehicle-props" v-if="vehicleGroup"> <div class="vehicle-props" v-if="vehicleData">
{{ vehicleGroup.speed }}km/h &bull; {{ vehicleGroup.length }}m &bull; {{ vehicleData.group.speed }}km/h &bull; {{ vehicleData.group.length }}m &bull;
{{ (vehicleGroup.weight / 1000).toFixed(1) }}t {{ (vehicleData.group.weight / 1000).toFixed(1) }}t
<span v-if="vehicleCargo">(+{{ (vehicleCargo.weight / 1000).toFixed(1) }}t)</span> <span v-if="vehicleCargo">(+{{ (vehicleCargo.weight / 1000).toFixed(1) }}t)</span>
</div> </div>
</div> </div>
@@ -73,18 +73,12 @@ export default defineComponent({
return this.tooltipStore.content.split(':')[0]; return this.tooltipStore.content.split(':')[0];
}, },
vehicleGroup() { vehicleData() {
if (!this.apiStore.vehiclesData) return null; return this.apiStore.vehiclesData?.find((v) => v.name == this.vehicleName);
const vehicle = this.apiStore.vehiclesData.vehicles.find((v) => v.name == this.vehicleName);
if (!vehicle) return null;
return this.apiStore.vehiclesData.vehicleGroups.find((g) => g.id == vehicle?.vehicleGroupsId);
}, },
vehicleCargo() { vehicleCargo() {
const x = this.vehicleGroup?.cargoTypes?.find( const x = this.vehicleData?.group.cargoTypes?.find(
(c) => c.id == this.tooltipStore.content.split(':')[1] (c) => c.id == this.tooltipStore.content.split(':')[1]
); );
+1 -6
View File
@@ -66,10 +66,6 @@
<span v-else>{{ train.driverName }}</span> <span v-else>{{ train.driverName }}</span>
</div> </div>
<div class="train-language-flag">
<FlagIcon :language-id="train.driverLanguageId" width="1.75em" />
</div>
</div> </div>
</div> </div>
@@ -203,11 +199,10 @@ import trainInfoMixin from '../../mixins/trainInfoMixin';
import trainCategoryMixin from '../../mixins/trainCategoryMixin'; import trainCategoryMixin from '../../mixins/trainCategoryMixin';
import ProgressBar from '../Global/ProgressBar.vue'; import ProgressBar from '../Global/ProgressBar.vue';
import StockList from '../Global/StockList.vue'; import StockList from '../Global/StockList.vue';
import FlagIcon from '../Global/FlagIcon.vue';
export default defineComponent({ export default defineComponent({
mixins: [trainInfoMixin, styleMixin, trainCategoryMixin], mixins: [trainInfoMixin, styleMixin, trainCategoryMixin],
components: { ProgressBar, StockList, FlagIcon }, components: { ProgressBar, StockList },
props: { props: {
train: { train: {
+3 -7
View File
@@ -69,8 +69,7 @@
"confirm": "ROGER THAT!", "confirm": "ROGER THAT!",
"no-data": "No data about the latest app update has been found", "no-data": "No data about the latest app update has been found",
"info-1": "This changelog will be available to see once again after clicking the version number in the footer", "info-1": "This changelog will be available to see once again after clicking the version number in the footer",
"info-2": "The full app changelog available on {link}", "info-2": "The full app changelog available on <a href='https://github.com/Spythere/stacjownik' target='_blank'>the project's GitHub</a>"
"info-2-link-text": "the project's GitHub page"
}, },
"app": { "app": {
"sceneries": "SCENERIES", "sceneries": "SCENERIES",
@@ -200,7 +199,6 @@
"search-dispatcher": "Dispatcher name", "search-dispatcher": "Dispatcher name",
"search-station": "Scenery name / #", "search-station": "Scenery name / #",
"search-author": "Timetable author name", "search-author": "Timetable author name",
"search-includesScenery": "Includes scenery name",
"search-issuedFrom": "Issuing scenery name", "search-issuedFrom": "Issuing scenery name",
"search-via": "Via scenery name", "search-via": "Via scenery name",
"search-terminatingAt": "Terminating scenery name", "search-terminatingAt": "Terminating scenery name",
@@ -318,9 +316,8 @@
"minTwoWayInt": "MIN. INTERNAL OTHER DOUBLE TRACK ROUTES" "minTwoWayInt": "MIN. INTERNAL OTHER DOUBLE TRACK ROUTES"
}, },
"sceneries-placeholder": "Search for scenery", "sceneries-placeholder": "Search for scenery",
"line-numbers-placeholder": "Line numbers (separated by commas)", "authors-placeholder": "Scenery author (other filters apply)",
"authors-placeholder": "Scenery author", "projects-placeholder": "Scenery project (other filters apply)",
"projects-placeholder": "Scenery project",
"search-button-title": "SEARCH", "search-button-title": "SEARCH",
"minimum-hours-title": "SHOW ONLY SCENERIES UNTIL:", "minimum-hours-title": "SHOW ONLY SCENERIES UNTIL:",
"now": "NOW", "now": "NOW",
@@ -337,7 +334,6 @@
"min-lvl": "Scenery\nlevel", "min-lvl": "Scenery\nlevel",
"status": "Status", "status": "Status",
"dispatcher": "Dispatcher", "dispatcher": "Dispatcher",
"dispatcher-lang": "Language",
"dispatcher-lvl": "Dispatcher\nlevel", "dispatcher-lvl": "Dispatcher\nlevel",
"routes-single": "1-track\nroutes", "routes-single": "1-track\nroutes",
"routes-double": "2-track\nroutes", "routes-double": "2-track\nroutes",
+3 -7
View File
@@ -68,8 +68,7 @@
"confirm": "PRZYJĄŁEM!", "confirm": "PRZYJĄŁEM!",
"no-data": "Nie znaleziono informacji o ostatnich zmianach w aplikacji", "no-data": "Nie znaleziono informacji o ostatnich zmianach w aplikacji",
"info-1": "Ten changelog będzie zawsze dostępny po kliknięciu numeru wersji w stopce strony", "info-1": "Ten changelog będzie zawsze dostępny po kliknięciu numeru wersji w stopce strony",
"info-2": "Pełny changelog dostępny na {link}", "info-2": "Pełny changelog dostępny na <a href='https://github.com/Spythere/stacjownik' target='_blank'>GitHubie projektu</a>"
"info-2-link-text": "GitHubie projektu"
}, },
"app": { "app": {
"sceneries": "SCENERIE", "sceneries": "SCENERIE",
@@ -196,7 +195,6 @@
"search-dispatcher": "Nick dyżurnego", "search-dispatcher": "Nick dyżurnego",
"search-station": "Nazwa scenerii / #", "search-station": "Nazwa scenerii / #",
"search-author": "Nick autora rozkładu jazdy", "search-author": "Nick autora rozkładu jazdy",
"search-includesScenery": "Zawiera scenerię",
"search-issuedFrom": "Sceneria początkowa", "search-issuedFrom": "Sceneria początkowa",
"search-via": "Przez scenerię", "search-via": "Przez scenerię",
"search-terminatingAt": "Sceneria końcowa", "search-terminatingAt": "Sceneria końcowa",
@@ -315,9 +313,8 @@
"minTwoWayInt": "SZLAKI DWUTOROWE NIEZELEKTR. WEWNĘTRZNE (MINIMUM)" "minTwoWayInt": "SZLAKI DWUTOROWE NIEZELEKTR. WEWNĘTRZNE (MINIMUM)"
}, },
"sceneries-placeholder": "Wyszukaj scenerię", "sceneries-placeholder": "Wyszukaj scenerię",
"line-numbers-placeholder": "Numery linii (oddzielone przecinkami)", "authors-placeholder": "Autor scenerii (uwzględnia inne filtry)",
"authors-placeholder": "Autor scenerii", "projects-placeholder": "Projekt scenerii (uwzględnia inne filtry)",
"projects-placeholder": "Projekt scenerii",
"search-button-title": "SZUKAJ", "search-button-title": "SZUKAJ",
"minimum-hours-title": "POKAŻ TYLKO SCENERIE DOSTĘPNE MINIMUM DO:", "minimum-hours-title": "POKAŻ TYLKO SCENERIE DOSTĘPNE MINIMUM DO:",
"now": "TERAZ", "now": "TERAZ",
@@ -334,7 +331,6 @@
"min-lvl": "Poziom\nscenerii", "min-lvl": "Poziom\nscenerii",
"status": "Status", "status": "Status",
"dispatcher": "Dyżurny", "dispatcher": "Dyżurny",
"dispatcher-lang": "Język",
"dispatcher-lvl": "Poziom\ndyżurnego", "dispatcher-lvl": "Poziom\ndyżurnego",
"routes-single": "Szlaki\n1-torowe", "routes-single": "Szlaki\n1-torowe",
"routes-double": "Szlaki\n2-torowe", "routes-double": "Szlaki\n2-torowe",
+1 -2
View File
@@ -69,8 +69,7 @@ export const initFilters = {
minTwoWayInt: 0, minTwoWayInt: 0,
minTwoWayCatenaryInt: 0, minTwoWayCatenaryInt: 0,
authors: '', authors: '',
projects: '', projects: ''
lines: ''
}; };
export const sliderStates = [ export const sliderStates = [
+9 -26
View File
@@ -122,27 +122,19 @@ export default defineComponent({
// Check the whole consist speed limit // Check the whole consist speed limit
const vehicleMaxSpeed = stockList.reduce((acc, stockName, i) => { const vehicleMaxSpeed = stockList.reduce((acc, stockName, i) => {
if (!this.apiStore.vehiclesData) return acc;
const [vehicleName, vehicleCargo] = stockName.split(':'); const [vehicleName, vehicleCargo] = stockName.split(':');
const vehicle = this.apiStore.vehiclesData.vehicles.find((v) => v.name == vehicleName); const vehicleData = this.apiStore.vehiclesData?.find((v) => v.name == vehicleName);
if (!vehicle) return acc; if (!vehicleData) return acc;
const vehicleGroup = this.apiStore.vehiclesData.vehicleGroups.find( let vehicleSpeed = vehicleData.group.speed;
(g) => g.id == vehicle.vehicleGroupsId
);
if (!vehicleGroup) return acc; if (vehicleData.type == 'wagon-freight') {
let vehicleSpeed = vehicleGroup.speed;
if (vehicle.type == 'wagon-freight') {
isPassenger = false; isPassenger = false;
if (vehicleCargo !== undefined && vehicleGroup.speedLoaded) { if (vehicleCargo !== undefined && vehicleData.group.speedLoaded) {
vehicleSpeed = vehicleGroup.speedLoaded; vehicleSpeed = vehicleData.group.speedLoaded;
} }
} }
@@ -151,23 +143,14 @@ export default defineComponent({
// Check the head vehicle speed limit // Check the head vehicle speed limit
const headLocoName = stockList[0]; const headLocoName = stockList[0];
const headLocoVehicleData = this.apiStore.vehiclesData?.find((v) => v.name == headLocoName);
const headLocoVehicle = this.apiStore.vehiclesData!.vehicles.find(
(v) => v.name == headLocoName
);
const headLocoVehicleGroup = this.apiStore.vehiclesData!.vehicleGroups.find(
(g) => g.id == headLocoVehicle?.vehicleGroupsId
);
if (!headLocoVehicleGroup) return vehicleMaxSpeed;
// Omit speed check for head vehicle if there's no data for it // Omit speed check for head vehicle if there's no data for it
if (!headLocoName || !headLocoVehicle || !headLocoVehicleGroup.massSpeeds) if (!headLocoName || !headLocoVehicleData || !headLocoVehicleData.group.massSpeeds)
return vehicleMaxSpeed; return vehicleMaxSpeed;
const massSpeeds = const massSpeeds =
headLocoVehicleGroup.massSpeeds[ headLocoVehicleData.group.massSpeeds[
stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo' stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo'
]; ];
+2 -2
View File
@@ -13,7 +13,7 @@ export const useApiStore = defineStore('apiStore', {
}, },
activeData: undefined as API.ActiveData.Response | undefined, activeData: undefined as API.ActiveData.Response | undefined,
vehiclesData: undefined as API.VehiclesData.Response | undefined, vehiclesData: undefined as API.Vehicles.Response | undefined,
donatorsData: [] as API.Donators.Response, donatorsData: [] as API.Donators.Response,
sceneryData: [] as StationJSONData[], sceneryData: [] as StationJSONData[],
@@ -111,7 +111,7 @@ export const useApiStore = defineStore('apiStore', {
async fetchVehiclesInfo() { async fetchVehiclesInfo() {
try { try {
const response = await this.client!.get<API.VehiclesData.Response>('api/getVehiclesData'); const response = await this.client!.get<API.Vehicles.Response>('api/getVehicles');
this.vehiclesData = response.data; this.vehiclesData = response.data;
this.dataStatuses.vehicles = response.data ? Status.Data.Loaded : Status.Data.Warning; this.dataStatuses.vehicles = response.data ? Status.Data.Loaded : Status.Data.Warning;
+3 -6
View File
@@ -38,8 +38,7 @@ export const useMainStore = defineStore('mainStore', {
modalLastClickedTarget: null, modalLastClickedTarget: null,
currentLocale: 'pl', currentLocale: 'pl',
isMigrateInfoCardOpen: false, isMigrateInfoCardOpen: false
pinnedStationNames: []
}) as MainStoreState, }) as MainStoreState,
actions: { actions: {
@@ -87,7 +86,6 @@ export const useMainStore = defineStore('mainStore', {
online: Boolean(train.online), online: Boolean(train.online),
driverId: train.driverId, driverId: train.driverId,
driverName: train.driverName, driverName: train.driverName,
driverLanguageId: train.driverLanguageId,
currentStationName: train.currentStationName, currentStationName: train.currentStationName,
currentStationHash: train.currentStationHash, currentStationHash: train.currentStationHash,
connectedTrack: train.connectedTrack, connectedTrack: train.connectedTrack,
@@ -259,7 +257,6 @@ export const useMainStore = defineStore('mainStore', {
dispatcherIsSupporter: false, dispatcherIsSupporter: false,
dispatcherStatus: Status.ActiveDispatcher.FREE, dispatcherStatus: Status.ActiveDispatcher.FREE,
dispatcherTimestamp: -1, dispatcherTimestamp: -1,
dispatcherLanguageId: -1,
isOnline: false, isOnline: false,
@@ -306,7 +303,6 @@ export const useMainStore = defineStore('mainStore', {
dispatcherIsSupporter: scenery.dispatcherIsSupporter, dispatcherIsSupporter: scenery.dispatcherIsSupporter,
dispatcherStatus: scenery.dispatcherStatus, dispatcherStatus: scenery.dispatcherStatus,
dispatcherTimestamp: dispatcherTimestamp, dispatcherTimestamp: dispatcherTimestamp,
dispatcherLanguageId: scenery.dispatcherLanguageId,
isOnline: scenery.isOnline == 1, isOnline: scenery.isOnline == 1,
@@ -435,6 +431,7 @@ export const useMainStore = defineStore('mainStore', {
return { return {
name: scenery.name, name: scenery.name,
generalInfo: { generalInfo: {
...scenery, ...scenery,
authors: scenery.authors?.split(',').map((a) => a.trim()), authors: scenery.authors?.split(',').map((a) => a.trim()),
@@ -449,7 +446,7 @@ export const useMainStore = defineStore('mainStore', {
}, },
allStationInfo(): Station[] { allStationInfo(): Station[] {
const onlineUnsavedStations: Station[] = this.activeSceneryList const onlineUnsavedStations = this.activeSceneryList
.filter( .filter(
(scenery) => (scenery) =>
this.stationList.findIndex((st) => st.name == scenery.name) == -1 && this.stationList.findIndex((st) => st.name == scenery.name) == -1 &&
+1 -21
View File
@@ -89,8 +89,7 @@ select {
font-size: 1em; font-size: 1em;
} }
input, input {
select {
background: none; background: none;
color: white; color: white;
font-size: 1em; font-size: 1em;
@@ -359,22 +358,3 @@ a.a-button {
background-color: #aaa; background-color: #aaa;
margin: 0.5em 0; margin: 0.5em 0;
} }
.g-checkbox {
position: relative;
display: inline-block;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
display: flex;
justify-content: center;
align-items: center;
input {
position: absolute;
width: 1px;
height: 1px;
}
}
+5 -1
View File
@@ -61,4 +61,8 @@
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
padding-right: 0.5em; padding-right: 0.5em;
} }
select.search-input {
}
+3 -50
View File
@@ -1,4 +1,4 @@
import { Status, Vehicle, VehicleGroup } from './common'; import { Status, VehicleData } from './common';
export enum APIDataStatus { export enum APIDataStatus {
OK = 'OK', OK = 'OK',
@@ -38,7 +38,6 @@ export namespace API {
dispatcherLevel: number | null; dispatcherLevel: number | null;
dispatcherRate: number; dispatcherRate: number;
dispatcherIsSupporter: boolean; dispatcherIsSupporter: boolean;
dispatcherLanguageId: number | null;
dispatcherStatus?: number; dispatcherStatus?: number;
isOnline: boolean; isOnline: boolean;
lastOnlineTimestamp: number; lastOnlineTimestamp: number;
@@ -115,7 +114,6 @@ export namespace API {
dispatcherId: number; dispatcherId: number;
dispatcherName: string; dispatcherName: string;
dispatcherIsSupporter: boolean; dispatcherIsSupporter: boolean;
dispatcherLanguageId: number;
stationName: string; stationName: string;
stationHash: string; stationHash: string;
region: string; region: string;
@@ -154,7 +152,6 @@ export namespace API {
driverId: number; driverId: number;
driverIsSupporter: boolean; driverIsSupporter: boolean;
driverLevel?: number; driverLevel?: number;
driverLanguageId: number;
currentStationName: string; currentStationName: string;
currentStationHash?: string; currentStationHash?: string;
@@ -224,7 +221,6 @@ export namespace API {
driverName: string; driverName: string;
driverLevel: number | null; driverLevel: number | null;
driverIsSupporter: boolean; driverIsSupporter: boolean;
driverLanguageId: number | null;
route: string; route: string;
twr: number; twr: number;
@@ -333,51 +329,8 @@ export namespace API {
export type Response = string[]; export type Response = string[];
} }
export namespace VehiclesData { export namespace Vehicles {
export interface VehicleObject { export type Response = VehicleData[];
id: number;
name: string;
type: string;
cabinName: string | null;
restrictions: Record<string, any> | null;
vehicleGroupsId: number;
}
export interface VehicleGroupObject {
id: number;
name: string;
speed: number;
speedLoaded?: number;
speedLoco?: number;
length: number;
weight: number;
cargoTypes: VehicleCargo[] | null;
locoProps: {
coldStart: boolean;
doubleManned: boolean;
} | null;
massSpeeds: VehicleGroupMassSpeeds | null;
}
export interface VehicleGroupMassSpeeds {
passenger: Record<string, number> | null;
cargo: Record<string, number> | null;
none: number | null;
}
export interface VehicleCargo {
id: string;
weight: number;
}
export interface Data {
vehicles: VehicleObject[];
vehicleGroups: VehicleGroupObject[];
}
export type Response = Data;
} }
} }
+43 -7
View File
@@ -1,6 +1,5 @@
import { RouteLocationRaw } from 'vue-router'; import { RouteLocationRaw } from 'vue-router';
import { StationJSONData } from '../store/typings'; import { StationJSONData } from '../store/typings';
import { API } from './api';
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault'; export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
export type ScenerySpawnType = 'passenger' | 'freight' | 'loco' | 'all'; export type ScenerySpawnType = 'passenger' | 'freight' | 'loco' | 'all';
@@ -60,7 +59,6 @@ export interface Train {
distance: number; distance: number;
connectedTrack: string; connectedTrack: string;
driverId: number; driverId: number;
driverLanguageId: number;
trainNo: number; trainNo: number;
driverName: string; driverName: string;
driverLevel: number; driverLevel: number;
@@ -97,7 +95,9 @@ export interface TrainTimetableData {
export interface Station { export interface Station {
name: string; name: string;
generalInfo?: StationGeneralInfo; generalInfo?: StationGeneralInfo;
onlineInfo?: ActiveScenery; onlineInfo?: ActiveScenery;
} }
@@ -107,7 +107,7 @@ export interface StationGeneralInfo {
abbr: string; abbr: string;
hash?: string; hash?: string;
reqLevel: number; reqLevel: number;
lines?: string; lines: string;
project: string; project: string;
projectUrl?: string; projectUrl?: string;
signalType: string; signalType: string;
@@ -163,7 +163,6 @@ export interface ActiveScenery {
dispatcherIsSupporter: boolean; dispatcherIsSupporter: boolean;
dispatcherStatus: Status.ActiveDispatcher | number; dispatcherStatus: Status.ActiveDispatcher | number;
dispatcherTimestamp: number | null; dispatcherTimestamp: number | null;
dispatcherLanguageId: number;
isOnline: boolean; isOnline: boolean;
stationTrains: Train[]; stationTrains: Train[];
scheduledTrains: CheckpointTrain[]; scheduledTrains: CheckpointTrain[];
@@ -172,7 +171,7 @@ export interface ActiveScenery {
confirmed: number; confirmed: number;
unconfirmed: number; unconfirmed: number;
}; };
missingCheckpoints: string[]; missingCheckpoints: string[];
} }
export interface ScenerySpawn { export interface ScenerySpawn {
@@ -217,8 +216,45 @@ export interface CheckpointTrain {
} }
// Vehicles Data // Vehicles Data
export type Vehicle = API.VehiclesData.VehicleObject;
export type VehicleGroup = API.VehiclesData.VehicleGroupObject; export interface VehicleData {
id: number;
name: string;
type: string;
cabinName: string | null;
restrictions: Record<string, any> | null;
vehicleGroupsId: number;
group: VehiclesGroup;
}
export interface VehiclesGroup {
id: number;
name: string;
speed: number;
speedLoaded?: number;
speedLoco?: number;
length: number;
weight: number;
cargoTypes: VehicleCargo[] | null;
locoProps: {
coldStart: boolean;
doubleManned: boolean;
} | null;
massSpeeds: VehicleGroupMassSpeeds | null;
}
export interface VehicleGroupMassSpeeds {
passenger: Record<string, number> | null;
cargo: Record<string, number> | null;
none: number | null;
}
export interface VehicleCargo {
id: string;
weight: number;
}
export interface TooltipUserTrain { export interface TooltipUserTrain {
driverName: string; driverName: string;
-5
View File
@@ -1,5 +0,0 @@
export const languageFlagNames = ['pl', 'en', 'de', 'cz', 'sk', 'ru', 'se', 'ua', 'it'];
export function getLanguageNameById(languageId: number) {
return languageFlagNames[languageId] ?? 'pl';
}
+3 -19
View File
@@ -272,7 +272,7 @@ export default defineComponent({
this.scrollDataLoaded = true; this.scrollDataLoaded = true;
}, },
async fetchHistoryData() { async fetchHistoryData() {
const queryParams: DispatchersQueryParams = {}; const queryParams: DispatchersQueryParams = {};
const dispatcherName = this.searchersValues['search-dispatcher'].trim() || undefined; const dispatcherName = this.searchersValues['search-dispatcher'].trim() || undefined;
@@ -280,25 +280,9 @@ export default defineComponent({
const dateFromString = this.searchersValues['search-date-from'].trim() || undefined; const dateFromString = this.searchersValues['search-date-from'].trim() || undefined;
const dateToString = this.searchersValues['search-date-to'].trim() || undefined; const dateToString = this.searchersValues['search-date-to'].trim() || undefined;
let dateFromISO: string | undefined = undefined;
let dateToISO: string | undefined = undefined;
if (dateFromString) {
let dateFrom = new Date(dateFromString);
dateFrom.setMinutes(dateFrom.getMinutes() + dateFrom.getTimezoneOffset());
dateFromISO = dateFrom.toISOString();
}
if (dateToString) {
let dateTo = new Date(dateToString);
dateTo.setMinutes(dateTo.getMinutes() + dateTo.getTimezoneOffset());
dateToISO = dateTo.toISOString();
}
queryParams['dispatcherName'] = dispatcherName; queryParams['dispatcherName'] = dispatcherName;
queryParams['dateFrom'] = dateFromString;
queryParams['dateFrom'] = dateFromISO; queryParams['dateTo'] = dateToString ? `${dateToString}T23:00:00` : undefined;
queryParams['dateTo'] = dateToISO;
queryParams['countLimit'] = 30; queryParams['countLimit'] = 30;
+8 -17
View File
@@ -132,7 +132,6 @@ interface TimetablesQueryParams {
issuedFrom?: string; issuedFrom?: string;
terminatingAt?: string; terminatingAt?: string;
via?: string; via?: string;
includesScenery?: string;
countFrom?: number; countFrom?: number;
countLimit?: number; countLimit?: number;
@@ -214,7 +213,6 @@ export default defineComponent({
'search-train': '', 'search-train': '',
'search-driver': '', 'search-driver': '',
'search-dispatcher': '', 'search-dispatcher': '',
'search-includesScenery': '',
'search-issuedFrom': '', 'search-issuedFrom': '',
'search-via': '', 'search-via': '',
'search-terminatingAt': '', 'search-terminatingAt': '',
@@ -357,25 +355,19 @@ export default defineComponent({
const driverName = this.searchersValues['search-driver'].trim() || undefined; const driverName = this.searchersValues['search-driver'].trim() || undefined;
const trainNo = this.searchersValues['search-train'].trim() || undefined; const trainNo = this.searchersValues['search-train'].trim() || undefined;
const authorName = this.searchersValues['search-dispatcher'].trim() || undefined; const authorName = this.searchersValues['search-dispatcher'].trim() || undefined;
const dateFromString = this.searchersValues['search-date-from'].trim() || undefined; const dateFrom = this.searchersValues['search-date-from'].trim() || undefined;
const includesScenery = this.searchersValues['search-includesScenery'].trim() || undefined;
const issuedFrom = this.searchersValues['search-issuedFrom'].trim() || undefined; const issuedFrom = this.searchersValues['search-issuedFrom'].trim() || undefined;
const via = this.searchersValues['search-via'].trim() || undefined; const via = this.searchersValues['search-via'].trim() || undefined;
const terminatingAt = this.searchersValues['search-terminatingAt'].trim() || undefined; const terminatingAt = this.searchersValues['search-terminatingAt'].trim() || undefined;
const categoryCode = this.searchersValues['select-categoryCode'].trim() || undefined; const categoryCode = this.searchersValues['select-categoryCode'].trim() || undefined;
let dateFromISO: string | undefined = undefined; let dateTo: string | undefined = undefined;
let dateToISO: string | undefined = undefined;
if (dateFromString) { if (dateFrom) {
let dateFrom = new Date(dateFromString); const d = new Date(dateFrom);
dateFrom.setMinutes(dateFrom.getMinutes() + dateFrom.getTimezoneOffset()); d.setDate(d.getDate() + 1);
let dateTo = new Date(dateFrom); dateTo = d.toISOString().split('T')[0];
dateTo.setDate(dateTo.getDate() + 1);
dateFromISO = dateFrom.toISOString();
dateToISO = dateTo.toISOString();
} }
const queryParams: TimetablesQueryParams = {}; const queryParams: TimetablesQueryParams = {};
@@ -438,9 +430,8 @@ export default defineComponent({
queryParams['countLimit'] = undefined; queryParams['countLimit'] = undefined;
queryParams['authorName'] = authorName; queryParams['authorName'] = authorName;
queryParams['dateFrom'] = dateFromISO; queryParams['dateFrom'] = dateFrom;
queryParams['dateTo'] = dateToISO; queryParams['dateTo'] = dateTo;
queryParams['includesScenery'] = includesScenery;
queryParams['issuedFrom'] = issuedFrom; queryParams['issuedFrom'] = issuedFrom;
queryParams['terminatingAt'] = terminatingAt; queryParams['terminatingAt'] = terminatingAt;
queryParams['via'] = via; queryParams['via'] = via;
+5 -4
View File
@@ -29,7 +29,10 @@
data-tooltip-type="HtmlTooltip" data-tooltip-type="HtmlTooltip"
:data-tooltip-content="`<b>${$t('app.language-tooltip-content')}</b>`" :data-tooltip-content="`<b>${$t('app.language-tooltip-content')}</b>`"
> >
<FlagIcon :language-id="mainStore.currentLocale == 'pl' ? 0 : 1" /> <img
:src="`/images/icon-${mainStore.currentLocale}.svg`"
alt="change language flag icon"
/>
</button> </button>
<a <a
@@ -82,7 +85,6 @@ import { reactive } from 'vue';
import { provide } from 'vue'; import { provide } from 'vue';
import { ActiveSorter } from '../components/StationsView/typings'; import { ActiveSorter } from '../components/StationsView/typings';
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import FlagIcon from '../components/Global/FlagIcon.vue';
const filterInitStates = { ...initFilters }; const filterInitStates = { ...initFilters };
@@ -91,8 +93,7 @@ export default defineComponent({
StationTable, StationTable,
StationFilterCard, StationFilterCard,
StationStats, StationStats,
DonationCard, DonationCard
FlagIcon
}, },
data: () => ({ data: () => ({
+2 -2
View File
@@ -4,7 +4,7 @@ import { VitePWA } from 'vite-plugin-pwa';
import path from 'path'; import path from 'path';
export default defineConfig({ export default defineConfig({
server: { port: 5123, open: false }, server: { port: 5123, open: true },
preview: { port: 4001, open: false }, preview: { port: 4001, open: false },
publicDir: 'public', publicDir: 'public',
css: { css: {
@@ -28,7 +28,7 @@ export default defineConfig({
runtimeCaching: [ runtimeCaching: [
{ {
urlPattern: urlPattern:
/^https:\/\/stacjownik.spythere.eu\/api\/(getVehiclesData|getDonators|getSceneries)/i, /^https:\/\/stacjownik.spythere.eu\/api\/(getVehicles|getDonators|getSceneries)/i,
handler: 'NetworkFirst', handler: 'NetworkFirst',
options: { options: {
cacheName: 'stacjownik-api-cache', cacheName: 'stacjownik-api-cache',