mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| febb22e1bc | |||
| 500f3c1223 | |||
| 221e0c7e82 | |||
| ca19f7e397 | |||
| a71ccd3e1a | |||
| d496c70fa8 | |||
| b9868ba52e | |||
| 59bd3fa2ef | |||
| e14d328ed9 | |||
| 36d71292bc | |||
| 2f6e2e7402 | |||
| e959eac6c5 | |||
| 8bedc4dfc6 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "stacjownik",
|
"name": "stacjownik",
|
||||||
"version": "1.11.2",
|
"version": "1.12.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
|
||||||
@include smallScreen() {
|
@include smallScreen() {
|
||||||
font-size: calc(0.5rem + 1.1vw);
|
font-size: calc(0.55rem + 1.1vw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@include screenLandscape() {
|
@include screenLandscape() {
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
@keydown.enter="navigateToScenery(item.stationName, item.isOnline)"
|
@keydown.enter="navigateToScenery(item.stationName, item.isOnline)"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<span>
|
<span class="item-general">
|
||||||
<b
|
<b
|
||||||
v-if="item.dispatcherLevel !== null"
|
v-if="item.dispatcherLevel !== null"
|
||||||
class="dispatcher-level"
|
class="level-badge dispatcher"
|
||||||
:style="calculateExpStyle(item.dispatcherLevel, item.dispatcherIsSupporter)"
|
:style="calculateExpStyle(item.dispatcherLevel, item.dispatcherIsSupporter)"
|
||||||
>
|
>
|
||||||
{{ item.dispatcherLevel >= 2 ? item.dispatcherLevel : 'L' }}
|
{{ item.dispatcherLevel >= 2 ? item.dispatcherLevel : 'L' }}
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<span class="region-badge" :class="item.region">PL1</span>
|
<span class="region-badge" :class="item.region">PL1</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span class="item-time">
|
||||||
<span :data-status="item.isOnline"> {{ item.isOnline ? $t('journal.online-since') : 'OFFLINE' }} </span>
|
<span :data-status="item.isOnline"> {{ item.isOnline ? $t('journal.online-since') : 'OFFLINE' }} </span>
|
||||||
<span>
|
<span>
|
||||||
{{ new Date(item.timestampFrom).toLocaleTimeString('pl-PL', { timeStyle: 'short' }) }}
|
{{ new Date(item.timestampFrom).toLocaleTimeString('pl-PL', { timeStyle: 'short' }) }}
|
||||||
@@ -99,18 +99,9 @@ export default defineComponent({
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../styles/animations.scss';
|
@import '../../styles/animations.scss';
|
||||||
@import '../../styles/responsive.scss';
|
@import '../../styles/responsive.scss';
|
||||||
|
@import '../../styles/badge.scss';
|
||||||
@import '../../styles/JournalSection.scss';
|
@import '../../styles/JournalSection.scss';
|
||||||
|
|
||||||
.region-badge {
|
|
||||||
padding: 0.1em 0.5em;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&.eu {
|
|
||||||
background-color: forestgreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li.sticky {
|
li.sticky {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -141,6 +132,18 @@ li.sticky {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-general {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
|
||||||
|
.level-badge {
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.journal_day {
|
.journal_day {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@@ -157,16 +160,4 @@ li.sticky {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dispatcher-level {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
line-height: 1.45em;
|
|
||||||
width: 1.45em;
|
|
||||||
height: 1.45em;
|
|
||||||
|
|
||||||
margin-right: 0.45em;
|
|
||||||
border-radius: 0.25em;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{ $t(tab.titlePath) }}
|
{{ $t(tab.titlePath) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stats-tab" v-show="areStatsOpen">
|
<div class="stats-tab" v-show="areStatsOpen">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<JournalDailyStats v-if="store.currentStatsTab == 'daily'" ref="dailyStatsComp" />
|
<JournalDailyStats v-if="store.currentStatsTab == 'daily'" ref="dailyStatsComp" />
|
||||||
@@ -35,7 +35,8 @@ type TStatTab = 'daily' | 'driver';
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
const dailyStatsComp: Ref<InstanceType<typeof JournalDailyStats> | null> = ref(null);
|
const dailyStatsComp: Ref<InstanceType<typeof JournalDailyStats> | null> = ref(null);
|
||||||
|
|
||||||
const areStatsOpen = ref(true);
|
const lastDailyStatsOpen = ref(false);
|
||||||
|
const areStatsOpen = ref(false);
|
||||||
const lastClickedTab = ref('daily');
|
const lastClickedTab = ref('daily');
|
||||||
|
|
||||||
let data = reactive({
|
let data = reactive({
|
||||||
@@ -54,9 +55,9 @@ let data = reactive({
|
|||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
function onTabButtonClick(tab: TStatTab) {
|
function onTabButtonClick(tab: TStatTab) {
|
||||||
if (lastClickedTab.value == tab || !areStatsOpen.value) {
|
if (lastClickedTab.value == tab || !areStatsOpen.value) areStatsOpen.value = !areStatsOpen.value;
|
||||||
areStatsOpen.value = !areStatsOpen.value;
|
|
||||||
}
|
if (tab == 'daily') lastDailyStatsOpen.value = areStatsOpen.value;
|
||||||
|
|
||||||
store.currentStatsTab = tab;
|
store.currentStatsTab = tab;
|
||||||
lastClickedTab.value = tab;
|
lastClickedTab.value = tab;
|
||||||
@@ -77,6 +78,7 @@ watch(
|
|||||||
|
|
||||||
lastClickedTab.value = statsData ? 'driver' : 'daily';
|
lastClickedTab.value = statsData ? 'driver' : 'daily';
|
||||||
if (statsData) areStatsOpen.value = true;
|
if (statsData) areStatsOpen.value = true;
|
||||||
|
if (!statsData) areStatsOpen.value = lastDailyStatsOpen.value;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,25 +6,34 @@
|
|||||||
:key="timetable.id"
|
:key="timetable.id"
|
||||||
>
|
>
|
||||||
<div class="journal_item-info">
|
<div class="journal_item-info">
|
||||||
<div class="info-top">
|
<div class="info-general">
|
||||||
<span
|
<span
|
||||||
|
class="general-train"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="showTimetable(timetable)"
|
@click="showTimetable(timetable)"
|
||||||
@keydown.enter="showTimetable(timetable)"
|
@keydown.enter="showTimetable(timetable)"
|
||||||
style="cursor: pointer"
|
style="cursor: pointer"
|
||||||
>
|
>
|
||||||
<b class="text--primary">{{ timetable.trainCategoryCode }} </b>
|
|
||||||
<b>{{ timetable.trainNo }}</b>
|
|
||||||
| <span>{{ timetable.driverName }}</span> |
|
|
||||||
<span class="text--grayed">#{{ timetable.id }}</span>
|
<span class="text--grayed">#{{ timetable.id }}</span>
|
||||||
<span v-if="timetable.driverLevel !== null">
|
<span>
|
||||||
|
|
<strong class="text--primary">
|
||||||
<b :style="calculateTextExpStyle(timetable.driverLevel, timetable.driverIsSupporter)">
|
{{ timetable.trainCategoryCode }}
|
||||||
{{ timetable.driverLevel < 2 ? 'L' : `${timetable.driverLevel} lvl` }}
|
</strong>
|
||||||
</b>
|
<strong> {{ timetable.trainNo }}</strong>
|
||||||
</span>
|
</span>
|
||||||
|
•
|
||||||
|
<strong
|
||||||
|
v-if="timetable.driverLevel !== null"
|
||||||
|
class="level-badge driver"
|
||||||
|
:style="calculateExpStyle(timetable.driverLevel, timetable.driverIsSupporter)"
|
||||||
|
>
|
||||||
|
{{ timetable.driverLevel < 2 ? 'L' : `${timetable.driverLevel}` }}
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
<strong>{{ timetable.driverName }}</strong>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
|
||||||
|
<span class="general-time">
|
||||||
<b class="info-date">{{ localeDay(timetable.beginDate, $i18n.locale) }}</b>
|
<b class="info-date">{{ localeDay(timetable.beginDate, $i18n.locale) }}</b>
|
||||||
<b
|
<b
|
||||||
class="info-status"
|
class="info-status"
|
||||||
@@ -86,6 +95,7 @@
|
|||||||
<b>{{ timetable.authorName }}</b>
|
<b>{{ timetable.authorName }}</b>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="timetable.stockString"
|
v-if="timetable.stockString"
|
||||||
class="btn--option btn--show"
|
class="btn--option btn--show"
|
||||||
@@ -94,6 +104,7 @@
|
|||||||
{{ $t('journal.stock-info') }}
|
{{ $t('journal.stock-info') }}
|
||||||
<img :src="getIcon(`arrow-${item.showStock.value ? 'asc' : 'desc'}`)" alt="Arrow" />
|
<img :src="getIcon(`arrow-${item.showStock.value ? 'asc' : 'desc'}`)" alt="Arrow" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="info-extended" v-if="timetable.stockString && item.showStock.value">
|
<div class="info-extended" v-if="timetable.stockString && item.showStock.value">
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<div>
|
||||||
@@ -189,6 +200,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
showTimetable(timetable: TimetableHistory) {
|
showTimetable(timetable: TimetableHistory) {
|
||||||
|
if (!timetable) return;
|
||||||
if (timetable.terminated) return;
|
if (timetable.terminated) return;
|
||||||
|
|
||||||
this.selectModalTrain(timetable.driverName + timetable.trainNo.toString());
|
this.selectModalTrain(timetable.driverName + timetable.trainNo.toString());
|
||||||
@@ -209,7 +221,6 @@ export default defineComponent({
|
|||||||
@import '../../styles/badge.scss';
|
@import '../../styles/badge.scss';
|
||||||
@import '../../styles/JournalSection.scss';
|
@import '../../styles/JournalSection.scss';
|
||||||
|
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: 0.25em 0;
|
margin: 0.25em 0;
|
||||||
}
|
}
|
||||||
@@ -236,10 +247,14 @@ hr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-top {
|
&-general {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
gap: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-route {
|
&-route {
|
||||||
@@ -251,6 +266,12 @@ hr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.general-train {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
ul.stock-list {
|
ul.stock-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
@@ -291,14 +312,9 @@ ul.stock-list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@include smallScreen {
|
@include smallScreen {
|
||||||
.info-top {
|
.info-general {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
span {
|
|
||||||
margin: 0.1em auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-extended {
|
.info-extended {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,31 @@
|
|||||||
<div class="list-warning" v-else-if="dispatcherHistoryList.length == 0">{{ $t('scenery.history-list-empty') }}</div>
|
<div class="list-warning" v-else-if="dispatcherHistoryList.length == 0">{{ $t('scenery.history-list-empty') }}</div>
|
||||||
|
|
||||||
<ul class="history-list" v-else>
|
<ul class="history-list" v-else>
|
||||||
<li class="list-item" v-for="historyItem in dispatcherHistoryList">
|
<li class="list-item" v-for="item in dispatcherHistoryList">
|
||||||
<div>
|
<router-link class="item-general" :to="`/journal/dispatchers?dispatcherName=${item.dispatcherName}`">
|
||||||
<router-link :to="`/journal/dispatchers?dispatcherName=${historyItem.dispatcherName}`">
|
<span class="text--grayed">#{{ item.stationHash }} </span>
|
||||||
<span class="text--grayed">#{{ historyItem.stationHash }} </span>
|
<b
|
||||||
<b>{{ historyItem.dispatcherName }}</b>
|
v-if="item.dispatcherLevel !== null"
|
||||||
</router-link>
|
class="level-badge dispatcher"
|
||||||
</div>
|
:style="calculateExpStyle(item.dispatcherLevel, item.dispatcherIsSupporter)"
|
||||||
|
>
|
||||||
|
{{ item.dispatcherLevel >= 2 ? item.dispatcherLevel : 'L' }}
|
||||||
|
</b>
|
||||||
|
|
||||||
<div v-if="historyItem.timestampTo">
|
<b>{{ item.dispatcherName }}</b>
|
||||||
<b>{{ $d(historyItem.timestampFrom) }}</b>
|
</router-link>
|
||||||
|
|
||||||
{{ timestampToString(historyItem.timestampFrom) }}
|
<div v-if="item.timestampTo">
|
||||||
- {{ timestampToString(historyItem.timestampTo) }} ({{ calculateDuration(historyItem.currentDuration) }})
|
<b>{{ $d(item.timestampFrom) }}</b>
|
||||||
|
|
||||||
|
{{ timestampToString(item.timestampFrom) }}
|
||||||
|
- {{ timestampToString(item.timestampTo) }} ({{ calculateDuration(item.currentDuration) }})
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dispatcher-online" v-else>
|
<div class="dispatcher-online" v-else>
|
||||||
{{ $t('journal.online-since') }}
|
{{ $t('journal.online-since') }}
|
||||||
<b>{{ timestampToString(historyItem.timestampFrom) }}</b>
|
<b>{{ timestampToString(item.timestampFrom) }}</b>
|
||||||
({{ calculateDuration(historyItem.currentDuration) }})
|
({{ calculateDuration(item.currentDuration) }})
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -39,10 +45,11 @@ import { DispatcherHistory } from '../../scripts/interfaces/api/DispatchersAPIDa
|
|||||||
import Station from '../../scripts/interfaces/Station';
|
import Station from '../../scripts/interfaces/Station';
|
||||||
import { URLs } from '../../scripts/utils/apiURLs';
|
import { URLs } from '../../scripts/utils/apiURLs';
|
||||||
import Loading from '../Global/Loading.vue';
|
import Loading from '../Global/Loading.vue';
|
||||||
|
import styleMixin from '../../mixins/styleMixin';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SceneryDispatchersHistory',
|
name: 'SceneryDispatchersHistory',
|
||||||
mixins: [dateMixin],
|
mixins: [dateMixin, styleMixin],
|
||||||
props: {
|
props: {
|
||||||
station: {
|
station: {
|
||||||
type: Object as PropType<Station>,
|
type: Object as PropType<Station>,
|
||||||
@@ -55,7 +62,7 @@ export default defineComponent({
|
|||||||
dataStatus: DataStatus.Loading,
|
dataStatus: DataStatus.Loading,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
activated() {
|
||||||
this.fetchAPIData();
|
this.fetchAPIData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -96,6 +103,13 @@ export default defineComponent({
|
|||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-general {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
.dispatcher-online {
|
.dispatcher-online {
|
||||||
color: springgreen;
|
color: springgreen;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="info-header">
|
<section class="info-header">
|
||||||
<a class="scenery-name" :href="station.generalInfo?.url">
|
<a class="scenery-name" :href="station.generalInfo?.url" target="_blank">
|
||||||
{{ station.name }}
|
{{ station.name }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="scenery-info">
|
<div class="scenery-info">
|
||||||
<section v-if="!timetableOnly">
|
<section v-if="!timetableOnly">
|
||||||
<div class="info-general" v-if="station.generalInfo">
|
<div class="scenery-info-general" v-if="station.generalInfo">
|
||||||
<scenery-info-icons :station="station" />
|
<scenery-info-icons :station="station" />
|
||||||
|
|
||||||
<div class="general-list">
|
<div class="scenery-general-list">
|
||||||
<span>
|
<span>
|
||||||
<b>{{ $t('availability.title') }}:</b> {{ $t(`availability.${station.generalInfo.availability}`) }}
|
<b>{{ $t('availability.title') }}:</b> {{ $t(`availability.${station.generalInfo.availability}`) }}
|
||||||
|
|
||||||
@@ -26,26 +26,32 @@
|
|||||||
</span>
|
</span>
|
||||||
<span v-if="station.generalInfo.project">
|
<span v-if="station.generalInfo.project">
|
||||||
• <b>{{ $t('scenery.project-title') }}: </b>
|
• <b>{{ $t('scenery.project-title') }}: </b>
|
||||||
<b style="color: salmon">{{ station.generalInfo.project }}</b>
|
<a
|
||||||
|
style="color: salmon; text-decoration: underline; font-weight: bold"
|
||||||
|
:href="station.generalInfo.projectUrl"
|
||||||
|
target="_blank"
|
||||||
|
>{{ station.generalInfo.project }}</a
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<scenery-info-routes :station="station" />
|
<scenery-info-routes :station="station" />
|
||||||
|
|
||||||
<div class="scenery-authors" v-if="station.generalInfo.authors && station.generalInfo.authors.length > 0">
|
<div class="scenery-authors" v-if="station.generalInfo.authors && station.generalInfo.authors.length > 0">
|
||||||
<b> {{ $t('scenery.authors-title', { authors: station.generalInfo.authors.length }, station.generalInfo.authors.length) }}: </b>
|
<b>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
'scenery.authors-title',
|
||||||
|
{ authors: station.generalInfo.authors.length },
|
||||||
|
station.generalInfo.authors.length
|
||||||
|
)
|
||||||
|
}}:
|
||||||
|
</b>
|
||||||
{{ station.generalInfo.authors.join(', ') }}
|
{{ station.generalInfo.authors.join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
|
||||||
<div class="scenery-topic" v-if="station.generalInfo.url">
|
|
||||||
<a :href="station.generalInfo.url" target="_blank">
|
|
||||||
> {{ $t('scenery.forum-topic', { name: station.name }) }} <
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin: 2em 0; height: 2px; background-color: white" />
|
<div style="margin: 2em 0; height: 2px; background-color: white"></div>
|
||||||
|
|
||||||
<!-- info dispatcher -->
|
<!-- info dispatcher -->
|
||||||
<scenery-info-dispatcher :station="station" :onlineFrom="onlineFrom" />
|
<scenery-info-dispatcher :station="station" :onlineFrom="onlineFrom" />
|
||||||
@@ -124,11 +130,11 @@ h3.section-header {
|
|||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-general {
|
.scenery-info-general {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.general-list {
|
.scenery-general-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
@@ -1,114 +1,108 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="info-routes" v-if="station.generalInfo">
|
<section class="info-routes" v-if="station.generalInfo">
|
||||||
<div class="routes one-way" v-if="station.generalInfo.routes.oneWay.length > 0">
|
<div class="routes one-way" v-if="station.generalInfo.routes.oneWay.length > 0">
|
||||||
<b>{{ $t('scenery.one-way-routes') }}</b>
|
<b>{{ $t('scenery.one-way-routes') }}</b>
|
||||||
|
|
||||||
<ul class="routes-list">
|
<ul class="routes-list">
|
||||||
<li
|
<li v-for="route in station.generalInfo.routes.oneWay">
|
||||||
v-for="route in station.generalInfo.routes.oneWay"
|
<span :class="{ 'no-catenary': !route.catenary, internal: route.isInternal }"> {{ route.name }}</span>
|
||||||
:class="{ 'no-catenary': !route.catenary, internal: route.isInternal }"
|
<span v-if="route.speed" class="speed">{{ route.speed }}</span>
|
||||||
>
|
<span v-if="route.SBL" class="sbl">SBL</span>
|
||||||
{{ route.name }}
|
</li>
|
||||||
<b v-if="route.SBL">SBL</b>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
|
||||||
</div>
|
<div class="routes two-way" v-if="station.generalInfo.routes.twoWay.length > 0">
|
||||||
|
<b>{{ $t('scenery.two-way-routes') }}</b>
|
||||||
<div class="routes two-way" v-if="station.generalInfo.routes.twoWay.length > 0">
|
|
||||||
<b>{{ $t('scenery.two-way-routes') }}</b>
|
<ul class="routes-list">
|
||||||
|
<li v-for="route in station.generalInfo.routes.twoWay">
|
||||||
<ul class="routes-list">
|
<span :class="{ 'no-catenary': !route.catenary, internal: route.isInternal }">{{ route.name }}</span>
|
||||||
<li
|
<span v-if="route.speed" class="speed">{{ route.speed }}</span>
|
||||||
v-for="route in station.generalInfo.routes.twoWay"
|
<span v-if="route.SBL" class="sbl">SBL</span>
|
||||||
:class="{ 'no-catenary': !route.catenary, internal: route.isInternal }"
|
</li>
|
||||||
>
|
</ul>
|
||||||
{{ route.name }} <b v-if="route.SBL">SBL</b>
|
</div>
|
||||||
</li>
|
</section>
|
||||||
</ul>
|
</template>
|
||||||
</div>
|
|
||||||
|
<script lang="ts">
|
||||||
<!-- <div
|
import { defineComponent } from 'vue';
|
||||||
class="route-info"
|
import Station from '../../../scripts/interfaces/Station';
|
||||||
:class="{ 'no-catenary': !route.catenary, internal: route.isInternal }"
|
|
||||||
v-for="route in [...station.generalInfo.routes.oneWay, ...station.generalInfo.routes.twoWay].filter(
|
export default defineComponent({
|
||||||
(route) => route.name != '-'
|
props: {
|
||||||
)"
|
station: {
|
||||||
:key="route.name"
|
type: Object as () => Station,
|
||||||
:title="`Szlak ${route.name}: ${route.isInternal ? 'wewnętrzny' : 'zewnętrzny'}, ${
|
default: {},
|
||||||
route.tracks == 2 ? 'dwutorowy' : 'jednotorowy'
|
},
|
||||||
}, ${route.catenary ? 'zelektryfikowany' : 'niezelektryfikowany'} z ${route.SBL ? 'SBL' : 'PBL'} ${
|
},
|
||||||
route.TWB ? 'i blokadą dwukierunkową' : ''
|
});
|
||||||
}`"
|
</script>
|
||||||
> -->
|
|
||||||
<!-- <span class="track-name">
|
<style lang="scss" scoped>
|
||||||
<b>{{ route.name }}</b>
|
.info-routes {
|
||||||
</span> -->
|
display: flex;
|
||||||
<!--
|
justify-content: center;
|
||||||
<span class="track-specs">
|
flex-wrap: wrap;
|
||||||
{{ route.tracks }}tor
|
|
||||||
<img v-if="route.catenary" :src="icons.trackCatenary" alt="icon track catenary" />
|
margin: 1em 0;
|
||||||
<img v-else :src="icons.trackNoCatenary" alt="icon track no catenary" />
|
}
|
||||||
|
|
||||||
<img v-if="route.TWB" :src="icons.trackTWB" alt="icon track twb" />
|
.routes {
|
||||||
<img v-if="route.SBL" :src="icons.trackSBL" alt="icon track sbl" />
|
display: flex;
|
||||||
</span> -->
|
justify-content: center;
|
||||||
<!-- </div> -->
|
align-items: center;
|
||||||
</section>
|
flex-wrap: wrap;
|
||||||
</template>
|
|
||||||
|
padding: 0.25em;
|
||||||
<script lang="ts">
|
}
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import Station from '../../../scripts/interfaces/Station';
|
ul.routes-list {
|
||||||
|
margin: 0.45em 0.25em;
|
||||||
export default defineComponent({
|
display: flex;
|
||||||
props: {
|
justify-content: center;
|
||||||
station: {
|
flex-wrap: wrap;
|
||||||
type: Object as () => Station,
|
|
||||||
default: {},
|
li {
|
||||||
},
|
margin: 0.5em 0.25em;
|
||||||
},
|
|
||||||
});
|
span {
|
||||||
</script>
|
padding: 0.2em 0.25em;
|
||||||
|
background-color: #007599;
|
||||||
<style lang="scss" scoped>
|
font-weight: bold;
|
||||||
.info-routes {
|
|
||||||
display: flex;
|
&.no-catenary {
|
||||||
justify-content: center;
|
background-color: #686868;
|
||||||
flex-wrap: wrap;
|
}
|
||||||
|
|
||||||
margin: 1em 0;
|
&.internal {
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.routes {
|
|
||||||
display: flex;
|
&.speed {
|
||||||
justify-content: center;
|
background-color: #404040;
|
||||||
align-items: center;
|
color: #cfcfcf;
|
||||||
flex-wrap: wrap;
|
}
|
||||||
|
|
||||||
padding: 0.25em;
|
&.sbl {
|
||||||
}
|
color: var(--clr-primary);
|
||||||
|
background-color: #404040;
|
||||||
ul.routes-list {
|
}
|
||||||
margin: 0.45em 0.25em;
|
|
||||||
display: flex;
|
&:last-child {
|
||||||
|
border-radius: 0 0.5em 0.5em 0;
|
||||||
li {
|
}
|
||||||
background-color: #007599;
|
|
||||||
|
&:first-child {
|
||||||
padding: 0.2em 0.25em;
|
border-radius: 0.5em 0 0 0.5em;
|
||||||
margin-left: 0.25em;
|
}
|
||||||
|
|
||||||
&.no-catenary {
|
&:only-child {
|
||||||
background-color: #686868;
|
border-radius: 0.5em;
|
||||||
}
|
|
||||||
|
}
|
||||||
&.internal {
|
}
|
||||||
text-decoration: underline;
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
b {
|
|
||||||
color: var(--clr-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -2,8 +2,46 @@
|
|||||||
<section class="scenery-timetables-history scenery-section">
|
<section class="scenery-timetables-history scenery-section">
|
||||||
<Loading v-if="dataStatus != 2" />
|
<Loading v-if="dataStatus != 2" />
|
||||||
|
|
||||||
<div class="list-warning" v-else-if="sceneryHistoryList.length == 0">{{ $t('scenery.history-list-empty') }}</div>
|
<table v-else-if="sceneryHistoryList.length">
|
||||||
<ul class="history-list" v-else>
|
<thead>
|
||||||
|
<th>{{ $t('scenery.timetables-history-id') }}</th>
|
||||||
|
<th>{{ $t('scenery.timetables-history-number')}}</th>
|
||||||
|
<th>{{ $t('scenery.timetables-history-route')}}</th>
|
||||||
|
<th>{{ $t('scenery.timetables-history-driver')}}</th>
|
||||||
|
<th>{{ $t('scenery.timetables-history-author')}}</th>
|
||||||
|
<th>{{ $t('scenery.timetables-history-date')}}</th>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="historyItem in sceneryHistoryList" @click="test">
|
||||||
|
<td>
|
||||||
|
<router-link :to="`/journal/timetables?timetableId=${historyItem.id}`">#{{ historyItem.id }}</router-link>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b class="text--primary">{{ historyItem.trainCategoryCode }}</b> <br />
|
||||||
|
{{ historyItem.trainNo }}
|
||||||
|
</td>
|
||||||
|
<td>{{ historyItem.route.replace('|', ' -> ') }}</td>
|
||||||
|
<td>{{ historyItem.driverName }}</td>
|
||||||
|
<td>
|
||||||
|
<router-link
|
||||||
|
v-if="historyItem.authorName"
|
||||||
|
:to="`/journal/dispatchers?dispatcherName=${historyItem.authorName}`"
|
||||||
|
>{{ historyItem.authorName }}
|
||||||
|
</router-link>
|
||||||
|
<i v-else>{{ $t('scenery.timetable-author-unknown') }}</i>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>{{ localeDay(historyItem.beginDate, $i18n.locale) }}</b>
|
||||||
|
{{ localeTime(historyItem.beginDate, $i18n.locale) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="list-warning" v-else>{{ $t('scenery.history-list-empty') }}</div>
|
||||||
|
|
||||||
|
<!-- <ul class="history-list" v-else>
|
||||||
<li class="list-item" v-for="historyItem in sceneryHistoryList">
|
<li class="list-item" v-for="historyItem in sceneryHistoryList">
|
||||||
<div>
|
<div>
|
||||||
<b>{{ localeDay(historyItem.beginDate, $i18n.locale) }}</b>
|
<b>{{ localeDay(historyItem.beginDate, $i18n.locale) }}</b>
|
||||||
@@ -19,16 +57,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>{{ historyItem.route.replace('|', ' -> ') }}</div>
|
<div>{{ historyItem.route.replace('|', ' -> ') }}</div>
|
||||||
<!-- <div>{{ historyItem.routeDistance }} km</div> -->
|
|
||||||
<div>
|
<div>
|
||||||
{{ $t('scenery.timetable-author-title') }}:
|
{{ $t('scenery.timetable-author-title') }}:
|
||||||
<b v-if="historyItem.authorName">{{ historyItem.authorName }}</b>
|
<b v-if="historyItem.authorName">{{ historyItem.authorName }}</b>
|
||||||
<i v-else>{{ $t('scenery.timetable-author-unknown') }}</i>
|
<i v-else>{{ $t('scenery.timetable-author-unknown') }}</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div v-if="historyItem.authorId">{{ historyItem.authorName }}</div> -->
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul> -->
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -57,7 +93,7 @@ export default defineComponent({
|
|||||||
dataStatus: DataStatus.Loading,
|
dataStatus: DataStatus.Loading,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
activated() {
|
||||||
this.fetchAPIData();
|
this.fetchAPIData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -72,6 +108,10 @@ export default defineComponent({
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
test() {
|
||||||
|
console.log('test');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: { Loading },
|
components: { Loading },
|
||||||
});
|
});
|
||||||
@@ -91,17 +131,29 @@ export default defineComponent({
|
|||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item {
|
table {
|
||||||
display: grid;
|
width: 100%;
|
||||||
grid-template-columns: 1fr 2fr 2fr 1fr;
|
border-collapse: collapse;
|
||||||
gap: 1em;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
background-color: #353535;
|
thead {
|
||||||
padding: 0.5em;
|
position: sticky;
|
||||||
margin: 0.5em 0;
|
top: 0;
|
||||||
|
background-color: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
line-height: 1.5em;
|
th {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
background-color: #353535;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0.75em;
|
||||||
|
border-bottom: solid 5px #111;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include smallScreen {
|
@include smallScreen {
|
||||||
|
|||||||
@@ -11,15 +11,14 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<strong>
|
<strong>
|
||||||
<span v-if="train.timetableData">{{ train.timetableData.category }} </span>
|
<span v-if="train.timetableData" class="text--primary">{{ train.timetableData.category }} </span>
|
||||||
<span class="train-number">{{ train.trainNo }}</span>
|
<span class="train-number">{{ train.trainNo }}</span>
|
||||||
</strong>
|
</strong>
|
||||||
<span>|</span>
|
<span>•</span>
|
||||||
<span>{{ train.driverName }}</span>
|
<b class="level-badge driver" :style="calculateExpStyle(train.driverLevel, train.isSupporter)">
|
||||||
<span>|</span>
|
{{ train.driverLevel < 2 ? 'L' : `${train.driverLevel}` }}
|
||||||
<b :style="calculateTextExpStyle(train.driverLevel, train.isSupporter)">
|
|
||||||
{{ train.driverLevel < 2 ? 'L' : `${train.driverLevel} lvl` }}
|
|
||||||
</b>
|
</b>
|
||||||
|
<span>{{ train.driverName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="timetable_route" v-if="train.timetableData">
|
<div class="timetable_route" v-if="train.timetableData">
|
||||||
@@ -117,6 +116,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../styles/responsive.scss';
|
@import '../../styles/responsive.scss';
|
||||||
|
@import '../../styles/badge.scss';
|
||||||
|
|
||||||
|
|
||||||
.image-warning {
|
.image-warning {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
@@ -172,6 +173,7 @@ export default defineComponent({
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
gap: 0.25em;
|
gap: 0.25em;
|
||||||
|
margin-right: 1.5em;
|
||||||
}
|
}
|
||||||
.train-status-badges {
|
.train-status-badges {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ import dateMixin from '../../mixins/dateMixin';
|
|||||||
import imageMixin from '../../mixins/imageMixin';
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
import Train from '../../scripts/interfaces/Train';
|
import Train from '../../scripts/interfaces/Train';
|
||||||
import TrainStop from '../../scripts/interfaces/TrainStop';
|
import TrainStop from '../../scripts/interfaces/TrainStop';
|
||||||
|
import { useStore } from '../../store/store';
|
||||||
import StopDate from '../Global/StopDate.vue';
|
import StopDate from '../Global/StopDate.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -106,6 +107,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
return {
|
return {
|
||||||
|
store: useStore(),
|
||||||
|
|
||||||
lastConfirmed: computed(() => {
|
lastConfirmed: computed(() => {
|
||||||
return props.train.timetableData!.followingStops.findIndex(
|
return props.train.timetableData!.followingStops.findIndex(
|
||||||
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed && !stops[i + 1]?.stopped
|
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed && !stops[i + 1]?.stopped
|
||||||
@@ -424,3 +427,4 @@ ul.stop_list > li.stop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -313,6 +313,13 @@
|
|||||||
"timetable-author-title": "Issued by",
|
"timetable-author-title": "Issued by",
|
||||||
"timetable-author-unknown": "Author unknown",
|
"timetable-author-unknown": "Author unknown",
|
||||||
|
|
||||||
|
"timetables-history-id": "ID",
|
||||||
|
"timetables-history-number": "Number",
|
||||||
|
"timetables-history-route": "Route",
|
||||||
|
"timetables-history-driver": "Driver",
|
||||||
|
"timetables-history-author": "TT author",
|
||||||
|
"timetables-history-date": "Date",
|
||||||
|
|
||||||
"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",
|
||||||
"history-list-empty": "No recorded scenery history!",
|
"history-list-empty": "No recorded scenery history!",
|
||||||
|
|
||||||
|
|||||||
@@ -317,6 +317,13 @@
|
|||||||
"timetable-author-title": "Wydany przez",
|
"timetable-author-title": "Wydany przez",
|
||||||
"timetable-author-unknown": "Autor nieznany",
|
"timetable-author-unknown": "Autor nieznany",
|
||||||
|
|
||||||
|
"timetables-history-id": "ID",
|
||||||
|
"timetables-history-number": "Numer",
|
||||||
|
"timetables-history-route": "Trasa",
|
||||||
|
"timetables-history-driver": "Maszynista",
|
||||||
|
"timetables-history-author": "Autor RJ",
|
||||||
|
"timetables-history-date": "Data",
|
||||||
|
|
||||||
"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",
|
||||||
"history-list-empty": "Brak historii dla tej scenerii!",
|
"history-list-empty": "Brak historii dla tej scenerii!",
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default defineComponent({
|
|||||||
const bgColor = exp > -1 ? (exp < 2 ? '#26B0D9' : `hsl(${-exp * 5 + 100}, 85%, 50%)`) : '#666';
|
const bgColor = exp > -1 ? (exp < 2 ? '#26B0D9' : `hsl(${-exp * 5 + 100}, 85%, 50%)`) : '#666';
|
||||||
|
|
||||||
const fontColor = exp > 14 || exp == -1 ? 'white' : 'black';
|
const fontColor = exp > 14 || exp == -1 ? 'white' : 'black';
|
||||||
const boxShadow = isSupporter ? `box-shadow: 0 0 10px 2px ${bgColor};` : '';
|
const boxShadow = isSupporter ? `box-shadow: 0 0 6px 2px ${bgColor};` : '';
|
||||||
|
|
||||||
return `background-color: ${bgColor}; color: ${fontColor}; ${boxShadow};`;
|
return `background-color: ${bgColor}; color: ${fontColor}; ${boxShadow};`;
|
||||||
},
|
},
|
||||||
@@ -14,7 +14,7 @@ export default defineComponent({
|
|||||||
calculateTextExpStyle(exp: number, isSupporter = false): string {
|
calculateTextExpStyle(exp: number, isSupporter = false): string {
|
||||||
const textColor = exp > -1 ? (exp < 2 ? '#26B0D9' : `hsl(${-exp * 5 + 100}, 75%, 50%)`) : '#666';
|
const textColor = exp > -1 ? (exp < 2 ? '#26B0D9' : `hsl(${-exp * 5 + 100}, 75%, 50%)`) : '#666';
|
||||||
|
|
||||||
return `color: ${textColor}; ${isSupporter ? 'text-shadow: 0 0 10px ' + textColor : ''};`;
|
return `color: ${textColor}; ${isSupporter ? 'text-shadow: 0 0 6px ' + textColor : ''};`;
|
||||||
},
|
},
|
||||||
|
|
||||||
statusClasses(occupiedTo: string) {
|
statusClasses(occupiedTo: string) {
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ export default interface Station {
|
|||||||
generalInfo?: {
|
generalInfo?: {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
|
||||||
reqLevel: number;
|
reqLevel: number;
|
||||||
// supportersOnly: boolean;
|
// supportersOnly: boolean;
|
||||||
|
|
||||||
lines: string;
|
lines: string;
|
||||||
project: string;
|
project: string;
|
||||||
|
projectUrl?: string;
|
||||||
|
|
||||||
signalType: string;
|
signalType: string;
|
||||||
controlType: string;
|
controlType: string;
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
export default interface StationRoutes {
|
export default interface StationRoutes {
|
||||||
oneWay:
|
oneWay: {
|
||||||
{
|
name: string;
|
||||||
name: string;
|
catenary: boolean;
|
||||||
catenary: boolean;
|
SBL: boolean;
|
||||||
SBL: boolean;
|
TWB: boolean;
|
||||||
TWB: boolean;
|
isInternal: boolean;
|
||||||
isInternal: boolean;
|
tracks: number;
|
||||||
tracks: number;
|
speed: number;
|
||||||
}[];
|
length: number;
|
||||||
|
}[];
|
||||||
twoWay: {
|
|
||||||
name: string;
|
twoWay: {
|
||||||
catenary: boolean;
|
name: string;
|
||||||
SBL: boolean;
|
catenary: boolean;
|
||||||
TWB: boolean;
|
SBL: boolean;
|
||||||
isInternal: boolean;
|
TWB: boolean;
|
||||||
tracks: number;
|
isInternal: boolean;
|
||||||
}[];
|
tracks: number;
|
||||||
|
speed: number;
|
||||||
/* [catenary, noCatenary] */
|
length: number;
|
||||||
oneWayCatenaryRouteNames: string[];
|
}[];
|
||||||
oneWayNoCatenaryRouteNames: string[];
|
|
||||||
twoWayCatenaryRouteNames: string[];
|
/* [catenary, noCatenary] */
|
||||||
twoWayNoCatenaryRouteNames: string[];
|
oneWayCatenaryRouteNames: string[];
|
||||||
sblRouteNames: string[];
|
oneWayNoCatenaryRouteNames: string[];
|
||||||
}
|
twoWayCatenaryRouteNames: string[];
|
||||||
|
twoWayNoCatenaryRouteNames: string[];
|
||||||
|
sblRouteNames: string[];
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default interface TrainStop {
|
export default interface TrainStop {
|
||||||
stopName: string;
|
stopName: string;
|
||||||
stopNameRAW: string;
|
stopNameRAW: string;
|
||||||
stopType: string;
|
stopType: string;
|
||||||
|
|||||||
+65
-58
@@ -24,6 +24,7 @@ export const useStore = defineStore('store', {
|
|||||||
|
|
||||||
stationList: [],
|
stationList: [],
|
||||||
trainList: [],
|
trainList: [],
|
||||||
|
routesList: [],
|
||||||
|
|
||||||
sceneryData: [],
|
sceneryData: [],
|
||||||
lastDispatcherStatuses: [],
|
lastDispatcherStatuses: [],
|
||||||
@@ -115,8 +116,8 @@ export const useStore = defineStore('store', {
|
|||||||
sceneries: timetable.sceneries,
|
sceneries: timetable.sceneries,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
} as Train;
|
||||||
}) as Train[];
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDispatcherStatus(onlineStationData: StationAPIData) {
|
getDispatcherStatus(onlineStationData: StationAPIData) {
|
||||||
@@ -294,73 +295,78 @@ export const useStore = defineStore('store', {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stationList = sceneryData.map((scenery) => ({
|
this.stationList = sceneryData.map((scenery) => {
|
||||||
name: scenery.name,
|
return {
|
||||||
|
name: scenery.name,
|
||||||
|
|
||||||
generalInfo: {
|
generalInfo: {
|
||||||
...scenery,
|
...scenery,
|
||||||
authors: scenery.authors?.split(',').map((a) => a.trim()),
|
authors: scenery.authors?.split(',').map((a) => a.trim()),
|
||||||
routes:
|
routes:
|
||||||
scenery.routes
|
scenery.routes
|
||||||
?.split(';')
|
?.split(';')
|
||||||
.filter((routeString) => routeString)
|
.filter((routeString) => routeString)
|
||||||
.reduce(
|
.reduce(
|
||||||
(acc, routeString) => {
|
(acc, routeString) => {
|
||||||
const specs1 = routeString.split('_')[0];
|
const specs1 = routeString.split('_')[0];
|
||||||
const isInternal = specs1.startsWith('!');
|
const isInternal = specs1.startsWith('!');
|
||||||
const name = isInternal ? specs1.replace('!', '') : specs1;
|
const name = isInternal ? specs1.replace('!', '') : specs1;
|
||||||
|
|
||||||
const specs2 = routeString.split('_')[1].split('');
|
const specs2 = routeString.split('_')[1].split('');
|
||||||
const twoWay = specs2[0] == '2';
|
const twoWay = specs2[0] == '2';
|
||||||
const catenary = specs2[1] == 'E';
|
const catenary = specs2[1] == 'E';
|
||||||
const SBL = specs2[2] == 'S';
|
const SBL = specs2[2] == 'S';
|
||||||
const TWB = specs2[3] ? true : false;
|
const TWB = specs2[3] ? true : false;
|
||||||
|
const speed = Number(routeString.split(':')[1]) || 0;
|
||||||
|
const length = Number(routeString.split(':')[2]) || 0;
|
||||||
|
|
||||||
const propName = twoWay
|
const propName = twoWay
|
||||||
? catenary
|
? catenary
|
||||||
? 'twoWayCatenaryRouteNames'
|
? 'twoWayCatenaryRouteNames'
|
||||||
: 'twoWayNoCatenaryRouteNames'
|
: 'twoWayNoCatenaryRouteNames'
|
||||||
: catenary
|
: catenary
|
||||||
? 'oneWayCatenaryRouteNames'
|
? 'oneWayCatenaryRouteNames'
|
||||||
: 'oneWayNoCatenaryRouteNames';
|
: 'oneWayNoCatenaryRouteNames';
|
||||||
|
|
||||||
acc[twoWay ? 'twoWay' : 'oneWay'].push({
|
acc[twoWay ? 'twoWay' : 'oneWay'].push({
|
||||||
name,
|
name,
|
||||||
SBL,
|
SBL,
|
||||||
TWB,
|
TWB,
|
||||||
catenary,
|
catenary,
|
||||||
isInternal,
|
isInternal,
|
||||||
tracks: twoWay ? 2 : 1,
|
tracks: twoWay ? 2 : 1,
|
||||||
});
|
length,
|
||||||
if (!isInternal) acc[propName].push(name);
|
speed,
|
||||||
|
});
|
||||||
|
if (!isInternal) acc[propName].push(name);
|
||||||
|
|
||||||
if (SBL) acc['sblRouteNames'].push(name);
|
if (SBL) acc['sblRouteNames'].push(name);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
oneWay: [],
|
oneWay: [],
|
||||||
twoWay: [],
|
twoWay: [],
|
||||||
sblRouteNames: [],
|
sblRouteNames: [],
|
||||||
oneWayCatenaryRouteNames: [],
|
oneWayCatenaryRouteNames: [],
|
||||||
oneWayNoCatenaryRouteNames: [],
|
oneWayNoCatenaryRouteNames: [],
|
||||||
twoWayCatenaryRouteNames: [],
|
twoWayCatenaryRouteNames: [],
|
||||||
twoWayNoCatenaryRouteNames: [],
|
twoWayNoCatenaryRouteNames: [],
|
||||||
} as StationRoutes
|
} as StationRoutes
|
||||||
) || {},
|
) || {},
|
||||||
checkpoints: scenery.checkpoints
|
checkpoints: scenery.checkpoints
|
||||||
? scenery.checkpoints.split(';').map((sub) => ({ checkpointName: sub, scheduledTrains: [] }))
|
? scenery.checkpoints.split(';').map((sub) => ({ checkpointName: sub, scheduledTrains: [] }))
|
||||||
: [],
|
: [],
|
||||||
},
|
},
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
connectToWebsocket() {
|
connectToWebsocket() {
|
||||||
const socket = io(URLs.stacjownikAPI, {
|
const socket = io(URLs.stacjownikAPI, {
|
||||||
transports: ['websocket', 'polling'],
|
// transports: ['websocket', 'polling'],
|
||||||
rememberUpgrade: true,
|
rememberUpgrade: true,
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
timeout: 2000,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('connect_error', (err) => {
|
socket.on('connect_error', (err) => {
|
||||||
@@ -374,8 +380,9 @@ export const useStore = defineStore('store', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('FETCH_DATA', {}, (data: APIData) => {
|
socket.emit('FETCH_DATA', {}, (data: APIData) => {
|
||||||
this.apiData = data;
|
|
||||||
this.dataStatuses.connection = DataStatus.Loaded;
|
this.dataStatuses.connection = DataStatus.Loaded;
|
||||||
|
|
||||||
|
this.apiData = data;
|
||||||
this.setOnlineData();
|
this.setOnlineData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export interface StationJSONData {
|
|||||||
url: string;
|
url: string;
|
||||||
lines: string;
|
lines: string;
|
||||||
project: string;
|
project: string;
|
||||||
|
projectUrl: string;
|
||||||
|
|
||||||
reqLevel: number;
|
reqLevel: number;
|
||||||
|
|
||||||
@@ -69,8 +70,9 @@ export interface StationJSONData {
|
|||||||
SUP: boolean;
|
SUP: boolean;
|
||||||
|
|
||||||
routes: string;
|
routes: string;
|
||||||
|
|
||||||
checkpoints: string | null;
|
checkpoints: string | null;
|
||||||
authors?: string;
|
authors?: string;
|
||||||
|
|
||||||
availability: Availability;
|
availability: Availability;
|
||||||
}
|
}
|
||||||
+58
-28
@@ -1,28 +1,58 @@
|
|||||||
.badge {
|
.badge {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
background: #585858;
|
background: #585858;
|
||||||
|
|
||||||
margin: 0.25em;
|
margin: 0.25em;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-none {
|
&-none {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
background: firebrick;
|
background: firebrick;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
@include smallScreen() {
|
@include smallScreen() {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.level-badge {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
&.driver {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 1.7em;
|
||||||
|
height: 1.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dispatcher {
|
||||||
|
border-radius: 0.25em;
|
||||||
|
|
||||||
|
width: 1.6em;
|
||||||
|
height: 1.6em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.region-badge {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&.eu {
|
||||||
|
background-color: forestgreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,19 +18,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 1rem;
|
width: 15px;
|
||||||
height: 1rem;
|
height: 15px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&-track {
|
&-track {
|
||||||
border-radius: 0.5em;
|
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-thumb {
|
&-thumb {
|
||||||
border-radius: 0.5em;
|
|
||||||
background-color: #666;
|
background-color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-corner {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@@ -47,7 +49,7 @@ body {
|
|||||||
|
|
||||||
&.no-scroll {
|
&.no-scroll {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
padding-right: 1rem;
|
padding-right: 15px;
|
||||||
|
|
||||||
@include smallScreen() {
|
@include smallScreen() {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{{ $t('app.offline') }}
|
{{ $t('app.offline') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Loading v-else-if="dataStatus == DataStatus.Initialized || dataStatus == DataStatus.Loading" />
|
<Loading v-else-if="dataStatus == DataStatus.Loading" />
|
||||||
|
|
||||||
<div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error">
|
<div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error">
|
||||||
{{ $t('app.error') }}
|
{{ $t('app.error') }}
|
||||||
@@ -111,7 +111,7 @@ export default defineComponent({
|
|||||||
statsCardOpen: false,
|
statsCardOpen: false,
|
||||||
currentOptionsActive: false,
|
currentOptionsActive: false,
|
||||||
|
|
||||||
dataStatus: DataStatus.Initialized,
|
dataStatus: DataStatus.Loading,
|
||||||
DataStatus,
|
DataStatus,
|
||||||
|
|
||||||
historyList: [] as DispatcherHistory[],
|
historyList: [] as DispatcherHistory[],
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
{{ $t('app.offline') }}
|
{{ $t('app.offline') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Loading v-else-if="dataStatus == DataStatus.Initialized || dataStatus == DataStatus.Loading" />
|
<Loading v-else-if="dataStatus == DataStatus.Loading" />
|
||||||
|
|
||||||
<div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error">
|
<div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error">
|
||||||
{{ $t('app.error') }}
|
{{ $t('app.error') }}
|
||||||
@@ -105,7 +105,7 @@ export default defineComponent({
|
|||||||
timetableHistory: [] as TimetableHistory[],
|
timetableHistory: [] as TimetableHistory[],
|
||||||
journalTimetableFilters,
|
journalTimetableFilters,
|
||||||
|
|
||||||
dataStatus: DataStatus.Initialized,
|
dataStatus: DataStatus.Loading,
|
||||||
dataErrorMessage: '',
|
dataErrorMessage: '',
|
||||||
|
|
||||||
DataStatus,
|
DataStatus,
|
||||||
@@ -215,7 +215,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async fetchHistoryData() {
|
async fetchHistoryData() {
|
||||||
if(this.dataStatus == DataStatus.Loading) return;
|
// if(this.dataStatus == DataStatus.Loading) return;
|
||||||
|
|
||||||
const queries: string[] = [];
|
const queries: string[] = [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user