reorder typów danych

This commit is contained in:
2023-06-04 00:33:43 +02:00
parent d32d5ad91b
commit 266edfd6e6
16 changed files with 611 additions and 605 deletions
@@ -100,7 +100,7 @@ import { DataStatus } from '../../scripts/enums/DataStatus';
import { DriverStatsAPIData } from '../../scripts/interfaces/api/DriverStatsAPIData'; import { DriverStatsAPIData } from '../../scripts/interfaces/api/DriverStatsAPIData';
import { URLs } from '../../scripts/utils/apiURLs'; import { URLs } from '../../scripts/utils/apiURLs';
import { useStore } from '../../store/store'; import { useStore } from '../../store/store';
import { JournalTimetableFilter } from '../../types/Journal/JournalTimetablesTypes'; import { JournalTimetableFilter } from '../../scripts/types/JournalTimetablesTypes';
import ActionButton from '../Global/ActionButton.vue'; import ActionButton from '../Global/ActionButton.vue';
import SelectBox from '../Global/SelectBox.vue'; import SelectBox from '../Global/SelectBox.vue';
import { JournalFilterSection } from '../../scripts/enums/JournalFilterType'; import { JournalFilterSection } from '../../scripts/enums/JournalFilterType';
+1 -1
View File
@@ -82,10 +82,10 @@
import { defineComponent, inject, PropType } from 'vue'; import { defineComponent, inject, PropType } from 'vue';
import imageMixin from '../../mixins/imageMixin'; import imageMixin from '../../mixins/imageMixin';
import keyMixin from '../../mixins/keyMixin'; import keyMixin from '../../mixins/keyMixin';
import { TrainFilter } from '../../types/Trains/TrainOptionsTypes';
import ActionButton from '../Global/ActionButton.vue'; import ActionButton from '../Global/ActionButton.vue';
import SelectBox from '../Global/SelectBox.vue'; import SelectBox from '../Global/SelectBox.vue';
import { TrainFilterSection } from '../../scripts/enums/TrainFilterType'; import { TrainFilterSection } from '../../scripts/enums/TrainFilterType';
import { TrainFilter } from '../../scripts/interfaces/Trains/TrainFilter';
export default defineComponent({ export default defineComponent({
components: { SelectBox, ActionButton }, components: { SelectBox, ActionButton },
@@ -1,5 +1,5 @@
import { JournalFilterSection, JournalFilterType } from '../../scripts/enums/JournalFilterType'; import { JournalFilterSection, JournalFilterType } from '../../scripts/enums/JournalFilterType';
import { JournalTimetableFilter } from '../../types/Journal/JournalTimetablesTypes'; import { JournalTimetableFilter } from '../../scripts/types/JournalTimetablesTypes';
export const journalTimetableFilters: JournalTimetableFilter[] = [ export const journalTimetableFilters: JournalTimetableFilter[] = [
{ {
+1 -1
View File
@@ -1,5 +1,5 @@
import { TrainFilterSection, TrainFilterType } from '../../scripts/enums/TrainFilterType'; import { TrainFilterSection, TrainFilterType } from '../../scripts/enums/TrainFilterType';
import { TrainFilter } from '../../types/Trains/TrainOptionsTypes'; import { TrainFilter } from '../../scripts/interfaces/Trains/TrainFilter';
export const trainFilters: TrainFilter[] = [ export const trainFilters: TrainFilter[] = [
{ {
@@ -1,49 +1,49 @@
import Filter from "../../scripts/interfaces/Filter"; import Filter from "../../interfaces/Filter";
export const filterInitStates: Filter = { export const filterInitStates: Filter = {
default: false, default: false,
notDefault: false, notDefault: false,
real: false, real: false,
fictional: false, fictional: false,
SPK: false, SPK: false,
SCS: false, SCS: false,
SPE: false, SPE: false,
SUP: false, SUP: false,
noSUP: false, noSUP: false,
ręczne: false, ręczne: false,
'ręczne+SPK': false, 'ręczne+SPK': false,
'ręczne+SCS': false, 'ręczne+SCS': false,
mechaniczne: false, mechaniczne: false,
'mechaniczne+SPK': false, 'mechaniczne+SPK': false,
'mechaniczne+SCS': false, 'mechaniczne+SCS': false,
współczesna: false, współczesna: false,
kształtowa: false, kształtowa: false,
historyczna: false, historyczna: false,
mieszana: false, mieszana: false,
SBL: false, SBL: false,
PBL: false, PBL: false,
minLevel: 0, minLevel: 0,
maxLevel: 20, maxLevel: 20,
minOneWayCatenary: 0, minOneWayCatenary: 0,
minOneWay: 0, minOneWay: 0,
minTwoWayCatenary: 0, minTwoWayCatenary: 0,
minTwoWay: 0, minTwoWay: 0,
'include-selected': false, 'include-selected': false,
'no-1track': false, 'no-1track': false,
'no-2track': false, 'no-2track': false,
free: true, free: true,
occupied: false, occupied: false,
ending: false, ending: false,
nonPublic: false, nonPublic: false,
unavailable: true, unavailable: true,
abandoned: true, abandoned: true,
afkStatus: false, afkStatus: false,
endingStatus: false, endingStatus: false,
noSpaceStatus: false, noSpaceStatus: false,
unavailableStatus: false, unavailableStatus: false,
unsignedStatus: false, unsignedStatus: false,
authors: '', authors: '',
onlineFromHours: 0, onlineFromHours: 0,
}; };
@@ -1,4 +1,4 @@
import { TrainFilterSection, TrainFilterType } from '../../scripts/enums/TrainFilterType'; import { TrainFilterSection, TrainFilterType } from '../../enums/TrainFilterType'
export interface TrainFilter { export interface TrainFilter {
id: TrainFilterType; id: TrainFilterType;
@@ -1,4 +1,4 @@
import { JournalTimetableSorter } from '../../../types/Journal/JournalTimetablesTypes'; import { JournalTimetableSorter } from '../../types/JournalTimetablesTypes';
export interface TimetablesQueryParams { export interface TimetablesQueryParams {
driverName?: string; driverName?: string;
+1 -1
View File
@@ -1,4 +1,4 @@
import { TrainFilter } from '../../types/Trains/TrainOptionsTypes'; import { TrainFilter } from '../interfaces/Trains/TrainFilter';
import { TrainFilterType } from '../enums/TrainFilterType'; import { TrainFilterType } from '../enums/TrainFilterType';
import Train from '../interfaces/Train'; import Train from '../interfaces/Train';
import TrainStop from '../interfaces/TrainStop'; import TrainStop from '../interfaces/TrainStop';
@@ -1,4 +1,4 @@
import { JournalFilterSection, JournalFilterType } from '../../scripts/enums/JournalFilterType'; import { JournalFilterSection, JournalFilterType } from '../enums/JournalFilterType';
export type JournalTimetableSearchKey = export type JournalTimetableSearchKey =
| 'search-driver' | 'search-driver'
@@ -1,156 +1,156 @@
import { HeadIdsTypes } from '../../scripts/data/stationHeaderNames'; import { HeadIdsTypes } from '../data/stationHeaderNames';
import Filter from '../../scripts/interfaces/Filter'; import Filter from '../interfaces/Filter';
import Station from '../../scripts/interfaces/Station'; import Station from '../interfaces/Station';
export const sortStations = (a: Station, b: Station, sorter: { headerName: HeadIdsTypes; dir: number }) => { export const sortStations = (a: Station, b: Station, sorter: { headerName: HeadIdsTypes; dir: number }) => {
let diff = 0; let diff = 0;
switch (sorter.headerName) { switch (sorter.headerName) {
case 'station': 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 'min-lvl': case 'min-lvl':
diff = (a.generalInfo?.reqLevel || 0) - (b.generalInfo?.reqLevel || 0); diff = (a.generalInfo?.reqLevel || 0) - (b.generalInfo?.reqLevel || 0);
break; break;
case 'status': case 'status':
diff = (a.onlineInfo?.statusTimestamp || 0) - (b.onlineInfo?.statusTimestamp || 0); diff = (a.onlineInfo?.statusTimestamp || 0) - (b.onlineInfo?.statusTimestamp || 0);
break; break;
case 'dispatcher': 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 'dispatcher-lvl': case 'dispatcher-lvl':
diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0); diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0);
break; break;
case 'user': case 'user':
diff = (b.onlineInfo ? b.onlineInfo.currentUsers : -1) - (a.onlineInfo ? a.onlineInfo.currentUsers : -1); diff = (b.onlineInfo ? b.onlineInfo.currentUsers : -1) - (a.onlineInfo ? a.onlineInfo.currentUsers : -1);
break; break;
case 'spawn': case 'spawn':
diff = (a.onlineInfo ? a.onlineInfo.spawns.length : -1) - (b.onlineInfo ? b.onlineInfo.spawns.length : -1); diff = (a.onlineInfo ? a.onlineInfo.spawns.length : -1) - (b.onlineInfo ? b.onlineInfo.spawns.length : -1);
break; break;
case 'timetableConfirmed': case 'timetableConfirmed':
diff = diff =
(a.onlineInfo?.scheduledTrains (a.onlineInfo?.scheduledTrains
? a.onlineInfo.scheduledTrains.filter((train) => train.stopInfo.confirmed).length ? a.onlineInfo.scheduledTrains.filter((train) => train.stopInfo.confirmed).length
: -1) - : -1) -
(b.onlineInfo?.scheduledTrains (b.onlineInfo?.scheduledTrains
? b.onlineInfo.scheduledTrains.filter((train) => train.stopInfo.confirmed).length ? b.onlineInfo.scheduledTrains.filter((train) => train.stopInfo.confirmed).length
: -1); : -1);
break; break;
case 'timetableUnconfirmed': case 'timetableUnconfirmed':
diff = diff =
(a.onlineInfo?.scheduledTrains (a.onlineInfo?.scheduledTrains
? a.onlineInfo.scheduledTrains.filter((train) => !train.stopInfo.confirmed).length ? a.onlineInfo.scheduledTrains.filter((train) => !train.stopInfo.confirmed).length
: -1) - : -1) -
(b.onlineInfo?.scheduledTrains (b.onlineInfo?.scheduledTrains
? b.onlineInfo.scheduledTrains.filter((train) => !train.stopInfo.confirmed).length ? b.onlineInfo.scheduledTrains.filter((train) => !train.stopInfo.confirmed).length
: -1); : -1);
break; break;
case 'timetableAll': case 'timetableAll':
diff = diff =
(a.onlineInfo?.scheduledTrains ? a.onlineInfo.scheduledTrains.length : -1) - (a.onlineInfo?.scheduledTrains ? a.onlineInfo.scheduledTrains.length : -1) -
(b.onlineInfo?.scheduledTrains ? b.onlineInfo.scheduledTrains.length : -1); (b.onlineInfo?.scheduledTrains ? b.onlineInfo.scheduledTrains.length : -1);
break; break;
default: default:
break; break;
} }
if (diff != 0) return Math.sign(diff) * sorter.dir; if (diff != 0) return Math.sign(diff) * sorter.dir;
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
}; };
export const filterStations = (station: Station, filters: Filter) => { export const filterStations = (station: Station, filters: Filter) => {
if (!station.onlineInfo && filters['free']) return false; if (!station.onlineInfo && filters['free']) return false;
if (station.onlineInfo) { if (station.onlineInfo) {
const { statusID, statusTimestamp } = station.onlineInfo; const { statusID, statusTimestamp } = station.onlineInfo;
const isEnding = statusID == 'ending' && filters['endingStatus']; const isEnding = statusID == 'ending' && filters['endingStatus'];
const isNotSigned = (statusID == 'not-signed' || statusID == 'unavailable') && filters['unavailableStatus']; const isNotSigned = (statusID == 'not-signed' || statusID == 'unavailable') && filters['unavailableStatus'];
const isAFK = statusID == 'brb' && filters['afkStatus']; const isAFK = statusID == 'brb' && filters['afkStatus'];
const isNoSpace = statusID == 'no-space' && filters['noSpaceStatus']; const isNoSpace = statusID == 'no-space' && filters['noSpaceStatus'];
const isOccupied = station.onlineInfo && filters['occupied']; const isOccupied = station.onlineInfo && filters['occupied'];
const isOnlineInBounds = const isOnlineInBounds =
(filters['onlineFromHours'] < 8 && (filters['onlineFromHours'] < 8 &&
statusTimestamp > 0 && statusTimestamp > 0 &&
statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000) || statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000) ||
(filters['onlineFromHours'] > 0 && statusTimestamp <= 0) || (filters['onlineFromHours'] > 0 && statusTimestamp <= 0) ||
(filters['onlineFromHours'] == 8 && statusID != 'no-limit'); (filters['onlineFromHours'] == 8 && statusID != 'no-limit');
if (isEnding || isOnlineInBounds || isNotSigned || isAFK || isNoSpace || isOccupied) return false; if (isEnding || isOnlineInBounds || isNotSigned || isAFK || isNoSpace || isOccupied) return false;
} }
if ((station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && filters['nonPublic']) return false; if ((station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && filters['nonPublic']) return false;
if (station.generalInfo) { if (station.generalInfo) {
const { routes, availability, controlType, lines, reqLevel, signalType, SUP, authors } = station.generalInfo; const { routes, availability, controlType, lines, reqLevel, signalType, SUP, authors } = station.generalInfo;
if (availability == 'unavailable' && filters['unavailable'] && !station.onlineInfo) return false; if (availability == 'unavailable' && filters['unavailable'] && !station.onlineInfo) return false;
if (availability == 'abandoned' && filters['abandoned'] && !station.onlineInfo) return false; if (availability == 'abandoned' && filters['abandoned'] && !station.onlineInfo) return false;
if (availability == 'default' && filters['default']) return false; if (availability == 'default' && filters['default']) return false;
if ( if (
availability != 'default' && availability != 'default' &&
filters['notDefault'] && filters['notDefault'] &&
!(availability == 'abandoned' || availability == 'unavailable') !(availability == 'abandoned' || availability == 'unavailable')
) )
return false; return false;
if (filters['real'] && lines) return false; if (filters['real'] && lines) return false;
if (filters['fictional'] && !lines) return false; if (filters['fictional'] && !lines) return false;
const otherAvailability = const otherAvailability =
availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned'; availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned';
if (reqLevel + (otherAvailability ? 1 : 0) < filters['minLevel']) return false; if (reqLevel + (otherAvailability ? 1 : 0) < filters['minLevel']) return false;
if (reqLevel + (otherAvailability ? 1 : 0) > filters['maxLevel']) return false; if (reqLevel + (otherAvailability ? 1 : 0) > filters['maxLevel']) return false;
if ( if (
filters['no-1track'] && filters['no-1track'] &&
(routes.oneWayCatenaryRouteNames.length != 0 || routes.oneWayNoCatenaryRouteNames.length != 0) (routes.oneWayCatenaryRouteNames.length != 0 || routes.oneWayNoCatenaryRouteNames.length != 0)
) )
return false; return false;
if ( if (
filters['no-2track'] && filters['no-2track'] &&
(routes.twoWayCatenaryRouteNames.length != 0 || routes.twoWayNoCatenaryRouteNames.length != 0) (routes.twoWayCatenaryRouteNames.length != 0 || routes.twoWayNoCatenaryRouteNames.length != 0)
) )
return false; return false;
if (routes.oneWayCatenaryRouteNames.length < filters['minOneWayCatenary']) return false; if (routes.oneWayCatenaryRouteNames.length < filters['minOneWayCatenary']) return false;
if (routes.oneWayNoCatenaryRouteNames.length < filters['minOneWay']) return false; if (routes.oneWayNoCatenaryRouteNames.length < filters['minOneWay']) return false;
if (routes.twoWayCatenaryRouteNames.length < filters['minTwoWayCatenary']) return false; if (routes.twoWayCatenaryRouteNames.length < filters['minTwoWayCatenary']) return false;
if (routes.twoWayNoCatenaryRouteNames.length < filters['minTwoWay']) return false; if (routes.twoWayNoCatenaryRouteNames.length < filters['minTwoWay']) return false;
if (filters[controlType]) return false; if (filters[controlType]) return false;
if (filters[signalType]) return false; if (filters[signalType]) return false;
if (filters['SUP'] && SUP) return false; if (filters['SUP'] && SUP) return false;
if (filters['noSUP'] && !SUP) return false; if (filters['noSUP'] && !SUP) return false;
if (filters['SBL'] && routes.sblRouteNames.length > 0) return false; if (filters['SBL'] && routes.sblRouteNames.length > 0) return false;
if (filters['PBL'] && routes.sblRouteNames.length == 0) return false; if (filters['PBL'] && routes.sblRouteNames.length == 0) return false;
if ( if (
filters['authors'].length > 3 && filters['authors'].length > 3 &&
!authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase()) !authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase())
) )
return false; return false;
} }
return true; return true;
}; };
+6
View File
@@ -0,0 +1,6 @@
import { defineStore } from 'pinia';
export const useJournalFiltersStore = defineStore('journalFiltersStore', {
state: () => ({}),
});
+99 -99
View File
@@ -1,99 +1,99 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import inputData from '../data/options.json'; import inputData from '../data/options.json';
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 '../scripts/constants/stores/initFilterStates';
import { filterStations, sortStations } from './utils/filterUtils'; import { filterStations, sortStations } from '../scripts/utils/filterUtils';
import { HeadIdsTypes } from '../scripts/data/stationHeaderNames'; 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: { headerName: 'station' as HeadIdsTypes, dir: 1 }, sorterActive: { headerName: 'station' as HeadIdsTypes, dir: 1 },
store: useStore(), store: useStore(),
lastClickedFilterId: '', lastClickedFilterId: '',
}; };
}, },
getters: { getters: {
areFiltersAtDefault(state) { areFiltersAtDefault(state) {
return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]); return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]);
}, },
}, },
actions: { actions: {
getFilteredStationList(stationList: Station[], region: string): Station[] { getFilteredStationList(stationList: Station[], region: string): Station[] {
return stationList return stationList
.map((station) => { .map((station) => {
if (station.onlineInfo && station.onlineInfo.region != region) { if (station.onlineInfo && station.onlineInfo.region != region) {
delete station.onlineInfo; delete station.onlineInfo;
} }
return station; return station;
}) })
.filter((station) => filterStations(station, this.filters)) .filter((station) => filterStations(station, this.filters))
.sort((a, b) => sortStations(a, b, this.sorterActive)); .sort((a, b) => sortStations(a, b, this.sorterActive));
}, },
setupFilters() { setupFilters() {
if (!StorageManager.isRegistered('options_saved')) return; if (!StorageManager.isRegistered('options_saved')) return;
this.inputs.options.forEach((option) => { this.inputs.options.forEach((option) => {
if (!StorageManager.isRegistered(option.name)) return; if (!StorageManager.isRegistered(option.name)) return;
const savedValue = StorageManager.getBooleanValue(option.name); const savedValue = StorageManager.getBooleanValue(option.name);
this.filters[option.name] = savedValue; this.filters[option.name] = savedValue;
option.value = !savedValue; option.value = !savedValue;
}); });
this.inputs.sliders.forEach((slider) => { this.inputs.sliders.forEach((slider) => {
if (!StorageManager.isRegistered(slider.name)) return; if (!StorageManager.isRegistered(slider.name)) return;
const savedValue = StorageManager.getNumericValue(slider.name); const savedValue = StorageManager.getNumericValue(slider.name);
this.filters[slider.name] = savedValue; this.filters[slider.name] = savedValue;
slider.value = savedValue; slider.value = savedValue;
}); });
}, },
changeFilterValue(filter: { name: string; value: any }) { changeFilterValue(filter: { name: string; value: any }) {
this.filters[filter.name] = filter.value; this.filters[filter.name] = filter.value;
if (StorageManager.isRegistered('options_saved')) StorageManager.setValue(filter.name, filter.value); if (StorageManager.isRegistered('options_saved')) StorageManager.setValue(filter.name, filter.value);
}, },
resetFilters() { resetFilters() {
this.filters = { ...filterInitStates }; this.filters = { ...filterInitStates };
this.inputs.options.forEach((option) => { this.inputs.options.forEach((option) => {
option.value = option.defaultValue; option.value = option.defaultValue;
StorageManager.setBooleanValue(option.name, !option.defaultValue); StorageManager.setBooleanValue(option.name, !option.defaultValue);
}); });
this.inputs.sliders.forEach((slider) => { this.inputs.sliders.forEach((slider) => {
slider.value = slider.defaultValue; slider.value = slider.defaultValue;
StorageManager.setNumericValue(slider.name, slider.defaultValue); StorageManager.setNumericValue(slider.name, slider.defaultValue);
}); });
}, },
resetSectionOptions(section: string) { resetSectionOptions(section: string) {
this.inputs.options.forEach((option) => { this.inputs.options.forEach((option) => {
if (option.section != section) return; if (option.section != section) return;
option.value = option.defaultValue; option.value = option.defaultValue;
this.filters[option.id] = !option.defaultValue; this.filters[option.id] = !option.defaultValue;
StorageManager.setBooleanValue(option.name, !option.defaultValue); StorageManager.setBooleanValue(option.name, !option.defaultValue);
}); });
}, },
changeSorter(headerName: HeadIdsTypes) { changeSorter(headerName: HeadIdsTypes) {
if (headerName == this.sorterActive.headerName) this.sorterActive.dir = -1 * this.sorterActive.dir; if (headerName == this.sorterActive.headerName) this.sorterActive.dir = -1 * this.sorterActive.dir;
else this.sorterActive.dir = 1; else this.sorterActive.dir = 1;
this.sorterActive.headerName = headerName; this.sorterActive.headerName = headerName;
}, },
}, },
}); });
+290 -290
View File
@@ -1,290 +1,290 @@
<template> <template>
<section class="journal-timetables"> <section class="journal-timetables">
<JournalHeader /> <JournalHeader />
<div class="journal_wrapper"> <div class="journal_wrapper">
<JournalOptions <JournalOptions
@on-search-confirm="fetchHistoryData" @on-search-confirm="fetchHistoryData"
@on-options-reset="resetOptions" @on-options-reset="resetOptions"
@on-refresh-data="fetchHistoryData" @on-refresh-data="fetchHistoryData"
:sorter-option-ids="['timestampFrom', 'duration']" :sorter-option-ids="['timestampFrom', 'duration']"
:data-status="dataStatus" :data-status="dataStatus"
:current-options-active="currentOptionsActive" :current-options-active="currentOptionsActive"
optionsType="dispatchers" optionsType="dispatchers"
/> />
<div class="list_wrapper" @scroll="handleScroll"> <div class="list_wrapper" @scroll="handleScroll">
<transition name="status-anim" mode="out-in"> <transition name="status-anim" mode="out-in">
<div :key="dataStatus"> <div :key="dataStatus">
<div class="journal_warning" v-if="store.isOffline"> <div class="journal_warning" v-if="store.isOffline">
{{ $t('app.offline') }} {{ $t('app.offline') }}
</div> </div>
<Loading v-else-if="dataStatus == DataStatus.Loading" /> <Loading v-else-if="dataStatus == DataStatus.Loading" />
<div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error"> <div v-else-if="dataStatus == DataStatus.Error" class="journal_warning error">
{{ $t('app.error') }} {{ $t('app.error') }}
</div> </div>
<div class="journal_warning" v-else-if="historyList.length == 0"> <div class="journal_warning" v-else-if="historyList.length == 0">
{{ $t('app.no-result') }} {{ $t('app.no-result') }}
</div> </div>
<div v-else> <div v-else>
<JournalDispatchersList :dispatcherHistory="computedHistoryList" /> <JournalDispatchersList :dispatcherHistory="computedHistoryList" />
<button <button
class="btn btn--option btn--load-data" class="btn btn--option btn--load-data"
v-if="!scrollNoMoreData && scrollDataLoaded && computedHistoryList.length > 15" v-if="!scrollNoMoreData && scrollDataLoaded && computedHistoryList.length > 15"
@click="addHistoryData" @click="addHistoryData"
> >
{{ $t('journal.load-data') }} {{ $t('journal.load-data') }}
</button> </button>
</div> </div>
</div> </div>
</transition> </transition>
<div class="journal_warning" v-if="scrollNoMoreData"> <div class="journal_warning" v-if="scrollNoMoreData">
{{ $t('journal.no-further-data') }} {{ $t('journal.no-further-data') }}
</div> </div>
<div class="journal_warning" v-else-if="!scrollDataLoaded"> <div class="journal_warning" v-else-if="!scrollDataLoaded">
{{ $t('journal.loading-further-data') }} {{ $t('journal.loading-further-data') }}
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, provide, reactive, Ref, ref } from 'vue'; import { defineComponent, provide, reactive, Ref, ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import ActionButton from '../components/Global/ActionButton.vue'; import ActionButton from '../components/Global/ActionButton.vue';
import JournalOptions from '../components/JournalView/JournalOptions.vue'; import JournalOptions from '../components/JournalView/JournalOptions.vue';
import DispatcherStats from '../components/JournalView/DispatcherStats.vue'; import DispatcherStats from '../components/JournalView/DispatcherStats.vue';
import SearchBox from '../components/Global/SearchBox.vue'; import SearchBox from '../components/Global/SearchBox.vue';
import Loading from '../components/Global/Loading.vue'; import Loading from '../components/Global/Loading.vue';
import { URLs } from '../scripts/utils/apiURLs'; import { URLs } from '../scripts/utils/apiURLs';
import { DataStatus } from '../scripts/enums/DataStatus'; import { DataStatus } from '../scripts/enums/DataStatus';
import { useStore } from '../store/store'; import { useStore } from '../store/store';
import JournalDispatchersList from '../components/JournalView/JournalDispatchersList.vue'; import JournalDispatchersList from '../components/JournalView/JournalDispatchersList.vue';
import { JournalDispatcherSearcher, JournalDispatcherSorter } from '../types/Journal/JournalDispatcherTypes'; import { JournalDispatcherSearcher, JournalDispatcherSorter } from '../scripts/types/JournalDispatcherTypes';
import { DispatcherHistory } from '../scripts/interfaces/api/DispatchersAPIData'; import { DispatcherHistory } from '../scripts/interfaces/api/DispatchersAPIData';
import JournalHeader from '../components/JournalView/JournalHeader.vue'; import JournalHeader from '../components/JournalView/JournalHeader.vue';
import { LocationQuery } from 'vue-router'; import { LocationQuery } from 'vue-router';
const DISPATCHERS_API_URL = `${URLs.stacjownikAPI}/api/getDispatchers`; const DISPATCHERS_API_URL = `${URLs.stacjownikAPI}/api/getDispatchers`;
export default defineComponent({ export default defineComponent({
components: { components: {
SearchBox, SearchBox,
ActionButton, ActionButton,
JournalOptions, JournalOptions,
DispatcherStats, DispatcherStats,
Loading, Loading,
JournalDispatchersList, JournalDispatchersList,
JournalHeader, JournalHeader,
}, },
name: 'JournalDispatchers', name: 'JournalDispatchers',
props: { props: {
sceneryName: { sceneryName: {
type: String, type: String,
required: false, required: false,
}, },
dispatcherName: { dispatcherName: {
type: String, type: String,
required: false, required: false,
}, },
}, },
data: () => ({ data: () => ({
currentQuery: '', currentQuery: '',
currentQueryArray: [] as string[], currentQueryArray: [] as string[],
scrollDataLoaded: true, scrollDataLoaded: true,
scrollNoMoreData: false, scrollNoMoreData: false,
showReturnButton: false, showReturnButton: false,
statsCardOpen: false, statsCardOpen: false,
currentOptionsActive: false, currentOptionsActive: false,
dataStatus: DataStatus.Loading, dataStatus: DataStatus.Loading,
DataStatus, DataStatus,
historyList: [] as DispatcherHistory[], historyList: [] as DispatcherHistory[],
}), }),
setup() { setup() {
const sorterActive: JournalDispatcherSorter = reactive({ id: 'timestampFrom', dir: -1 }); const sorterActive: JournalDispatcherSorter = reactive({ id: 'timestampFrom', dir: -1 });
const journalFilterActive = ref({}); const journalFilterActive = ref({});
const searchersValues = reactive({ const searchersValues = reactive({
'search-dispatcher': '', 'search-dispatcher': '',
'search-station': '', 'search-station': '',
'search-date': '', 'search-date': '',
} as JournalDispatcherSearcher); } as JournalDispatcherSearcher);
const countFromIndex = ref(0); const countFromIndex = ref(0);
const countLimit = 15; const countLimit = 15;
provide('sorterActive', sorterActive); provide('sorterActive', sorterActive);
provide('journalFilterActive', journalFilterActive); provide('journalFilterActive', journalFilterActive);
provide('searchersValues', searchersValues); provide('searchersValues', searchersValues);
const scrollElement: Ref<HTMLElement | null> = ref(null); const scrollElement: Ref<HTMLElement | null> = ref(null);
return { return {
store: useStore(), store: useStore(),
sorterActive, sorterActive,
searchersValues, searchersValues,
countFromIndex, countFromIndex,
countLimit, countLimit,
scrollElement, scrollElement,
maxCount: ref(15), maxCount: ref(15),
}; };
}, },
watch: { watch: {
currentQueryArray(q: string[]) { currentQueryArray(q: string[]) {
this.currentOptionsActive = this.currentOptionsActive =
q.length > 2 || q.some((qv) => qv.startsWith('sortBy=') && qv.split('=')[1] != 'timestampFrom'); q.length > 2 || q.some((qv) => qv.startsWith('sortBy=') && qv.split('=')[1] != 'timestampFrom');
}, },
}, },
computed: { computed: {
computedHistoryList() { computedHistoryList() {
return this.historyList.filter( return this.historyList.filter(
(doc) => doc.isOnline || (doc.currentDuration && doc.currentDuration > 10 * 60000) (doc) => doc.isOnline || (doc.currentDuration && doc.currentDuration > 10 * 60000)
); );
}, },
}, },
beforeRouteUpdate(to, _) { beforeRouteUpdate(to, _) {
this.handleQueries(to.query); this.handleQueries(to.query);
this.fetchHistoryData(); this.fetchHistoryData();
}, },
activated() { activated() {
this.handleQueries(this.$route.query); this.handleQueries(this.$route.query);
this.fetchHistoryData(); this.fetchHistoryData();
}, },
methods: { methods: {
handleScroll(e: Event) { handleScroll(e: Event) {
const listElement = e.target as HTMLElement; const listElement = e.target as HTMLElement;
const scrollTop = listElement.scrollTop; const scrollTop = listElement.scrollTop;
const elementHeight = listElement.scrollHeight - listElement.offsetHeight; const elementHeight = listElement.scrollHeight - listElement.offsetHeight;
if (!this.scrollDataLoaded || this.scrollNoMoreData || this.dataStatus != DataStatus.Loaded) return; if (!this.scrollDataLoaded || this.scrollNoMoreData || this.dataStatus != DataStatus.Loaded) return;
if (scrollTop > elementHeight * 0.85) this.addHistoryData(); if (scrollTop > elementHeight * 0.85) this.addHistoryData();
}, },
handleQueries(query: LocationQuery) { handleQueries(query: LocationQuery) {
if ('sceneryName' in query) this.searchersValues['search-station'] = `${query.sceneryName}`; if ('sceneryName' in query) this.searchersValues['search-station'] = `${query.sceneryName}`;
if ('dispatcherName' in query) this.searchersValues['search-dispatcher'] = `${query.dispatcherName}`; if ('dispatcherName' in query) this.searchersValues['search-dispatcher'] = `${query.dispatcherName}`;
}, },
setSearchers(date: string, station: string, dispatcher: string) { setSearchers(date: string, station: string, dispatcher: string) {
this.searchersValues['search-date'] = date; this.searchersValues['search-date'] = date;
this.searchersValues['search-station'] = station; this.searchersValues['search-station'] = station;
this.searchersValues['search-dispatcher'] = dispatcher; this.searchersValues['search-dispatcher'] = dispatcher;
}, },
resetOptions() { resetOptions() {
this.setSearchers('', '', ''); this.setSearchers('', '', '');
this.sorterActive.id = 'timestampFrom'; this.sorterActive.id = 'timestampFrom';
this.fetchHistoryData(); this.fetchHistoryData();
}, },
async addHistoryData() { async addHistoryData() {
this.scrollDataLoaded = false; this.scrollDataLoaded = false;
const countFrom = this.historyList.length; const countFrom = this.historyList.length;
const responseData: DispatcherHistory[] = await ( const responseData: DispatcherHistory[] = await (
await axios.get(`${DISPATCHERS_API_URL}?${this.currentQuery}&countFrom=${countFrom}`) await axios.get(`${DISPATCHERS_API_URL}?${this.currentQuery}&countFrom=${countFrom}`)
).data; ).data;
if (!responseData) return; if (!responseData) return;
if (responseData.length == 0) { if (responseData.length == 0) {
this.scrollNoMoreData = true; this.scrollNoMoreData = true;
return; return;
} }
this.historyList.push(...responseData); this.historyList.push(...responseData);
this.scrollDataLoaded = true; this.scrollDataLoaded = true;
}, },
async fetchHistoryData() { async fetchHistoryData() {
const queries: string[] = []; const queries: string[] = [];
const dispatcher = this.searchersValues['search-dispatcher'].trim(); const dispatcher = this.searchersValues['search-dispatcher'].trim();
const station = this.searchersValues['search-station'].trim(); const station = this.searchersValues['search-station'].trim();
const dateString = this.searchersValues['search-date'].trim(); const dateString = this.searchersValues['search-date'].trim();
const timestampFrom = dateString ? Date.parse(new Date(dateString).toISOString()) - 120 * 60 * 1000 : undefined; const timestampFrom = dateString ? Date.parse(new Date(dateString).toISOString()) - 120 * 60 * 1000 : undefined;
const timestampTo = timestampFrom ? timestampFrom + 86400000 : undefined; const timestampTo = timestampFrom ? timestampFrom + 86400000 : undefined;
if (dispatcher) queries.push(`dispatcherName=${dispatcher}`); if (dispatcher) queries.push(`dispatcherName=${dispatcher}`);
if (station) queries.push(`stationName=${station}`); if (station) queries.push(`stationName=${station}`);
if (timestampFrom && timestampTo) queries.push(`timestampFrom=${timestampFrom}`, `timestampTo=${timestampTo}`); if (timestampFrom && timestampTo) queries.push(`timestampFrom=${timestampFrom}`, `timestampTo=${timestampTo}`);
// Z API: const SORT_TYPES = ['allStopsCount', 'endDate', 'beginDate', 'routeDistance']; // Z API: const SORT_TYPES = ['allStopsCount', 'endDate', 'beginDate', 'routeDistance'];
if (this.sorterActive.id == 'timestampFrom') queries.push('sortBy=timestampFrom'); if (this.sorterActive.id == 'timestampFrom') queries.push('sortBy=timestampFrom');
else if (this.sorterActive.id == 'duration') queries.push('sortBy=currentDuration'); else if (this.sorterActive.id == 'duration') queries.push('sortBy=currentDuration');
else queries.push('sortBy=timestampFrom'); else queries.push('sortBy=timestampFrom');
queries.push('countLimit=30'); queries.push('countLimit=30');
if (this.currentQuery != queries.join('&')) this.dataStatus = DataStatus.Loading; if (this.currentQuery != queries.join('&')) this.dataStatus = DataStatus.Loading;
this.currentQuery = queries.join('&'); this.currentQuery = queries.join('&');
this.currentQueryArray = queries; this.currentQueryArray = queries;
try { try {
const responseData: DispatcherHistory[] = await ( const responseData: DispatcherHistory[] = await (
await axios.get(`${DISPATCHERS_API_URL}?${this.currentQuery}`) await axios.get(`${DISPATCHERS_API_URL}?${this.currentQuery}`)
).data; ).data;
if (!responseData) { if (!responseData) {
this.dataStatus = DataStatus.Error; this.dataStatus = DataStatus.Error;
return; return;
} }
if (!responseData) return; if (!responseData) return;
// Response data exists // Response data exists
this.historyList = responseData; this.historyList = responseData;
// Stats display // Stats display
this.store.dispatcherStatsName = this.store.dispatcherStatsName =
this.historyList.length > 0 && this.searchersValues['search-dispatcher'].trim() this.historyList.length > 0 && this.searchersValues['search-dispatcher'].trim()
? this.historyList[0].dispatcherName ? this.historyList[0].dispatcherName
: ''; : '';
this.dataStatus = DataStatus.Loaded; this.dataStatus = DataStatus.Loaded;
} catch (error) { } catch (error) {
this.dataStatus = DataStatus.Error; this.dataStatus = DataStatus.Error;
} }
this.scrollNoMoreData = false; this.scrollNoMoreData = false;
this.scrollDataLoaded = true; this.scrollDataLoaded = true;
}, },
}, },
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../styles/JournalSection.scss'; @import '../styles/JournalSection.scss';
</style> </style>
+2 -2
View File
@@ -70,12 +70,12 @@ import JournalHeader from '../components/JournalView/JournalHeader.vue';
import JournalTimetablesList from '../components/JournalView/JournalTimetablesList.vue'; import JournalTimetablesList from '../components/JournalView/JournalTimetablesList.vue';
import Loading from '../components/Global/Loading.vue'; import Loading from '../components/Global/Loading.vue';
import { JournalTimetableSorter } from '../types/Journal/JournalTimetablesTypes'; import { JournalTimetableSorter } from '../scripts/types/JournalTimetablesTypes';
import { DataStatus } from '../scripts/enums/DataStatus'; import { DataStatus } from '../scripts/enums/DataStatus';
import { TimetableHistory } from '../scripts/interfaces/api/TimetablesAPIData'; import { TimetableHistory } from '../scripts/interfaces/api/TimetablesAPIData';
import { URLs } from '../scripts/utils/apiURLs'; import { URLs } from '../scripts/utils/apiURLs';
import { useStore } from '../store/store'; import { useStore } from '../store/store';
import { JournalTimetableSearchType } from '../types/Journal/JournalTimetablesTypes'; import { JournalTimetableSearchType } from '../scripts/types/JournalTimetablesTypes';
import { journalTimetableFilters } from '../constants/Journal/JournalTimetablesConsts'; import { journalTimetableFilters } from '../constants/Journal/JournalTimetablesConsts';
import { LocationQuery } from 'vue-router'; import { LocationQuery } from 'vue-router';
+1 -1
View File
@@ -21,7 +21,7 @@ import modalTrainMixin from '../mixins/modalTrainMixin';
import Train from '../scripts/interfaces/Train'; import Train from '../scripts/interfaces/Train';
import { filteredTrainList } from '../scripts/managers/trainFilterManager'; import { filteredTrainList } from '../scripts/managers/trainFilterManager';
import { useStore } from '../store/store'; import { useStore } from '../store/store';
import { TrainFilter } from '../types/Trains/TrainOptionsTypes'; import { TrainFilter } from '../scripts/interfaces/Trains/TrainFilter';
export default defineComponent({ export default defineComponent({
components: { components: {