mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3be964ec99 | |||
| caf6137ca3 | |||
| 0f2e5e084b |
@@ -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
|
||||
@@ -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
@@ -15,8 +15,8 @@ app.get('/api/getSceneries', (_, res) => {
|
||||
res.sendFile(path.join(cwd(), 'endpoints', 'getSceneries.json'));
|
||||
});
|
||||
|
||||
app.get('/api/getVehiclesData', (_, res) => {
|
||||
res.sendFile(path.join(cwd(), 'endpoints', 'getVehiclesData.json'));
|
||||
app.get('/api/getVehicles', (_, res) => {
|
||||
res.sendFile(path.join(cwd(), 'endpoints', 'getVehicles.json'));
|
||||
});
|
||||
|
||||
app.get('/api/getDonators', (_, res) => {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "stacjownik",
|
||||
"version": "1.31.0",
|
||||
"version": "1.30.7",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
+3
-239
@@ -1,213 +1,11 @@
|
||||
<template>
|
||||
<div class="app_container">
|
||||
<UpdateCard
|
||||
: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)"
|
||||
/>
|
||||
<AppNewDomainInfo />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '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 lang="ts" setup>
|
||||
import AppNewDomainInfo from './components/App/AppNewDomainInfo.vue';
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -234,38 +32,4 @@ export default defineComponent({
|
||||
.app_main {
|
||||
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>
|
||||
|
||||
@@ -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>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<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>
|
||||
|
||||
<div class="features-body" v-if="htmlChangelog != ''" v-html="htmlChangelog"></div>
|
||||
@@ -13,14 +13,7 @@
|
||||
<p class="bottom-info">
|
||||
{{ $t('update.info-1') }}
|
||||
<br />
|
||||
|
||||
<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>
|
||||
<span v-html="$t('update.info-2')"></span>
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -58,7 +51,7 @@ export default defineComponent({
|
||||
watch: {
|
||||
isUpdateCardOpen(val: boolean) {
|
||||
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) {
|
||||
margin-top: 1em;
|
||||
padding: 0.5em 0;
|
||||
padding: 0.25em 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
::v-deep(h3) {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
::v-deep(ul) {
|
||||
list-style: disc;
|
||||
padding: 0 1.5em;
|
||||
list-style: initial;
|
||||
padding: 1em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
@@ -117,7 +105,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0.5em auto;
|
||||
margin: 0 auto;
|
||||
padding: 0.5em 0.75em;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
@@ -129,6 +117,5 @@ p.bottom-info {
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -205,7 +205,7 @@ const availableCategories = computed(() => {
|
||||
for (const stockName of stockList) {
|
||||
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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -10,7 +10,6 @@ export namespace Journal {
|
||||
| 'search-train'
|
||||
| 'search-date-from'
|
||||
| 'search-dispatcher'
|
||||
| 'search-includesScenery'
|
||||
| 'search-issuedFrom'
|
||||
| 'search-terminatingAt'
|
||||
| 'search-via'
|
||||
|
||||
@@ -151,7 +151,6 @@ export default defineComponent({
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/responsive';
|
||||
@use '../../styles/scenery-history-table';
|
||||
@use '../../styles/badge';
|
||||
|
||||
.scenery-dispatchers-history {
|
||||
height: 100%;
|
||||
|
||||
@@ -57,8 +57,20 @@ export default defineComponent({
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss">
|
||||
@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 {
|
||||
display: flex;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<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" />
|
||||
{{ $t('scenery.spawns') }}
|
||||
<span class="text--primary">{{ onlineScenery?.spawns.length || '0' }}</span>
|
||||
@@ -53,23 +53,10 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../../styles/badge';
|
||||
|
||||
ul {
|
||||
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 {
|
||||
&-move,
|
||||
&-enter-active,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<section class="info-user-list">
|
||||
<h3 class="user-header">
|
||||
<h3 class="user-header section-header">
|
||||
<img src="/images/icon-user.svg" alt="Users icon" />
|
||||
{{ $t('scenery.users') }}
|
||||
<span class="text--primary">{{ onlineScenery?.stationTrains?.length || 0 }}</span
|
||||
@@ -111,8 +111,6 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../../styles/badge';
|
||||
|
||||
$no-timetable: #aaa;
|
||||
$departed: springgreen;
|
||||
$stopped: #ffa600;
|
||||
@@ -120,17 +118,6 @@ $online: gold;
|
||||
$terminated: salmon;
|
||||
$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 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
id="scenery-search"
|
||||
list="sceneries"
|
||||
:placeholder="$t('filters.sceneries-placeholder')"
|
||||
@change="handleSceneriesInput"
|
||||
@focus="preventKeyDown = true"
|
||||
@blur="preventKeyDown = false"
|
||||
/>
|
||||
@@ -45,40 +44,42 @@
|
||||
</button>
|
||||
</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
|
||||
v-model="filters['lines']"
|
||||
id="line-numbers-search"
|
||||
:placeholder="$t('filters.line-numbers-placeholder')"
|
||||
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="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">
|
||||
<img src="/images/icon-exit.svg" alt="reset authors search" />
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<section class="card_input-search">
|
||||
<select id="projects" name="projects" v-model="filters['projects']">
|
||||
<option value="">{{ $t('filters.projects-placeholder') }}</option>
|
||||
<option v-for="(project, i) in projectsOptions" :key="i" :value="project">
|
||||
{{ project }}
|
||||
</option>
|
||||
</select>
|
||||
<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" />
|
||||
@@ -91,7 +92,7 @@
|
||||
v-for="(sectionFilters, sectionKey) in filtersSections"
|
||||
:key="sectionKey"
|
||||
>
|
||||
<h3 class="section-header">
|
||||
<h3 class="text--primary">
|
||||
<span class="active-indicator" v-if="!areSectionFiltersDefault(sectionKey)"></span>
|
||||
{{ $t(`filters.sections.${sectionKey}`) }}
|
||||
<button @click="resetSectionFilters(sectionKey)">RESET</button>
|
||||
@@ -121,7 +122,7 @@
|
||||
</section>
|
||||
|
||||
<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">
|
||||
<button class="btn--action" @click="subHour">-</button>
|
||||
@@ -216,6 +217,8 @@ export default defineComponent({
|
||||
sliderStates,
|
||||
|
||||
minimumHours: 0,
|
||||
authorSearchFilter: '',
|
||||
projectSearchFilter: '',
|
||||
|
||||
currentRegion: { id: '', value: '' },
|
||||
|
||||
@@ -273,8 +276,6 @@ export default defineComponent({
|
||||
authorsOptions() {
|
||||
return this.store.stationList
|
||||
.reduce((acc, station) => {
|
||||
if (station.generalInfo?.hidden === true) return acc;
|
||||
|
||||
station.generalInfo?.authors?.forEach((author) => {
|
||||
if (author.trim() != '' && !acc.includes(author.toLocaleLowerCase()))
|
||||
acc.push(author.toLocaleLowerCase());
|
||||
@@ -288,10 +289,8 @@ export default defineComponent({
|
||||
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());
|
||||
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[])
|
||||
@@ -321,15 +320,11 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
resetAuthorsInput() {
|
||||
this.filters['authors'] = '';
|
||||
this.filters['authors'] = this.authorSearchFilter;
|
||||
},
|
||||
|
||||
resetProjectsInput() {
|
||||
this.filters['projects'] = '';
|
||||
},
|
||||
|
||||
resetLineNumbersInput() {
|
||||
this.filters['lines'] = '';
|
||||
this.filters['projects'] = this.projectSearchFilter;
|
||||
},
|
||||
|
||||
handleSceneriesInput() {
|
||||
@@ -374,6 +369,7 @@ export default defineComponent({
|
||||
|
||||
// Reset local model values
|
||||
this.minimumHours = 0;
|
||||
this.authorSearchFilter = '';
|
||||
|
||||
// Reset global filters
|
||||
Object.keys(this.filters).forEach((filterKey) => {
|
||||
@@ -417,14 +413,6 @@ export default defineComponent({
|
||||
@use '../../styles/animations';
|
||||
|
||||
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;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
@@ -506,12 +494,15 @@ h3.hours-section-header {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.5em;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
|
||||
&.authors {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.section-filters {
|
||||
@@ -582,6 +573,12 @@ h3.hours-section-header {
|
||||
}
|
||||
|
||||
.option-section h3 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.25em;
|
||||
|
||||
gap: 0.5em;
|
||||
|
||||
button {
|
||||
padding: 0.15em;
|
||||
color: coral;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class="header-text"
|
||||
:class="headerName"
|
||||
>
|
||||
<div class="header_wrapper">
|
||||
<span class="header_wrapper">
|
||||
<div v-html="$t(`sceneries.headers.${headerName}`)"></div>
|
||||
|
||||
<img
|
||||
@@ -23,7 +23,7 @@
|
||||
:src="`/images/icon-arrow-${activeSorter.dir == 1 ? 'asc' : 'desc'}.svg`"
|
||||
alt="sort icon"
|
||||
/>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
|
||||
<th
|
||||
@@ -52,14 +52,14 @@
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr
|
||||
<router-link
|
||||
v-for="station in filteredStationList"
|
||||
class="a-row"
|
||||
tabindex="0"
|
||||
role="row"
|
||||
:key="station.name"
|
||||
@click.right.prevent="openForumSite($event, station.generalInfo?.url)"
|
||||
@click="getSceneryRoute(station)"
|
||||
@keydown.enter="getSceneryRoute(station)"
|
||||
@keydown.space.prevent="openForumSite($event, station.generalInfo?.url)"
|
||||
:to="getSceneryRoute(station)"
|
||||
>
|
||||
<td class="station-name" :class="station.generalInfo?.availability">
|
||||
<b v-if="station.generalInfo?.project" style="color: salmon">{{
|
||||
@@ -314,7 +314,7 @@
|
||||
>
|
||||
{{ station.onlineInfo?.scheduledTrainCount.confirmed ?? '-' }}
|
||||
</td>
|
||||
</tr>
|
||||
</router-link>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -384,13 +384,15 @@ export default defineComponent({
|
||||
|
||||
methods: {
|
||||
getSceneryRoute(station: Station) {
|
||||
this.$router.push({
|
||||
// TODO: Hide tooltips when navigating away
|
||||
|
||||
return {
|
||||
name: 'SceneryView',
|
||||
query: {
|
||||
station: station.name,
|
||||
region: this.$route.query.region || undefined
|
||||
}
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
openDonationCard(e: Event) {
|
||||
@@ -457,78 +459,78 @@ table {
|
||||
width: 100%;
|
||||
min-width: 1250px;
|
||||
white-space: wrap;
|
||||
}
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
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;
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&.min-lvl {
|
||||
width: 4em;
|
||||
thead tr {
|
||||
background-color: var(--clr-bg3);
|
||||
}
|
||||
|
||||
&.status {
|
||||
width: 10em;
|
||||
}
|
||||
thead th {
|
||||
&.station {
|
||||
width: 12em;
|
||||
}
|
||||
|
||||
&.dispatcher {
|
||||
width: 12em;
|
||||
}
|
||||
&.min-lvl {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
&.dispatcher-lvl {
|
||||
width: 6em;
|
||||
}
|
||||
&.status {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
&.routes-double,
|
||||
&.routes-single {
|
||||
width: 7em;
|
||||
}
|
||||
&.dispatcher {
|
||||
width: 12em;
|
||||
}
|
||||
|
||||
&.general {
|
||||
width: 11em;
|
||||
}
|
||||
&.dispatcher-lvl {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
&.header-image {
|
||||
width: 3.5em;
|
||||
&.routes-double,
|
||||
&.routes-single {
|
||||
width: 7em;
|
||||
}
|
||||
|
||||
&.user {
|
||||
width: 5em;
|
||||
&.general {
|
||||
width: 11em;
|
||||
}
|
||||
|
||||
&.header-image {
|
||||
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 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 1.5em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
tr,
|
||||
.a-row {
|
||||
background-color: $rowCol;
|
||||
vertical-align: middle;
|
||||
|
||||
@@ -548,7 +550,6 @@ tbody tr {
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 2.5em;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.2;
|
||||
|
||||
@@ -145,33 +145,13 @@ function filterSliderValues(filters: Record<string, any>, generalInfo: StationGe
|
||||
}
|
||||
|
||||
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
if (
|
||||
filters['authors'].length > 3 &&
|
||||
generalInfo.authors &&
|
||||
!generalInfo.authors.some(
|
||||
(a) => a.toLocaleLowerCase() == filters['authors'].toLocaleLowerCase()
|
||||
)
|
||||
)
|
||||
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;
|
||||
return (
|
||||
(filters['authors'].length > 3 &&
|
||||
!generalInfo.authors
|
||||
?.map((a) => a.toLocaleLowerCase())
|
||||
.includes(filters['authors'].toLocaleLowerCase())) ||
|
||||
(filters['projects'].length > 0 && generalInfo.project != filters['projects'])
|
||||
);
|
||||
}
|
||||
|
||||
export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
<span v-if="vehicleCargo">({{ vehicleCargo.id }})</span>
|
||||
</div>
|
||||
|
||||
<div class="vehicle-props" v-if="vehicleGroup">
|
||||
{{ vehicleGroup.speed }}km/h • {{ vehicleGroup.length }}m •
|
||||
{{ (vehicleGroup.weight / 1000).toFixed(1) }}t
|
||||
<div class="vehicle-props" v-if="vehicleData">
|
||||
{{ vehicleData.group.speed }}km/h • {{ vehicleData.group.length }}m •
|
||||
{{ (vehicleData.group.weight / 1000).toFixed(1) }}t
|
||||
<span v-if="vehicleCargo">(+{{ (vehicleCargo.weight / 1000).toFixed(1) }}t)</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,18 +73,12 @@ export default defineComponent({
|
||||
return this.tooltipStore.content.split(':')[0];
|
||||
},
|
||||
|
||||
vehicleGroup() {
|
||||
if (!this.apiStore.vehiclesData) return null;
|
||||
|
||||
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);
|
||||
vehicleData() {
|
||||
return this.apiStore.vehiclesData?.find((v) => v.name == this.vehicleName);
|
||||
},
|
||||
|
||||
vehicleCargo() {
|
||||
const x = this.vehicleGroup?.cargoTypes?.find(
|
||||
const x = this.vehicleData?.group.cargoTypes?.find(
|
||||
(c) => c.id == this.tooltipStore.content.split(':')[1]
|
||||
);
|
||||
|
||||
|
||||
+3
-6
@@ -69,8 +69,7 @@
|
||||
"confirm": "ROGER THAT!",
|
||||
"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-2": "The full app changelog available on {link}",
|
||||
"info-2-link-text": "the project's GitHub page"
|
||||
"info-2": "The full app changelog available on <a href='https://github.com/Spythere/stacjownik' target='_blank'>the project's GitHub</a>"
|
||||
},
|
||||
"app": {
|
||||
"sceneries": "SCENERIES",
|
||||
@@ -200,7 +199,6 @@
|
||||
"search-dispatcher": "Dispatcher name",
|
||||
"search-station": "Scenery name / #",
|
||||
"search-author": "Timetable author name",
|
||||
"search-includesScenery": "Includes scenery name",
|
||||
"search-issuedFrom": "Issuing scenery name",
|
||||
"search-via": "Via scenery name",
|
||||
"search-terminatingAt": "Terminating scenery name",
|
||||
@@ -318,9 +316,8 @@
|
||||
"minTwoWayInt": "MIN. INTERNAL OTHER DOUBLE TRACK ROUTES"
|
||||
},
|
||||
"sceneries-placeholder": "Search for scenery",
|
||||
"line-numbers-placeholder": "Line numbers (separated by commas)",
|
||||
"authors-placeholder": "Scenery author",
|
||||
"projects-placeholder": "Scenery project",
|
||||
"authors-placeholder": "Scenery author (other filters apply)",
|
||||
"projects-placeholder": "Scenery project (other filters apply)",
|
||||
"search-button-title": "SEARCH",
|
||||
"minimum-hours-title": "SHOW ONLY SCENERIES UNTIL:",
|
||||
"now": "NOW",
|
||||
|
||||
+3
-6
@@ -68,8 +68,7 @@
|
||||
"confirm": "PRZYJĄŁEM!",
|
||||
"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-2": "Pełny changelog dostępny na {link}",
|
||||
"info-2-link-text": "GitHubie projektu"
|
||||
"info-2": "Pełny changelog dostępny na <a href='https://github.com/Spythere/stacjownik' target='_blank'>GitHubie projektu</a>"
|
||||
},
|
||||
"app": {
|
||||
"sceneries": "SCENERIE",
|
||||
@@ -196,7 +195,6 @@
|
||||
"search-dispatcher": "Nick dyżurnego",
|
||||
"search-station": "Nazwa scenerii / #",
|
||||
"search-author": "Nick autora rozkładu jazdy",
|
||||
"search-includesScenery": "Zawiera scenerię",
|
||||
"search-issuedFrom": "Sceneria początkowa",
|
||||
"search-via": "Przez scenerię",
|
||||
"search-terminatingAt": "Sceneria końcowa",
|
||||
@@ -315,9 +313,8 @@
|
||||
"minTwoWayInt": "SZLAKI DWUTOROWE NIEZELEKTR. WEWNĘTRZNE (MINIMUM)"
|
||||
},
|
||||
"sceneries-placeholder": "Wyszukaj scenerię",
|
||||
"line-numbers-placeholder": "Numery linii (oddzielone przecinkami)",
|
||||
"authors-placeholder": "Autor scenerii",
|
||||
"projects-placeholder": "Projekt scenerii",
|
||||
"authors-placeholder": "Autor scenerii (uwzględnia inne filtry)",
|
||||
"projects-placeholder": "Projekt scenerii (uwzględnia inne filtry)",
|
||||
"search-button-title": "SZUKAJ",
|
||||
"minimum-hours-title": "POKAŻ TYLKO SCENERIE DOSTĘPNE MINIMUM DO:",
|
||||
"now": "TERAZ",
|
||||
|
||||
@@ -69,8 +69,7 @@ export const initFilters = {
|
||||
minTwoWayInt: 0,
|
||||
minTwoWayCatenaryInt: 0,
|
||||
authors: '',
|
||||
projects: '',
|
||||
lines: ''
|
||||
projects: ''
|
||||
};
|
||||
|
||||
export const sliderStates = [
|
||||
|
||||
@@ -122,27 +122,19 @@ export default defineComponent({
|
||||
|
||||
// Check the whole consist speed limit
|
||||
const vehicleMaxSpeed = stockList.reduce((acc, stockName, i) => {
|
||||
if (!this.apiStore.vehiclesData) return acc;
|
||||
|
||||
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(
|
||||
(g) => g.id == vehicle.vehicleGroupsId
|
||||
);
|
||||
let vehicleSpeed = vehicleData.group.speed;
|
||||
|
||||
if (!vehicleGroup) return acc;
|
||||
|
||||
let vehicleSpeed = vehicleGroup.speed;
|
||||
|
||||
if (vehicle.type == 'wagon-freight') {
|
||||
if (vehicleData.type == 'wagon-freight') {
|
||||
isPassenger = false;
|
||||
|
||||
if (vehicleCargo !== undefined && vehicleGroup.speedLoaded) {
|
||||
vehicleSpeed = vehicleGroup.speedLoaded;
|
||||
if (vehicleCargo !== undefined && vehicleData.group.speedLoaded) {
|
||||
vehicleSpeed = vehicleData.group.speedLoaded;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,23 +143,14 @@ export default defineComponent({
|
||||
|
||||
// Check the head vehicle speed limit
|
||||
const headLocoName = stockList[0];
|
||||
|
||||
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;
|
||||
const headLocoVehicleData = this.apiStore.vehiclesData?.find((v) => v.name == headLocoName);
|
||||
|
||||
// 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;
|
||||
|
||||
const massSpeeds =
|
||||
headLocoVehicleGroup.massSpeeds[
|
||||
headLocoVehicleData.group.massSpeeds[
|
||||
stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo'
|
||||
];
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export const useApiStore = defineStore('apiStore', {
|
||||
},
|
||||
|
||||
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,
|
||||
sceneryData: [] as StationJSONData[],
|
||||
@@ -111,7 +111,7 @@ export const useApiStore = defineStore('apiStore', {
|
||||
|
||||
async fetchVehiclesInfo() {
|
||||
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.dataStatuses.vehicles = response.data ? Status.Data.Loaded : Status.Data.Warning;
|
||||
|
||||
@@ -38,8 +38,7 @@ export const useMainStore = defineStore('mainStore', {
|
||||
modalLastClickedTarget: null,
|
||||
currentLocale: 'pl',
|
||||
|
||||
isMigrateInfoCardOpen: false,
|
||||
pinnedStationNames: []
|
||||
isMigrateInfoCardOpen: false
|
||||
}) as MainStoreState,
|
||||
|
||||
actions: {
|
||||
@@ -432,6 +431,7 @@ export const useMainStore = defineStore('mainStore', {
|
||||
|
||||
return {
|
||||
name: scenery.name,
|
||||
|
||||
generalInfo: {
|
||||
...scenery,
|
||||
authors: scenery.authors?.split(',').map((a) => a.trim()),
|
||||
@@ -446,7 +446,7 @@ export const useMainStore = defineStore('mainStore', {
|
||||
},
|
||||
|
||||
allStationInfo(): Station[] {
|
||||
const onlineUnsavedStations: Station[] = this.activeSceneryList
|
||||
const onlineUnsavedStations = this.activeSceneryList
|
||||
.filter(
|
||||
(scenery) =>
|
||||
this.stationList.findIndex((st) => st.name == scenery.name) == -1 &&
|
||||
|
||||
+1
-21
@@ -89,8 +89,7 @@ select {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
input {
|
||||
background: none;
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
@@ -359,22 +358,3 @@ a.a-button {
|
||||
background-color: #aaa;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +61,8 @@
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
select.search-input {
|
||||
|
||||
}
|
||||
|
||||
+3
-46
@@ -1,4 +1,4 @@
|
||||
import { Status, Vehicle, VehicleGroup } from './common';
|
||||
import { Status, VehicleData } from './common';
|
||||
|
||||
export enum APIDataStatus {
|
||||
OK = 'OK',
|
||||
@@ -329,51 +329,8 @@ export namespace API {
|
||||
export type Response = string[];
|
||||
}
|
||||
|
||||
export namespace VehiclesData {
|
||||
export interface VehicleObject {
|
||||
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;
|
||||
export namespace Vehicles {
|
||||
export type Response = VehicleData[];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-5
@@ -1,6 +1,5 @@
|
||||
import { RouteLocationRaw } from 'vue-router';
|
||||
import { StationJSONData } from '../store/typings';
|
||||
import { API } from './api';
|
||||
|
||||
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
|
||||
export type ScenerySpawnType = 'passenger' | 'freight' | 'loco' | 'all';
|
||||
@@ -96,7 +95,9 @@ export interface TrainTimetableData {
|
||||
|
||||
export interface Station {
|
||||
name: string;
|
||||
|
||||
generalInfo?: StationGeneralInfo;
|
||||
|
||||
onlineInfo?: ActiveScenery;
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ export interface StationGeneralInfo {
|
||||
abbr: string;
|
||||
hash?: string;
|
||||
reqLevel: number;
|
||||
lines?: string;
|
||||
lines: string;
|
||||
project: string;
|
||||
projectUrl?: string;
|
||||
signalType: string;
|
||||
@@ -170,7 +171,7 @@ export interface ActiveScenery {
|
||||
confirmed: number;
|
||||
unconfirmed: number;
|
||||
};
|
||||
missingCheckpoints: string[];
|
||||
missingCheckpoints: string[];
|
||||
}
|
||||
|
||||
export interface ScenerySpawn {
|
||||
@@ -215,8 +216,45 @@ export interface CheckpointTrain {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
driverName: string;
|
||||
|
||||
@@ -272,7 +272,7 @@ export default defineComponent({
|
||||
this.scrollDataLoaded = true;
|
||||
},
|
||||
|
||||
async fetchHistoryData() {
|
||||
async fetchHistoryData() {
|
||||
const queryParams: DispatchersQueryParams = {};
|
||||
|
||||
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 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['dateFrom'] = dateFromISO;
|
||||
queryParams['dateTo'] = dateToISO;
|
||||
queryParams['dateFrom'] = dateFromString;
|
||||
queryParams['dateTo'] = dateToString ? `${dateToString}T23:00:00` : undefined;
|
||||
|
||||
queryParams['countLimit'] = 30;
|
||||
|
||||
|
||||
@@ -132,7 +132,6 @@ interface TimetablesQueryParams {
|
||||
issuedFrom?: string;
|
||||
terminatingAt?: string;
|
||||
via?: string;
|
||||
includesScenery?: string;
|
||||
|
||||
countFrom?: number;
|
||||
countLimit?: number;
|
||||
@@ -214,7 +213,6 @@ export default defineComponent({
|
||||
'search-train': '',
|
||||
'search-driver': '',
|
||||
'search-dispatcher': '',
|
||||
'search-includesScenery': '',
|
||||
'search-issuedFrom': '',
|
||||
'search-via': '',
|
||||
'search-terminatingAt': '',
|
||||
@@ -357,25 +355,19 @@ export default defineComponent({
|
||||
const driverName = this.searchersValues['search-driver'].trim() || undefined;
|
||||
const trainNo = this.searchersValues['search-train'].trim() || undefined;
|
||||
const authorName = this.searchersValues['search-dispatcher'].trim() || undefined;
|
||||
const dateFromString = this.searchersValues['search-date-from'].trim() || undefined;
|
||||
const includesScenery = this.searchersValues['search-includesScenery'].trim() || undefined;
|
||||
const dateFrom = this.searchersValues['search-date-from'].trim() || undefined;
|
||||
const issuedFrom = this.searchersValues['search-issuedFrom'].trim() || undefined;
|
||||
const via = this.searchersValues['search-via'].trim() || undefined;
|
||||
const terminatingAt = this.searchersValues['search-terminatingAt'].trim() || undefined;
|
||||
const categoryCode = this.searchersValues['select-categoryCode'].trim() || undefined;
|
||||
|
||||
let dateFromISO: string | undefined = undefined;
|
||||
let dateToISO: string | undefined = undefined;
|
||||
let dateTo: string | undefined = undefined;
|
||||
|
||||
if (dateFromString) {
|
||||
let dateFrom = new Date(dateFromString);
|
||||
dateFrom.setMinutes(dateFrom.getMinutes() + dateFrom.getTimezoneOffset());
|
||||
if (dateFrom) {
|
||||
const d = new Date(dateFrom);
|
||||
d.setDate(d.getDate() + 1);
|
||||
|
||||
let dateTo = new Date(dateFrom);
|
||||
dateTo.setDate(dateTo.getDate() + 1);
|
||||
|
||||
dateFromISO = dateFrom.toISOString();
|
||||
dateToISO = dateTo.toISOString();
|
||||
dateTo = d.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
const queryParams: TimetablesQueryParams = {};
|
||||
@@ -438,9 +430,8 @@ export default defineComponent({
|
||||
queryParams['countLimit'] = undefined;
|
||||
|
||||
queryParams['authorName'] = authorName;
|
||||
queryParams['dateFrom'] = dateFromISO;
|
||||
queryParams['dateTo'] = dateToISO;
|
||||
queryParams['includesScenery'] = includesScenery;
|
||||
queryParams['dateFrom'] = dateFrom;
|
||||
queryParams['dateTo'] = dateTo;
|
||||
queryParams['issuedFrom'] = issuedFrom;
|
||||
queryParams['terminatingAt'] = terminatingAt;
|
||||
queryParams['via'] = via;
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { VitePWA } from 'vite-plugin-pwa';
|
||||
import path from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
server: { port: 5123, open: false },
|
||||
server: { port: 5123, open: true },
|
||||
preview: { port: 4001, open: false },
|
||||
publicDir: 'public',
|
||||
css: {
|
||||
@@ -28,7 +28,7 @@ export default defineConfig({
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern:
|
||||
/^https:\/\/stacjownik.spythere.eu\/api\/(getVehiclesData|getDonators|getSceneries)/i,
|
||||
/^https:\/\/stacjownik.spythere.eu\/api\/(getVehicles|getDonators|getSceneries)/i,
|
||||
handler: 'NetworkFirst',
|
||||
options: {
|
||||
cacheName: 'stacjownik-api-cache',
|
||||
|
||||
Reference in New Issue
Block a user