Compare commits

..

15 Commits

Author SHA1 Message Date
Spythere 69fa15c70a v1.14.1
v1.14.1
2023-04-13 19:25:30 +02:00
Spythere 9192067388 1.14.1 2023-04-13 19:21:36 +02:00
Spythere 2b41e5b857 hotfix 2023-04-13 19:21:24 +02:00
Spythere 674680ff14 1.14: hotfixy
1.14 hotfixy
2023-04-13 19:15:38 +02:00
Spythere 475bd2ff10 przeniesienie skrótów do widoku scenerii 2023-04-13 19:11:44 +02:00
Spythere 074d1eb155 Hotfix tłumaczeń 2023-04-13 18:50:00 +02:00
Spythere 378393de89 Wersja 1.14.0
Wersja 1.14.0
2023-04-13 15:45:39 +02:00
Spythere 03e61083a7 tłumaczenie stopki 2023-04-13 15:37:34 +02:00
Spythere 0b746fce8c hotfix headera 2023-04-13 15:32:41 +02:00
Spythere 5883e710be bump wersji: 1.14 2023-04-13 15:26:22 +02:00
Spythere 3d0695a17b Poprawki w headerze i stopce 2023-04-13 15:25:39 +02:00
Spythere 4adb76eeb0 feature: podpisy status indicatorów dla RJ 2023-04-11 00:33:14 +02:00
Spythere 4c41076519 feature: skrót posterunku w tabelce 2023-04-09 01:37:11 +02:00
Spythere 77f61d17fd hotfix: wygląd badge'a 2023-04-09 00:19:53 +02:00
Spythere 032a84cbcf feature: historia zmian w zestawieniu pociągów 2023-03-20 22:39:23 +01:00
28 changed files with 441 additions and 385 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.13.0", "version": "1.14.1",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+5
View File
@@ -91,6 +91,11 @@ footer.app_footer {
max-width: 100%; max-width: 100%;
padding: 0.5em; padding: 0.5em;
img {
width: 1.1em;
vertical-align: text-bottom;
}
z-index: 10; z-index: 10;
background: #111; background: #111;
+2
View File
@@ -23,6 +23,8 @@
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a> <a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
{{ new Date().getUTCFullYear() }} | {{ new Date().getUTCFullYear() }} |
<a :href="releaseURL" target="_blank">v{{ VERSION }}{{ isOnProductionHost ? '' : 'dev' }}</a> <a :href="releaseURL" target="_blank">v{{ VERSION }}{{ isOnProductionHost ? '' : 'dev' }}</a>
<br />
<a href="https://discord.gg/x2mpNN3svk"><img :src="getIcon('discord', 'png')" alt="">&nbsp;<b>{{ $t('footer.discord') }}</b></a>
<div style="display: none">&int; ukryta taktyczna całka do programowania w HTMLu</div> <div style="display: none">&int; ukryta taktyczna całka do programowania w HTMLu</div>
</footer> </footer>
+27 -65
View File
@@ -6,16 +6,6 @@
<img :src="getIcon('pl')" alt="icon-pl" @click="changeLang('en')" v-if="currentLang == 'pl'" /> <img :src="getIcon('pl')" alt="icon-pl" @click="changeLang('en')" v-if="currentLang == 'pl'" />
<img :src="getIcon('en', 'jpg')" alt="icon-en" @click="changeLang('pl')" v-else /> <img :src="getIcon('en', 'jpg')" alt="icon-en" @click="changeLang('pl')" v-else />
</span> </span>
<span class="icons-bottom">
<a href="https://www.paypal.com/paypalme/spythere" target="_blank">
<img :src="getIcon('dollar')" alt="icon paypal" />
</a>
<a href="https://discord.gg/x2mpNN3svk" target="_blank">
<img :src="getIcon('discord', 'png')" alt="icon discord" />
</a>
</span>
</div> </div>
<div class="header_body"> <div class="header_body">
@@ -33,6 +23,12 @@
<div class="info_counter"> <div class="info_counter">
<img :src="getIcon('dispatcher')" alt="icon dispatcher" /> <img :src="getIcon('dispatcher')" alt="icon dispatcher" />
<span class="text--primary">{{ onlineDispatchersCount }}</span> <span class="text--primary">{{ onlineDispatchersCount }}</span>
<!-- <span class="g-tooltip">
<b class="text--primary">{{ factorU }}U</b>
<div class="content">Test</div>
</span> -->
<span class="text--grayed"> / </span> <span class="text--grayed"> / </span>
<span class="text--primary">{{ onlineTrainsCount }}</span> <span class="text--primary">{{ onlineTrainsCount }}</span>
<img :src="getIcon('train')" alt="icon train" /> <img :src="getIcon('train')" alt="icon train" />
@@ -98,11 +94,17 @@ export default defineComponent({
onlineTrainsCount() { onlineTrainsCount() {
return this.store.trainList.filter((train) => train.online).length; return this.store.trainList.filter((train) => train.online).length;
}, },
onlineDispatchersCount() { onlineDispatchersCount() {
return this.store.stationList.filter( return this.store.stationList.filter(
(station) => station.onlineInfo && station.onlineInfo.region == this.store.region.id (station) => station.onlineInfo && station.onlineInfo.region == this.store.region.id
).length; ).length;
}, },
factorU() {
return this.onlineDispatchersCount == 0 ? '-' : (this.onlineTrainsCount / this.onlineDispatchersCount).toFixed(2);
},
computedRegions() { computedRegions() {
return options.regions.map((region) => { return options.regions.map((region) => {
const regionStationCount = const regionStationCount =
@@ -135,22 +137,20 @@ export default defineComponent({
.header { .header {
&_body { &_body {
max-width: 21em;
position: relative; position: relative;
max-width: 20em;
@include smallScreen {
max-width: 18em;
}
} }
&_container { &_container {
display: flex; display: flex;
justify-content: center; justify-content: center;
position: relative;
width: 1350px;
padding: 0.5em 0.3em 0 0.3em;
border-radius: 0 0 1em 1em; border-radius: 0 0 1em 1em;
@include smallScreen {
position: relative;
margin-top: 0.5em;
}
} }
&_brand { &_brand {
@@ -158,6 +158,7 @@ export default defineComponent({
img { img {
width: 100%; width: 100%;
margin: 0 auto; margin: 0 auto;
} }
} }
@@ -165,9 +166,7 @@ export default defineComponent({
&_info { &_info {
display: grid; display: grid;
grid-template-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
max-width: 100%; font-size: 1.15em;
font-size: 1.2em;
} }
&_links { &_links {
@@ -184,57 +183,20 @@ export default defineComponent({
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
height: 100%;
display: flex; padding: 0.5em;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
padding: 0.5em 0.5em;
@include smallScreen() { @include smallScreen {
right: auto; transform: translateX(85%);
left: 0.75em;
padding: 0;
align-items: center;
} }
} }
} }
// ICONS // ICONS
.icons { .icons-top {
position: relative; img {
width: 2.5em;
&-top { cursor: pointer;
img {
width: 2.5em;
cursor: pointer;
}
margin-bottom: 0.5em;
}
&-bottom {
display: flex;
a {
margin-left: 0.6em;
user-select: none;
}
img {
width: 1.9em;
}
@include smallScreen() {
flex-direction: column;
a {
margin: 0.25em 0;
}
}
} }
} }
+12 -15
View File
@@ -164,7 +164,7 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { DataStatus } from '../../scripts/enums/DataStatus'; import { DataStatus } from '../../scripts/enums/DataStatus';
import { useStore } from '../../store/store'; import { useStore } from '../../store/store';
import { StoreState } from '../../store/storeTypes'; import { StoreState } from '../../scripts/interfaces/store/storeTypes';
export default defineComponent({ export default defineComponent({
data() { data() {
@@ -303,9 +303,11 @@ export default defineComponent({
.status-indicator { .status-indicator {
position: absolute; position: absolute;
left: 110%;
bottom: 0; bottom: 0;
right: 0;
z-index: 100; z-index: 100;
transform: translateX(1.5em);
} }
.indicator { .indicator {
@@ -330,7 +332,7 @@ export default defineComponent({
background-color: #171717; background-color: #171717;
border-radius: 0.75em; border-radius: 0.75em;
min-width: 13em; width: 13em;
text-align: center; text-align: center;
overflow: none; overflow: none;
@@ -354,22 +356,16 @@ export default defineComponent({
} }
@include midScreen() { @include midScreen() {
left: 50%; left: auto;
top: 100%; right: 200%;
transform: translate(-50%, 0);
margin-left: 0;
margin-top: 0.75em;
&::before { &::before {
border-left: 10px solid transparent;
border-right: 10px solid transparent; border-right: 10px solid transparent;
border-bottom: 10px solid #171717; border-left: 12px solid #171717;
right: 0;
left: auto;
top: 0; transform: translate(100%, -50%);
left: 50%;
transform: translate(-50%, -100%);
} }
} }
@@ -379,3 +375,4 @@ export default defineComponent({
} }
} }
</style> </style>
+6 -30
View File
@@ -3,6 +3,10 @@
<div class="select-box_content"> <div class="select-box_content">
<button class="selected" @click="toggleBox"> <button class="selected" @click="toggleBox">
<span>{{ computedSelectedItem.selectedValue || computedSelectedItem.value }}</span> <span>{{ computedSelectedItem.selectedValue || computedSelectedItem.value }}</span>
<div class="arrow">
<img :src="listOpen ? getIcon('arrow-asc') : getIcon('arrow-desc')" alt="arrow-icon" />
</div>
</button> </button>
<ul class="options" :ref="(el) => (listRef = el as Element)"> <ul class="options" :ref="(el) => (listRef = el as Element)">
@@ -21,10 +25,6 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="arrow">
<img :src="listOpen ? getIcon('arrow-asc') : getIcon('arrow-desc')" alt="arrow-icon" />
</div>
</div> </div>
</template> </template>
@@ -129,46 +129,22 @@ export default defineComponent({
} }
.select-box { .select-box {
position: relative; display: flex;
width: auto; align-items: center;
} }
.arrow { .arrow {
position: absolute;
top: 50%;
right: 0;
padding: 0;
img { img {
vertical-align: middle; vertical-align: middle;
width: 1.35em; width: 1.35em;
} }
transform: translateY(-50%);
pointer-events: none;
} }
button.selected { button.selected {
background-color: transparent;
color: paleturquoise; color: paleturquoise;
font-size: 1em;
font-weight: bold; font-weight: bold;
padding: 0.1em 0.5em; padding: 0.1em 0.5em;
margin-right: 2em;
display: flex;
width: 100%;
cursor: pointer;
border: none;
outline: none;
text-align: left;
&:focus { &:focus {
background-color: #262626; background-color: #262626;
@@ -1,7 +1,7 @@
<template> <template>
<transition-group class="journal-list" tag="ul" name="list-anim"> <transition-group class="journal-list" tag="ul" name="list-anim">
<li <li
v-for="{ timetable, sceneryList, ...item } in computedTimetableHistory" v-for="{ timetable, sceneryList, stockHistoryComp, ...item } in computedTimetableHistory"
class="journal_item" class="journal_item"
:key="timetable.id" :key="timetable.id"
@click="item.showExtra.value = !item.showExtra.value" @click="item.showExtra.value = !item.showExtra.value"
@@ -129,24 +129,58 @@
<img :src="getIcon(`arrow-${item.showExtra.value ? 'asc' : 'desc'}`)" alt="Arrow" /> <img :src="getIcon(`arrow-${item.showExtra.value ? 'asc' : 'desc'}`)" alt="Arrow" />
</button> </button>
<div class="info-extended" v-if="timetable.stockString && item.showExtra.value"> <!-- Dodatkowe informacje -->
<div class="info-extended" v-if="timetable.stockString && timetable.stockMass && item.showExtra.value">
<hr /> <hr />
<div>
<span class="badge info-badge"> <div class="stock-specs">
<span class="badge specs-badge">
<span>{{ $t('journal.stock-max-speed') }}</span> <span>{{ $t('journal.stock-max-speed') }}</span>
<span>{{ timetable.maxSpeed }}km/h</span> <span>{{ timetable.maxSpeed }}km/h</span>
</span> </span>
<span class="badge info-badge"> <span class="badge specs-badge">
<span>{{ $t('journal.stock-length') }}</span> <span>{{ $t('journal.stock-length') }}</span>
<span>{{ timetable.stockLength }}m</span> <span>
{{
item.currentHistoryIndex.value == 0
? timetable.stockLength
: stockHistoryComp[item.currentHistoryIndex.value].stockLength || timetable.stockLength
}}m
</span>
</span> </span>
<span class="badge info-badge"> <span class="badge specs-badge">
<span>{{ $t('journal.stock-mass') }}</span> <span>{{ $t('journal.stock-mass') }}</span>
<span>{{ Math.floor(timetable.stockMass! / 1000) }}t</span> <span>
{{
Math.floor(
(item.currentHistoryIndex.value == 0
? timetable.stockMass!
: stockHistoryComp[item.currentHistoryIndex.value].stockMass || timetable.stockMass) / 1000
)
}}t
</span>
</span> </span>
</div> </div>
<div class="stock-history" v-if="stockHistoryComp.length > 1">
<button
class="btn--action"
v-for="(sh, i) in stockHistoryComp"
:data-checked="i == item.currentHistoryIndex.value"
@click.stop="item.currentHistoryIndex.value = i"
>
{{ sh.updatedAt }}
</button>
</div>
<ul class="stock-list"> <ul class="stock-list">
<li v-for="(car, i) in timetable.stockString.split(';')" :key="i"> <li
v-for="(car, i) in (item.currentHistoryIndex.value == 0
? timetable.stockString
: stockHistoryComp[item.currentHistoryIndex.value].stockString
).split(';')"
:key="i"
>
<img <img
@error="onImageError" @error="onImageError"
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${car.split(':')[0]}.png`" :src="`https://rj.td2.info.pl/dist/img/thumbnails/${car.split(':')[0]}.png`"
@@ -168,7 +202,6 @@ import imageMixin from '../../mixins/imageMixin';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import { TimetableHistory } from '../../scripts/interfaces/api/TimetablesAPIData'; import { TimetableHistory } from '../../scripts/interfaces/api/TimetablesAPIData';
import { TimetableStop } from '../../scripts/interfaces/api/TrainAPIData';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -185,7 +218,24 @@ export default defineComponent({
return this.timetableHistory.map((timetable) => ({ return this.timetableHistory.map((timetable) => ({
timetable, timetable,
sceneryList: this.getSceneryList(timetable), sceneryList: this.getSceneryList(timetable),
stockHistoryComp: timetable.stockHistory
.slice()
.reverse()
.map((h) => {
const historyData = h.split('@');
return {
updatedAt: new Date(Number(historyData[0])).toLocaleTimeString(this.$i18n.locale, {
hour: '2-digit',
minute: '2-digit',
}),
stockString: historyData[1],
stockMass: Number(historyData[2]) || undefined,
stockLength: Number(historyData[3]) || undefined,
};
}),
showExtra: ref(false), showExtra: ref(false),
currentHistoryIndex: ref(0),
})); }));
}, },
}, },
@@ -308,6 +358,38 @@ ul.stock-list {
color: #aaa; color: #aaa;
font-size: 0.9em; font-size: 0.9em;
} }
li > img {
vertical-align: text-bottom;
max-height: 60px;
}
}
.stock-specs {
display: flex;
flex-wrap: wrap;
gap: 0.5em;
margin-top: 0.5em;
.specs-badge {
margin: 0;
span:last-child {
color: black;
background-color: $accentCol;
}
}
}
.stock-history {
display: flex;
flex-wrap: wrap;
gap: 0.5em;
margin-top: 1em;
button[data-checked='true'] {
color: $accentCol;
}
} }
.scenery-list { .scenery-list {
@@ -328,13 +410,6 @@ ul.stock-list {
} }
} }
.info-badge {
span:last-child {
color: black;
background-color: $accentCol;
}
}
@include smallScreen { @include smallScreen {
.info-general { .info-general {
flex-direction: column; flex-direction: column;
@@ -351,5 +426,13 @@ ul.stock-list {
.btn--show { .btn--show {
margin: 1em auto 0 auto; margin: 1em auto 0 auto;
} }
.stock-specs {
justify-content: center;
}
.stock-history {
justify-content: center;
}
} }
</style> </style>
+9 -3
View File
@@ -4,6 +4,8 @@
{{ station.name }} {{ station.name }}
</a> </a>
<div class="scenery-abbrev">{{ $t('scenery.abbrev') }} <b>{{ station.generalInfo?.abbr }}</b></div>
<div class="scenery-hash" v-if="station.onlineInfo?.hash">#{{ station.onlineInfo.hash }}</div> <div class="scenery-hash" v-if="station.onlineInfo?.hash">#{{ station.onlineInfo.hash }}</div>
</section> </section>
</template> </template>
@@ -28,16 +30,20 @@ export default defineComponent({
.scenery-name { .scenery-name {
font-weight: bold; font-weight: bold;
position: relative;
font-size: 3em; font-size: 3em;
text-transform: uppercase; text-transform: uppercase;
} }
.scenery-abbrev {
font-size: 1.3em;
color: #aaa;
}
.scenery-hash { .scenery-hash {
margin-top: 0.5em;
color: #aaa; color: #aaa;
font-size: 1.2em; font-size: 1.2em;
} }
</style> </style>
+2 -1
View File
@@ -30,8 +30,9 @@
style="color: salmon; text-decoration: underline; font-weight: bold" style="color: salmon; text-decoration: underline; font-weight: bold"
:href="station.generalInfo.projectUrl" :href="station.generalInfo.projectUrl"
target="_blank" target="_blank"
>{{ station.generalInfo.project }}</a
> >
{{ station.generalInfo.project }}
</a>
</span> </span>
</div> </div>
@@ -1,47 +1,19 @@
<template> <template>
<div class="general-status"> <div class="general-status">
<span :class="scheduledTrain.stopStatus"> <span :class="computedScheduledTrain.stopStatus" :title="computedScheduledTrain.stopStatusDescription">
<span v-if="scheduledTrain.stopStatus == 'arriving'"> {{ computedScheduledTrain.stopStatusIndicator }}
<span v-if="scheduledTrain.prevDepartureLine">({{ scheduledTrain.prevDepartureLine }})</span>
{{ scheduledTrain.prevStationName }}
&gt;<span v-if="scheduledTrain.nextArrivalLine"> ({{ scheduledTrain.nextArrivalLine }}) </span>
{{ scheduledTrain.nextStationName || '---' }}
</span>
<span v-else-if="scheduledTrain.stopStatus == 'departed'">
&gt;&gt; <span v-if="scheduledTrain.nextArrivalLine"> ({{ scheduledTrain.nextArrivalLine }}) </span>
{{ scheduledTrain.nextStationName }}
</span>
<span v-else-if="scheduledTrain.stopStatus == 'departed-away'">
&gt;&gt;&gt;
<span v-if="scheduledTrain.nextArrivalLine"> ({{ scheduledTrain.nextArrivalLine }}) </span>
{{ scheduledTrain.nextStationName }}
</span>
<span v-else-if="scheduledTrain.stopStatus == 'online'">
&gt;
<span v-if="scheduledTrain.nextArrivalLine">
({{ scheduledTrain.nextArrivalLine }}) {{ scheduledTrain.nextStationName }}
</span>
<span v-else-if="!scheduledTrain.nextStationName">{{ $t('timetables.end') }}</span>
<span v-else>{{ scheduledTrain.nextStationName }}</span>
</span>
<span v-else-if="scheduledTrain.stopStatus == 'stopped'">
&gt;
<span v-if="scheduledTrain.nextArrivalLine"> ({{ scheduledTrain.nextArrivalLine }}) </span>
{{ scheduledTrain.nextStationName }}
</span>
<span v-else-if="scheduledTrain.stopStatus == 'terminated'">X {{ $t('timetables.terminated') }}</span>
</span> </span>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import ScheduledTrain from '../../scripts/interfaces/ScheduledTrain'; import { ScheduledTrain, StopStatus } from '../../scripts/interfaces/ScheduledTrain';
interface ScheduledTrainComp extends ScheduledTrain {
stopStatusIndicator: string;
stopStatusDescription: string;
}
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -50,6 +22,58 @@ export default defineComponent({
required: true, required: true,
}, },
}, },
computed: {
computedScheduledTrain(): ScheduledTrainComp {
const { prevDepartureLine, prevStationName, stopStatus, nextArrivalLine, nextStationName } = this.scheduledTrain;
const prevDepartureIndicator = prevDepartureLine ? `(${prevDepartureLine}) ${prevStationName}` : '---';
const nextArrivalIndicator = nextArrivalLine ? `(${nextArrivalLine}) ${nextStationName}` : '---';
let stopStatusDescription = '',
stopStatusIndicator = '';
switch (stopStatus) {
case StopStatus.arriving:
stopStatusIndicator = `${this.$t('timetables.from')}: ${prevDepartureIndicator}`;
stopStatusDescription = this.$t('timetables.desc-arriving', { prevStationName, prevDepartureLine });
break;
case StopStatus.online:
case StopStatus.stopped:
stopStatusIndicator = nextArrivalLine
? `${this.$t('timetables.to')}: ${nextArrivalIndicator}`
: `${this.$t('timetables.desc-end')}`;
stopStatusDescription = nextArrivalLine
? this.$t(`timetables.desc-${stopStatus}`, { nextStationName, nextArrivalLine })
: '';
break;
case StopStatus.departed:
stopStatusIndicator = `${this.$t('timetables.to')}: ${nextArrivalIndicator}`;
stopStatusDescription = this.$t('timetables.desc-departed', { nextStationName, nextArrivalLine });
break;
case StopStatus['departed-away']:
stopStatusIndicator = `${this.$t('timetables.to')}: ${nextArrivalIndicator}`;
stopStatusDescription = this.$t('timetables.desc-departed-away', { nextStationName, nextArrivalLine });
break;
case StopStatus.terminated:
stopStatusIndicator = `X ${this.$t('timetables.desc-terminated')}`;
stopStatusDescription = this.$t('timetables.desc-terminated');
break;
default:
break;
}
return {
...this.scheduledTrain,
stopStatusDescription,
stopStatusIndicator,
};
},
},
}); });
</script> </script>
@@ -86,3 +110,4 @@ export default defineComponent({
} }
} }
</style> </style>
@@ -50,9 +50,6 @@ export default defineComponent({
handleDbClick(e: Event) { handleDbClick(e: Event) {
e.preventDefault(); e.preventDefault();
const lastClicked = this.filterStore.lastClickedFilterId == this.option.id;
console.log(this.filterStore.lastClickedFilterId);
this.filterStore.lastClickedFilterId = this.option.id; this.filterStore.lastClickedFilterId = this.option.id;
this.option.value = true; this.option.value = true;
@@ -96,51 +93,8 @@ button {
} }
&[data-selected='true'] { &[data-selected='true'] {
// &.reality {
// background-color: $realityCol;
// box-shadow: 0 0 6px 1px $realityCol;
// }
// &.access {
// background-color: $accessCol;
// box-shadow: 0 0 6px 1px $accessCol;
// }
// &.control {
// background-color: $controlCol;
// box-shadow: 0 0 6px 1px $controlCol;
// }
// &.signals {
// background-color: $signalCol;
// box-shadow: 0 0 6px 1px $signalCol;
// }
// &.routes {
// background-color: $routesCol;
// box-shadow: 0 0 6px 1px $routesCol;
// }
// &.status {
// background-color: $statusCol;
// box-shadow: 0 0 6px 1px $statusCol;
// }
// &.save {
// background-color: $saveCol;
// box-shadow: 0 0 6px 1px $saveCol;
// }
// &.troll {
// background-color: firebrick;
// box-shadow: 0 0 6px 1px firebrick;
// }
// & {
background-color: forestgreen; background-color: forestgreen;
font-weight: bold; font-weight: bold;
// }
} }
} }
</style> </style>
@@ -128,7 +128,6 @@ import { useStore } from '../../store/store';
import ActionButton from '../Global/ActionButton.vue'; import ActionButton from '../Global/ActionButton.vue';
import FilterOption from './FilterOption.vue'; import FilterOption from './FilterOption.vue';
import { filterInitStates } from '../../store/constants/initFilterStates';
export default defineComponent({ export default defineComponent({
components: { ActionButton, FilterOption }, components: { ActionButton, FilterOption },
+14 -11
View File
@@ -8,26 +8,26 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<th v-for="(id, i) in headIds" :key="id" @click="() => changeSorter(i)"> <th v-for="(headerName, i) in headIds" :key="headerName" @click="changeSorter(headerName)">
<span class="header_wrapper"> <span class="header_wrapper">
<div v-html="$t(`sceneries.${id}`)"></div> <div v-html="$t(`sceneries.${headerName}`)"></div>
<img <img
class="sort-icon" class="sort-icon"
v-if="sorterActive.index == i" v-if="sorterActive.headerName == headerName"
:src="sorterActive.dir == 1 ? getIcon('arrow-asc') : getIcon('arrow-desc')" :src="sorterActive.dir == 1 ? getIcon('arrow-asc') : getIcon('arrow-desc')"
alt="sort icon" alt="sort icon"
/> />
</span> </span>
</th> </th>
<th v-for="(id, i) in headIconsIds" :key="id" @click="() => changeSorter(i + 7)"> <th v-for="(headerName, i) in headIconsIds" :key="headerName" @click="changeSorter(headerName)">
<span class="header_wrapper"> <span class="header_wrapper">
<img :src="getIcon(id)" :alt="id" :title="$t(`sceneries.${id}s`)" /> <img :src="getIcon(headerName)" :alt="headerName" :title="$t(`sceneries.${headerName}s`)" />
<img <img
class="sort-icon" class="sort-icon"
v-if="sorterActive.index == i + 7" v-if="sorterActive.headerName == headerName"
:src="sorterActive.dir == 1 ? getIcon('arrow-asc') : getIcon('arrow-desc')" :src="sorterActive.dir == 1 ? getIcon('arrow-asc') : getIcon('arrow-desc')"
alt="sort icon" alt="sort icon"
/> />
@@ -236,6 +236,7 @@ import Station from '../../scripts/interfaces/Station';
import { useStationFiltersStore } from '../../store/stationFiltersStore'; import { useStationFiltersStore } from '../../store/stationFiltersStore';
import { useStore } from '../../store/store'; import { useStore } from '../../store/store';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -249,8 +250,8 @@ export default defineComponent({
mixins: [styleMixin, dateMixin, stationInfoMixin, returnBtnMixin, imageMixin], mixins: [styleMixin, dateMixin, stationInfoMixin, returnBtnMixin, imageMixin],
data: () => ({ data: () => ({
headIds: ['station', 'min-lvl', 'status', 'dispatcher', 'dispatcher-lvl', 'routes', 'general'], headIconsIds,
headIconsIds: ['user', 'spawn', 'timetable'], headIds,
lastSelectedStationName: '', lastSelectedStationName: '',
}), }),
@@ -291,8 +292,10 @@ export default defineComponent({
window.open(url, '_blank'); window.open(url, '_blank');
}, },
changeSorter(i: number) { changeSorter(headerName: HeadIdsTypes) {
this.stationFiltersStore.changeSorter(i); if (headerName == 'general' || headerName == 'routes') return;
this.stationFiltersStore.changeSorter(headerName);
}, },
}, },
}); });
@@ -349,7 +352,7 @@ table {
position: sticky; position: sticky;
top: 0; top: 0;
min-width: 75px; min-width: 80px;
padding: 0.5em; padding: 0.5em;
background-color: $bgCol; background-color: $bgCol;
@@ -202,7 +202,6 @@ ul.stock-list {
img { img {
max-height: 60px; max-height: 60px;
max-width: 320px;
} }
} }
+19 -3
View File
@@ -15,6 +15,9 @@
"migration-confirm": "Roger that!", "migration-confirm": "Roger that!",
"offline": "App is in the offline mode!" "offline": "App is in the offline mode!"
}, },
"footer": {
"discord": "Stacjownik Discord server"
},
"update": { "update": {
"title": "New version of the app is available!", "title": "New version of the app is available!",
"paragraph1": "Enjoy the application and may the green signal be with you!", "paragraph1": "Enjoy the application and may the green signal be with you!",
@@ -214,7 +217,7 @@
"no-stations": "No stations to show here!", "no-stations": "No stations to show here!",
"scenery-search": "Search for scenery..." "scenery-search": "Search for scenery..."
}, },
"trains": { "trains": {
"no-trains": "No trains to show here!", "no-trains": "No trains to show here!",
"loading": "Loading train data...", "loading": "Loading train data...",
"offline": "Offline ride", "offline": "Offline ride",
@@ -284,7 +287,7 @@
"stock-info": "EXTRA INFO", "stock-info": "EXTRA INFO",
"stock-length": "Length", "stock-length": "Length",
"stock-mass": "Mass", "stock-mass": "Mass",
"stock-max-speed": "Maximum registered speed", "stock-max-speed": "Max. speed",
"load-data": "Load further data...", "load-data": "Load further data...",
@@ -328,6 +331,7 @@
"history-btn": "View the dispatcher history", "history-btn": "View the dispatcher history",
"info-btn": "Return to the scenery view", "info-btn": "Return to the scenery view",
"authors-title": "Scenery author | Scenery authors", "authors-title": "Scenery author | Scenery authors",
"abbrev": "Station symbol:",
"lines-title": "Real lines", "lines-title": "Real lines",
"project-title": "Project name", "project-title": "Project name",
"one-way-routes": "One way routes", "one-way-routes": "One way routes",
@@ -368,7 +372,19 @@
"end": "Timetable terminates here", "end": "Timetable terminates here",
"terminated": "Timetable terminated", "terminated": "Timetable terminated",
"begins": "BEGINS HERE", "begins": "BEGINS HERE",
"terminates": "TERMINATES\nHERE" "terminates": "TERMINATES\nHERE",
"from": "FROM",
"to": "TO",
"desc-arriving": "The train is not here yet. It's going to come from: {prevStationName} (szlak {prevDepartureLine})",
"desc-online": "The train is at the station. It's going to leave to: {nextStationName} (szlak {nextArrivalLine})",
"desc-stopped": "The train is at the station and is stopped. It's going to leave towards: {nextStationName} (szlak {nextArrivalLine})",
"desc-next-arrival": "Leaves towards: {nextStationName} (szlak {nextArrivalLine})",
"desc-departed": "The train is at the station and it's been departed. Leaves towards: {nextStationName} (szlak {nextArrivalLine})",
"desc-departed-away": "The train has been departed to: {nextStationName} (szlak {nextArrivalLine})",
"desc-end": "The train terminates here",
"desc-terminated": "The train has been terminated"
}, },
"history": { "history": {
"title": "TIMETABLE JOURNAL", "title": "TIMETABLE JOURNAL",
+20 -5
View File
@@ -15,7 +15,9 @@
"migration-confirm": "Przyjąłem!", "migration-confirm": "Przyjąłem!",
"offline": "Aplikacja w trybie offline!" "offline": "Aplikacja w trybie offline!"
}, },
"footer": {
"discord": "Serwer Discord Stacjownika"
},
"update": { "update": {
"title": "Nowa wersja Stacjownika jest dostępna!", "title": "Nowa wersja Stacjownika jest dostępna!",
"paragraph1": "Miłego korzystania z aplikacji i niech S2 będzie z wami!", "paragraph1": "Miłego korzystania z aplikacji i niech S2 będzie z wami!",
@@ -23,7 +25,6 @@
"confirm-button": "ZAKTUALIZUJ", "confirm-button": "ZAKTUALIZUJ",
"later-button": "PÓŹNIEJ" "later-button": "PÓŹNIEJ"
}, },
"data-status": { "data-status": {
"S1-offline": "<b>Sygnał S1</b> <br> Aplikacja działa w trybie offline!", "S1-offline": "<b>Sygnał S1</b> <br> Aplikacja działa w trybie offline!",
"S1a-connection": "<b>Sygnał S1a</b> <br> Błąd podczas próby połączenia się z API Stacjownika!", "S1a-connection": "<b>Sygnał S1a</b> <br> Błąd podczas próby połączenia się z API Stacjownika!",
@@ -136,7 +137,7 @@
}, },
"filters": { "filters": {
"desc": " &bull; Kliknięcie: zaznaczenie / odznaczenie filtru <br /> &bull; Podwójne kliknięcie: odznaczenie reszty filtrów z <b class='text--primary'>grupy</b> <br /> &bull; <span style='color: coral'>RESET</span>: zresetowanie filtrów z <b class='text--primary'>grupy</b>", "desc": " &bull; Kliknięcie: zaznaczenie / odznaczenie filtru <br /> &bull; Podwójne kliknięcie: odznaczenie reszty filtrów z <b class='text--primary'>grupy</b> <br /> &bull; <span style='color: coral'>RESET</span>: zresetowanie filtrów z <b class='text--primary'>grupy</b>",
"sections": { "sections": {
"reality": "FIKCYJNOŚĆ SCENERII", "reality": "FIKCYJNOŚĆ SCENERII",
"package-access": "DOSTĘPNOŚĆ W PACZCE", "package-access": "DOSTĘPNOŚĆ W PACZCE",
@@ -207,6 +208,7 @@
}, },
"sceneries": { "sceneries": {
"station": "Stacja", "station": "Stacja",
"abbr": "Skrót\nposterunku",
"min-lvl": "Min. poziom\ndyżurnego", "min-lvl": "Min. poziom\ndyżurnego",
"status": "Status", "status": "Status",
"dispatcher": "Dyżurny", "dispatcher": "Dyżurny",
@@ -290,7 +292,7 @@
"stock-info": "DODATKOWE INFORMACJE", "stock-info": "DODATKOWE INFORMACJE",
"stock-length": "Długość", "stock-length": "Długość",
"stock-mass": "Masa", "stock-mass": "Masa",
"stock-max-speed": "Maks. zarejestrowana prędkość", "stock-max-speed": "Prędkość maks.",
"load-data": "Pobierz dalszą historię...", "load-data": "Pobierz dalszą historię...",
@@ -334,6 +336,7 @@
"history-btn": "Przejdź do widoku historii dyżurnych ruchu", "history-btn": "Przejdź do widoku historii dyżurnych ruchu",
"info-btn": "Wróć do widoku scenerii", "info-btn": "Wróć do widoku scenerii",
"authors-title": "Autor scenerii | Autorzy scenerii", "authors-title": "Autor scenerii | Autorzy scenerii",
"abbrev": "Skrót posterunku:",
"lines-title": "Rzeczywiste linie", "lines-title": "Rzeczywiste linie",
"project-title": "Projekt", "project-title": "Projekt",
"one-way-routes": "Szlaki jednotorowe", "one-way-routes": "Szlaki jednotorowe",
@@ -374,7 +377,19 @@
"end": "Koniec rozkładu jazdy", "end": "Koniec rozkładu jazdy",
"terminated": "Rozkład jazdy zakończony", "terminated": "Rozkład jazdy zakończony",
"begins": "ROZPOCZYNA\nBIEG", "begins": "ROZPOCZYNA\nBIEG",
"terminates": "KOŃCZY BIEG" "terminates": "KOŃCZY BIEG",
"from": "Z",
"to": "DO",
"desc-arriving": "Pociągu nie ma jeszcze na tej scenerii. Przyjedzie z: {prevStationName} (szlak {prevDepartureLine})",
"desc-online": "Pociąg jest na tej scenerii. Odjedzie do: {nextStationName} (szlak {nextArrivalLine})",
"desc-stopped": "Pociąg jest na tej scenerii i odbywa postój. Odjedzie do: {nextStationName} (szlak {nextArrivalLine})",
"desc-next-arrival": "Odjeżdża do: {nextStationName} (szlak {nextArrivalLine})",
"desc-departed": "Pociąg jest na tej scenerii i został odprawiony. Odjeżdża do: {nextStationName} (szlak {nextArrivalLine})",
"desc-departed-away": "Pociąg został odprawiony i odjechał do: {nextStationName} (szlak {nextArrivalLine})",
"desc-end": "Pociąg kończy bieg",
"desc-terminated": "Pociąg skończył bieg"
}, },
"history": { "history": {
"title": "DZIENNIK ROZKŁADÓW JAZDY" "title": "DZIENNIK ROZKŁADÓW JAZDY"
+13
View File
@@ -0,0 +1,13 @@
export const headIds = [
'station',
'min-lvl',
'status',
'dispatcher',
'dispatcher-lvl',
'routes',
'general',
] as const;
export const headIconsIds = ['user', 'spawn', 'timetable'] as const;
export type HeadIdsTypes = typeof headIds[number] | typeof headIconsIds[number];
+34 -25
View File
@@ -1,32 +1,41 @@
import TrainStop from "./TrainStop"; import TrainStop from './TrainStop';
export default interface ScheduledTrain { export enum StopStatus {
trainId: string; 'arriving' = 'arriving',
trainNo: number; 'departed' = 'departed',
'departed-away' = 'departed-away',
driverName: string; 'online' = 'online',
driverId: number; 'stopped' = 'stopped',
currentStationName: string; 'terminated' = 'terminated',
currentStationHash: string; }
category: string;
stopInfo: TrainStop;
terminatesAt: string; export interface ScheduledTrain {
beginsAt: string; trainId: string;
trainNo: number;
prevStationName: string; driverName: string;
nextStationName: string; driverId: number;
currentStationName: string;
currentStationHash: string;
category: string;
stopInfo: TrainStop;
arrivingLine: string | null; terminatesAt: string;
departureLine: string | null; beginsAt: string;
prevDepartureLine: string | null; prevStationName: string;
nextArrivalLine: string | null; nextStationName: string;
signal: string; arrivingLine: string | null;
connectedTrack: string; departureLine: string | null;
stopLabel: string; prevDepartureLine: string | null;
stopStatus: string; nextArrivalLine: string | null;
stopStatusID: number;
} signal: string;
connectedTrack: string;
stopLabel: string;
stopStatus: StopStatus;
stopStatusID: number;
}
+5 -3
View File
@@ -1,5 +1,5 @@
import { Availability } from '../../store/storeTypes'; import { Availability } from './store/storeTypes';
import ScheduledTrain from './ScheduledTrain'; import {ScheduledTrain} from './ScheduledTrain';
import StationRoutes from './StationRoutes'; import StationRoutes from './StationRoutes';
export default interface Station { export default interface Station {
@@ -8,9 +8,11 @@ export default interface Station {
generalInfo?: { generalInfo?: {
name: string; name: string;
url: string; url: string;
abbr: string;
reqLevel: number; reqLevel: number;
// supportersOnly: boolean; // supportersOnly: boolean;
lines: string; lines: string;
project: string; project: string;
@@ -38,6 +38,8 @@ export interface TimetableHistory {
stopsString?: string; stopsString?: string;
stockString?: string; stockString?: string;
stockHistory: string[];
stockMass?: number; stockMass?: number;
stockLength?: number; stockLength?: number;
maxSpeed?: number; maxSpeed?: number;
@@ -1,78 +1,79 @@
import { Socket } from 'socket.io-client'; import { Socket } from 'socket.io-client';
import { DataStatus } from '../scripts/enums/DataStatus'; import { DataStatus } from '../../enums/DataStatus';
import StationAPIData from '../scripts/interfaces/api/StationAPIData'; import StationAPIData from '../api/StationAPIData';
import { TrainAPIData } from '../scripts/interfaces/api/TrainAPIData'; import { TrainAPIData } from '../api/TrainAPIData';
import Station from '../scripts/interfaces/Station'; import Station from '../Station';
import Train from '../scripts/interfaces/Train'; import Train from '../Train';
import { DispatcherStatsAPIData } from '../scripts/interfaces/api/DispatcherStatsAPIData'; import { DispatcherStatsAPIData } from '../api/DispatcherStatsAPIData';
import { DriverStatsAPIData } from '../scripts/interfaces/api/DriverStatsAPIData'; import { DriverStatsAPIData } from '../api/DriverStatsAPIData';
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault'; export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
export interface StoreState { export interface StoreState {
stationList: Station[]; stationList: Station[];
trainList: Train[]; trainList: Train[];
apiData: APIData; apiData: APIData;
lastDispatcherStatuses: { hash: string; statusTimestamp: number; statusID: string }[]; lastDispatcherStatuses: { hash: string; statusTimestamp: number; statusID: string }[];
sceneryData: any[][]; sceneryData: any[][];
region: { id: string; value: string }; region: { id: string; value: string };
trainCount: number; trainCount: number;
stationCount: number; stationCount: number;
webSocket?: Socket; webSocket?: Socket;
isOffline: boolean; isOffline: boolean;
dispatcherStatsName: string; dispatcherStatsName: string;
dispatcherStatsData?: DispatcherStatsAPIData; dispatcherStatsData?: DispatcherStatsAPIData;
driverStatsName: string; driverStatsName: string;
driverStatsData?: DriverStatsAPIData; driverStatsData?: DriverStatsAPIData;
driverStatsStatus: DataStatus; driverStatsStatus: DataStatus;
chosenModalTrainId?: string; chosenModalTrainId?: string;
currentStatsTab: 'daily' | 'driver'; currentStatsTab: 'daily' | 'driver';
dataStatuses: { dataStatuses: {
connection: DataStatus; connection: DataStatus;
sceneries: DataStatus; sceneries: DataStatus;
timetables: DataStatus; timetables: DataStatus;
dispatchers: DataStatus; dispatchers: DataStatus;
trains: DataStatus; trains: DataStatus;
}; };
listenerLaunched: boolean; listenerLaunched: boolean;
blockScroll: boolean; blockScroll: boolean;
} }
export interface APIData { export interface APIData {
stations?: StationAPIData[]; stations?: StationAPIData[];
dispatchers?: string[][]; dispatchers?: string[][];
trains?: TrainAPIData[]; trains?: TrainAPIData[];
connectedSocketCount: number; connectedSocketCount: number;
} }
export interface StationJSONData { export interface StationJSONData {
name: string; name: string;
url: string; abbr: string;
lines: string; url: string;
project: string; lines: string;
projectUrl: string; project: string;
projectUrl: string;
reqLevel: number;
reqLevel: number;
signalType: string;
controlType: string; signalType: string;
controlType: string;
SUP: boolean;
SUP: boolean;
routes: string;
routes: string;
checkpoints: string | null;
authors?: string; checkpoints: string | null;
authors?: string;
availability: Availability;
} availability: Availability;
}
+1 -1
View File
@@ -1,7 +1,7 @@
export const URLs = { export const URLs = {
stacjownikAPI: stacjownikAPI:
import.meta.env.VITE_APP_API_DEV == 1 && !import.meta.env.PROD import.meta.env.VITE_APP_API_DEV == 1 && !import.meta.env.PROD
? 'http://localhost:3000' ? 'http://localhost:3001'
: 'https://spythere.pl', : 'https://spythere.pl',
stacjownikAPIDev: 'localhost:3000', stacjownikAPIDev: 'localhost:3000',
}; };
+10 -11
View File
@@ -1,4 +1,4 @@
import ScheduledTrain from '../interfaces/ScheduledTrain'; import { ScheduledTrain, StopStatus } from '../interfaces/ScheduledTrain';
import Train from '../interfaces/Train'; import Train from '../interfaces/Train';
import TrainStop from '../interfaces/TrainStop'; import TrainStop from '../interfaces/TrainStop';
@@ -74,32 +74,32 @@ export const parseSpawns = (spawnString: string) => {
export const getTimestamp = (date: string | null): number => (date ? new Date(date).getTime() : 0); export const getTimestamp = (date: string | null): number => (date ? new Date(date).getTime() : 0);
export const getTrainStopStatus = (stopInfo: TrainStop, currentStationName: string, stationName: string) => { export const getTrainStopStatus = (stopInfo: TrainStop, currentStationName: string, stationName: string) => {
let stopStatus = '', let stopStatus = StopStatus['arriving'],
stopLabel = '', stopLabel = '',
stopStatusID = -1; stopStatusID = -1;
if (stopInfo.terminatesHere && stopInfo.confirmed) { if (stopInfo.terminatesHere && stopInfo.confirmed) {
stopStatus = 'terminated'; stopStatus = StopStatus['terminated'];
stopLabel = 'Skończył bieg'; stopLabel = 'Skończył bieg';
stopStatusID = 5; stopStatusID = 5;
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName == stationName) { } else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName == stationName) {
stopStatus = 'departed'; stopStatus = StopStatus['departed'];
stopLabel = 'Odprawiony'; stopLabel = 'Odprawiony';
stopStatusID = 2; stopStatusID = 2;
} else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName != stationName) { } else if (!stopInfo.terminatesHere && stopInfo.confirmed && currentStationName != stationName) {
stopStatus = 'departed-away'; stopStatus = StopStatus['departed-away'];
stopLabel = 'Odjechał'; stopLabel = 'Odjechał';
stopStatusID = 4; stopStatusID = 4;
} else if (currentStationName == stationName && !stopInfo.stopped) { } else if (currentStationName == stationName && !stopInfo.stopped) {
stopStatus = 'online'; stopStatus = StopStatus['online'];
stopLabel = 'Na stacji'; stopLabel = 'Na stacji';
stopStatusID = 0; stopStatusID = 0;
} else if (currentStationName == stationName && stopInfo.stopped) { } else if (currentStationName == stationName && stopInfo.stopped) {
stopStatus = 'stopped'; stopStatus = StopStatus['stopped'];
stopLabel = 'Postój'; stopLabel = 'Postój';
stopStatusID = 1; stopStatusID = 1;
} else if (currentStationName != stationName) { } else if (currentStationName != stationName) {
stopStatus = 'arriving'; stopStatus = StopStatus['arriving'];
stopLabel = 'W drodze'; stopLabel = 'W drodze';
stopStatusID = 3; stopStatusID = 3;
} }
@@ -122,7 +122,7 @@ export function getScheduledTrain(train: Train, trainStopIndex: number, stationN
for (let i = trainStopIndex - 1; i >= 0; i--) { for (let i = trainStopIndex - 1; i >= 0; i--) {
if (/strong|podg/g.test(followingStops[i].stopName)) { if (/strong|podg/g.test(followingStops[i].stopName)) {
prevStationName = followingStops[i].stopNameRAW.replace(/,.*/g,""); prevStationName = followingStops[i].stopNameRAW.replace(/,.*/g, '');
break; break;
} }
@@ -130,7 +130,7 @@ export function getScheduledTrain(train: Train, trainStopIndex: number, stationN
for (let i = trainStopIndex + 1; i < followingStops.length; i++) { for (let i = trainStopIndex + 1; i < followingStops.length; i++) {
if (/strong|podg/g.test(followingStops[i].stopName)) { if (/strong|podg/g.test(followingStops[i].stopName)) {
nextStationName = followingStops[i].stopNameRAW.replace(/,.*/g,""); nextStationName = followingStops[i].stopNameRAW.replace(/,.*/g, '');
break; break;
} }
@@ -172,7 +172,6 @@ export function getScheduledTrain(train: Train, trainStopIndex: number, stationN
signal: train.signal, signal: train.signal,
connectedTrack: train.connectedTrack, connectedTrack: train.connectedTrack,
driverName: train.driverName, driverName: train.driverName,
driverId: train.driverId, driverId: train.driverId,
currentStationName: train.currentStationName, currentStationName: train.currentStationName,
+5 -7
View File
@@ -1,18 +1,18 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import inputData from '../data/options.json'; import inputData from '../data/options.json';
import Filter from '../scripts/interfaces/Filter';
import Station from '../scripts/interfaces/Station'; import Station from '../scripts/interfaces/Station';
import StorageManager from '../scripts/managers/storageManager'; import StorageManager from '../scripts/managers/storageManager';
import { useStore } from './store'; import { useStore } from './store';
import { filterInitStates } from './constants/initFilterStates'; import { filterInitStates } from './constants/initFilterStates';
import { filterStations, sortStations } from './utils/filterUtils'; import { filterStations, sortStations } from './utils/filterUtils';
import { HeadIdsTypes } from '../scripts/data/stationHeaderNames';
export const useStationFiltersStore = defineStore('stationFiltersStore', { export const useStationFiltersStore = defineStore('stationFiltersStore', {
state() { state() {
return { return {
inputs: inputData, inputs: inputData,
filters: { ...filterInitStates }, filters: { ...filterInitStates },
sorterActive: { index: 0, dir: 1 }, sorterActive: { headerName: 'station' as HeadIdsTypes, dir: 1 },
store: useStore(), store: useStore(),
lastClickedFilterId: '', lastClickedFilterId: '',
}; };
@@ -89,13 +89,11 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
}); });
}, },
changeSorter(index: number) { changeSorter(headerName: HeadIdsTypes) {
if (index > 4 && index < 7) return; if (headerName == this.sorterActive.headerName) this.sorterActive.dir = -1 * this.sorterActive.dir;
if (index == this.sorterActive.index) this.sorterActive.dir = -1 * this.sorterActive.dir;
else this.sorterActive.dir = 1; else this.sorterActive.dir = 1;
this.sorterActive.index = index; this.sorterActive.headerName = headerName;
}, },
}, },
}); });
+2 -2
View File
@@ -3,7 +3,7 @@ import { defineStore } from 'pinia';
import { io } from 'socket.io-client'; import { io } from 'socket.io-client';
import { DataStatus } from '../scripts/enums/DataStatus'; import { DataStatus } from '../scripts/enums/DataStatus';
import StationAPIData from '../scripts/interfaces/api/StationAPIData'; import StationAPIData from '../scripts/interfaces/api/StationAPIData';
import ScheduledTrain from '../scripts/interfaces/ScheduledTrain'; import {ScheduledTrain} from '../scripts/interfaces/ScheduledTrain';
import Station from '../scripts/interfaces/Station'; import Station from '../scripts/interfaces/Station';
import StationRoutes from '../scripts/interfaces/StationRoutes'; import StationRoutes from '../scripts/interfaces/StationRoutes';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
@@ -15,7 +15,7 @@ import {
getScheduledTrain, getScheduledTrain,
parseSpawns, parseSpawns,
} from '../scripts/utils/storeUtils'; } from '../scripts/utils/storeUtils';
import { APIData, StationJSONData, StoreState } from './storeTypes'; import { APIData, StationJSONData, StoreState } from '../scripts/interfaces/store/storeTypes';
export const useStore = defineStore('store', { export const useStore = defineStore('store', {
state: () => state: () =>
+11 -10
View File
@@ -1,34 +1,35 @@
import { HeadIdsTypes } from '../../scripts/data/stationHeaderNames';
import Filter from '../../scripts/interfaces/Filter'; import Filter from '../../scripts/interfaces/Filter';
import Station from '../../scripts/interfaces/Station'; import Station from '../../scripts/interfaces/Station';
export const sortStations = (a: Station, b: Station, sorter: { index: number; dir: number }) => { export const sortStations = (a: Station, b: Station, sorter: { headerName: HeadIdsTypes; dir: number }) => {
switch (sorter.index) { switch (sorter.headerName) {
case 0: case 'station':
return sorter.dir == 1 ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); return sorter.dir == 1 ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name);
case 1: case 'min-lvl':
if ((a.generalInfo?.reqLevel || 0) > (b.generalInfo?.reqLevel || 0)) return sorter.dir; if ((a.generalInfo?.reqLevel || 0) > (b.generalInfo?.reqLevel || 0)) return sorter.dir;
if ((a.generalInfo?.reqLevel || 0) < (b.generalInfo?.reqLevel || 0)) return -sorter.dir; if ((a.generalInfo?.reqLevel || 0) < (b.generalInfo?.reqLevel || 0)) return -sorter.dir;
break; break;
case 2: case 'status':
if ((a.onlineInfo?.statusTimestamp || 0) > (b.onlineInfo?.statusTimestamp || 0)) return sorter.dir; if ((a.onlineInfo?.statusTimestamp || 0) > (b.onlineInfo?.statusTimestamp || 0)) return sorter.dir;
if ((a.onlineInfo?.statusTimestamp || 0) < (b.onlineInfo?.statusTimestamp || 0)) return -sorter.dir; if ((a.onlineInfo?.statusTimestamp || 0) < (b.onlineInfo?.statusTimestamp || 0)) return -sorter.dir;
break; break;
case 3: case 'dispatcher':
if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') > (b.onlineInfo?.dispatcherName.toLowerCase() || '')) if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') > (b.onlineInfo?.dispatcherName.toLowerCase() || ''))
return sorter.dir; return sorter.dir;
if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') < (b.onlineInfo?.dispatcherName.toLowerCase() || '')) if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') < (b.onlineInfo?.dispatcherName.toLowerCase() || ''))
return -sorter.dir; return -sorter.dir;
break; break;
case 4: case 'dispatcher-lvl':
if ((a.onlineInfo?.dispatcherExp || 0) > (b.onlineInfo?.dispatcherExp || 0)) return sorter.dir; if ((a.onlineInfo?.dispatcherExp || 0) > (b.onlineInfo?.dispatcherExp || 0)) return sorter.dir;
if ((a.onlineInfo?.dispatcherExp || 0) < (b.onlineInfo?.dispatcherExp || 0)) return -sorter.dir; if ((a.onlineInfo?.dispatcherExp || 0) < (b.onlineInfo?.dispatcherExp || 0)) return -sorter.dir;
break; break;
case 7: case 'user':
if ((a.onlineInfo?.currentUsers || 0) > (b.onlineInfo?.currentUsers || 0)) return sorter.dir; if ((a.onlineInfo?.currentUsers || 0) > (b.onlineInfo?.currentUsers || 0)) return sorter.dir;
if ((a.onlineInfo?.currentUsers || 0) < (b.onlineInfo?.currentUsers || 0)) return -sorter.dir; if ((a.onlineInfo?.currentUsers || 0) < (b.onlineInfo?.currentUsers || 0)) return -sorter.dir;
@@ -36,13 +37,13 @@ export const sortStations = (a: Station, b: Station, sorter: { index: number; di
if ((a.onlineInfo?.maxUsers || 0) < (b.onlineInfo?.maxUsers || 0)) return -sorter.dir; if ((a.onlineInfo?.maxUsers || 0) < (b.onlineInfo?.maxUsers || 0)) return -sorter.dir;
break; break;
case 8: case 'spawn':
if ((a.onlineInfo?.spawns.length || 0) > (b.onlineInfo?.spawns.length || 0)) return sorter.dir; if ((a.onlineInfo?.spawns.length || 0) > (b.onlineInfo?.spawns.length || 0)) return sorter.dir;
if ((a.onlineInfo?.spawns.length || 0) < (b.onlineInfo?.spawns.length || 0)) return -sorter.dir; if ((a.onlineInfo?.spawns.length || 0) < (b.onlineInfo?.spawns.length || 0)) return -sorter.dir;
break; break;
case 9: case 'timetable':
if ((a.onlineInfo?.scheduledTrains?.length || 0) > (b.onlineInfo?.scheduledTrains?.length || 0)) if ((a.onlineInfo?.scheduledTrains?.length || 0) > (b.onlineInfo?.scheduledTrains?.length || 0))
return sorter.dir; return sorter.dir;
if ((a.onlineInfo?.scheduledTrains?.length || 0) < (b.onlineInfo?.scheduledTrains?.length || 0)) if ((a.onlineInfo?.scheduledTrains?.length || 0) < (b.onlineInfo?.scheduledTrains?.length || 0))
+1 -2
View File
@@ -4,12 +4,11 @@
display: inline-block; display: inline-block;
padding: 0; padding: 0;
background: #585858;
margin: 0.25em; margin: 0.25em;
span { span {
display: inline-block; display: inline-block;
background: #585858;
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
} }
-11
View File
@@ -52,17 +52,6 @@ export default defineComponent({
mounted() { mounted() {
this.filterStore.setupFilters(); this.filterStore.setupFilters();
// this.filterStore.inputs.options.forEach((option) => {
// const value = StorageManager.getBooleanValue(option.name);
// option.value = value;
// this.filterStore.changeFilterValue({ name: option.name, value: value });
// });
// this.filterStore.inputs.sliders.forEach((slider) => {
// const value = StorageManager.getNumericValue(slider.name);
// slider.value = value;
// this.filterStore.changeFilterValue({ name: slider.name, value: value });
// });
}, },
}); });
</script> </script>