Extract departures settings to its own component and store module
This commit is contained in:
parent
87e4121444
commit
5c8a0238f1
@ -26,4 +26,4 @@ server {
|
|||||||
internal;
|
internal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,4 @@
|
|||||||
<ul class="departures__list list-underlined">
|
<ul class="departures__list list-underlined">
|
||||||
<departure :departure="departure" :key="departure.key" v-for="departure in departures"/>
|
<departure :departure="departure" :key="departure.key" v-for="departure in departures"/>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="alert alert-info" v-if="stops.length === 0">
|
|
||||||
<ui-icon icon="info"/>
|
|
||||||
Wybierz przystanki korzystając z wyszukiwarki poniżej, aby zobaczyć listę odjazdów.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
31
resources/components/settings/departures.html
Normal file
31
resources/components/settings/departures.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<fragment>
|
||||||
|
<div class="form-group">
|
||||||
|
<h3 class="popper__heading flex">
|
||||||
|
<label class="text" for="departures-auto-refresh-interval">
|
||||||
|
<ui-icon icon="refresh" fixed-width/>
|
||||||
|
autoodświeżanie
|
||||||
|
</label>
|
||||||
|
<ui-switch id="departures-auto-refresh" :value="autorefresh" @input="update({ autorefresh: $event })" class="flex-space-left"/>
|
||||||
|
</h3>
|
||||||
|
<div class="flex " v-if="autorefresh">
|
||||||
|
<label for="departures-auto-refresh-interval" class="text">
|
||||||
|
<span class="sr-only">częstotliwość odświeżania</span>
|
||||||
|
co
|
||||||
|
</label>
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<input type="text" class="form-control form-control-sm form-control-simple" id="departures-auto-refresh-interval"
|
||||||
|
:value="autorefreshInterval" @input="update({ autorefreshInterval: Number.parseInt($event.target.value) })" />
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text" aria-label="sekund">s</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="text" for="departures-count">
|
||||||
|
<ui-icon icon="line-bus" fixed-width/>
|
||||||
|
liczba wpisów
|
||||||
|
</label>
|
||||||
|
<ui-numeric-input id="departures-count" :value="displayedEntriesCount" @input="update({ displayedEntriesCount: $event })" :min="1" :max="20"/>
|
||||||
|
</div>
|
||||||
|
</fragment>
|
@ -38,6 +38,11 @@ label {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-addon:disabled {
|
||||||
|
opacity: 1;
|
||||||
|
color: rgba($dark, .5)
|
||||||
|
}
|
||||||
|
|
||||||
.input-group-prepend {
|
.input-group-prepend {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@ import Vue from 'vue'
|
|||||||
import store from '../store'
|
import store from '../store'
|
||||||
import { Component, Watch } from "vue-property-decorator";
|
import { Component, Watch } from "vue-property-decorator";
|
||||||
import { Mutation, Action } from 'vuex-class'
|
import { Mutation, Action } from 'vuex-class'
|
||||||
import { ObtainPayload } from "../store/departures";
|
|
||||||
import { Stop } from "../model";
|
import { Stop } from "../model";
|
||||||
import { PopperComponent } from "./utils";
|
import { DeparturesSettingsState } from "../store/settings/departures";
|
||||||
|
|
||||||
@Component({ store })
|
@Component({ store })
|
||||||
export class Application extends Vue {
|
export class Application extends Vue {
|
||||||
@ -23,15 +22,9 @@ export class Application extends Vue {
|
|||||||
messages: {
|
messages: {
|
||||||
active: true,
|
active: true,
|
||||||
interval: 60
|
interval: 60
|
||||||
},
|
|
||||||
departures: {
|
|
||||||
active: true,
|
|
||||||
interval: 10
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private count = 8;
|
|
||||||
|
|
||||||
private intervals = { messages: null, departures: null };
|
private intervals = { messages: null, departures: null };
|
||||||
|
|
||||||
get messages() {
|
get messages() {
|
||||||
@ -60,16 +53,39 @@ export class Application extends Vue {
|
|||||||
this.$el.classList.remove('not-ready');
|
this.$el.classList.remove('not-ready');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.initDeparturesRefreshInterval();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initDeparturesRefreshInterval() {
|
||||||
|
const departuresAutorefreshCallback = () => {
|
||||||
|
const {autorefresh, autorefreshInterval} = this.$store.state['departures-settings'] as DeparturesSettingsState;
|
||||||
|
|
||||||
|
if (this.intervals.departures) {
|
||||||
|
clearInterval(this.intervals.departures);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autorefresh) {
|
||||||
|
this.intervals.departures = setInterval(() => this.updateDepartures(), Math.max(5, autorefreshInterval) * 1000)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$store.watch(({"departures-settings": state}) => state.autorefresh, departuresAutorefreshCallback);
|
||||||
|
this.$store.watch(({"departures-settings": state}) => state.autorefreshInterval, departuresAutorefreshCallback);
|
||||||
|
|
||||||
|
departuresAutorefreshCallback();
|
||||||
|
}
|
||||||
|
|
||||||
@Action('messages/update') updateMessages: () => void;
|
@Action('messages/update') updateMessages: () => void;
|
||||||
@Action('departures/update') updateDepartures: (payload: ObtainPayload) => void;
|
@Action('departures/update') updateDepartures: () => void;
|
||||||
|
|
||||||
@Mutation add: (stops: Stop[]) => void;
|
@Mutation add: (stops: Stop[]) => void;
|
||||||
@Mutation remove: (stop: Stop) => void;
|
@Mutation remove: (stop: Stop) => void;
|
||||||
@Mutation clear: () => void;
|
@Mutation clear: () => void;
|
||||||
|
|
||||||
@Watch('stops')
|
@Watch('stops')
|
||||||
onStopUpdate(this: any, stops) {
|
onStopUpdate() {
|
||||||
this.updateDepartures({ stops });
|
this.updateDepartures();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('autorefresh', { immediate: true, deep: true })
|
@Watch('autorefresh', { immediate: true, deep: true })
|
||||||
@ -79,17 +95,8 @@ export class Application extends Vue {
|
|||||||
this.intervals.messages = null;
|
this.intervals.messages = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.intervals.departures) {
|
|
||||||
clearInterval(this.intervals.departures);
|
|
||||||
this.intervals.messages = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.messages.active) {
|
if (settings.messages.active) {
|
||||||
this.intervals.messages = setInterval(() => this.updateMessages(), Math.max(5, settings.messages.interval) * 1000);
|
this.intervals.messages = setInterval(() => this.updateMessages(), Math.max(5, settings.messages.interval) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.departures.active) {
|
|
||||||
this.intervals.departures = setInterval(() => this.updateDepartures({ stops: this.stops }), Math.max(5, settings.departures.interval) * 1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { Departure, Stop } from "../model";
|
import { Departure } from "../model";
|
||||||
import { Component, Prop, Watch } from "vue-property-decorator";
|
import { Component, Prop, Watch } from "vue-property-decorator";
|
||||||
import { namespace } from 'vuex-class';
|
import store, { Departures } from '../store'
|
||||||
import store from '../store'
|
|
||||||
import { Trip } from "../model/trip";
|
import { Trip } from "../model/trip";
|
||||||
import urls from "../urls";
|
import urls from "../urls";
|
||||||
import { Jsonified } from "../utils";
|
import { Jsonified } from "../utils";
|
||||||
import * as moment from "moment";
|
import * as moment from "moment";
|
||||||
|
|
||||||
const { State } = namespace('departures');
|
|
||||||
|
|
||||||
@Component({ template: require("../../components/departures.html"), store })
|
@Component({ template: require("../../components/departures.html"), store })
|
||||||
export class DeparturesComponent extends Vue {
|
export class DeparturesComponent extends Vue {
|
||||||
@State departures: Departure[];
|
@Departures.State departures: Departure[];
|
||||||
|
|
||||||
@Prop(Array)
|
|
||||||
stops: Stop[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({ template: require("../../components/departures/departure.html") })
|
@Component({ template: require("../../components/departures/departure.html") })
|
||||||
|
@ -10,3 +10,5 @@ export * from './app'
|
|||||||
export * from './favourites'
|
export * from './favourites'
|
||||||
export * from './trip'
|
export * from './trip'
|
||||||
export * from './ui'
|
export * from './ui'
|
||||||
|
export * from './settings'
|
||||||
|
export { Departures } from "../store";
|
||||||
|
21
resources/ts/components/settings/departures.ts
Normal file
21
resources/ts/components/settings/departures.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Prop } from "vue-property-decorator";
|
||||||
|
import store, { DeparturesSettings } from "../../store";
|
||||||
|
import Vue from "vue";
|
||||||
|
import { DeparturesSettingsState } from "../../store/settings/departures";
|
||||||
|
|
||||||
|
@Component({ template: require("../../../components/settings/departures.html"), store })
|
||||||
|
export class SettingsDepartures extends Vue {
|
||||||
|
@DeparturesSettings.State
|
||||||
|
public autorefresh: boolean;
|
||||||
|
|
||||||
|
@DeparturesSettings.State
|
||||||
|
public autorefreshInterval: number;
|
||||||
|
|
||||||
|
@DeparturesSettings.State
|
||||||
|
public displayedEntriesCount: number;
|
||||||
|
|
||||||
|
@DeparturesSettings.Mutation
|
||||||
|
public update: (state: Partial<DeparturesSettingsState>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.component('SettingsDepartures', SettingsDepartures);
|
1
resources/ts/components/settings/index.ts
Normal file
1
resources/ts/components/settings/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./departures"
|
@ -1,7 +1,6 @@
|
|||||||
import { FetchingState } from "../utils";
|
import { FetchingState } from "../utils";
|
||||||
import { Moment } from "moment";
|
import { Moment } from "moment";
|
||||||
import { Module, MutationTree } from "vuex";
|
import { Module, MutationTree } from "vuex";
|
||||||
import { RootState } from "./root";
|
|
||||||
import * as moment from "moment";
|
import * as moment from "moment";
|
||||||
|
|
||||||
export interface CommonState {
|
export interface CommonState {
|
||||||
@ -24,4 +23,4 @@ export const mutations: MutationTree<CommonState> = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default { state, mutations };
|
export default { state, mutations };
|
||||||
|
@ -10,10 +10,6 @@ export interface DeparturesState extends CommonState {
|
|||||||
departures: Departure[],
|
departures: Departure[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ObtainPayload {
|
|
||||||
stops: Stop[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const departures: Module<DeparturesState, RootState> = {
|
export const departures: Module<DeparturesState, RootState> = {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: {
|
state: {
|
||||||
@ -29,10 +25,15 @@ export const departures: Module<DeparturesState, RootState> = {
|
|||||||
...common.mutations
|
...common.mutations
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async update({ commit }, { stops }: ObtainPayload) {
|
async update({ commit }) {
|
||||||
|
const count = this.state['departures-settings'].displayedEntriesCount;
|
||||||
|
const stops = this.state.stops;
|
||||||
|
|
||||||
commit('fetching');
|
commit('fetching');
|
||||||
|
|
||||||
const response = await fetch(urls.prepare(urls.departures, {
|
const response = await fetch(urls.prepare(urls.departures, {
|
||||||
stop: stops.map(stop => stop.id),
|
stop: stops.map(stop => stop.id),
|
||||||
|
limit: count || 8,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -4,9 +4,10 @@ import messages, { MessagesState } from './messages';
|
|||||||
import departures, { DeparturesState } from './departures'
|
import departures, { DeparturesState } from './departures'
|
||||||
import favourites, { FavouritesState, localStorageSaver } from './favourites'
|
import favourites, { FavouritesState, localStorageSaver } from './favourites'
|
||||||
|
|
||||||
import { state, mutations, actions, RootState } from "./root";
|
import { actions, mutations, RootState, state } from "./root";
|
||||||
import VuexPersistence from "vuex-persist";
|
import VuexPersistence from "vuex-persist";
|
||||||
import { namespace } from "vuex-class";
|
import { namespace } from "vuex-class";
|
||||||
|
import departureSettings from "./settings/departures";
|
||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
messages: MessagesState;
|
messages: MessagesState;
|
||||||
@ -15,7 +16,7 @@ export type State = {
|
|||||||
} & RootState;
|
} & RootState;
|
||||||
|
|
||||||
const localStoragePersist = new VuexPersistence<State>({
|
const localStoragePersist = new VuexPersistence<State>({
|
||||||
reducer: state => ({ favourites: state.favourites })
|
modules: ['favourites', 'departures-settings'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const sessionStoragePersist = new VuexPersistence<State>({
|
const sessionStoragePersist = new VuexPersistence<State>({
|
||||||
@ -25,7 +26,12 @@ const sessionStoragePersist = new VuexPersistence<State>({
|
|||||||
|
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
state, mutations, actions,
|
state, mutations, actions,
|
||||||
modules: { messages, departures, favourites },
|
modules: {
|
||||||
|
messages,
|
||||||
|
departures,
|
||||||
|
favourites,
|
||||||
|
'departures-settings': departureSettings
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
// todo: remove after some time
|
// todo: remove after some time
|
||||||
localStorageSaver('favourites.favourites', 'favourites'),
|
localStorageSaver('favourites.favourites', 'favourites'),
|
||||||
@ -37,3 +43,5 @@ const store = new Vuex.Store({
|
|||||||
export default store;
|
export default store;
|
||||||
|
|
||||||
export const Favourites = namespace('favourites');
|
export const Favourites = namespace('favourites');
|
||||||
|
export const DeparturesSettings = namespace('departures-settings');
|
||||||
|
export const Departures = namespace('departures');
|
||||||
|
24
resources/ts/store/settings/departures.ts
Normal file
24
resources/ts/store/settings/departures.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ActionContext, Module } from "vuex";
|
||||||
|
import { RootState } from "../root";
|
||||||
|
|
||||||
|
export type DeparturesSettingsState = {
|
||||||
|
autorefresh: boolean;
|
||||||
|
autorefreshInterval?: number;
|
||||||
|
displayedEntriesCount?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const departureSettings: Module<DeparturesSettingsState, RootState> = {
|
||||||
|
namespaced: true,
|
||||||
|
state: {
|
||||||
|
autorefresh: true,
|
||||||
|
autorefreshInterval: 10,
|
||||||
|
displayedEntriesCount: 10
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
update(state: DeparturesSettingsState, patch: Partial<DeparturesSettingsState>) {
|
||||||
|
Object.assign(state, patch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default departureSettings;
|
@ -68,7 +68,7 @@ class DeparturesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
||||||
{
|
{
|
||||||
$stops = $stops->all(new IdFilter($request->query->get('stop')));
|
$stops = $stops->all(new IdFilter($request->query->get('stop', [])));
|
||||||
$result = $departures->current($stops, ...$this->getModifiersFromRequest($request));
|
$result = $departures->current($stops, ...$this->getModifiersFromRequest($request));
|
||||||
|
|
||||||
return $this->json(
|
return $this->json(
|
||||||
|
@ -73,38 +73,15 @@
|
|||||||
</button>
|
</button>
|
||||||
<portal to="popups">
|
<portal to="popups">
|
||||||
<popper reference="settings-departures" v-if="visibility.departures" arrow placement="left-start" @leave="visibility.departures = false">
|
<popper reference="settings-departures" v-if="visibility.departures" arrow placement="left-start" @leave="visibility.departures = false">
|
||||||
<div class="form-group">
|
<settings-departures></settings-departures>
|
||||||
<h3 class="popper__heading flex">
|
|
||||||
<label class="text" for="departures-auto-refresh-interval">
|
|
||||||
<ui-icon icon="refresh" fixed-width></ui-icon>
|
|
||||||
autoodświeżanie
|
|
||||||
</label>
|
|
||||||
<ui-switch id="departures-auto-refresh" v-model="autorefresh.departures.active" class="flex-space-left"></ui-switch>
|
|
||||||
</h3>
|
|
||||||
<div class="flex " v-if="autorefresh.departures.active">
|
|
||||||
<label for="departures-auto-refresh-interval" class="text">
|
|
||||||
<span class="sr-only">częstotliwość odświeżania</span>
|
|
||||||
co
|
|
||||||
</label>
|
|
||||||
<div class="input-group input-group-sm">
|
|
||||||
<input type="text" class="form-control form-control-sm form-control-simple" id="departures-auto-refresh-interval" v-model="autorefresh.departures.interval"/>
|
|
||||||
<div class="input-group-append">
|
|
||||||
<span class="input-group-text" aria-label="sekund">s</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="text" for="departures-count">
|
|
||||||
<ui-icon icon="line-bus" fixed-width></ui-icon>
|
|
||||||
Liczba wpisów
|
|
||||||
</label>
|
|
||||||
<ui-numeric-input id="departures-count" v-model="count" :min="1" :max="16"></ui-numeric-input>
|
|
||||||
</div>
|
|
||||||
</popper>
|
</popper>
|
||||||
</portal>
|
</portal>
|
||||||
</header>
|
</header>
|
||||||
<departures :stops="stops"></departures>
|
<departures :stops="stops" v-if="stops.length > 0"></departures>
|
||||||
|
<div class="alert alert-info" v-else>
|
||||||
|
<ui-icon icon="info"></ui-icon>
|
||||||
|
Wybierz przystanki korzystając z wyszukiwarki poniżej, aby zobaczyć listę odjazdów.
|
||||||
|
</div>
|
||||||
{% if provider.attribution %}
|
{% if provider.attribution %}
|
||||||
<div class="attribution">
|
<div class="attribution">
|
||||||
<ui-icon icon="info"></ui-icon>
|
<ui-icon icon="info"></ui-icon>
|
||||||
|
Loading…
Reference in New Issue
Block a user