mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 13:28:11 +00:00
chore: filters improvements
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<button class="card-button btn--filled btn--image" @click="toggleCard">
|
<button class="card-button btn--filled btn--image" @click="toggleCard">
|
||||||
<img class="button_icon" src="/images/icon-filter2.svg" alt="filter icon" />
|
<img class="button_icon" src="/images/icon-filter2.svg" alt="filter icon" />
|
||||||
<p>[F] {{ $t('options.filters') }}</p>
|
<p>[F] {{ $t('options.filters') }}</p>
|
||||||
<span class="active-indicator" v-if="!areFiltersAtDefaultComp"></span>
|
<span class="active-indicator" v-if="changedFilters.length != 0"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<label for="scenery-search">
|
<label for="scenery-search">
|
||||||
@@ -33,6 +33,12 @@
|
|||||||
<div class="card_title flex">{{ $t('filters.title') }}</div>
|
<div class="card_title flex">{{ $t('filters.title') }}</div>
|
||||||
<p class="card_info" v-html="$t('filters.desc')"></p>
|
<p class="card_info" v-html="$t('filters.desc')"></p>
|
||||||
|
|
||||||
|
<div class="changed-filters" v-if="changedFilters.length > 0">
|
||||||
|
{{ $t('filters.changed-filters-count') }} <b>{{ changedFilters.length }}</b>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="changed-filters" v-else>{{ $t('filters.no-changed-filters') }}</div>
|
||||||
|
|
||||||
<section class="card_options">
|
<section class="card_options">
|
||||||
<div
|
<div
|
||||||
class="option-section"
|
class="option-section"
|
||||||
@@ -40,33 +46,31 @@
|
|||||||
:key="sectionKey"
|
:key="sectionKey"
|
||||||
>
|
>
|
||||||
<h3 class="text--primary">
|
<h3 class="text--primary">
|
||||||
|
<span class="active-indicator" v-if="!areSectionFiltersDefault(sectionKey)"></span>
|
||||||
{{ $t(`filters.sections.${sectionKey}`) }}
|
{{ $t(`filters.sections.${sectionKey}`) }}
|
||||||
|
<button @click="resetSectionFilters(sectionKey)">RESET</button>
|
||||||
<button @click="resetSectionOptions(sectionKey)">RESET</button>
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<!--
|
|
||||||
@dblclick="handleDbClick"
|
|
||||||
|
|
||||||
-->
|
|
||||||
<div class="section-filters">
|
<div class="section-filters">
|
||||||
<div
|
<label
|
||||||
v-for="filter in sectionFilters"
|
v-for="filterKey in sectionFilters"
|
||||||
@click="() => (filters[filter] = !filters[filter])"
|
@click="() => (filters[filterKey] = !filters[filterKey])"
|
||||||
|
@dblclick="setSingleSectionFilter(sectionKey, filterKey)"
|
||||||
|
:for="filterKey"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
:checked="filters[filter]"
|
:checked="filters[filterKey]"
|
||||||
v-model="filters[filter]"
|
v-model="filters[filterKey]"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:class="sectionKey"
|
:class="sectionKey"
|
||||||
:name="filter"
|
:name="filterKey"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
{{ $t(`filters.${filter}`) }}
|
{{ $t(`filters.${filterKey}`) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -143,8 +147,8 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn--action"
|
class="btn--action"
|
||||||
:disabled="areFiltersAtDefaultComp"
|
:disabled="changedFilters.length == 0"
|
||||||
:data-disabled="areFiltersAtDefaultComp"
|
:data-disabled="changedFilters.length == 0"
|
||||||
@click="resetFilters"
|
@click="resetFilters"
|
||||||
>
|
>
|
||||||
[R] {{ $t('filters.reset') }}
|
[R] {{ $t('filters.reset') }}
|
||||||
@@ -170,11 +174,14 @@ import {
|
|||||||
filtersSections,
|
filtersSections,
|
||||||
initSliders,
|
initSliders,
|
||||||
initFilters,
|
initFilters,
|
||||||
areFiltersAtDefault
|
getChangedFilters
|
||||||
} from '../../managers/stationFilterManager';
|
} from '../../managers/stationFilterManager';
|
||||||
|
|
||||||
import { StationFilterSection } from '../../managers/stationFilterManager';
|
import { StationFilterSection } from '../../managers/stationFilterManager';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'options_saved';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { FilterOption },
|
components: { FilterOption },
|
||||||
@@ -182,7 +189,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
saveOptions: false,
|
saveOptions: false,
|
||||||
STORAGE_KEY: 'options_saved',
|
|
||||||
|
|
||||||
filtersSections,
|
filtersSections,
|
||||||
initSliders,
|
initSliders,
|
||||||
@@ -205,18 +211,27 @@ export default defineComponent({
|
|||||||
|
|
||||||
const filters = inject('StationsView_filters') as Record<string, any>;
|
const filters = inject('StationsView_filters') as Record<string, any>;
|
||||||
|
|
||||||
const areFiltersAtDefaultComp = computed(() => areFiltersAtDefault(filters));
|
const changedFilters = computed(() => getChangedFilters(filters));
|
||||||
|
|
||||||
|
// Save filters to persistent storage
|
||||||
|
watch(filters, (value) => {
|
||||||
|
if (!StorageManager.isRegistered(STORAGE_KEY)) return;
|
||||||
|
|
||||||
|
Object.keys(value).forEach((filterKey) => {
|
||||||
|
StorageManager.setValue(filterKey, filters[filterKey]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isVisible,
|
isVisible,
|
||||||
store,
|
store,
|
||||||
filters,
|
filters,
|
||||||
areFiltersAtDefaultComp
|
changedFilters
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.saveOptions = StorageManager.isRegistered(this.STORAGE_KEY);
|
this.saveOptions = StorageManager.isRegistered(STORAGE_KEY);
|
||||||
|
|
||||||
if (StorageManager.isRegistered('onlineFromHours') && this.saveOptions) {
|
if (StorageManager.isRegistered('onlineFromHours') && this.saveOptions) {
|
||||||
this.minimumHours = StorageManager.getNumericValue('onlineFromHours');
|
this.minimumHours = StorageManager.getNumericValue('onlineFromHours');
|
||||||
@@ -301,11 +316,11 @@ export default defineComponent({
|
|||||||
this.saveOptions = !this.saveOptions;
|
this.saveOptions = !this.saveOptions;
|
||||||
|
|
||||||
if (!this.saveOptions) {
|
if (!this.saveOptions) {
|
||||||
StorageManager.unregisterStorage(this.STORAGE_KEY);
|
StorageManager.unregisterStorage(STORAGE_KEY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageManager.registerStorage(this.STORAGE_KEY);
|
StorageManager.registerStorage(STORAGE_KEY);
|
||||||
|
|
||||||
Object.keys(this.filters).forEach((filterKey) => {
|
Object.keys(this.filters).forEach((filterKey) => {
|
||||||
StorageManager.setValue(filterKey, this.filters[filterKey]);
|
StorageManager.setValue(filterKey, this.filters[filterKey]);
|
||||||
@@ -323,9 +338,21 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
resetSectionOptions(key: string) {
|
areSectionFiltersDefault(sectionKey: StationFilterSection) {
|
||||||
filtersSections[key as StationFilterSection].forEach((filter) => {
|
return filtersSections[sectionKey].every((filterKey) => {
|
||||||
this.filters[filter] = (initFilters as any)[filter];
|
return this.filters[filterKey] == initFilters[filterKey];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resetSectionFilters(sectionKey: StationFilterSection) {
|
||||||
|
filtersSections[sectionKey].forEach((filterKey) => {
|
||||||
|
this.filters[filterKey] = initFilters[filterKey];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setSingleSectionFilter(sectionKey: StationFilterSection, chosenKey: string) {
|
||||||
|
filtersSections[sectionKey].forEach((filterKey) => {
|
||||||
|
if (filterKey != chosenKey) this.filters[filterKey] = initFilters[filterKey];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -360,6 +387,11 @@ h3.section-header {
|
|||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.changed-filters {
|
||||||
|
background-color: #111;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.card_controls {
|
.card_controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
@@ -440,7 +472,7 @@ h3.section-header {
|
|||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-filters > div {
|
.section-filters > label {
|
||||||
position: relative;
|
position: relative;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
@@ -516,19 +548,15 @@ h3.section-header {
|
|||||||
.slider {
|
.slider {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|
||||||
&-value {
|
&-value {
|
||||||
color: $accentCol;
|
color: $accentCol;
|
||||||
margin-right: 0.5em;
|
|
||||||
padding: 0.1em 0.2em;
|
padding: 0.1em 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-content {
|
|
||||||
flex-grow: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-input {
|
&-input {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
@@ -537,7 +565,6 @@ h3.section-header {
|
|||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
min-width: 25%;
|
min-width: 25%;
|
||||||
max-width: 120px;
|
|
||||||
|
|
||||||
&:focus-visible ~ * {
|
&:focus-visible ~ * {
|
||||||
color: gold;
|
color: gold;
|
||||||
@@ -612,5 +639,14 @@ h3.section-header {
|
|||||||
.card_controls > button.card-button > p {
|
.card_controls > button.card-button > p {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&-input {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -302,8 +302,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="no-stations" v-else>
|
<div class="no-stations" v-else>
|
||||||
{{ $t('sceneries.no-stations') }} (region: <b>{{ mainStore.region.name }}</b
|
<div>
|
||||||
>)
|
{{ $t('sceneries.no-stations') }} (region: <b>{{ mainStore.region.name }}</b
|
||||||
|
>)
|
||||||
|
</div>
|
||||||
|
<div class="text--primary" v-if="getChangedFilters(filters).length != 0">
|
||||||
|
{{ $t('sceneries.active-filters') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -311,15 +316,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, inject, computed } from 'vue';
|
import { defineComponent, inject, computed } from 'vue';
|
||||||
import StationStatusBadge from '../Global/StationStatusBadge.vue';
|
import StationStatusBadge from '../Global/StationStatusBadge.vue';
|
||||||
|
import Loading from '../Global/Loading.vue';
|
||||||
import dateMixin from '../../mixins/dateMixin';
|
import dateMixin from '../../mixins/dateMixin';
|
||||||
import styleMixin from '../../mixins/styleMixin';
|
import styleMixin from '../../mixins/styleMixin';
|
||||||
import { useMainStore } from '../../store/mainStore';
|
|
||||||
import Loading from '../Global/Loading.vue';
|
|
||||||
import { Status } from '../../typings/common';
|
|
||||||
import { useApiStore } from '../../store/apiStore';
|
import { useApiStore } from '../../store/apiStore';
|
||||||
|
import { useMainStore } from '../../store/mainStore';
|
||||||
|
import { Status } from '../../typings/common';
|
||||||
import { useTooltipStore } from '../../store/tooltipStore';
|
import { useTooltipStore } from '../../store/tooltipStore';
|
||||||
import { filterStations, sortStations } from '../../scripts/utils/stationFilterUtils';
|
import { getChangedFilters } from '../../managers/stationFilterManager';
|
||||||
import { ActiveSorter, HeadIdsType, headIconsIds, headIds } from './typings';
|
import { ActiveSorter, HeadIdsType, headIconsIds, headIds } from './typings';
|
||||||
|
import { filterStations, sortStations } from './utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
emits: ['toggleDonationModal'],
|
emits: ['toggleDonationModal'],
|
||||||
@@ -330,7 +336,8 @@ export default defineComponent({
|
|||||||
data: () => ({
|
data: () => ({
|
||||||
headIconsIds,
|
headIconsIds,
|
||||||
headIds,
|
headIds,
|
||||||
lastSelectedStationName: ''
|
lastSelectedStationName: '',
|
||||||
|
getChangedFilters
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@@ -346,15 +353,13 @@ export default defineComponent({
|
|||||||
.filter((station) => filterStations(station, filters))
|
.filter((station) => filterStations(station, filters))
|
||||||
.sort((a, b) => sortStations(a, b, activeSorter))
|
.sort((a, b) => sortStations(a, b, activeSorter))
|
||||||
);
|
);
|
||||||
// const areFiltersAtDefault = computed(() => {
|
|
||||||
|
|
||||||
// })
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Status: Status.Data,
|
Status: Status.Data,
|
||||||
mainStore,
|
mainStore,
|
||||||
apiStore,
|
apiStore,
|
||||||
tooltipStore,
|
tooltipStore,
|
||||||
|
filters,
|
||||||
filteredStationList,
|
filteredStationList,
|
||||||
activeSorter
|
activeSorter
|
||||||
};
|
};
|
||||||
@@ -419,7 +424,7 @@ $rowCol: #424242;
|
|||||||
|
|
||||||
.no-stations {
|
.no-stations {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.5em;
|
font-size: 1.25em;
|
||||||
|
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,275 @@
|
|||||||
|
import { ActiveSorter } from '../../components/StationsView/typings';
|
||||||
|
import { ActiveScenery, StationGeneralInfo, Status } from '../../typings/common';
|
||||||
|
import { Station } from '../../typings/common';
|
||||||
|
|
||||||
|
const dispatcherStatusPriority = [
|
||||||
|
Status.ActiveDispatcher.UNKNOWN,
|
||||||
|
Status.ActiveDispatcher.INVALID,
|
||||||
|
Status.ActiveDispatcher.NOT_LOGGED_IN,
|
||||||
|
Status.ActiveDispatcher.UNAVAILABLE,
|
||||||
|
Status.ActiveDispatcher.AFK,
|
||||||
|
Status.ActiveDispatcher.ENDING,
|
||||||
|
Status.ActiveDispatcher.NO_SPACE,
|
||||||
|
undefined
|
||||||
|
];
|
||||||
|
|
||||||
|
const filtersAssociations: Record<string, string> = {
|
||||||
|
mechaniczne: 'mechanical',
|
||||||
|
ręczne: 'manual',
|
||||||
|
'mechaniczne+SPK': 'SPK-M',
|
||||||
|
'ręczne+SPK': 'SPK-R',
|
||||||
|
'mechaniczne+SCS': 'SCS-M',
|
||||||
|
'ręczne+SCS': 'SCS-R',
|
||||||
|
współczesna: 'modern',
|
||||||
|
historyczna: 'historical',
|
||||||
|
kształtowa: 'semaphores',
|
||||||
|
mieszana: 'mixed'
|
||||||
|
};
|
||||||
|
|
||||||
|
function filterStatusSection(
|
||||||
|
filters: Record<string, any>,
|
||||||
|
{ dispatcherStatus, dispatcherTimestamp }: ActiveScenery
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
(filters['endingStatus'] && dispatcherStatus == Status.ActiveDispatcher.ENDING) ||
|
||||||
|
(filters['unavailableStatus'] &&
|
||||||
|
(dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE ||
|
||||||
|
dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN)) ||
|
||||||
|
(filters['afkStatus'] && dispatcherStatus == Status.ActiveDispatcher.AFK) ||
|
||||||
|
(filters['noSpaceStatus'] && dispatcherStatus == Status.ActiveDispatcher.NO_SPACE) ||
|
||||||
|
(filters['occupied'] && dispatcherStatus != Status.ActiveDispatcher.FREE) ||
|
||||||
|
(filters['onlineFromHours'] > 0 &&
|
||||||
|
(dispatcherTimestamp ?? 0) <= Date.now() + filters['onlineFromHours'] * 3600000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTimetablesSection(filters: Record<string, any>, station: Station) {
|
||||||
|
return (
|
||||||
|
(filters['withoutActiveTimetables'] &&
|
||||||
|
(!station.onlineInfo || station.onlineInfo.scheduledTrainCount.all == 0)) ||
|
||||||
|
(filters['withActiveTimetables'] &&
|
||||||
|
station.onlineInfo &&
|
||||||
|
(station.onlineInfo.scheduledTrainCount.all != 0 ||
|
||||||
|
station.onlineInfo.dispatcherStatus == Status.ActiveDispatcher.FREE))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterAccessibilitySection(filters: Record<string, any>, station: Station) {
|
||||||
|
if (
|
||||||
|
filters['nonPublic'] &&
|
||||||
|
(!station.generalInfo || station.generalInfo.availability == 'nonPublic')
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!station.generalInfo) return false;
|
||||||
|
|
||||||
|
const { availability } = station.generalInfo;
|
||||||
|
|
||||||
|
return (
|
||||||
|
(filters['unavailable'] && availability == 'unavailable' && !station.onlineInfo) ||
|
||||||
|
(filters['abandoned'] && availability == 'abandoned' && !station.onlineInfo) ||
|
||||||
|
(filters['default'] && availability == 'default') ||
|
||||||
|
(filters['notDefault'] &&
|
||||||
|
availability != 'default' &&
|
||||||
|
availability != 'abandoned' &&
|
||||||
|
availability != 'unavailable')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterRealitySection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
return (filters['real'] && generalInfo.lines) || (filters['fictional'] && !generalInfo.lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterProgramsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
return (
|
||||||
|
(filters['SUP'] && generalInfo.SUP) ||
|
||||||
|
(filters['noSUP'] && !generalInfo.SUP) ||
|
||||||
|
(filters['ASDEK'] && generalInfo.ASDEK) ||
|
||||||
|
(filters['noASDEK'] && !generalInfo.ASDEK)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterControlsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
return (
|
||||||
|
filters[generalInfo.controlType] == true ||
|
||||||
|
filters[filtersAssociations[generalInfo.controlType]] == true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterSignalsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
return (
|
||||||
|
filters[generalInfo.signalType] == true ||
|
||||||
|
filters[filtersAssociations[generalInfo.signalType]] == true ||
|
||||||
|
(filters['SBL'] && generalInfo.routes.sblNames.length > 0) ||
|
||||||
|
(filters['PBL'] && generalInfo.routes.sblNames.length == 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterStationType(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
const singleTracks = generalInfo.routes.single.filter((r) => !r.isInternal);
|
||||||
|
const doubleTracks = generalInfo.routes.double.filter((r) => !r.isInternal);
|
||||||
|
|
||||||
|
let isJunction = singleTracks.length > 0 && doubleTracks.length > 0;
|
||||||
|
|
||||||
|
return (filters['junction'] && isJunction) || (filters['nonJunction'] && !isJunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterSliderValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
const { availability, reqLevel, routes } = generalInfo;
|
||||||
|
|
||||||
|
const otherAvailability =
|
||||||
|
availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned';
|
||||||
|
|
||||||
|
return (
|
||||||
|
filters['minLevel'] > reqLevel + (otherAvailability ? 1 : 0) ||
|
||||||
|
filters['maxLevel'] < reqLevel + (otherAvailability ? 1 : 0) ||
|
||||||
|
filters['minVmax'] > routes.maxRouteSpeed ||
|
||||||
|
filters['maxVmax'] < routes.minRouteSpeed ||
|
||||||
|
(filters['no-1track'] && routes.single.length != 0) ||
|
||||||
|
(filters['no-2track'] && routes.double.length != 0) ||
|
||||||
|
filters['minOneWayCatenary'] > routes.singleElectrifiedNames.length ||
|
||||||
|
filters['minOneWay'] > routes.singleOtherNames.length ||
|
||||||
|
filters['minTwoWayCatenary'] > routes.doubleElectrifiedNames.length ||
|
||||||
|
filters['minTwoWay'] > routes.doubleOtherNames.length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||||
|
return (
|
||||||
|
filters['authors'].length > 3 &&
|
||||||
|
!generalInfo.authors
|
||||||
|
?.map((a) => a.toLocaleLowerCase())
|
||||||
|
.includes(filters['authors'].toLocaleLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
|
||||||
|
let diff = 0;
|
||||||
|
|
||||||
|
switch (sorter.headerName) {
|
||||||
|
case 'station':
|
||||||
|
return sorter.dir == 1 ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name);
|
||||||
|
|
||||||
|
case 'min-lvl':
|
||||||
|
diff = (a.generalInfo?.reqLevel || 0) - (b.generalInfo?.reqLevel || 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'status':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo?.dispatcherTimestamp ??
|
||||||
|
dispatcherStatusPriority.indexOf(a.onlineInfo?.dispatcherStatus)) -
|
||||||
|
(b.onlineInfo?.dispatcherTimestamp ??
|
||||||
|
dispatcherStatusPriority.indexOf(b.onlineInfo?.dispatcherStatus));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'dispatcher':
|
||||||
|
if (
|
||||||
|
(a.onlineInfo?.dispatcherName.toLowerCase() || '') >
|
||||||
|
(b.onlineInfo?.dispatcherName.toLowerCase() || '')
|
||||||
|
)
|
||||||
|
return sorter.dir;
|
||||||
|
if (
|
||||||
|
(a.onlineInfo?.dispatcherName.toLowerCase() || '') <
|
||||||
|
(b.onlineInfo?.dispatcherName.toLowerCase() || '')
|
||||||
|
)
|
||||||
|
return -sorter.dir;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'dispatcher-lvl':
|
||||||
|
diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'routes-single':
|
||||||
|
diff =
|
||||||
|
(a.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1) -
|
||||||
|
(b.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'routes-double':
|
||||||
|
diff =
|
||||||
|
(a.generalInfo?.routes.double.filter((r) => !r.hidden && !r.isInternal).length ?? -1) -
|
||||||
|
(b.generalInfo?.routes.double.filter((r) => !r.hidden && !r.isInternal).length ?? -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'user':
|
||||||
|
diff =
|
||||||
|
(b.onlineInfo?.stationTrains ? b.onlineInfo.stationTrains.length : -1) -
|
||||||
|
(a.onlineInfo?.stationTrains ? a.onlineInfo.stationTrains.length : -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'like':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo ? a.onlineInfo.dispatcherRate : -Infinity) -
|
||||||
|
(b.onlineInfo ? b.onlineInfo.dispatcherRate : -Infinity);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'spawn':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo ? a.onlineInfo.spawns.length : -1) -
|
||||||
|
(b.onlineInfo ? b.onlineInfo.spawns.length : -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'timetableConfirmed':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo?.scheduledTrainCount.confirmed ?? -1) -
|
||||||
|
(b.onlineInfo?.scheduledTrainCount.confirmed ?? -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'timetableUnconfirmed':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo?.scheduledTrainCount.unconfirmed ?? -1) -
|
||||||
|
(b.onlineInfo?.scheduledTrainCount.unconfirmed ?? -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'timetableAll':
|
||||||
|
diff =
|
||||||
|
(a.onlineInfo?.scheduledTrainCount.all ?? -1) -
|
||||||
|
(b.onlineInfo?.scheduledTrainCount.all ?? -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff != 0) return Math.sign(diff) * sorter.dir;
|
||||||
|
return a.name.localeCompare(b.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const filterStations = (station: Station, filters: Record<string, any>) => {
|
||||||
|
if (filters['free'] && (!station.onlineInfo || station.onlineInfo.dispatcherId == -1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Scenery Timetables section
|
||||||
|
if (filterTimetablesSection(filters, station)) return false;
|
||||||
|
|
||||||
|
// Scenery Accessibility section
|
||||||
|
if (filterAccessibilitySection(filters, station)) return false;
|
||||||
|
|
||||||
|
// Scenery Status section
|
||||||
|
if (station.onlineInfo && filterStatusSection(filters, station.onlineInfo)) return false;
|
||||||
|
|
||||||
|
if (station.generalInfo) {
|
||||||
|
// Scenery Reality section
|
||||||
|
if (filterRealitySection(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery Additional Programs section
|
||||||
|
if (filterProgramsSection(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery Controls section
|
||||||
|
if (filterControlsSection(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery Signalling section(s)
|
||||||
|
if (filterSignalsSection(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery Station Type section
|
||||||
|
if (filterStationType(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery sliders
|
||||||
|
if (filterSliderValues(filters, station.generalInfo)) return false;
|
||||||
|
|
||||||
|
// Scenery Authors section
|
||||||
|
if (filterInputValues(filters, station.generalInfo)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
<Loading v-else-if="apiStore.dataStatuses.connection == Status.Loading" key="loading" />
|
<Loading v-else-if="apiStore.dataStatuses.connection == Status.Loading" key="loading" />
|
||||||
|
|
||||||
<div class="table-warning" key="no-trains" v-else-if="trains.length == 0">
|
<div class="table-warning" key="no-trains" v-else-if="trains.length == 0">
|
||||||
{{ $t('trains.no-trains') }}
|
{{ $t('trains.no-trains') }} (region: <b>{{ store.region.name }}</b
|
||||||
|
>)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<transition-group name="list-anim" tag="ul">
|
<transition-group name="list-anim" tag="ul">
|
||||||
@@ -108,8 +109,7 @@ export default defineComponent({
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
padding: 1em 0;
|
padding: 1em 0;
|
||||||
|
font-size: 1.25em;
|
||||||
font-size: 1.5em;
|
|
||||||
|
|
||||||
background: #1a1a1a;
|
background: #1a1a1a;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -187,6 +187,9 @@
|
|||||||
"spawns": "OPEN SPAWNS"
|
"spawns": "OPEN SPAWNS"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"changed-filters-count": "Changed filters:",
|
||||||
|
"no-changed-filters": "No changed filters",
|
||||||
|
|
||||||
"all-available": "ALL AVAILABLE",
|
"all-available": "ALL AVAILABLE",
|
||||||
"all-free": "CURRENTLY FREE",
|
"all-free": "CURRENTLY FREE",
|
||||||
|
|
||||||
@@ -297,7 +300,8 @@
|
|||||||
"single-track-routes-other": "Not electrified single-track routes count: "
|
"single-track-routes-other": "Not electrified single-track routes count: "
|
||||||
},
|
},
|
||||||
"no-stations": "No stations to show here!",
|
"no-stations": "No stations to show here!",
|
||||||
"scenery-search": "Search for scenery..."
|
"scenery-search": "Search for scenery...",
|
||||||
|
"active-filters": "Attention! You got active filters!"
|
||||||
},
|
},
|
||||||
"station-stats": {
|
"station-stats": {
|
||||||
"u-factor": "U-factor",
|
"u-factor": "U-factor",
|
||||||
|
|||||||
+5
-1
@@ -184,6 +184,9 @@
|
|||||||
"spawns": "OTWARTE SPAWNY"
|
"spawns": "OTWARTE SPAWNY"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"changed-filters-count": "Zmienione filtry:",
|
||||||
|
"no-changed-filters": "Brak zmienionych filtrów",
|
||||||
|
|
||||||
"all-available": "WSZYSTKIE DOSTĘPNE",
|
"all-available": "WSZYSTKIE DOSTĘPNE",
|
||||||
"all-free": "WSZYSTKIE WOLNE",
|
"all-free": "WSZYSTKIE WOLNE",
|
||||||
|
|
||||||
@@ -291,7 +294,8 @@
|
|||||||
"single-track-routes-other": "Liczba niezelektryfikowanych szlaków jednotorowych: "
|
"single-track-routes-other": "Liczba niezelektryfikowanych szlaków jednotorowych: "
|
||||||
},
|
},
|
||||||
"no-stations": "Brak stacji do wyświetlenia!",
|
"no-stations": "Brak stacji do wyświetlenia!",
|
||||||
"scenery-search": "Wyszukaj scenerię..."
|
"scenery-search": "Wyszukaj scenerię...",
|
||||||
|
"active-filters": "Uwaga! Masz obecnie aktywne filtry!"
|
||||||
},
|
},
|
||||||
"station-stats": {
|
"station-stats": {
|
||||||
"u-factor": "Współczynnik Ugla",
|
"u-factor": "Współczynnik Ugla",
|
||||||
|
|||||||
@@ -109,8 +109,11 @@ export function setupFilters(currentFilters: Record<string, any>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function areFiltersAtDefault(currentFilters: Record<string, any>) {
|
export function getChangedFilters(currentFilters: Record<string, any>): string[] {
|
||||||
return Object.keys(currentFilters).every(
|
return (
|
||||||
(filterKey) => currentFilters[filterKey] === initFilters[filterKey as keyof typeof initFilters]
|
Object.keys(currentFilters).filter(
|
||||||
|
(filterKey) =>
|
||||||
|
currentFilters[filterKey] !== initFilters[filterKey as keyof typeof initFilters]
|
||||||
|
) ?? []
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
import { ActiveSorter } from '../../components/StationsView/typings';
|
|
||||||
import { ActiveScenery, StationGeneralInfo, Status } from '../../typings/common';
|
|
||||||
import { Station } from '../../typings/common';
|
|
||||||
|
|
||||||
const dispatcherStatusPriority = [
|
|
||||||
Status.ActiveDispatcher.UNKNOWN,
|
|
||||||
Status.ActiveDispatcher.INVALID,
|
|
||||||
Status.ActiveDispatcher.NOT_LOGGED_IN,
|
|
||||||
Status.ActiveDispatcher.UNAVAILABLE,
|
|
||||||
Status.ActiveDispatcher.AFK,
|
|
||||||
Status.ActiveDispatcher.ENDING,
|
|
||||||
Status.ActiveDispatcher.NO_SPACE,
|
|
||||||
undefined
|
|
||||||
];
|
|
||||||
|
|
||||||
const filtersAssociations: Record<string, string> = {
|
|
||||||
mechaniczne: 'mechanical',
|
|
||||||
ręczne: 'manual',
|
|
||||||
'mechaniczne+SPK': 'SPK-M',
|
|
||||||
'ręczne+SPK': 'SPK-R',
|
|
||||||
'mechaniczne+SCS': 'SCS-M',
|
|
||||||
'ręczne+SCS': 'SCS-R',
|
|
||||||
współczesna: 'modern',
|
|
||||||
historyczna: 'historical',
|
|
||||||
kształtowa: 'semaphores',
|
|
||||||
mieszana: 'mixed'
|
|
||||||
};
|
|
||||||
|
|
||||||
function filterStatusSection(
|
|
||||||
filters: Record<string, any>,
|
|
||||||
{ dispatcherStatus, dispatcherTimestamp }: ActiveScenery
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
(filters['endingStatus'] && dispatcherStatus == Status.ActiveDispatcher.ENDING) ||
|
|
||||||
(filters['unavailableStatus'] &&
|
|
||||||
(dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE ||
|
|
||||||
dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN)) ||
|
|
||||||
(filters['afkStatus'] && dispatcherStatus == Status.ActiveDispatcher.AFK) ||
|
|
||||||
(filters['noSpaceStatus'] && dispatcherStatus == Status.ActiveDispatcher.NO_SPACE) ||
|
|
||||||
(filters['occupied'] && dispatcherStatus != Status.ActiveDispatcher.FREE) ||
|
|
||||||
(filters['onlineFromHours'] > 0 &&
|
|
||||||
(dispatcherTimestamp ?? 0) <= Date.now() + filters['onlineFromHours'] * 3600000)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterTimetablesSection(filters: Record<string, any>, station: Station) {
|
|
||||||
return (
|
|
||||||
(filters['withoutActiveTimetables'] &&
|
|
||||||
(!station.onlineInfo || station.onlineInfo.scheduledTrainCount.all == 0)) ||
|
|
||||||
(filters['withActiveTimetables'] &&
|
|
||||||
station.onlineInfo &&
|
|
||||||
(station.onlineInfo.scheduledTrainCount.all != 0 ||
|
|
||||||
station.onlineInfo.dispatcherStatus == Status.ActiveDispatcher.FREE))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterAccessibilitySection(filters: Record<string, any>, station: Station) {
|
|
||||||
if (
|
|
||||||
filters['nonPublic'] &&
|
|
||||||
(!station.generalInfo || station.generalInfo.availability == 'nonPublic')
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!station.generalInfo) return false;
|
|
||||||
|
|
||||||
const { availability } = station.generalInfo;
|
|
||||||
|
|
||||||
return (
|
|
||||||
(filters['unavailable'] && availability == 'unavailable' && !station.onlineInfo) ||
|
|
||||||
(filters['abandoned'] && availability == 'abandoned' && !station.onlineInfo) ||
|
|
||||||
(filters['default'] && availability == 'default') ||
|
|
||||||
(filters['notDefault'] &&
|
|
||||||
availability != 'default' &&
|
|
||||||
availability != 'abandoned' &&
|
|
||||||
availability != 'unavailable')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterRealitySection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
return (filters['real'] && generalInfo.lines) || (filters['fictional'] && !generalInfo.lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterProgramsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
return (
|
|
||||||
(filters['SUP'] && generalInfo.SUP) ||
|
|
||||||
(filters['noSUP'] && !generalInfo.SUP) ||
|
|
||||||
(filters['ASDEK'] && generalInfo.ASDEK) ||
|
|
||||||
(filters['noASDEK'] && !generalInfo.ASDEK)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterControlsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
return (
|
|
||||||
filters[generalInfo.controlType] == true ||
|
|
||||||
filters[filtersAssociations[generalInfo.controlType]] == true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterSignalsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
return (
|
|
||||||
filters[generalInfo.signalType] == true ||
|
|
||||||
filters[filtersAssociations[generalInfo.signalType]] == true ||
|
|
||||||
(filters['SBL'] && generalInfo.routes.sblNames.length > 0) ||
|
|
||||||
(filters['PBL'] && generalInfo.routes.sblNames.length == 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterStationType(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
const singleTracks = generalInfo.routes.single.filter((r) => !r.isInternal);
|
|
||||||
const doubleTracks = generalInfo.routes.double.filter((r) => !r.isInternal);
|
|
||||||
|
|
||||||
let isJunction = singleTracks.length > 0 && doubleTracks.length > 0;
|
|
||||||
|
|
||||||
return (filters['junction'] && isJunction) || (filters['nonJunction'] && !isJunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterSliderValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
const { availability, reqLevel, routes } = generalInfo;
|
|
||||||
|
|
||||||
const otherAvailability =
|
|
||||||
availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned';
|
|
||||||
|
|
||||||
return (
|
|
||||||
filters['minLevel'] > reqLevel + (otherAvailability ? 1 : 0) ||
|
|
||||||
filters['maxLevel'] < reqLevel + (otherAvailability ? 1 : 0) ||
|
|
||||||
filters['minVmax'] > routes.maxRouteSpeed ||
|
|
||||||
filters['maxVmax'] < routes.minRouteSpeed ||
|
|
||||||
(filters['no-1track'] && routes.single.length != 0) ||
|
|
||||||
(filters['no-2track'] && routes.double.length != 0) ||
|
|
||||||
filters['minOneWayCatenary'] > routes.singleElectrifiedNames.length ||
|
|
||||||
filters['minOneWay'] > routes.singleOtherNames.length ||
|
|
||||||
filters['minTwoWayCatenary'] > routes.doubleElectrifiedNames.length ||
|
|
||||||
filters['minTwoWay'] > routes.doubleOtherNames.length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
|
||||||
return (
|
|
||||||
filters['authors'].length > 3 &&
|
|
||||||
!generalInfo.authors
|
|
||||||
?.map((a) => a.toLocaleLowerCase())
|
|
||||||
.includes(filters['authors'].toLocaleLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
|
|
||||||
let diff = 0;
|
|
||||||
|
|
||||||
switch (sorter.headerName) {
|
|
||||||
case 'station':
|
|
||||||
return sorter.dir == 1 ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name);
|
|
||||||
|
|
||||||
case 'min-lvl':
|
|
||||||
diff = (a.generalInfo?.reqLevel || 0) - (b.generalInfo?.reqLevel || 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'status':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo?.dispatcherTimestamp ??
|
|
||||||
dispatcherStatusPriority.indexOf(a.onlineInfo?.dispatcherStatus)) -
|
|
||||||
(b.onlineInfo?.dispatcherTimestamp ??
|
|
||||||
dispatcherStatusPriority.indexOf(b.onlineInfo?.dispatcherStatus));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'dispatcher':
|
|
||||||
if (
|
|
||||||
(a.onlineInfo?.dispatcherName.toLowerCase() || '') >
|
|
||||||
(b.onlineInfo?.dispatcherName.toLowerCase() || '')
|
|
||||||
)
|
|
||||||
return sorter.dir;
|
|
||||||
if (
|
|
||||||
(a.onlineInfo?.dispatcherName.toLowerCase() || '') <
|
|
||||||
(b.onlineInfo?.dispatcherName.toLowerCase() || '')
|
|
||||||
)
|
|
||||||
return -sorter.dir;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'dispatcher-lvl':
|
|
||||||
diff = (a.onlineInfo?.dispatcherExp || 0) - (b.onlineInfo?.dispatcherExp || 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'routes-single':
|
|
||||||
diff =
|
|
||||||
(a.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1) -
|
|
||||||
(b.generalInfo?.routes.single.filter((r) => !r.hidden && !r.isInternal).length ?? -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'routes-double':
|
|
||||||
diff =
|
|
||||||
(a.generalInfo?.routes.double.filter((r) => !r.hidden && !r.isInternal).length ?? -1) -
|
|
||||||
(b.generalInfo?.routes.double.filter((r) => !r.hidden && !r.isInternal).length ?? -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'user':
|
|
||||||
diff =
|
|
||||||
(b.onlineInfo?.stationTrains ? b.onlineInfo.stationTrains.length : -1) -
|
|
||||||
(a.onlineInfo?.stationTrains ? a.onlineInfo.stationTrains.length : -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'like':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo ? a.onlineInfo.dispatcherRate : -Infinity) -
|
|
||||||
(b.onlineInfo ? b.onlineInfo.dispatcherRate : -Infinity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'spawn':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo ? a.onlineInfo.spawns.length : -1) -
|
|
||||||
(b.onlineInfo ? b.onlineInfo.spawns.length : -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'timetableConfirmed':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo?.scheduledTrainCount.confirmed ?? -1) -
|
|
||||||
(b.onlineInfo?.scheduledTrainCount.confirmed ?? -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'timetableUnconfirmed':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo?.scheduledTrainCount.unconfirmed ?? -1) -
|
|
||||||
(b.onlineInfo?.scheduledTrainCount.unconfirmed ?? -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'timetableAll':
|
|
||||||
diff =
|
|
||||||
(a.onlineInfo?.scheduledTrainCount.all ?? -1) -
|
|
||||||
(b.onlineInfo?.scheduledTrainCount.all ?? -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diff != 0) return Math.sign(diff) * sorter.dir;
|
|
||||||
return a.name.localeCompare(b.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const filterStations = (station: Station, filters: Record<string, any>) => {
|
|
||||||
if (filters['free'] && (!station.onlineInfo || station.onlineInfo.dispatcherId == -1))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Scenery Timetables section
|
|
||||||
if (filterTimetablesSection(filters, station)) return false;
|
|
||||||
|
|
||||||
// Scenery Accessibility section
|
|
||||||
if (filterAccessibilitySection(filters, station)) return false;
|
|
||||||
|
|
||||||
// Scenery Status section
|
|
||||||
if (station.onlineInfo && filterStatusSection(filters, station.onlineInfo)) return false;
|
|
||||||
|
|
||||||
if (station.generalInfo) {
|
|
||||||
// Scenery Reality section
|
|
||||||
if (filterRealitySection(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery Additional Programs section
|
|
||||||
if (filterProgramsSection(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery Controls section
|
|
||||||
if (filterControlsSection(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery Signalling section(s)
|
|
||||||
if (filterSignalsSection(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery Station Type section
|
|
||||||
if (filterStationType(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery sliders
|
|
||||||
if (filterSliderValues(filters, station.generalInfo)) return false;
|
|
||||||
|
|
||||||
// Scenery Authors section
|
|
||||||
if (filterInputValues(filters, station.generalInfo)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import { defineStore } from 'pinia';
|
|
||||||
import inputData from '../data/options.json';
|
|
||||||
import { useMainStore } from './mainStore';
|
|
||||||
import { filterStations, sortStations } from '../scripts/utils/stationFilterUtils';
|
|
||||||
import StorageManager from '../managers/storageManager';
|
|
||||||
import { HeadIdsType } from '../components/StationsView/typings';
|
|
||||||
|
|
||||||
export const useStationFiltersStore = defineStore('stationFiltersStore', {
|
|
||||||
state() {
|
|
||||||
return {
|
|
||||||
inputs: inputData,
|
|
||||||
// filters: { ...filterInitStates },
|
|
||||||
sorterActive: { headerName: 'station' as HeadIdsType, dir: 1 },
|
|
||||||
lastClickedFilterId: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
getters: {
|
|
||||||
areFiltersAtDefault: (state) => {
|
|
||||||
return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]);
|
|
||||||
},
|
|
||||||
|
|
||||||
filteredStationList: (state) => {
|
|
||||||
const store = useMainStore();
|
|
||||||
|
|
||||||
return store.allStationInfo
|
|
||||||
.filter((station) => filterStations(station, state.filters))
|
|
||||||
.sort((a, b) => sortStations(a, b, state.sorterActive));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
setupFilters() {
|
|
||||||
if (!StorageManager.isRegistered('options_saved')) return;
|
|
||||||
|
|
||||||
this.inputs.options.forEach((option) => {
|
|
||||||
if (!StorageManager.isRegistered(option.name)) return;
|
|
||||||
const savedValue = StorageManager.getBooleanValue(option.name);
|
|
||||||
|
|
||||||
this.filters[option.name] = savedValue;
|
|
||||||
option.value = !savedValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.inputs.sliders.forEach((slider) => {
|
|
||||||
if (!StorageManager.isRegistered(slider.name)) return;
|
|
||||||
const savedValue = StorageManager.getNumericValue(slider.name);
|
|
||||||
|
|
||||||
this.filters[slider.name] = savedValue;
|
|
||||||
slider.value = savedValue;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
changeFilterValue(name: string, value: any) {
|
|
||||||
this.filters[name] = value;
|
|
||||||
if (StorageManager.isRegistered('options_saved')) StorageManager.setValue(name, value);
|
|
||||||
},
|
|
||||||
|
|
||||||
// resetFilters() {
|
|
||||||
// // this.filters = { ...filterInitStates };
|
|
||||||
|
|
||||||
// this.inputs.options.forEach((option) => {
|
|
||||||
// option.value = option.defaultValue;
|
|
||||||
// StorageManager.setBooleanValue(option.name, !option.defaultValue);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// this.inputs.sliders.forEach((slider) => {
|
|
||||||
// slider.value = slider.defaultValue;
|
|
||||||
// StorageManager.setNumericValue(slider.name, slider.defaultValue);
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
|
|
||||||
resetSectionOptions(section: string) {
|
|
||||||
this.inputs.options
|
|
||||||
.filter((option) => option.section == section)
|
|
||||||
.forEach((option) => {
|
|
||||||
option.value = option.defaultValue;
|
|
||||||
StorageManager.setBooleanValue(option.name, !option.defaultValue);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
changeSorter(headerName: HeadIdsType) {
|
|
||||||
if (headerName == this.sorterActive.headerName)
|
|
||||||
this.sorterActive.dir = -1 * this.sorterActive.dir;
|
|
||||||
else this.sorterActive.dir = 1;
|
|
||||||
|
|
||||||
this.sorterActive.headerName = headerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -200,7 +200,7 @@ button.back-btn {
|
|||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
font-size: 1.5em;
|
font-size: 1.25em;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin: 1em auto;
|
margin: 1em auto;
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import { useMainStore } from '../store/mainStore';
|
|||||||
import DonationModal from '../components/Global/DonationModal.vue';
|
import DonationModal from '../components/Global/DonationModal.vue';
|
||||||
import StationStats from '../components/StationsView/StationStats.vue';
|
import StationStats from '../components/StationsView/StationStats.vue';
|
||||||
import { initFilters, setupFilters } from '../managers/stationFilterManager';
|
import { initFilters, setupFilters } from '../managers/stationFilterManager';
|
||||||
import { filterStations, sortStations } from '../scripts/utils/stationFilterUtils';
|
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import { provide } from 'vue';
|
import { provide } from 'vue';
|
||||||
import { ActiveSorter } from '../components/StationsView/typings';
|
import { ActiveSorter } from '../components/StationsView/typings';
|
||||||
|
|||||||
Reference in New Issue
Block a user