mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "stacjownik",
|
"name": "stacjownik",
|
||||||
"version": "1.30.6",
|
"version": "1.30.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-gb" viewBox="0 0 640 480">
|
||||||
|
<path fill="#012169" d="M0 0h640v480H0z"/>
|
||||||
|
<path fill="#FFF" d="m75 0 244 181L562 0h78v62L400 241l240 178v61h-80L320 301 81 480H0v-60l239-178L0 64V0z"/>
|
||||||
|
<path fill="#C8102E" d="m424 281 216 159v40L369 281zm-184 20 6 35L54 480H0zM640 0v3L391 191l2-44L590 0zM0 0l239 176h-60L0 42z"/>
|
||||||
|
<path fill="#FFF" d="M241 0v480h160V0zM0 160v160h640V160z"/>
|
||||||
|
<path fill="#C8102E" d="M0 193v96h640v-96zM273 0v480h96V0z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 504 B |
@@ -1,4 +1,6 @@
|
|||||||
<svg width="39" height="23" viewBox="0 0 39 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-pl" viewBox="0 0 640 480">
|
||||||
<rect width="39" height="23" fill="#FF0F0F"/>
|
<g fill-rule="evenodd">
|
||||||
<rect width="39" height="11.5" fill="white"/>
|
<path fill="#fff" d="M640 480H0V0h640z"/>
|
||||||
|
<path fill="#dc143c" d="M640 480H0V240h640z"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 219 B |
+3
-10
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<Tooltip />
|
<Tooltip />
|
||||||
|
|
||||||
<AppHeader :current-lang="store.currentLocale" @change-lang="changeLang" />
|
<AppHeader />
|
||||||
|
|
||||||
<main class="app_main">
|
<main class="app_main">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
@@ -159,18 +159,11 @@ export default defineComponent({
|
|||||||
this.apiStore.connectToAPI();
|
this.apiStore.connectToAPI();
|
||||||
},
|
},
|
||||||
|
|
||||||
changeLang(lang: string) {
|
|
||||||
this.$i18n.locale = lang;
|
|
||||||
this.store.currentLocale = lang;
|
|
||||||
|
|
||||||
StorageManager.setStringValue('lang', lang);
|
|
||||||
},
|
|
||||||
|
|
||||||
loadLang() {
|
loadLang() {
|
||||||
const storageLang = StorageManager.getStringValue('lang');
|
const storageLang = StorageManager.getStringValue('lang');
|
||||||
|
|
||||||
if (storageLang) {
|
if (storageLang) {
|
||||||
this.changeLang(storageLang);
|
this.store.changeLocale(storageLang);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +172,7 @@ export default defineComponent({
|
|||||||
const naviLanguage = window.navigator.language.toString();
|
const naviLanguage = window.navigator.language.toString();
|
||||||
|
|
||||||
if (!naviLanguage.startsWith('pl')) {
|
if (!naviLanguage.startsWith('pl')) {
|
||||||
this.changeLang('en');
|
this.store.changeLocale('en');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,18 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<header class="app_header">
|
<header class="app_header">
|
||||||
<div class="header_container">
|
<div class="header_container">
|
||||||
<div class="header_icons">
|
|
||||||
<span class="icons-top">
|
|
||||||
<img
|
|
||||||
src="/images/icon-pl.svg"
|
|
||||||
alt="icon-pl"
|
|
||||||
@click="changeLang('en')"
|
|
||||||
v-if="currentLang == 'pl'"
|
|
||||||
/>
|
|
||||||
<img src="/images/icon-en.jpg" alt="icon-en" @click="changeLang('pl')" v-else />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="header_body">
|
<div class="header_body">
|
||||||
<StatusIndicator />
|
<StatusIndicator />
|
||||||
|
|
||||||
@@ -76,27 +64,12 @@ import RegionDropdown from '../Global/RegionDropdown.vue';
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { StatusIndicator, Clock, RegionDropdown },
|
components: { StatusIndicator, Clock, RegionDropdown },
|
||||||
|
|
||||||
emits: ['changeLang'],
|
|
||||||
|
|
||||||
props: {
|
|
||||||
currentLang: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
store: useMainStore()
|
store: useMainStore()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
|
||||||
changeLang(lang: string) {
|
|
||||||
this.$emit('changeLang', lang);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
onlineTrainsCount() {
|
onlineTrainsCount() {
|
||||||
return this.store.trainList.filter((train) => train.region == this.store.region.id).length;
|
return this.store.trainList.filter((train) => train.region == this.store.region.id).length;
|
||||||
@@ -141,7 +114,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
border-radius: 0 0 1em 1em;
|
border-radius: 0 0 1em 1em;
|
||||||
|
|
||||||
@include responsive.smallScreen{
|
@include responsive.smallScreen {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
@@ -180,20 +153,12 @@ export default defineComponent({
|
|||||||
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
@include responsive.smallScreen{
|
@include responsive.smallScreen {
|
||||||
transform: translateX(85%);
|
transform: translateX(85%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICONS
|
|
||||||
.icons-top {
|
|
||||||
img {
|
|
||||||
width: 2.5em;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// COUNTER
|
// COUNTER
|
||||||
.info_counter {
|
.info_counter {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
<h1>{{ $t('welcome.title') }}</h1>
|
<h1>{{ $t('welcome.title') }}</h1>
|
||||||
|
|
||||||
<div class="language-select">
|
<div class="language-select">
|
||||||
<button :data-active="$i18n.locale == 'pl'" @click="changeLang('pl')">
|
<button :data-active="$i18n.locale == 'pl'" @click="store.changeLocale('pl')">
|
||||||
<img src="/images/icon-pl.svg" alt="" width="45" />
|
<img src="/images/icon-pl.svg" alt="" width="45" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button :data-active="$i18n.locale == 'en'" @click="changeLang('en')">
|
<button :data-active="$i18n.locale == 'en'" @click="store.changeLocale('en')">
|
||||||
<img src="/images/icon-en.jpg" alt="" width="45" />
|
<img src="/images/icon-en.svg" alt="" width="45" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -114,12 +114,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import Card from '../Global/Card.vue';
|
import Card from '../Global/Card.vue';
|
||||||
import { useMainStore } from '../../store/mainStore';
|
import { useMainStore } from '../../store/mainStore';
|
||||||
import StorageManager from '../../managers/storageManager';
|
|
||||||
|
|
||||||
const i18n = useI18n();
|
|
||||||
const store = useMainStore();
|
const store = useMainStore();
|
||||||
|
|
||||||
const emit = defineEmits(['toggleCard']);
|
const emit = defineEmits(['toggleCard']);
|
||||||
@@ -130,13 +127,6 @@ const props = defineProps({
|
|||||||
function toggleCard(state: boolean) {
|
function toggleCard(state: boolean) {
|
||||||
emit('toggleCard', state);
|
emit('toggleCard', state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeLang(localeName: string) {
|
|
||||||
i18n.locale.value = localeName;
|
|
||||||
store.currentLocale = localeName;
|
|
||||||
|
|
||||||
StorageManager.setStringValue('lang', localeName);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<img
|
<img
|
||||||
v-for="(thumbnailImage, imageIndex) in images"
|
v-for="(thumbnailImage, imageIndex) in images"
|
||||||
:src="`https://stacjownik.spythere.eu/static/thumbnails/${thumbnailImage}.png`"
|
:src="`https://stacjownik.spythere.eu/static/thumbnails/${thumbnailImage}.png`"
|
||||||
height="60"
|
height="70"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
data-tooltip-type="VehiclePreviewTooltip"
|
data-tooltip-type="VehiclePreviewTooltip"
|
||||||
:data-tooltip-content="vehicleString"
|
:data-tooltip-content="vehicleString"
|
||||||
@@ -56,16 +56,17 @@ function onImageLoad() {
|
|||||||
transition: opacity 100ms ease-in-out;
|
transition: opacity 100ms ease-in-out;
|
||||||
|
|
||||||
&[data-load-status='loading'] {
|
&[data-load-status='loading'] {
|
||||||
min-height: 60px;
|
min-height: 70px;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stock-text {
|
.stock-text {
|
||||||
|
max-width: 90%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
font-size: 0.9em;
|
font-size: 0.85em;
|
||||||
margin-bottom: 0.25em;
|
margin: 0 auto;
|
||||||
padding: 0.25em 0;
|
padding: 0.25em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,36 +40,28 @@
|
|||||||
<span>
|
<span>
|
||||||
{{ $t('scenery.timetable-issued-date') }}
|
{{ $t('scenery.timetable-issued-date') }}
|
||||||
<b>
|
<b>
|
||||||
{{
|
{{ parseCreatedDate(timetableHistory, $i18n.locale) }}
|
||||||
localeDateTime(
|
|
||||||
timetableHistory.createdAt > timetableHistory.beginDate
|
|
||||||
? timetableHistory.beginDate
|
|
||||||
: timetableHistory.createdAt,
|
|
||||||
$i18n.locale
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</b></span
|
|
||||||
>
|
|
||||||
<span v-if="timetableHistory.authorName">
|
|
||||||
{{ $t('scenery.timetable-issued-by') }}
|
|
||||||
<b>
|
|
||||||
<router-link
|
|
||||||
:to="`/journal/timetables?search-dispatcher=${timetableHistory.authorName}`"
|
|
||||||
>
|
|
||||||
{{ timetableHistory.authorName }}
|
|
||||||
</router-link>
|
|
||||||
</b>
|
</b>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
{{ $t('scenery.timetable-issued-for') }}
|
{{ $t('scenery.timetable-issued-for') }}
|
||||||
<b>
|
<router-link
|
||||||
<router-link
|
class="journal-link"
|
||||||
:to="`/journal/timetables?search-driver=${timetableHistory.driverName}`"
|
:to="`/journal/timetables?search-driver=${timetableHistory.driverName}`"
|
||||||
>
|
>
|
||||||
{{ timetableHistory.driverName }}
|
{{ timetableHistory.driverName }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</b>
|
</span>
|
||||||
|
|
||||||
|
<span v-if="timetableHistory.authorName">
|
||||||
|
{{ $t('scenery.timetable-issued-by') }}
|
||||||
|
<router-link
|
||||||
|
class="journal-link"
|
||||||
|
:to="`/journal/timetables?search-dispatcher=${timetableHistory.authorName}`"
|
||||||
|
>
|
||||||
|
{{ timetableHistory.authorName }}
|
||||||
|
</router-link>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
@@ -106,7 +98,7 @@ import { useApiStore } from '../../store/apiStore';
|
|||||||
import routerMixin from '../../mixins/routerMixin';
|
import routerMixin from '../../mixins/routerMixin';
|
||||||
import { useMainStore } from '../../store/mainStore';
|
import { useMainStore } from '../../store/mainStore';
|
||||||
|
|
||||||
const historyModeList = ['via', 'issuedFrom', 'terminatingAt'] as const;
|
const historyModeList = ['includesScenery', 'issuedFrom', 'via', 'terminatingAt'] as const;
|
||||||
type HistoryMode = (typeof historyModeList)[number];
|
type HistoryMode = (typeof historyModeList)[number];
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -131,12 +123,12 @@ export default defineComponent({
|
|||||||
dataStatus: Status.Data.Loading,
|
dataStatus: Status.Data.Loading,
|
||||||
DataStatus: Status.Data,
|
DataStatus: Status.Data,
|
||||||
|
|
||||||
checkedHistoryMode: 'via' as HistoryMode
|
checkedHistoryMode: 'includesScenery' as HistoryMode
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async activated() {
|
async activated() {
|
||||||
this.checkedHistoryMode = 'via';
|
this.checkedHistoryMode = 'includesScenery';
|
||||||
this.fetchAPIData();
|
this.fetchAPIData();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -154,6 +146,7 @@ export default defineComponent({
|
|||||||
const requestFilters: Record<string, any> = {};
|
const requestFilters: Record<string, any> = {};
|
||||||
requestFilters[this.checkedHistoryMode] = stationName.toString();
|
requestFilters[this.checkedHistoryMode] = stationName.toString();
|
||||||
requestFilters.countLimit = 30;
|
requestFilters.countLimit = 30;
|
||||||
|
requestFilters['returnType'] = 'short';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response: API.TimetableHistory.Response = await (
|
const response: API.TimetableHistory.Response = await (
|
||||||
@@ -183,6 +176,18 @@ export default defineComponent({
|
|||||||
[`search-${this.checkedHistoryMode}`]: this.station?.name || this.onlineScenery?.name
|
[`search-${this.checkedHistoryMode}`]: this.station?.name || this.onlineScenery?.name
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
parseCreatedDate(timetable: API.TimetableHistory.Data, locale: string) {
|
||||||
|
const createdDate =
|
||||||
|
timetable.createdAt > timetable.beginDate
|
||||||
|
? new Date(timetable.beginDate)
|
||||||
|
: new Date(timetable.createdAt);
|
||||||
|
|
||||||
|
return createdDate.toLocaleString(locale == 'pl' ? 'pl-PL' : 'en-GB', {
|
||||||
|
timeStyle: 'short',
|
||||||
|
dateStyle: 'medium'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { Loading }
|
components: { Loading }
|
||||||
@@ -217,7 +222,15 @@ export default defineComponent({
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
padding: 0.35em;
|
padding: 0.35em;
|
||||||
min-width: 120px;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-link {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #eee;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--clr-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,7 @@
|
|||||||
<template v-else>{{ $t('filters.no-changed-filters') }}</template>
|
<template v-else>{{ $t('filters.no-changed-filters') }}</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="card_sceneries-search">
|
<section class="card_input-search">
|
||||||
<h3 class="section-header">{{ $t('filters.sceneries-search') }}</h3>
|
|
||||||
|
|
||||||
<datalist id="sceneries">
|
<datalist id="sceneries">
|
||||||
<option
|
<option
|
||||||
v-for="scenery in sortedStationList"
|
v-for="scenery in sortedStationList"
|
||||||
@@ -32,18 +30,60 @@
|
|||||||
></option>
|
></option>
|
||||||
</datalist>
|
</datalist>
|
||||||
|
|
||||||
<form action="javascript:void(0);" @submit="handleSceneriesInput">
|
<input
|
||||||
<input
|
v-model="chosenSearchScenery"
|
||||||
v-model="chosenSearchScenery"
|
id="scenery-search"
|
||||||
id="scenery-search"
|
list="sceneries"
|
||||||
list="sceneries"
|
:placeholder="$t('filters.sceneries-placeholder')"
|
||||||
:placeholder="$t('filters.sceneries-placeholder')"
|
@focus="preventKeyDown = true"
|
||||||
@focus="preventKeyDown = true"
|
@blur="preventKeyDown = false"
|
||||||
@blur="preventKeyDown = false"
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
<button class="btn--action">{{ $t('filters.search-button-title') }}</button>
|
<button class="btn--action" @click="handleSceneriesInput">
|
||||||
</form>
|
{{ $t('filters.search-button-title') }}
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<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
|
||||||
|
type="text"
|
||||||
|
id="author"
|
||||||
|
list="authors"
|
||||||
|
name="authors"
|
||||||
|
v-model="filters['authors']"
|
||||||
|
:placeholder="$t('filters.authors-placeholder')"
|
||||||
|
@focus="preventKeyDown = true"
|
||||||
|
@blur="preventKeyDown = false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button class="btn--action btn--image" @click="resetAuthorsInput">
|
||||||
|
<img src="/images/icon-exit.svg" alt="reset authors search" />
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="card_input-search">
|
||||||
|
<datalist id="projects" name="projects">
|
||||||
|
<option v-for="(project, i) in projectsOptions" :key="i" :value="project"></option>
|
||||||
|
</datalist>
|
||||||
|
|
||||||
|
<input
|
||||||
|
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">
|
||||||
|
<img src="/images/icon-exit.svg" alt="reset projects search" />
|
||||||
|
</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card_options">
|
<section class="card_options">
|
||||||
@@ -97,29 +137,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card_authors-search">
|
|
||||||
<h3 class="section-header">{{ $t('filters.authors-search') }}</h3>
|
|
||||||
|
|
||||||
<datalist id="authors" name="authors">
|
|
||||||
<option v-for="(author, i) in authorsHint" :key="i" :value="author"></option>
|
|
||||||
</datalist>
|
|
||||||
|
|
||||||
<form action="javascript:void(0);" @submit="handleAuthorsInput">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="author"
|
|
||||||
list="authors"
|
|
||||||
name="authors"
|
|
||||||
v-model="authors"
|
|
||||||
:placeholder="$t('filters.authors-placeholder')"
|
|
||||||
@focus="preventKeyDown = true"
|
|
||||||
@blur="preventKeyDown = false"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button class="btn--action">{{ $t('filters.search-button-title') }}</button>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card_sliders">
|
<section class="card_sliders">
|
||||||
<div class="slider" v-for="(slider, i) in sliderStates" :key="i">
|
<div class="slider" v-for="(slider, i) in sliderStates" :key="i">
|
||||||
<input
|
<input
|
||||||
@@ -200,7 +217,8 @@ export default defineComponent({
|
|||||||
sliderStates,
|
sliderStates,
|
||||||
|
|
||||||
minimumHours: 0,
|
minimumHours: 0,
|
||||||
authors: '',
|
authorSearchFilter: '',
|
||||||
|
projectSearchFilter: '',
|
||||||
|
|
||||||
currentRegion: { id: '', value: '' },
|
currentRegion: { id: '', value: '' },
|
||||||
|
|
||||||
@@ -255,11 +273,7 @@ export default defineComponent({
|
|||||||
.sort((s1, s2) => (s1.name > s2.name ? 1 : -1));
|
.sort((s1, s2) => (s1.name > s2.name ? 1 : -1));
|
||||||
},
|
},
|
||||||
|
|
||||||
currentOptionsActive() {
|
authorsOptions() {
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
authorsHint() {
|
|
||||||
return this.store.stationList
|
return this.store.stationList
|
||||||
.reduce((acc, station) => {
|
.reduce((acc, station) => {
|
||||||
station.generalInfo?.authors?.forEach((author) => {
|
station.generalInfo?.authors?.forEach((author) => {
|
||||||
@@ -270,6 +284,17 @@ export default defineComponent({
|
|||||||
return acc;
|
return acc;
|
||||||
}, [] as string[])
|
}, [] as string[])
|
||||||
.sort((a, b) => a.localeCompare(b));
|
.sort((a, b) => a.localeCompare(b));
|
||||||
|
},
|
||||||
|
|
||||||
|
projectsOptions() {
|
||||||
|
return this.store.stationList
|
||||||
|
.reduce((acc, station) => {
|
||||||
|
if (!station.generalInfo || !station.generalInfo.project || station.generalInfo.hidden) return acc;
|
||||||
|
if (!acc.includes(station.generalInfo.project.trim())) acc.push(station.generalInfo.project.trim());
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, [] as string[])
|
||||||
|
.sort((a, b) => a.localeCompare(b));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -294,8 +319,12 @@ export default defineComponent({
|
|||||||
this.scrollTop = (e.target as HTMLElement).scrollTop;
|
this.scrollTop = (e.target as HTMLElement).scrollTop;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAuthorsInput() {
|
resetAuthorsInput() {
|
||||||
this.filters['authors'] = this.authors;
|
this.filters['authors'] = this.authorSearchFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
resetProjectsInput() {
|
||||||
|
this.filters['projects'] = this.projectSearchFilter;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSceneriesInput() {
|
handleSceneriesInput() {
|
||||||
@@ -340,7 +369,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
// Reset local model values
|
// Reset local model values
|
||||||
this.minimumHours = 0;
|
this.minimumHours = 0;
|
||||||
this.authors = '';
|
this.authorSearchFilter = '';
|
||||||
|
|
||||||
// Reset global filters
|
// Reset global filters
|
||||||
Object.keys(this.filters).forEach((filterKey) => {
|
Object.keys(this.filters).forEach((filterKey) => {
|
||||||
@@ -456,27 +485,23 @@ h3.section-header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_authors-search,
|
.card_input-search {
|
||||||
.card_sceneries-search {
|
|
||||||
margin: 1em 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 0.5em;
|
||||||
|
|
||||||
form {
|
button {
|
||||||
display: flex;
|
height: 100%;
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5em;
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 70%;
|
width: 100%;
|
||||||
max-width: 400px;
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
outline: 1px solid white;
|
border: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.authors {
|
||||||
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,10 +146,11 @@ function filterSliderValues(filters: Record<string, any>, generalInfo: StationGe
|
|||||||
|
|
||||||
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
return (
|
return (
|
||||||
filters['authors'].length > 3 &&
|
(filters['authors'].length > 3 &&
|
||||||
!generalInfo.authors
|
!generalInfo.authors
|
||||||
?.map((a) => a.toLocaleLowerCase())
|
?.map((a) => a.toLocaleLowerCase())
|
||||||
.includes(filters['authors'].toLocaleLowerCase())
|
.includes(filters['authors'].toLocaleLowerCase())) ||
|
||||||
|
(filters['projects'].length > 0 && generalInfo.project != filters['projects'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-7
@@ -76,6 +76,7 @@
|
|||||||
"tooltip-driver-offline": "Driver is offline",
|
"tooltip-driver-offline": "Driver is offline",
|
||||||
"tooltip-scenery-offline": "Scenery is offline",
|
"tooltip-scenery-offline": "Scenery is offline",
|
||||||
"pojazdownik-link-content": "POJAZDOWNIK",
|
"pojazdownik-link-content": "POJAZDOWNIK",
|
||||||
|
"language-tooltip-content": "JĘZYK / LANGUAGE",
|
||||||
"gnr-link-content": "TRAIN ORDERS <br> GENERATOR"
|
"gnr-link-content": "TRAIN ORDERS <br> GENERATOR"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
@@ -305,10 +306,9 @@
|
|||||||
"minTwoWayCatenaryInt": "MIN. INTERNAL CATENARY DOUBLE TRACK ROUTES",
|
"minTwoWayCatenaryInt": "MIN. INTERNAL CATENARY DOUBLE TRACK ROUTES",
|
||||||
"minTwoWayInt": "MIN. INTERNAL OTHER DOUBLE TRACK ROUTES"
|
"minTwoWayInt": "MIN. INTERNAL OTHER DOUBLE TRACK ROUTES"
|
||||||
},
|
},
|
||||||
"sceneries-search": "SCENERY SEARCH:",
|
"sceneries-placeholder": "Search for scenery",
|
||||||
"sceneries-placeholder": "Enter scenery name...",
|
"authors-placeholder": "Scenery author (other filters apply)",
|
||||||
"authors-search": "SEARCH BY AUTHOR NAME (other filters apply):",
|
"projects-placeholder": "Scenery project (other filters apply)",
|
||||||
"authors-placeholder": "Enter the author nickname...",
|
|
||||||
"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",
|
||||||
@@ -560,12 +560,13 @@
|
|||||||
"option-active-timetables": "Active timetables",
|
"option-active-timetables": "Active timetables",
|
||||||
"option-timetables-history": "Timetables history PL1",
|
"option-timetables-history": "Timetables history PL1",
|
||||||
"option-dispatchers-history": "Dispatchers history PL1",
|
"option-dispatchers-history": "Dispatchers history PL1",
|
||||||
"timetable-via": "ALL TIMETABLES",
|
"timetable-includesScenery": "ALL TIMETABLES",
|
||||||
|
"timetable-via": "PASSES THROUGH",
|
||||||
"timetable-issuedFrom": "BEGINS HERE",
|
"timetable-issuedFrom": "BEGINS HERE",
|
||||||
"timetable-terminatingAt": "TERMINATES HERE",
|
"timetable-terminatingAt": "ENDS HERE",
|
||||||
"timetable-issued-date": "Issued",
|
"timetable-issued-date": "Issued",
|
||||||
"timetable-issued-by": " by:",
|
"timetable-issued-by": " by:",
|
||||||
"timetable-issued-for": " for driver:",
|
"timetable-issued-for": " for:",
|
||||||
"dispatcher-rate": "Rate:",
|
"dispatcher-rate": "Rate:",
|
||||||
"dispatcher-status-changes": "Status changes:",
|
"dispatcher-status-changes": "Status changes:",
|
||||||
"req-level": "all dispatcher levels | dispatcher level {lvl} required | dispatcher level {lvl} required",
|
"req-level": "all dispatcher levels | dispatcher level {lvl} required | dispatcher level {lvl} required",
|
||||||
|
|||||||
+8
-7
@@ -73,6 +73,7 @@
|
|||||||
"tooltip-driver-offline": "Maszynista offline",
|
"tooltip-driver-offline": "Maszynista offline",
|
||||||
"tooltip-scenery-offline": "Sceneria offline",
|
"tooltip-scenery-offline": "Sceneria offline",
|
||||||
"pojazdownik-link-content": "POJAZDOWNIK",
|
"pojazdownik-link-content": "POJAZDOWNIK",
|
||||||
|
"language-tooltip-content": "JĘZYK / LANGUAGE",
|
||||||
"gnr-link-content": "GENERATOR <br> ROZKAZÓW PISEMNYCH"
|
"gnr-link-content": "GENERATOR <br> ROZKAZÓW PISEMNYCH"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
@@ -303,10 +304,9 @@
|
|||||||
"minTwoWayCatenaryInt": "SZLAKI DWUTOROWE ZELEKTR. WEWNĘTRZNE (MINIMUM)",
|
"minTwoWayCatenaryInt": "SZLAKI DWUTOROWE ZELEKTR. WEWNĘTRZNE (MINIMUM)",
|
||||||
"minTwoWayInt": "SZLAKI DWUTOROWE NIEZELEKTR. WEWNĘTRZNE (MINIMUM)"
|
"minTwoWayInt": "SZLAKI DWUTOROWE NIEZELEKTR. WEWNĘTRZNE (MINIMUM)"
|
||||||
},
|
},
|
||||||
"sceneries-search": "WYSZUKAJ SCENERIĘ:",
|
"sceneries-placeholder": "Wyszukaj scenerię",
|
||||||
"sceneries-placeholder": "Wpisz nazwę scenerii...",
|
"authors-placeholder": "Autor scenerii (uwzględnia inne filtry)",
|
||||||
"authors-search": "WYSZUKAJ AUTORA (uwzględnia inne filtry):",
|
"projects-placeholder": "Projekt scenerii (uwzględnia inne filtry)",
|
||||||
"authors-placeholder": "Wpisz nick autora...",
|
|
||||||
"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",
|
||||||
@@ -546,12 +546,13 @@
|
|||||||
"option-active-timetables": "Aktywne rozkłady jazdy",
|
"option-active-timetables": "Aktywne rozkłady jazdy",
|
||||||
"option-timetables-history": "Historia rozkładów PL1",
|
"option-timetables-history": "Historia rozkładów PL1",
|
||||||
"option-dispatchers-history": "Historia dyżurów PL1",
|
"option-dispatchers-history": "Historia dyżurów PL1",
|
||||||
"timetable-via": "WSZYSTKIE RJ",
|
"timetable-includesScenery": "WSZYSTKIE RJ",
|
||||||
|
"timetable-via": "PRZEJEŻDŻA",
|
||||||
"timetable-issuedFrom": "ROZPOCZYNA BIEG",
|
"timetable-issuedFrom": "ROZPOCZYNA BIEG",
|
||||||
"timetable-terminatingAt": "KOŃCZY BIEG",
|
"timetable-terminatingAt": "KOŃCZY BIEG",
|
||||||
"timetable-issued-date": "Wystawiony",
|
"timetable-issued-date": "Wystawiony: ",
|
||||||
"timetable-issued-by": " przez:",
|
"timetable-issued-by": " przez:",
|
||||||
"timetable-issued-for": " dla maszynisty:",
|
"timetable-issued-for": " dla:",
|
||||||
"dispatcher-rate": "Ocena:",
|
"dispatcher-rate": "Ocena:",
|
||||||
"dispatcher-status-changes": "Zmiany statusów:",
|
"dispatcher-status-changes": "Zmiany statusów:",
|
||||||
"req-level": "ogólnodostępna | minimum {lvl} poziom dyżurnego | minimum {lvl} poziom dyżurnego",
|
"req-level": "ogólnodostępna | minimum {lvl} poziom dyżurnego | minimum {lvl} poziom dyżurnego",
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ export const initFilters = {
|
|||||||
minTwoWayCatenary: 0,
|
minTwoWayCatenary: 0,
|
||||||
minTwoWayInt: 0,
|
minTwoWayInt: 0,
|
||||||
minTwoWayCatenaryInt: 0,
|
minTwoWayCatenaryInt: 0,
|
||||||
authors: ''
|
authors: '',
|
||||||
|
projects: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sliderStates = [
|
export const sliderStates = [
|
||||||
@@ -83,7 +84,7 @@ export const sliderStates = [
|
|||||||
{ id: 'minTwoWay', minRange: 0, maxRange: 5, step: 1 },
|
{ id: 'minTwoWay', minRange: 0, maxRange: 5, step: 1 },
|
||||||
{ id: 'minTwoWayCatenary', minRange: 0, maxRange: 5, step: 1 },
|
{ id: 'minTwoWayCatenary', minRange: 0, maxRange: 5, step: 1 },
|
||||||
{ id: 'minTwoWayInt', minRange: 0, maxRange: 5, step: 1 },
|
{ id: 'minTwoWayInt', minRange: 0, maxRange: 5, step: 1 },
|
||||||
{ id: 'minTwoWayCatenaryInt', minRange: 0, maxRange: 5, step: 1 },
|
{ id: 'minTwoWayCatenaryInt', minRange: 0, maxRange: 5, step: 1 }
|
||||||
];
|
];
|
||||||
|
|
||||||
export type StationFilter = keyof typeof initFilters;
|
export type StationFilter = keyof typeof initFilters;
|
||||||
@@ -97,7 +98,18 @@ export const filtersSections: Record<StationFilterSection, StationFilter[]> = {
|
|||||||
stationType: ['junction', 'nonJunction'],
|
stationType: ['junction', 'nonJunction'],
|
||||||
access: ['nonPublic', 'unavailable', 'abandoned'],
|
access: ['nonPublic', 'unavailable', 'abandoned'],
|
||||||
addons: ['SUP', 'ASDEK', 'noSUP', 'noASDEK'],
|
addons: ['SUP', 'ASDEK', 'noSUP', 'noASDEK'],
|
||||||
control: ['SPK', 'SCS', 'SPE', 'SCS-SPK', 'SPK-M', 'SCS-M', 'mechanical', 'SPK-R', 'SCS-R', 'manual'],
|
control: [
|
||||||
|
'SPK',
|
||||||
|
'SCS',
|
||||||
|
'SPE',
|
||||||
|
'SCS-SPK',
|
||||||
|
'SPK-M',
|
||||||
|
'SCS-M',
|
||||||
|
'mechanical',
|
||||||
|
'SPK-R',
|
||||||
|
'SCS-R',
|
||||||
|
'manual'
|
||||||
|
],
|
||||||
blockades: ['SBL', 'PBL'],
|
blockades: ['SBL', 'PBL'],
|
||||||
signals: ['modern', 'semaphores', 'mixed', 'historical']
|
signals: ['modern', 'semaphores', 'mixed', 'historical']
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
} from '../typings/common';
|
} from '../typings/common';
|
||||||
import { useApiStore } from './apiStore';
|
import { useApiStore } from './apiStore';
|
||||||
import { MainStoreState } from './typings';
|
import { MainStoreState } from './typings';
|
||||||
|
import i18n from '../i18n';
|
||||||
|
import StorageManager from '../managers/storageManager';
|
||||||
|
|
||||||
const checkpointsTrains: Map<string, CheckpointTrain[]> = new Map();
|
const checkpointsTrains: Map<string, CheckpointTrain[]> = new Map();
|
||||||
const unknownSceneryCheckpoints: Map<string, Set<string>> = new Map();
|
const unknownSceneryCheckpoints: Map<string, Set<string>> = new Map();
|
||||||
@@ -37,6 +39,15 @@ export const useMainStore = defineStore('mainStore', {
|
|||||||
currentLocale: 'pl'
|
currentLocale: 'pl'
|
||||||
}) as MainStoreState,
|
}) as MainStoreState,
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
changeLocale(localeName: string) {
|
||||||
|
(i18n.global.locale.value as any) = localeName;
|
||||||
|
this.currentLocale = localeName;
|
||||||
|
|
||||||
|
StorageManager.setStringValue('lang', localeName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
trainList(): Train[] {
|
trainList(): Train[] {
|
||||||
const apiStore = useApiStore();
|
const apiStore = useApiStore();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export interface StationJSONData {
|
|||||||
project: string;
|
project: string;
|
||||||
projectUrl: string;
|
projectUrl: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
|
hidden: boolean;
|
||||||
|
|
||||||
reqLevel: number;
|
reqLevel: number;
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ export interface StationGeneralInfo {
|
|||||||
availability: Availability;
|
availability: Availability;
|
||||||
routes: StationRoutes;
|
routes: StationRoutes;
|
||||||
checkpoints: string[];
|
checkpoints: string[];
|
||||||
|
hidden: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StationRoutes {
|
export interface StationRoutes {
|
||||||
|
|||||||
@@ -13,6 +13,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="topbar-links">
|
<div class="topbar-links">
|
||||||
|
<button
|
||||||
|
class="btn--image lang-button"
|
||||||
|
@click="toggleLocales()"
|
||||||
|
data-tooltip-type="HtmlTooltip"
|
||||||
|
:data-tooltip-content="`<b>${$t('app.language-tooltip-content')}</b>`"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`/images/icon-${mainStore.currentLocale}.svg`"
|
||||||
|
alt="change language flag icon"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
class="a-button btn--image gnr-link"
|
class="a-button btn--image gnr-link"
|
||||||
href="https://generator-td2.web.app/"
|
href="https://generator-td2.web.app/"
|
||||||
@@ -96,6 +108,10 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
toggleDonationCard(value: boolean) {
|
toggleDonationCard(value: boolean) {
|
||||||
this.isDonationCardOpen = value;
|
this.isDonationCardOpen = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleLocales() {
|
||||||
|
this.mainStore.changeLocale(this.mainStore.currentLocale == 'pl' ? 'en' : 'pl');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -149,6 +165,11 @@ button.donation-button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.lang-button {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
a.pojazdownik-link {
|
a.pojazdownik-link {
|
||||||
background-color: #1f263b;
|
background-color: #1f263b;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user