Migracja z wersji Vue 2 na Vue 3

This commit is contained in:
2021-06-29 02:26:36 +02:00
parent 6391b997b1
commit 26ae065837
49 changed files with 2906 additions and 3279 deletions
-333
View File
@@ -1,333 +0,0 @@
<template>
<div class="history_view">
<div class="history_wrapper">
<div class="header">
<h2>{{ $t("journal.title") }}</h2>
<p style="color: #ccc">
{{ $t("journal.subtitle") }}
</p>
<!-- <select-box
:itemList="filteredStationList"
:title="$t('journal.select')"
@itemSelected="itemSelected"
/> -->
<div class="disclaimer" v-html="$t('journal.disclaimer')"></div>
</div>
<div class="list">
<div class="list_wrapper">
<!-- <div class="list_loading" v-if="dataLoading">POBIERANIE DANYCH...</div> -->
<transition name="list-anim" mode="out-in">
<ul
class="list_content"
v-if="
!dataLoading &&
!historyLoading &&
computedHistoryList.length != 0
"
:key="inputStationName"
>
<li v-if="currentDispatcherFrom != -1" class="current">
<div class="dispatcher-name">
<a
:href="`https://td2.info.pl/profile/?u=${currentDispatcherId}`"
>{{ currentDispatcher }}</a
>
</div>
<div class="dispatcher-date">
<span style="color: #bbb">{{
new Date(currentDispatcherFrom).toLocaleDateString("pl-PL")
}}</span>
{{
new Date(currentDispatcherFrom).toLocaleTimeString(
"pl-PL",
{ hour: "2-digit", minute: "2-digit" }
)
}}
</div>
</li>
<li v-for="(history, i) in computedHistoryList" :key="i">
<div class="dispatcher-name">
<a
:href="`https://td2.info.pl/profile/?u=${history.dispatcherId}`"
>{{ history.dispatcherName }}</a
>
</div>
<div class="dispatcher-date">
<div>
<span style="color: #888">{{
history.dispatcherFromDate
}}</span>
{{ history.dispatcherFromTime }}
</div>
<div>
<span style="color: #888">{{
history.dispatcherToDate
}}</span>
{{ history.dispatcherToTime }}
</div>
</div>
</li>
</ul>
</transition>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import axios from "axios";
import { Component, Vue, Watch } from "vue-property-decorator";
import { Getter } from "vuex-class";
import Station from "@/scripts/interfaces/Station";
import Scenery from "@/scripts/interfaces/Scenery";
import SelectBox from "@/components/Global/SelectBox.vue";
@Component({ components: { SelectBox } })
export default class HistoryView extends Vue {
@Getter("getStationList") stationList!: Station[];
sceneryHistoryList: Scenery[] = [];
currentSceneryHistory: Scenery["dispatcherHistory"] = [];
currentDispatcher: string = "";
currentDispatcherId: number = 0;
currentDispatcherFrom: number = -1;
inputStationName = "";
dataLoading = true; /* Initial data */
historyLoading = false; /* History loaded after input is checked */
async mounted() {
try {
const responseData: Scenery[] = await (
await axios.get(
"https://stacjownik.herokuapp.com/api/getSceneryInfo?items=-1"
)
).data;
this.sceneryHistoryList = responseData;
} catch (error) {
console.error(error);
}
this.dataLoading = false;
}
get filteredStationList() {
return this.sceneryHistoryList
.map((station) => station.stationName)
.sort((a, b) => (a.toLowerCase() >= b.toLowerCase() ? 1 : -1));
}
get computedHistoryList() {
return this.currentSceneryHistory
.map(
({ dispatcherName, dispatcherFrom, dispatcherTo, dispatcherId }) => ({
dispatcherName,
dispatcherFrom,
dispatcherTo,
dispatcherId,
dispatcherFromDate: new Date(dispatcherFrom).toLocaleDateString(
"pl-PL"
),
dispatcherFromTime: new Date(dispatcherFrom).toLocaleTimeString(
"pl-PL",
{ hour: "2-digit", minute: "2-digit" }
),
dispatcherToDate: new Date(dispatcherTo).toLocaleDateString("pl-PL"),
dispatcherToTime: new Date(dispatcherTo).toLocaleTimeString("pl-PL", {
hour: "2-digit",
minute: "2-digit",
}),
})
)
.reverse();
}
async itemSelected(itemName: string) {
try {
this.historyLoading = true;
const selectedScenery: Scenery = await (
await axios.get(
`https://stacjownik.herokuapp.com/api/getSceneryInfo?name=${itemName}&items=10`
)
).data;
this.currentSceneryHistory = selectedScenery.dispatcherHistory;
this.currentDispatcher = selectedScenery.currentDispatcher;
this.currentDispatcherId = selectedScenery.currentDispatcherId;
this.currentDispatcherFrom = selectedScenery.currentDispatcherFrom;
} catch (error) {
console.error(error);
}
this.historyLoading = false;
}
}
</script>
<style scoped lang="scss">
@import "../styles/responsive.scss";
.history {
&_view {
font-size: 1.2em;
}
&_wrapper {
width: 100%;
height: 100%;
text-align: center;
margin-top: 0.5em;
}
}
.list-anim {
&-enter-active,
&-leave-active {
transition: all 150ms ease-out;
}
&-enter,
&-leave-to {
opacity: 0.1;
transform: scale(0.95);
}
&-move {
transition: transform 100ms;
}
}
.disclaimer {
color: #aaa;
}
.search-box {
display: flex;
justify-content: center;
align-items: center;
&_content {
position: relative;
margin: 1em 0;
font-size: 1em;
}
select {
border: none;
font-size: 1em;
background-color: rgb(87, 87, 87);
padding: 0.3em;
padding-right: 50px;
outline: none;
color: white;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
cursor: pointer;
}
label {
position: relative;
&.disabled::after {
color: gray;
}
&::after {
content: "<>";
position: absolute;
top: -5%;
right: 0.3em;
font-weight: bold;
}
}
}
.list {
text-align: center;
margin: 1em 0;
display: flex;
justify-content: center;
&_loading,
&_no-info {
margin: 0.3em 0;
padding: 0.5em 2em;
color: white;
}
&_loading {
background-color: #b96b11;
}
&_no-info {
background-color: firebrick;
}
&_wrapper {
@include smallScreen() {
width: 95%;
font-size: 0.9em;
}
}
&_content {
max-height: 75vh;
overflow: auto;
padding: 0.2em 0.5em;
}
&_content > li {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
background: #222;
padding: 0.3em 0.8em;
margin: 0.3em 0;
gap: 10em;
@include smallScreen() {
gap: 1em;
}
& > div {
margin: 0 1em;
}
&.current {
background: #007200;
}
& > .dispatcher-name {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.1em;
font-weight: 500;
}
}
}
</style>
+51 -36
View File
@@ -11,8 +11,14 @@
</action-button>
</div>
<div class="scenery-wrapper" v-if="stationInfo">
<SceneryInfo :stationInfo="stationInfo" :timetableOnly="timetableOnly" />
<div
class="scenery-wrapper"
v-if="stationInfo"
>
<SceneryInfo
:stationInfo="stationInfo"
:timetableOnly="timetableOnly"
/>
<SceneryTimetable
:stationInfo="stationInfo"
@@ -24,49 +30,58 @@
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import { Getter } from "vuex-class";
import Station from "@/scripts/interfaces/Station";
import { StoreData } from "@/scripts/interfaces/StoreData";
import { DataStatus } from "@/scripts/enums/DataStatus";
import SceneryInfo from "@/components/SceneryView/SceneryInfo.vue";
import SceneryTimetable from "@/components/SceneryView/SceneryTimetable.vue";
import { StoreData } from "@/scripts/interfaces/StoreData";
import { DataStatus } from "@/scripts/enums/DataStatus";
import ActionButton from "@/components/Global/ActionButton.vue";
@Component({
import { computed, ComputedRef, defineComponent } from "@vue/runtime-core";
import { useStore } from "@/store";
import { GETTERS } from "@/constants/storeConstants";
import { useRoute } from "vue-router";
export default defineComponent({
components: { SceneryInfo, SceneryTimetable, ActionButton },
})
export default class SceneryView extends Vue {
@Getter("getAllData") data!: StoreData;
timetableOnly: boolean = false;
setup() {
const route = useRoute();
const store = useStore();
activated() {
this.timetableOnly =
this.$route.query["timetable_only"] == "1" ? true : false;
}
get isComponentVisible() {
return this.$route.path === "/scenery";
}
get isDataLoaded() {
return this.data.dataConnectionStatus == DataStatus.Loaded;
}
get stationInfo(): Station | undefined {
if (!this.$route.query.station) return;
return this.data.stationList.find(
(station) =>
station.stationName ===
this.$route.query.station.toString().replaceAll("_", " ")
const data: ComputedRef<StoreData> = computed(
() => store.getters[GETTERS.allData]
);
}
}
const timetableOnly = computed(() =>
route.query["timetable_only"] == "1" ? true : false
);
const isComponentVisible = computed(() => route.path === "/scenery");
const isDataLoaded = computed(
() => data.value.dataConnectionStatus === DataStatus.Loaded
);
const stationInfo = computed(() => {
if (!route.query.station) return;
return data.value.stationList.find(
(station) =>
station.stationName ===
route.query.station?.toString().replaceAll("_", " ")
);
});
return {
data,
timetableOnly,
isComponentVisible,
isDataLoaded,
stationInfo,
};
},
});
</script>
<style lang="scss" scoped>
+82 -113
View File
@@ -1,14 +1,9 @@
<template>
<div class="stations-view">
<DonationModal
:modalHidden="modalHidden"
@toggleModal="toggleModal"
/>
<div class="wrapper">
<div class="body">
<div class="options-bar">
<action-button @click.native="() => toggleCardsState('filter')">
<action-button @click="() => toggleCardsState('filter')">
<img
class="button_icon"
:src="require('@/assets/icon-filter2.svg')"
@@ -42,7 +37,7 @@
<transition name="card-anim">
<FilterCard
v-if="filterCardOpen"
:showCard="filterCardOpen"
:exit="() => toggleCardsState('filter')"
@changeFilterValue="changeFilterValue"
@resetFilters="resetFilters"
@@ -52,10 +47,6 @@
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import { Getter } from "vuex-class";
import Station from "@/scripts/interfaces/Station";
import StorageManager from "@/scripts/managers/storageManager";
@@ -68,128 +59,106 @@ import FilterCard from "@/components/StationsView/FilterCard.vue";
import ActionButton from "@/components/Global/ActionButton.vue";
import { StoreData } from "@/scripts/interfaces/StoreData";
import { DataStatus } from "@/scripts/enums/DataStatus";
import { computed, ComputedRef, defineComponent, reactive } from "vue";
import { useStore } from "@/store";
import { GETTERS } from "@/constants/storeConstants";
@Component({
export default defineComponent({
components: {
StationTable,
FilterCard,
ActionButton,
},
})
export default class StationsView extends Vue {
STORAGE_KEY: string = "options_saved";
STORAGE_MODAL: string = "modal";
data: () => ({
trainIcon: require("@/assets/icon-train.svg"),
timetableIcon: require("@/assets/icon-timetable.svg"),
dolarIcon: require("@/assets/icon-dolar.svg"),
filterCardOpen: false,
modalHidden: true,
STORAGE_KEY: "options_saved",
inputs: inputData,
}),
setup() {
const store = useStore();
const filterManager = reactive(new StationFilterManager());
const focusedStationName = "";
trainIcon: string = require("@/assets/icon-train.svg");
timetableIcon: string = require("@/assets/icon-timetable.svg");
dolarIcon: string = require("@/assets/icon-dolar.svg");
const data: ComputedRef<StoreData> = computed(
() => store.getters[GETTERS.allData]
);
filterManager: StationFilterManager = new StationFilterManager();
focusedStationName: string = "";
filterCardOpen: boolean = false;
modalHidden: boolean = true;
inputs = inputData;
@Getter("getStationList") stationList!: Station[];
@Getter("getAllData") data!: StoreData;
get dataStatusClass() {
if (this.data.dataConnectionStatus == DataStatus.Loading) return "loading";
if (this.data.dataConnectionStatus == DataStatus.Error) return "error";
return "success";
}
get timetableDataStatusClass() {
if (this.data.timetableDataStatus == DataStatus.Loading) return "loading";
if (this.data.timetableDataStatus == DataStatus.Error) return "error";
return "success";
}
mounted() {
this.initializeOptionsStorage();
// this.initializeModalStorage();
window.addEventListener("keydown", (e: KeyboardEvent) => {
if (e.keyCode == 27 && this.focusedStationName != "") {
this.focusedStationName = "";
}
const computedStations: ComputedRef<Station[]> = computed(() => {
return filterManager.getFilteredStationList(
store.getters[GETTERS.stationList]
);
});
}
initializeOptionsStorage() {
const getStatusClass = computed(() => {
if (data.value.dataConnectionStatus == DataStatus.Loading)
return "loading";
if (data.value.dataConnectionStatus == DataStatus.Error) return "error";
return "success";
});
const timetableDataStatusClass = computed(() => {
if (data.value.timetableDataStatus == DataStatus.Loading)
return "loading";
if (data.value.timetableDataStatus == DataStatus.Error) return "error";
return "success";
});
const focusedStationInfo = computed(() =>
computedStations.value.find(
(station) => station.stationName === focusedStationName
)
);
return {
data,
computedStations,
filterManager,
getStatusClass,
timetableDataStatusClass,
focusedStationName,
focusedStationInfo,
};
},
mounted() {
if (!StorageManager.isRegistered(this.STORAGE_KEY)) return;
this.inputs.options.forEach((option) => {
const value = StorageManager.getBooleanValue(option.name);
this.changeFilterValue({ name: option.name, value: value ? 0 : 1 });
option.value = value;
});
this.inputs.sliders.forEach((slider) => {
const value = StorageManager.getNumericValue(slider.name);
this.changeFilterValue({ name: slider.name, value });
slider.value = value;
});
}
initializeModalStorage() {
if (StorageManager.isRegistered(`${this.STORAGE_MODAL}_hidden`))
this.modalHidden = StorageManager.getBooleanValue(
`${this.STORAGE_MODAL}_hidden`
);
}
toggleModal() {
this.modalHidden = !this.modalHidden;
StorageManager.setBooleanValue(
`${this.STORAGE_MODAL}_hidden`,
this.modalHidden
);
}
toggleCardsState(name: string): void {
if (name == "filter") {
this.filterCardOpen = !this.filterCardOpen;
}
}
changeSorter(index: number) {
this.filterManager.changeSorter(index);
}
changeFilterValue(filter: { name: string; value: number }) {
this.filterManager.changeFilterValue(filter);
}
resetFilters() {
this.filterManager.resetFilters();
}
get computedStations() {
return this.filterManager.getFilteredStationList(this.stationList);
}
closeCard() {
this.focusedStationName = "";
}
setFocusedStation(name: string) {
this.focusedStationName = this.focusedStationName == name ? "" : name;
}
get focusedStationInfo() {
return this.computedStations.find(
(station) => station.stationName === this.focusedStationName
);
}
}
},
methods: {
toggleCardsState(name: string): void {
if (name == "filter") {
this.filterCardOpen = !this.filterCardOpen;
}
},
changeSorter(index: number) {
this.filterManager.changeSorter(index);
},
changeFilterValue(filter: { name: string; value: number }) {
this.filterManager.changeFilterValue(filter);
},
resetFilters() {
this.filterManager.resetFilters();
},
closeCard() {
this.focusedStationName = "";
},
setFocusedStation(name: string) {
this.focusedStationName = this.focusedStationName == name ? "" : name;
},
},
});
</script>
<style lang="scss" scoped>
@@ -202,7 +171,7 @@ export default class StationsView extends Vue {
transition: all $animDuration $animType;
}
&-enter,
&-enter-from,
&-leave-to {
transform: translate(-50%, -50%) scale(0.85);
opacity: 0;
+110 -78
View File
@@ -2,11 +2,14 @@
<section class="trains-view">
<div class="wrapper">
<div class="options-bar">
<TrainStats :trains="trains" :trainStatsOpen="trainStatsOpen" />
<TrainStats
:trains="trainList"
:trainStatsOpen="trainStatsOpen"
/>
<TrainOptions
:queryTrain="queryTrain"
@change-sorter="changeSorter"
@changeSorter="changeSorter"
@changeSearchedTrain="changeSearchedTrain"
@changeSearchedDriver="changeSearchedDriver"
/>
@@ -14,7 +17,6 @@
<TrainTable
:computedTrains="computedTrains"
:timetableDataStatus="timetableDataStatus"
:queryTrain="queryTrain"
/>
</div>
@@ -22,105 +24,135 @@
</template>
<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { Getter } from "vuex-class";
import { computed, ComputedRef, defineComponent, ref } from "vue";
import { DataStatus } from "@/scripts/enums/DataStatus";
import Train from "@/scripts/interfaces/Train";
import TrainTable from "@/components/TrainsView/TrainTable.vue";
import TrainStats from "@/components/TrainsView/TrainStats.vue";
import TrainOptions from "@/components/TrainsView/TrainOptions.vue";
import ActionButton from "@/components/Global/ActionButton.vue";
import { DataStatus } from "@/scripts/enums/DataStatus";
@Component({
import { useStore } from "@/store";
import { GETTERS } from "@/constants/storeConstants";
const filteredTrainList = (
trainList: Train[],
searchedTrain: string,
searchedDriver: string,
sorterActive: { id: string; dir: number }
) => {
return trainList
.filter(
(train) =>
train.online &&
(searchedTrain.length > 0
? train.trainNo.toString().includes(searchedTrain)
: true) &&
(searchedDriver.length > 0
? train.driverName
.toLowerCase()
.includes(searchedDriver.toLowerCase())
: true)
)
.sort((a: Train, b: Train) => {
switch (sorterActive.id) {
case "mass":
if (a.mass > b.mass) return sorterActive.dir;
return -sorterActive.dir;
case "distance":
if (
(a.timetableData?.routeDistance || -1) >
(b.timetableData?.routeDistance || -1)
)
return sorterActive.dir;
return -sorterActive.dir;
case "speed":
if (a.speed > b.speed) return sorterActive.dir;
return -sorterActive.dir;
case "timetable":
if (a.trainNo > b.trainNo) return sorterActive.dir;
return -sorterActive.dir;
case "length":
if (a.length > b.length) return sorterActive.dir;
return -sorterActive.dir;
default:
break;
}
return 0;
});
};
export default defineComponent({
components: {
TrainTable,
TrainStats,
TrainOptions,
ActionButton,
},
})
export default class TrainsView extends Vue {
@Getter("getTrainList") trains!: Train[];
@Getter("getTimetableDataStatus") timetableDataStatus!: DataStatus;
// Passed in route as query parameters
@Prop() readonly queryTrain!: string;
props: ["queryTrain"],
statsIcon = require("@/assets/icon-stats.svg");
data: () => ({
statsIcon: require("@/assets/icon-stats.svg"),
trainStatsOpen: false,
}),
sorterActive: { id: string; dir: number } = { id: "distance", dir: -1 };
setup() {
const store = useStore();
trainStatsOpen: boolean = false;
const trainList: ComputedRef<Train[]> = computed(
() => store.getters[GETTERS.trainList]
);
searchedTrain: string = "";
searchedDriver: string = "";
const timetableDataStatus: ComputedRef<DataStatus> = computed(
() => store.getters[GETTERS.timetableDataStatus]
);
changeSearchedTrain(trainNo: string) {
this.searchedTrain = trainNo;
}
const sorterActive = ref({ id: "distance", dir: -1 });
const searchedDriver = ref("");
const searchedTrain = ref("");
changeSearchedDriver(name: string) {
this.searchedDriver = name;
}
const computedTrains: ComputedRef<Train[]> = computed(() => {
if (timetableDataStatus.value != DataStatus.Loaded) return [];
changeSorter(sorter: { id: string; dir: number }) {
this.sorterActive = sorter;
}
return filteredTrainList(
trainList.value,
searchedTrain.value,
searchedDriver.value,
sorterActive.value
);
});
get computedTrains() {
return this.timetableDataStatus != DataStatus.Loaded
? []
: this.trains
.filter(
(train) =>
train.online &&
(this.searchedTrain.length > 0
? train.trainNo.toString().includes(this.searchedTrain)
: true) &&
(this.searchedDriver.length > 0
? train.driverName
.toLowerCase()
.includes(this.searchedDriver.toLowerCase())
: true)
)
.sort((a, b) => {
switch (this.sorterActive.id) {
case "mass":
if (a.mass > b.mass) return this.sorterActive.dir;
return -this.sorterActive.dir;
return {
trainList,
computedTrains,
searchedTrain,
searchedDriver,
sorterActive,
};
},
case "distance":
if (
(a.timetableData?.routeDistance || -1) >
(b.timetableData?.routeDistance || -1)
)
return this.sorterActive.dir;
methods: {
changeSearchedTrain(trainNo: string) {
this.searchedTrain = trainNo;
},
return -this.sorterActive.dir;
changeSearchedDriver(name: string) {
this.searchedDriver = name;
},
case "speed":
if (a.speed > b.speed) return this.sorterActive.dir;
return -this.sorterActive.dir;
case "timetable":
if (a.trainNo > b.trainNo) return this.sorterActive.dir;
return -this.sorterActive.dir;
case "length":
if (a.length > b.length) return this.sorterActive.dir;
return -this.sorterActive.dir;
default:
break;
}
return 0;
});
}
}
changeSorter(sorter: { id: string; dir: number }) {
this.sorterActive = sorter;
},
},
});
</script>
<style lang="scss" scoped>