Cleanup i restrukturyzacja widoku scenerii

This commit is contained in:
2022-01-05 13:23:57 +01:00
parent 054f8434e6
commit 526f2bef37
11 changed files with 571 additions and 465 deletions
+44 -393
View File
@@ -1,189 +1,49 @@
<template> <template>
<div class="scenery-info"> <div class="scenery-info">
<div class="info-header"> <!-- info header -->
<div class="scenery-name"> <scenery-info-header :station="station" />
<div v-if="station.generalInfo?.project" style="color: salmon; font-size: 0.6em; line-height: 0.7em;">
{{ station.generalInfo.project }}
</div>
<a v-if="station.generalInfo?.url" :href="station.generalInfo.url" target="_blank" rel="noopener noreferrer">{{
station.name
}}</a>
<span v-else>{{ station.name }}</span>
</div>
<div class="scenery-hash" v-if="station.onlineInfo?.hash">#{{ station.onlineInfo.hash }}</div>
</div>
<section v-if="!timetableOnly"> <section v-if="!timetableOnly">
<div class="info-stats" :class="!station.onlineInfo ? 'no-stats' : ''"> <!-- info stats -->
<span class="likes"> <scenery-info-stats :station="station" />
<img :src="likeIcon" alt="icon-like" /> <!-- info icons -->
<span>{{ station.onlineInfo?.dispatcherRate || '0' }}</span> <scenery-info-icons :station="station" />
</span>
<span class="users">
<img :src="userIcon" alt="icon-user" />
<span>{{ station.onlineInfo?.currentUsers || '0' }}</span>
/
<span>{{ station.onlineInfo?.maxUsers || '0' }}</span>
</span>
<span class="spawns">
<img :src="spawnIcon" alt="icon-spawn" />
<span>{{ station.onlineInfo?.spawns.length || '0' }}</span>
</span>
<span class="schedules">
<img :src="timetableIcon" alt="icon-timetable" />
<span>
<span style="color: #eee">{{ station.onlineInfo?.scheduledTrains?.length || '0' }}</span>
/
<span style="color: #bbb"
>{{ station.onlineInfo?.scheduledTrains?.filter((train) => train.stopInfo.confirmed).length || '0' }}
</span>
</span>
</span>
</div>
<div class="info-brief">
<img
v-if="station.generalInfo?.controlType"
:src="require(`@/assets/icon-${station.generalInfo.controlType}.svg`)"
:alt="station.generalInfo.controlType"
:title="$t('desc.control-type') + $t(`controls.${station.generalInfo.controlType}`)"
/>
<img
v-if="station.generalInfo?.signalType"
:src="require(`@/assets/icon-${station.generalInfo.signalType}.svg`)"
:alt="station.generalInfo.signalType"
:title="$t('desc.signals-type') + $t(`signals.${station.generalInfo.signalType}`)"
/>
<img
v-if="station.generalInfo && station.generalInfo.SBL !== ''"
:src="SBLIcon"
:alt="$t('desc.SBL') + `${station.generalInfo.SBL}`"
:title="$t('desc.SBL') + `${station.generalInfo.SBL}`"
/>
<img
v-if="station.generalInfo && station.generalInfo.TWB !== ''"
:src="TWBIcon"
alt="two way route blockade"
:title="
`${
station.generalInfo.TWB === 'TAK' ? $t('desc.TWB-all') : $t('desc.TWB-routes') + station.generalInfo.TWB
}`
"
/>
<img v-if="station.generalInfo?.default" :src="td2Icon" alt="default scenery" :title="$t('desc.default')" />
<img
v-if="station.generalInfo?.nonPublic"
:src="lockIcon"
alt="non public scenery"
:title="$t('desc.non-public')"
/>
<img
v-if="station.generalInfo?.unavailable"
:src="unavailableIcon"
alt="icon unavailable"
:title="$t('desc.unavailable')"
/>
<img
v-if="station.generalInfo && station.generalInfo.lines != ''"
:src="realIcon"
alt="real scenery"
:title="`${$t('desc.real')} ${station.generalInfo.lines}`"
/>
<img v-if="!station.generalInfo" :src="unknownIcon" alt="icon-unknown" :title="$t('desc.unknown')" />
</div>
<div class="info-dispatcher">
<div class="dispatcher" v-if="station.onlineInfo">
<span
class="dispatcher_level"
:style="calculateExpStyle(station.onlineInfo.dispatcherExp, station.onlineInfo.dispatcherIsSupporter)"
>
{{ station.onlineInfo.dispatcherExp > 1 ? station.onlineInfo.dispatcherExp : 'L' }}
</span>
<span class="dispatcher_name">{{ station.onlineInfo.dispatcherName }}</span>
</div>
<span class="status-badge" v-if="station.onlineInfo" :class="station.onlineInfo.statusID">
{{ $t(`status.${station.onlineInfo.statusID}`) }}
{{ station.onlineInfo.statusID == 'online' ? station.onlineInfo.statusTimeString : '' }}
</span>
<span class="status-badge free" v-else>
{{ $t('status.free') }}
</span>
</div>
<!-- info dispatcher -->
<scenery-info-dispatcher :station="station" />
<div class="info-lists"> <div class="info-lists">
<div class="user-list"> <!-- user list -->
<h3 class="user-header"> <scenery-info-user-list :station="station" />
{{ $t('scenery.users') }}
<img :src="userIcon" alt="icon-user" />
</h3>
<div <!-- spawn list -->
v-for="(train, i) in computedStationTrains" <scenery-info-spawn-list :station="station" />
class="user"
:class="train.stopStatus"
:key="train.trainNo + i"
tabindex="0"
@click="() => navigateToTrain(train.trainNo)"
@keydown="(e) => { if(e.keyCode == 13) navigateToTrain(train.trainNo) }"
>
<span class="user_train">{{ train.trainNo }}</span>
<span class="user_name">{{ train.driverName }}</span>
</div>
<div class="user offline" v-if="!computedStationTrains || computedStationTrains.length == 0">
{{ $t('scenery.no-users') }}
</div>
</div>
<div class="spawn-list">
<h3 class="spawn-header">
{{ $t('scenery.spawns') }}
<img :src="spawnIcon" alt="icon-spawn" />
</h3>
<span v-if="station.onlineInfo">
<span
class="spawn"
v-for="(spawn, i) in station.onlineInfo.spawns"
:key="spawn.spawnName + station.onlineInfo?.dispatcherName + i"
>
<span class="spawn_name">{{ spawn.spawnName }}</span>
<span class="spawn_length">{{ spawn.spawnLength }}m</span>
</span>
</span>
<span class="spawn none" v-if="!station.onlineInfo || station.onlineInfo.spawns.length == 0"
>{{ $t('scenery.no-spawns') }}
</span>
</div>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Station from '@/scripts/interfaces/Station';
import styleMixin from '@/mixins/styleMixin';
import { computed, defineComponent } from '@vue/runtime-core'; import { computed, defineComponent } from '@vue/runtime-core';
import SceneryInfoDispatcher from './SceneryInfo/SceneryInfoDispatcher.vue';
import SceneryInfoIcons from './SceneryInfo/SceneryInfoIcons.vue';
import SceneryInfoStats from './SceneryInfo/SceneryInfoStats.vue';
import SceneryInfoHeader from './SceneryInfo/SceneryInfoHeader.vue';
import SceneryInfoUserList from './SceneryInfo/SceneryInfoUserList.vue';
import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue';
import Station from '@/scripts/interfaces/Station';
export default defineComponent({ export default defineComponent({
components: {
SceneryInfoDispatcher,
SceneryInfoIcons,
SceneryInfoStats,
SceneryInfoHeader,
SceneryInfoUserList,
SceneryInfoSpawnList,
},
props: { props: {
station: { station: {
type: Object as () => Station, type: Object as () => Station,
@@ -192,63 +52,13 @@ export default defineComponent({
timetableOnly: Boolean, timetableOnly: Boolean,
}, },
mixins: [styleMixin],
data: () => ({
likeIcon: require('@/assets/icon-like.svg'),
spawnIcon: require('@/assets/icon-spawn.svg'),
timetableIcon: require('@/assets/icon-timetable.svg'),
userIcon: require('@/assets/icon-user.svg'),
SBLIcon: require('@/assets/icon-SBL.svg'),
TWBIcon: require('@/assets/icon-2way-block.svg'),
td2Icon: require('@/assets/icon-td2.svg'),
lockIcon: require('@/assets/icon-lock.svg'),
unavailableIcon: require('@/assets/icon-unavailable.svg'),
unknownIcon: require('@/assets/icon-unknown.svg'),
realIcon: require('@/assets/icon-real.svg'),
}),
setup(props) {
const computedStationTrains = computed(() => {
if (!props.station) return [];
if (!props.station.onlineInfo) return [];
if (!props.station.onlineInfo.stationTrains) return [];
return props.station.onlineInfo.stationTrains.map((train) => {
const scheduledTrainStatus = props.station.onlineInfo?.scheduledTrains?.find(
(st) => st.trainNo === train.trainNo
);
return {
...train,
stopStatus: scheduledTrainStatus?.stopStatus || 'no-timetable',
};
});
});
return { computedStationTrains };
},
methods: {
navigateToTrain(trainNo: number) {
this.$router.push({
name: 'TrainsView',
query: { train: trainNo.toString() },
});
},
},
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss">
@import '../../styles/responsive.scss'; @import '../../styles/responsive.scss';
@import '../../styles/user_badge.scss';
@import '../../styles/variables.scss';
h3 { h3.section-header {
margin: 0.5em 0; margin: 0.5em 0;
padding: 0.3em; padding: 0.3em;
@@ -264,123 +74,14 @@ h3 {
} }
} }
.info { .info-lists {
&-header { display: flex;
padding: 2em 1em;
& > .scenery-name { align-items: center;
font-weight: bold; flex-direction: column;
color: $accentCol;
font-size: 3.5em;
text-transform: uppercase;
@include smallScreen() {
font-size: 2.75em;
}
}
& > .scenery-hash {
line-height: 0.8em;
color: #aaa;
font-size: 1.5em;
}
}
&-stats {
padding: 1rem 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
font-size: 1.65em;
&.no-stats {
opacity: 0.5;
}
& > span {
display: flex;
align-items: center;
margin: 0.3em;
}
.likes,
.spawns {
color: $accentCol;
}
span > img {
width: 1.2em;
margin-right: 0.5em;
}
}
&-brief {
padding: 1em 0;
img {
width: 3.5em;
margin: 0 0.5em;
border: 2px solid #4e4e4e;
border-radius: 0.5em;
}
}
&-dispatcher {
display: flex;
align-items: center;
justify-content: center;
.dispatcher {
font-size: 2em;
&_level {
display: inline-block;
margin-right: 0.3em;
background: firebrick;
border-radius: 0.1em;
width: 1.5em;
height: 1.5em;
line-height: 1.5em;
font-weight: bold;
}
&_name {
margin-right: 1em;
}
}
.status-badge {
font-size: 1.2em;
}
}
&-lists {
display: flex;
align-items: center;
flex-direction: column;
& > .user-list {
ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
}
}
} }
.user, .badge {
.spawn {
font-weight: 600; font-weight: 600;
display: inline-block; display: inline-block;
@@ -394,68 +95,18 @@ h3 {
display: inline-block; display: inline-block;
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
} }
}
.user { &-none {
cursor: pointer; font-weight: 600;
&_train { padding: 0.2em 0.4em;
color: black;
background-color: $no-timetable;
transition: background-color 200ms;
-ms-transition: background-color 200ms;
-webkit-transition: background-color 200ms;
}
&.no-timetable .user_train {
background-color: $no-timetable;
}
&.departed > &_train {
background-color: $departed;
}
&.stopped > &_train {
background-color: $stopped;
}
&.online > &_train {
background-color: $online;
}
&.terminated > &_train {
background-color: $terminated;
}
&.disconnected > &_train {
background-color: $disconnected;
}
&.offline {
background: firebrick; background: firebrick;
pointer-events: none;
}
}
.spawn { text-align: center;
&_length {
background: $accentCol;
color: black;
}
}
.spawn.none, @include smallScreen() {
.user.offline { font-size: 1em;
font-weight: 600; }
padding: 0.2em 0.4em;
background: firebrick;
text-align: center;
@include smallScreen() {
font-size: 1em;
} }
} }
</style> </style>
@@ -0,0 +1,79 @@
<template>
<section class="info-dispatcher">
<div class="dispatcher" v-if="station.onlineInfo">
<span
class="dispatcher_level"
:style="calculateExpStyle(station.onlineInfo.dispatcherExp, station.onlineInfo.dispatcherIsSupporter)"
>
{{ station.onlineInfo.dispatcherExp > 1 ? station.onlineInfo.dispatcherExp : 'L' }}
</span>
<span class="dispatcher_name">{{ station.onlineInfo.dispatcherName }}</span>
</div>
<span class="status-badge" v-if="station.onlineInfo" :class="station.onlineInfo.statusID">
{{ $t(`status.${station.onlineInfo.statusID}`) }}
{{ station.onlineInfo.statusID == 'online' ? station.onlineInfo.statusTimeString : '' }}
</span>
<span class="status-badge free" v-else>
{{ $t('status.free') }}
</span>
</section>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import styleMixin from '@/mixins/styleMixin';
import Station from '@/scripts/interfaces/Station';
export default defineComponent({
mixins: [styleMixin],
props: {
station: {
type: Object as () => Station,
default: {},
},
},
data: () => ({
icons: {
spawn: require('@/assets/icon-spawn.svg'),
},
}),
});
</script>
<style lang="scss" scoped>
.info-dispatcher {
display: flex;
align-items: center;
justify-content: center;
.dispatcher {
font-size: 2em;
&_level {
display: inline-block;
margin-right: 0.3em;
background: firebrick;
border-radius: 0.1em;
width: 1.5em;
height: 1.5em;
line-height: 1.5em;
font-weight: bold;
}
&_name {
margin-right: 1em;
}
}
.status-badge {
font-size: 1.2em;
}
}
</style>
@@ -0,0 +1,61 @@
<template>
<section class="info-header">
<div class="scenery-name">
<div v-if="station.generalInfo?.project" style="color: salmon; font-size: 0.6em; line-height: 0.7em;">
{{ station.generalInfo.project }}
</div>
<a v-if="station.generalInfo?.url" :href="station.generalInfo.url" target="_blank" rel="noopener noreferrer">{{
station.name
}}</a>
<span v-else>{{ station.name }}</span>
</div>
<div class="scenery-hash" v-if="station.onlineInfo?.hash">#{{ station.onlineInfo.hash }}</div>
</section>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Station from '@/scripts/interfaces/Station';
export default defineComponent({
props: {
station: {
type: Object as () => Station,
default: {},
},
},
});
</script>
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
@import '../../../styles/responsive.scss';
.info-header {
padding: 2em 1em;
& > .scenery-name {
font-weight: bold;
color: $accentCol;
font-size: 3.5em;
text-transform: uppercase;
@include smallScreen() {
font-size: 2.75em;
}
}
& > .scenery-hash {
line-height: 0.8em;
color: #aaa;
font-size: 1.5em;
}
}
</style>
@@ -0,0 +1,100 @@
<template>
<section class="info-icons">
<img
v-if="station.generalInfo?.controlType"
:src="require(`@/assets/icon-${station.generalInfo.controlType}.svg`)"
:alt="station.generalInfo.controlType"
:title="$t('desc.control-type') + $t(`controls.${station.generalInfo.controlType}`)"
/>
<img
v-if="station.generalInfo?.signalType"
:src="require(`@/assets/icon-${station.generalInfo.signalType}.svg`)"
:alt="station.generalInfo.signalType"
:title="$t('desc.signals-type') + $t(`signals.${station.generalInfo.signalType}`)"
/>
<img
v-if="station.generalInfo && station.generalInfo.SBL !== ''"
:src="icons.SBL"
:alt="$t('desc.SBL') + `${station.generalInfo.SBL}`"
:title="$t('desc.SBL') + `${station.generalInfo.SBL}`"
/>
<img
v-if="station.generalInfo && station.generalInfo.TWB !== ''"
:src="icons.TWB"
alt="two way route blockade"
:title="
`${station.generalInfo.TWB === 'TAK' ? $t('desc.TWB-all') : $t('desc.TWB-routes') + station.generalInfo.TWB}`
"
/>
<img v-if="station.generalInfo?.default" :src="icons.td2" alt="default scenery" :title="$t('desc.default')" />
<img
v-if="station.generalInfo?.nonPublic"
:src="icons.lock"
alt="non public scenery"
:title="$t('desc.non-public')"
/>
<img
v-if="station.generalInfo?.unavailable"
:src="icons.unavailable"
alt="icon unavailable"
:title="$t('desc.unavailable')"
/>
<img
v-if="station.generalInfo && station.generalInfo.lines != ''"
:src="icons.real"
alt="real scenery"
:title="`${$t('desc.real')} ${station.generalInfo.lines}`"
/>
<img v-if="!station.generalInfo" :src="icons.unknown" alt="icon-unknown" :title="$t('desc.unknown')" />
</section>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Station from '@/scripts/interfaces/Station';
export default defineComponent({
props: {
station: {
type: Object as () => Station,
default: {},
},
},
data: () => ({
icons: {
SBL: require('@/assets/icon-SBL.svg'),
TWB: require('@/assets/icon-2way-block.svg'),
td2: require('@/assets/icon-td2.svg'),
lock: require('@/assets/icon-lock.svg'),
unavailable: require('@/assets/icon-unavailable.svg'),
unknown: require('@/assets/icon-unknown.svg'),
real: require('@/assets/icon-real.svg'),
},
}),
});
</script>
<style lang="scss" scoped>
.info-icons {
padding: 1em 0;
img {
width: 3.5em;
margin: 0 0.5em;
border: 2px solid #4e4e4e;
border-radius: 0.5em;
}
}
</style>
@@ -0,0 +1,54 @@
<template>
<section class="info-spawn-list">
<h3 class="spawn-header section-header">
{{ $t('scenery.spawns') }}
<img :src="icons.spawn" alt="icon-spawn" />
</h3>
<span v-if="station.onlineInfo">
<span
class="badge spawn"
v-for="(spawn, i) in station.onlineInfo.spawns"
:key="spawn.spawnName + station.onlineInfo?.dispatcherName + i"
>
<span class="spawn_name">{{ spawn.spawnName }}</span>
<span class="spawn_length">{{ spawn.spawnLength }}m</span>
</span>
</span>
<span class="badge spawn badge-none" v-if="!station.onlineInfo || station.onlineInfo.spawns.length == 0"
>{{ $t('scenery.no-spawns') }}
</span>
</section>
</template>
<script lang="ts">
import Station from '@/scripts/interfaces/Station';
import { defineComponent } from 'vue';
export default defineComponent({
props: {
station: {
type: Object as () => Station,
default: {},
},
},
data: () => ({
icons: {
spawn: require('@/assets/icon-spawn.svg'),
},
}),
});
</script>
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
.spawn {
&_length {
background: $accentCol;
color: black;
}
}
</style>
@@ -0,0 +1,90 @@
<template>
<section class="info-stats" :class="!station.onlineInfo ? 'no-stats' : ''">
<span class="likes">
<img :src="icons.like" alt="icon-like" />
<span>{{ station.onlineInfo?.dispatcherRate || '0' }}</span>
</span>
<span class="users">
<img :src="icons.user" alt="icon-user" />
<span>{{ station.onlineInfo?.currentUsers || '0' }}</span>
/
<span>{{ station.onlineInfo?.maxUsers || '0' }}</span>
</span>
<span class="spawns">
<img :src="icons.spawn" alt="icon-spawn" />
<span>{{ station.onlineInfo?.spawns.length || '0' }}</span>
</span>
<span class="schedules">
<img :src="icons.timetable" alt="icon-timetable" />
<span>
<span style="color: #eee">{{ station.onlineInfo?.scheduledTrains?.length || '0' }}</span>
/
<span style="color: #bbb"
>{{ station.onlineInfo?.scheduledTrains?.filter((train) => train.stopInfo.confirmed).length || '0' }}
</span>
</span>
</span>
</section>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Station from '@/scripts/interfaces/Station';
export default defineComponent({
props: {
station: {
type: Object as () => Station,
default: {},
},
},
data: () => ({
icons: {
like: require('@/assets/icon-like.svg'),
timetable: require('@/assets/icon-timetable.svg'),
user: require('@/assets/icon-user.svg'),
spawn: require('@/assets/icon-spawn.svg'),
},
}),
});
</script>
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
.info-stats {
padding: 1rem 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
font-size: 1.65em;
&.no-stats {
opacity: 0.5;
}
& > span {
display: flex;
align-items: center;
margin: 0.3em;
}
.likes,
.spawns {
color: $accentCol;
}
span > img {
width: 1.2em;
margin-right: 0.5em;
}
}
</style>
@@ -0,0 +1,134 @@
<template>
<section class="info-user-list">
<h3 class="user-header section-header">
{{ $t('scenery.users') }}
<img :src="icons.user" alt="icon-user" />
</h3>
<div
v-for="(train, i) in computedStationTrains"
class="badge user"
:class="train.stopStatus"
:key="train.trainNo + i"
tabindex="0"
@click="() => navigateToTrain(train.trainNo)"
@keydown.enter="navigateToTrain(train.trainNo)"
>
<span class="user_train">{{ train.trainNo }}</span>
<span class="user_name">{{ train.driverName }}</span>
</div>
<div class="badge user badge-none" v-if="!computedStationTrains || computedStationTrains.length == 0">
{{ $t('scenery.no-users') }}
</div>
</section>
</template>
<script lang="ts">
import Station from '@/scripts/interfaces/Station';
import { computed, defineComponent } from 'vue';
export default defineComponent({
props: {
station: {
type: Object as () => Station,
default: {},
},
},
setup(props) {
const computedStationTrains = computed(() => {
if (!props.station) return [];
if (!props.station.onlineInfo) return [];
if (!props.station.onlineInfo.stationTrains) return [];
return props.station.onlineInfo.stationTrains.map((train) => {
const scheduledTrainStatus = props.station.onlineInfo?.scheduledTrains?.find(
(st) => st.trainNo === train.trainNo
);
return {
...train,
stopStatus: scheduledTrainStatus?.stopStatus || 'no-timetable',
};
});
});
return { computedStationTrains };
},
data: () => ({
icons: {
user: require('@/assets/icon-user.svg'),
},
}),
methods: {
navigateToTrain(trainNo: number) {
this.$router.push({
name: 'TrainsView',
query: { train: trainNo.toString() },
});
},
},
});
</script>
<style lang="scss" scoped>
$no-timetable: #aaa;
$departed: springgreen;
$stopped: #ffa600;
$online: gold;
$terminated: red;
$disconnected: slategray;
.info-user-list {
ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
}
.user {
cursor: pointer;
&_train {
color: black;
background-color: $no-timetable;
transition: background-color 200ms;
-ms-transition: background-color 200ms;
-webkit-transition: background-color 200ms;
}
&.no-timetable .user_train {
background-color: $no-timetable;
}
&.departed > &_train {
background-color: $departed;
}
&.stopped > &_train {
background-color: $stopped;
}
&.online > &_train {
background-color: $online;
}
&.terminated > &_train {
background-color: $terminated;
}
&.disconnected > &_train {
background-color: $disconnected;
}
&.offline {
background: firebrick;
pointer-events: none;
}
}
</style>
@@ -35,11 +35,7 @@
:key="i + 1" :key="i + 1"
tabindex="0" tabindex="0"
@click="navigateToTrain(scheduledTrain.trainNo)" @click="navigateToTrain(scheduledTrain.trainNo)"
@keydown=" @keydown.enter="navigateToTrain(scheduledTrain.trainNo)"
(e) => {
if (e.keyCode == 13) navigateToTrain(scheduledTrain.trainNo);
}
"
> >
<span class="timetable-general"> <span class="timetable-general">
<span class="general-info"> <span class="general-info">
+1 -1
View File
@@ -38,7 +38,7 @@
v-for="(station, i) in stations" v-for="(station, i) in stations"
:key="i + station.name" :key="i + station.name"
@click="() => setScenery(station.name)" @click="() => setScenery(station.name)"
@keydown="(e) => { if(e.keyCode == 13) setScenery(station.name) }" @keydown.enter="setScenery(station.name)"
tabindex="0" tabindex="0"
> >
<td <td
+7 -12
View File
@@ -18,17 +18,9 @@
v-for="(train, i) in computedTrains" v-for="(train, i) in computedTrains"
:key="i" :key="i"
tabindex="0" tabindex="0"
@keydown=" @keydown.enter="changeScheduleShowState(train.timetableData?.timetableId)"
(e) => {
if (e.keyCode == 13) changeScheduleShowState(train.timetableData?.timetableId); :ref="el => registerReference(el, train.timetableData?.timetableId)"
}
"
:ref="
(el) => {
if (!train.timetableData) return;
elList[train.timetableData.timetableId] = el;
}
"
> >
<div class="wrapper" @click="changeScheduleShowState(train.timetableData?.timetableId)"> <div class="wrapper" @click="changeScheduleShowState(train.timetableData?.timetableId)">
<span class="info"> <span class="info">
@@ -268,6 +260,10 @@ export default defineComponent({
}, 10); }, 10);
}, },
registerReference(el: HTMLElement, timetableId: number | undefined) {
if(timetableId) this.elList[timetableId] = el;
},
focusOnTrain(trainNoStr: string) { focusOnTrain(trainNoStr: string) {
const timetableId = this.computedTrains.find((train) => train.trainNo == Number(trainNoStr))?.timetableData const timetableId = this.computedTrains.find((train) => train.trainNo == Number(trainNoStr))?.timetableData
?.timetableId; ?.timetableId;
@@ -335,7 +331,6 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../styles/responsive.scss'; @import '../../styles/responsive.scss';
@import '../../styles/user_badge.scss';
.unfold { .unfold {
&-leave-active, &-leave-active,
-54
View File
@@ -1,54 +0,0 @@
$no-timetable: #aaa;
$departed: springgreen;
$stopped: #ffa600;
$online: gold;
$terminated: red;
$disconnected: slategray;
.user-badge {
border: 2px solid white;
z-index: 4;
margin-top: 0.5rem;
margin-right: 0.5rem;
border-radius: 0.7em;
padding: 0.3em 0.5em;
font-size: 0.95em;
&.borderless {
border: none;
margin: 0;
padding: 0;
}
&.no-timetable {
border: 2px solid $no-timetable;
a {
color: $no-timetable;
pointer-events: none;
}
}
&.departed {
border: 2px solid $departed;
}
&.stopped {
border: 2px solid $stopped;
}
&.online {
border: 2px solid $online;
}
&.terminated {
border: 2px solid $terminated;
}
&.disconnected {
border: 1px solid $disconnected;
}
}