Merge pull request #110 from Spythere/development

v1.28.1
This commit is contained in:
Spythere
2024-09-18 20:09:22 +02:00
committed by GitHub
15 changed files with 131 additions and 92 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "stacjownik", "name": "stacjownik",
"version": "1.28.0", "version": "1.28.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+3
View File
@@ -0,0 +1,3 @@
<svg width="144" height="144" viewBox="0 0 144 144" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M82.7143 61.3284L118.429 7L22 74.9104H68.4286L36.2857 137L122 61.3284H82.7143Z" fill="#FFF500"/>
</svg>

After

Width:  |  Height:  |  Size: 213 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="144" height="144" viewBox="0 0 144 144" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="9.20437" y="2.4661" width="36.5457" height="57.8287" rx="16.7449" transform="matrix(0.869001 -0.494811 0.505207 0.862998 50.006 87.4256)" stroke="white" stroke-width="13.3959"/>
<rect x="9.20437" y="2.4661" width="36.5457" height="57.8287" rx="16.7449" transform="matrix(0.869001 -0.494811 0.505207 0.862998 14.9599 29.6039)" stroke="white" stroke-width="13.3959"/>
<path d="M65.1133 58.145L79.8524 84.3103" stroke="white" stroke-width="10.0469" stroke-linecap="round" stroke-linejoin="bevel"/>
</svg>

After

Width:  |  Height:  |  Size: 611 B

