mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Cleanup i restrukturyzacja widoku scenerii
This commit is contained in:
@@ -1,189 +1,49 @@
|
||||
<template>
|
||||
<div class="scenery-info">
|
||||
<div 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>
|
||||
</div>
|
||||
<!-- info header -->
|
||||
<scenery-info-header :station="station" />
|
||||
|
||||
<section v-if="!timetableOnly">
|
||||
<div class="info-stats" :class="!station.onlineInfo ? 'no-stats' : ''">
|
||||
<span class="likes">
|
||||
<img :src="likeIcon" alt="icon-like" />
|
||||
<span>{{ station.onlineInfo?.dispatcherRate || '0' }}</span>
|
||||
</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 stats -->
|
||||
<scenery-info-stats :station="station" />
|
||||
<!-- info icons -->
|
||||
<scenery-info-icons :station="station" />
|
||||
|
||||
<!-- info dispatcher -->
|
||||
<scenery-info-dispatcher :station="station" />
|
||||
|
||||
<div class="info-lists">
|
||||
<div class="user-list">
|
||||
<h3 class="user-header">
|
||||
{{ $t('scenery.users') }}
|
||||
<img :src="userIcon" alt="icon-user" />
|
||||
</h3>
|
||||
<!-- user list -->
|
||||
<scenery-info-user-list :station="station" />
|
||||
|
||||
<div
|
||||
v-for="(train, i) in computedStationTrains"
|
||||
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>
|
||||
<!-- spawn list -->
|
||||
<scenery-info-spawn-list :station="station" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Station from '@/scripts/interfaces/Station';
|
||||
import styleMixin from '@/mixins/styleMixin';
|
||||
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({
|
||||
components: {
|
||||
SceneryInfoDispatcher,
|
||||
SceneryInfoIcons,
|
||||
SceneryInfoStats,
|
||||
SceneryInfoHeader,
|
||||
SceneryInfoUserList,
|
||||
SceneryInfoSpawnList,
|
||||
},
|
||||
props: {
|
||||
station: {
|
||||
type: Object as () => Station,
|
||||
@@ -192,63 +52,13 @@ export default defineComponent({
|
||||
|
||||
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>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss">
|
||||
@import '../../styles/responsive.scss';
|
||||
@import '../../styles/user_badge.scss';
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
h3 {
|
||||
h3.section-header {
|
||||
margin: 0.5em 0;
|
||||
padding: 0.3em;
|
||||
|
||||
@@ -264,123 +74,14 @@ h3 {
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
&-header {
|
||||
padding: 2em 1em;
|
||||
.info-lists {
|
||||
display: flex;
|
||||
|
||||
& > .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;
|
||||
}
|
||||
}
|
||||
|
||||
&-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.user,
|
||||
.spawn {
|
||||
.badge {
|
||||
font-weight: 600;
|
||||
|
||||
display: inline-block;
|
||||
@@ -394,68 +95,18 @@ h3 {
|
||||
display: inline-block;
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
.user {
|
||||
cursor: pointer;
|
||||
&-none {
|
||||
font-weight: 600;
|
||||
|
||||
&_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 {
|
||||
padding: 0.2em 0.4em;
|
||||
background: firebrick;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.spawn {
|
||||
&_length {
|
||||
background: $accentCol;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
text-align: center;
|
||||
|
||||
.spawn.none,
|
||||
.user.offline {
|
||||
font-weight: 600;
|
||||
|
||||
padding: 0.2em 0.4em;
|
||||
background: firebrick;
|
||||
|
||||
text-align: center;
|
||||
|
||||
@include smallScreen() {
|
||||
font-size: 1em;
|
||||
@include smallScreen() {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</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"
|
||||
tabindex="0"
|
||||
@click="navigateToTrain(scheduledTrain.trainNo)"
|
||||
@keydown="
|
||||
(e) => {
|
||||
if (e.keyCode == 13) navigateToTrain(scheduledTrain.trainNo);
|
||||
}
|
||||
"
|
||||
@keydown.enter="navigateToTrain(scheduledTrain.trainNo)"
|
||||
>
|
||||
<span class="timetable-general">
|
||||
<span class="general-info">
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
v-for="(station, i) in stations"
|
||||
:key="i + station.name"
|
||||
@click="() => setScenery(station.name)"
|
||||
@keydown="(e) => { if(e.keyCode == 13) setScenery(station.name) }"
|
||||
@keydown.enter="setScenery(station.name)"
|
||||
tabindex="0"
|
||||
>
|
||||
<td
|
||||
|
||||
@@ -18,17 +18,9 @@
|
||||
v-for="(train, i) in computedTrains"
|
||||
:key="i"
|
||||
tabindex="0"
|
||||
@keydown="
|
||||
(e) => {
|
||||
if (e.keyCode == 13) changeScheduleShowState(train.timetableData?.timetableId);
|
||||
}
|
||||
"
|
||||
:ref="
|
||||
(el) => {
|
||||
if (!train.timetableData) return;
|
||||
elList[train.timetableData.timetableId] = el;
|
||||
}
|
||||
"
|
||||
@keydown.enter="changeScheduleShowState(train.timetableData?.timetableId)"
|
||||
|
||||
:ref="el => registerReference(el, train.timetableData?.timetableId)"
|
||||
>
|
||||
<div class="wrapper" @click="changeScheduleShowState(train.timetableData?.timetableId)">
|
||||
<span class="info">
|
||||
@@ -268,6 +260,10 @@ export default defineComponent({
|
||||
}, 10);
|
||||
},
|
||||
|
||||
registerReference(el: HTMLElement, timetableId: number | undefined) {
|
||||
if(timetableId) this.elList[timetableId] = el;
|
||||
},
|
||||
|
||||
focusOnTrain(trainNoStr: string) {
|
||||
const timetableId = this.computedTrains.find((train) => train.trainNo == Number(trainNoStr))?.timetableData
|
||||
?.timetableId;
|
||||
@@ -335,7 +331,6 @@ export default defineComponent({
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../styles/responsive.scss';
|
||||
@import '../../styles/user_badge.scss';
|
||||
|
||||
.unfold {
|
||||
&-leave-active,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user