+1
View File
@@ -81,6 +81,7 @@ export default defineComponent({
async mounted() { async mounted() {
window.addEventListener('mousemove', (e: MouseEvent) => this.tooltipStore.handle(e)); window.addEventListener('mousemove', (e: MouseEvent) => this.tooltipStore.handle(e));
window.addEventListener('mousedown', () => this.tooltipStore.hide());
}, },
methods: { methods: {
+3 -22
View File
@@ -1,21 +1,11 @@
<template> <template>
<div class="stock-list"> <div class="stock-list">
<ul> <ul>
<li <li v-for="({ images, imagesFallbacks, vehicleString }, i) in thumbnailNames" :key="i">
v-for="(
{ vehicleName, vehicleCargo, images, imagesFallbacks, vehicleString }, i
) in thumbnailNames"
:key="i"
>
<div class="stock-text">
<div>{{ vehicleName.replace(/_/g, ' ') }}</div>
<small v-if="vehicleCargo">({{ vehicleCargo }})</small>
</div>
<span> <span>
<VehicleThumbnail <VehicleThumbnail
v-for="(thumbnailImage, imageIndex) in images" v-for="(thumbnailImage, imageIndex) in images"
:vehicle-name="vehicleString" :vehicle-string="vehicleString"
:img-name="thumbnailImage" :img-name="thumbnailImage"
:fallback-name="imagesFallbacks[imageIndex]" :fallback-name="imagesFallbacks[imageIndex]"
/> />
@@ -59,13 +49,12 @@ export default defineComponent({
return (this.tractionOnly ? this.trainStockList.slice(0, 1) : this.trainStockList) return (this.tractionOnly ? this.trainStockList.slice(0, 1) : this.trainStockList)
.filter((v) => v.length != 0) .filter((v) => v.length != 0)
.map((vehicleString) => { .map((vehicleString) => {
const [vehicleName, vehicleCargo] = vehicleString.split(':'); const [vehicleName] = vehicleString.split(':');
const vehicleThumbnailData = { const vehicleThumbnailData = {
images: [] as string[], images: [] as string[],
imagesFallbacks: [] as string[], imagesFallbacks: [] as string[],
vehicleName, vehicleName,
vehicleCargo,
vehicleString vehicleString
}; };
@@ -187,12 +176,4 @@ ul > li > span {
align-items: flex-end; align-items: flex-end;
cursor: crosshair; cursor: crosshair;
} }
.stock-text {
text-align: center;
color: #aaa;
font-size: 0.9em;
margin-bottom: 0.25em;
padding: 0.25em 0;
}
</style> </style>
+22 -11
View File
@@ -1,12 +1,16 @@
<template> <template>
<div class="vehicle-thumbnail" :data-load-status="imgStatus"> <div class="vehicle-thumbnail" :data-load-status="imgStatus" ref="thumbRef">
<div class="stock-text">
<div>{{ vehicleName }}</div>
<small v-if="vehicleCargo">({{ vehicleCargo }})</small>
</div>
<img <img
ref="imgRef"
:src="`https://static.spythere.eu/thumbnails/v2/${imgName}.png`" :src="`https://static.spythere.eu/thumbnails/v2/${imgName}.png`"
height="60" height="60"
loading="lazy" loading="lazy"
data-tooltip-type="VehiclePreviewTooltip" data-tooltip-type="VehiclePreviewTooltip"
:data-tooltip-content="vehicleName" :data-tooltip-content="vehicleString"
@error="onImageError" @error="onImageError"
@load="onImageLoad" @load="onImageLoad"
/> />
@@ -14,19 +18,21 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Ref, ref } from 'vue'; import { computed, Ref, ref } from 'vue';
const props = defineProps({ const props = defineProps({
vehicleName: { type: String, required: true }, vehicleString: { type: String, required: true },
imgName: { type: String, required: true }, imgName: { type: String, required: true },
fallbackName: { type: String, required: true }, fallbackName: { type: String, required: true },
placeholderName: String placeholderName: String
}); });
const imgRef = ref(null) as Ref<HTMLElement | null>; const thumbRef = ref(null) as Ref<HTMLElement | null>;
const imgStatus = ref('loading'); const imgStatus = ref('loading');
const vehicleName = computed(() => props.vehicleString.split(':')[0].replace(/_/g, ' '));
const vehicleCargo = computed(() => props.vehicleString.split(':')[1]);
function onImageError(event: Event) { function onImageError(event: Event) {
(event.target as HTMLImageElement).src = `/images/${props.fallbackName}.png`; (event.target as HTMLImageElement).src = `/images/${props.fallbackName}.png`;
imgStatus.value = 'error'; imgStatus.value = 'error';
@@ -37,13 +43,15 @@ function onImageLoad() {
imgStatus.value = 'loaded'; imgStatus.value = 'loaded';
} }
if (imgRef.value) imgRef.value.style.opacity = '1'; if (thumbRef.value) thumbRef.value.style.opacity = '1';
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.vehicle-thumbnail { .vehicle-thumbnail {
position: relative; position: relative;
opacity: 0;
transition: opacity 100ms ease-in-out;
&[data-load-status='loading'] { &[data-load-status='loading'] {
min-height: 60px; min-height: 60px;
@@ -51,8 +59,11 @@ function onImageLoad() {
} }
} }
img { .stock-text {
opacity: 0; text-align: center;
transition: opacity 100ms ease-in-out; color: #aaa;
font-size: 0.9em;
margin-bottom: 0.25em;
padding: 0.25em 0;
} }
</style> </style>
@@ -91,10 +91,6 @@ export default defineComponent({
deep: true, deep: true,
handler() { handler() {
this.extraInfoIndexes.length = 0; this.extraInfoIndexes.length = 0;
this.$nextTick(() => {
console.log(this.$el.querySelector('ul'));
});
} }
} }
}, },
+1 -2
View File
@@ -32,12 +32,11 @@ export default defineComponent({
<style scoped> <style scoped>
.tooltip-content { .tooltip-content {
width: 300px; width: 200px;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
border-radius: 0.25em; border-radius: 0.25em;
width: 100%;
background-color: #1b1b1b; background-color: #1b1b1b;
box-shadow: 0 0 5px 2px #aaa; box-shadow: 0 0 5px 2px #aaa;
} }
+1 -2
View File
@@ -32,12 +32,11 @@ export default defineComponent({
<style scoped> <style scoped>
.tooltip-content { .tooltip-content {
width: 300px; width: 200px;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
border-radius: 0.25em; border-radius: 0.25em;
width: 100%;
background-color: #1b1b1b; background-color: #1b1b1b;
box-shadow: 0 0 5px 2px #aaa; box-shadow: 0 0 5px 2px #aaa;
} }
@@ -77,9 +77,11 @@ export default defineComponent({
}, },
vehicleCargo() { vehicleCargo() {
return this.vehicleData?.group.cargoTypes?.find( const x = this.vehicleData?.group.cargoTypes?.find(
(c) => c.id == this.tooltipStore.content.split(':')[1] (c) => c.id == this.tooltipStore.content.split(':')[1]
); );
return x;
} }
} }
}); });
+1 -1
View File
@@ -70,7 +70,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import { TrainScheduleStop } from './TrainSchedule.vue'; import { TrainScheduleStop } from './typings';
export default defineComponent({ export default defineComponent({
mixins: [dateMixin], mixins: [dateMixin],
+43 -46
View File
@@ -55,12 +55,28 @@
<span>{{ stop.departureLine }}</span> <span>{{ stop.departureLine }}</span>
<span v-if="stop.departureLineInfo"> <span v-if="stop.departureLineInfo">
| {{ stop.departureLineInfo.routeSpeed }} | {{ stop.departureLineInfo.routeSpeed }}
<span v-if="stop.departureLineInfo.isElectric">⚡</span>
<img <img
v-else :src="
src="/images/icon-we4a.png" stop.departureLineInfo.isElectric
:title="$t('trains.we4a-tooltip')" ? '/images/icon-catenary.svg'
: '/images/icon-we4a.png'
"
width="10" width="10"
data-tooltip-type="BaseTooltip"
:data-tooltip-content="
$t(
`trains.${!stop.departureLineInfo.isElectric ? 'no-' : ''}catenary-tooltip`
)
"
/>
<img
v-if="stop.departureLineInfo.isRouteSBL"
src="/images/icon-sbl-transparent.svg"
width="10"
data-tooltip-type="BaseTooltip"
:data-tooltip-content="$t('trains.sbl-tooltip')"
/> />
</span> </span>
</div> </div>
@@ -71,7 +87,7 @@
> >
<span>{{ scheduleStops[i + 1].sceneryName }}</span> <span>{{ scheduleStops[i + 1].sceneryName }}</span>
<span v-if="stop.departureLineInfo?.routeTracks == 1"> &UpDownArrow;</span> <span v-if="stop.departureLineInfo?.routeTracks == 1"> &UpDownArrow;</span>
<span v-else> &UpArrowDownArrow;</span> <span v-else> &DownArrowUpArrow;</span>
</div> </div>
<div class="scenery-route"> <div class="scenery-route">
@@ -79,13 +95,29 @@
<span v-if="scheduleStops[i + 1].arrivalLineInfo"> <span v-if="scheduleStops[i + 1].arrivalLineInfo">
| {{ scheduleStops[i + 1].arrivalLineInfo!.routeSpeed }} | {{ scheduleStops[i + 1].arrivalLineInfo!.routeSpeed }}
<span v-if="scheduleStops[i + 1].arrivalLineInfo!.isElectric">⚡</span>
<img <img
v-else :src="
src="/images/icon-we4a.png" scheduleStops[i + 1].arrivalLineInfo!.isElectric
:title="$t('trains.we4a-tooltip')" ? '/images/icon-catenary.svg'
: '/images/icon-we4a.png'
"
data-tooltip-type="BaseTooltip"
:data-tooltip-content="
$t(
`trains.${!scheduleStops[i + 1].arrivalLineInfo!.isElectric ? 'no-' : ''}catenary-tooltip`
)
"
width="10" width="10"
/> />
<img
v-if="scheduleStops[i + 1].arrivalLineInfo!.isRouteSBL"
src="/images/icon-sbl-transparent.svg"
width="10"
data-tooltip-type="BaseTooltip"
:data-tooltip-content="$t('trains.sbl-tooltip')"
/>
</span> </span>
</div> </div>
</span> </span>
@@ -105,43 +137,7 @@ import StockList from '../Global/StockList.vue';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import { StationRoutesInfo, Train } from '../../typings/common'; import { StationRoutesInfo, Train } from '../../typings/common';
import { TrainScheduleStop } from './typings';
export interface TrainScheduleStop {
nameHtml: string;
nameRaw: string;
status: 'confirmed' | 'unconfirmed' | 'stopped';
type: string;
position: 'begin' | 'end' | 'en-route';
arrivalScheduled: number;
arrivalReal: number;
departureScheduled: number;
departureReal: number;
departureDelay: number;
arrivalDelay: number;
duration: number | null;
isActive: boolean;
isLastConfirmed: boolean;
isSBL: boolean;
sceneryName: string | null;
distance: number;
arrivalLine: string | null;
departureLine: string | null;
arrivalLineInfo?: StationRoutesInfo;
departureLineInfo?: StationRoutesInfo;
isExternal: boolean;
comments: string | null;
}
export default defineComponent({ export default defineComponent({
components: { StopLabel, StockList }, components: { StopLabel, StockList },
@@ -534,6 +530,7 @@ $blinkAnim: 0.5s ease-in-out alternate infinite blink;
img { img {
width: 1em; width: 1em;
cursor: help;
} }
} }
+39
View File
@@ -1,3 +1,5 @@
import { StationRoutesInfo } from "../../typings/common";
export enum TrainFilterSection { export enum TrainFilterSection {
TRAIN_TYPE = 'TRAIN_TYPE', TRAIN_TYPE = 'TRAIN_TYPE',
TIMETABLE_TYPE = 'TIMETABLE_TYPE', TIMETABLE_TYPE = 'TIMETABLE_TYPE',
@@ -117,3 +119,40 @@ export const sorterOptions: TrainSorter[] = [
value: 'długość' value: 'długość'
} }
]; ];
export interface TrainScheduleStop {
nameHtml: string;
nameRaw: string;
status: 'confirmed' | 'unconfirmed' | 'stopped';
type: string;
position: 'begin' | 'end' | 'en-route';
arrivalScheduled: number;
arrivalReal: number;
departureScheduled: number;
departureReal: number;
departureDelay: number;
arrivalDelay: number;
duration: number | null;
isActive: boolean;
isLastConfirmed: boolean;
isSBL: boolean;
sceneryName: string | null;
distance: number;
arrivalLine: string | null;
departureLine: string | null;
arrivalLineInfo?: StationRoutesInfo;
departureLineInfo?: StationRoutesInfo;
isExternal: boolean;
comments: string | null;
}
+4 -1
View File
@@ -377,7 +377,10 @@
"current-track": "on track", "current-track": "on track",
"vmax-tooltip": "Maximum train speed based on rolling stock vehicles - braked weight is not included", "vmax-tooltip": "Maximum train speed based on rolling stock vehicles - braked weight is not included",
"we4a-tooltip": "Non-electrified track",
"catenary-tooltip": "Electrified route",
"no-catenary-tooltip": "Non-electrified route",
"sbl-tooltip": "Route with SBL\n(automatic block signalling)",
"delayed": "Delayed: ", "delayed": "Delayed: ",
"preponed": "Ahead of schedule: ", "preponed": "Ahead of schedule: ",
+4 -1
View File
@@ -364,7 +364,10 @@
"current-track": "na szlaku", "current-track": "na szlaku",
"vmax-tooltip": "Maksymalna prędkość na podstawie pojazdów w składzie - nie bierze pod uwagę masy hamowania", "vmax-tooltip": "Maksymalna prędkość na podstawie pojazdów w składzie - nie bierze pod uwagę masy hamowania",
"we4a-tooltip": "Szlak niezelektryfikowany",
"catenary-tooltip": "Szlak zelektryfikowany",
"no-catenary-tooltip": "Szlak niezelektryfikowany",
"sbl-tooltip": "Szlak posiadający\nsamoczynną blokadę liniową",
"delayed": "Opóźniony: ", "delayed": "Opóźniony: ",
"preponed": "Przed czasem: ", "preponed": "Przed czasem: ",