Move messaging settings to vuex store

This commit is contained in:
Kacper Donat 2020-03-19 20:22:50 +01:00
parent 10756226f1
commit cde6507197
11 changed files with 157 additions and 78 deletions

View File

@ -1,15 +1,29 @@
<ul class="messages list-unstyled"> <div class="messages mb-2">
<li class="message alert" :class="`alert-${type(message)}`" v-for="message in messages"> <ul class="list-unstyled mb-0">
<ui-icon :icon="`message-${type(message)}`" fixed-width /> <li class="message alert" :class="`alert-${type(message)}`" v-for="message in messages">
{{ message.message }} <ui-icon :icon="`message-${message.type}`" fixed-width/>
{{ message.message }}
<div class="message__info"> <div class="message__info">
<small class="message__date"> <small class="message__date">
Komunikat ważny od Komunikat ważny od
{{ message.validFrom.format('HH:mm') }} {{ message.validFrom.format('HH:mm') }}
do do
{{ message.validTo.format('HH:mm') }} {{ message.validTo.format('HH:mm') }}
</small> </small>
</div>
</li>
</ul>
<template v-if="nonDisplayedCount > 0">
<div class="flex">
<button class="btn btn-action btn-sm flex-space-left" @click="showAll = !showAll">
<template v-if="showAll">
<ui-icon icon="chevron-up"/> {{ nonDisplayedCount }} mniej
</template>
<template v-else>
<ui-icon icon="chevron-down"/> {{ nonDisplayedCount }} więcej
</template>
</button>
</div> </div>
</li> </template>
</ul> </div>

View File

@ -0,0 +1,31 @@
<fragment>
<div class="form-group">
<div class="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"/>
</div>
<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="messages" fixed-width/>
wyświetlanych komunikatów
</label>
<ui-numeric-input id="departures-count" :value="displayedEntriesCount" @input="update({ displayedEntriesCount: $event })" :min="1" />
</div>
</fragment>

View File

@ -4,6 +4,7 @@ import { Component, Watch } from "vue-property-decorator";
import { Mutation, Action } from 'vuex-class' import { Mutation, Action } from 'vuex-class'
import { Stop } from "../model"; import { Stop } from "../model";
import { DeparturesSettingsState } from "../store/settings/departures"; import { DeparturesSettingsState } from "../store/settings/departures";
import { MessagesSettingsState } from "../store/settings/messages";
@Component({ store }) @Component({ store })
export class Application extends Vue { export class Application extends Vue {
@ -18,13 +19,6 @@ export class Application extends Vue {
picker: 'search' picker: 'search'
}; };
private autorefresh = {
messages: {
active: true,
interval: 60
}
};
private intervals = { messages: null, departures: null }; private intervals = { messages: null, departures: null };
get messages() { get messages() {
@ -55,6 +49,7 @@ export class Application extends Vue {
created() { created() {
this.initDeparturesRefreshInterval(); this.initDeparturesRefreshInterval();
this.initMessagesRefreshInterval();
} }
private initDeparturesRefreshInterval() { private initDeparturesRefreshInterval() {
@ -76,6 +71,25 @@ export class Application extends Vue {
departuresAutorefreshCallback(); departuresAutorefreshCallback();
} }
private initMessagesRefreshInterval() {
const messagesAutorefreshCallback = () => {
const {autorefresh, autorefreshInterval} = this.$store.state['messages-settings'] as MessagesSettingsState;
if (this.intervals.messages) {
clearInterval(this.intervals.messages);
}
if (autorefresh) {
this.intervals.messages = setInterval(() => this.updateMessages(), Math.max(5, autorefreshInterval) * 1000)
}
};
this.$store.watch(({"messages-settings": state}) => state.autorefresh, messagesAutorefreshCallback);
this.$store.watch(({"messages-settings": state}) => state.autorefreshInterval, messagesAutorefreshCallback);
messagesAutorefreshCallback();
}
@Action('messages/update') updateMessages: () => void; @Action('messages/update') updateMessages: () => void;
@Action('departures/update') updateDepartures: () => void; @Action('departures/update') updateDepartures: () => void;
@ -87,16 +101,4 @@ export class Application extends Vue {
onStopUpdate() { onStopUpdate() {
this.updateDepartures(); this.updateDepartures();
} }
@Watch('autorefresh', { immediate: true, deep: true })
onAutorefreshUpdate(settings) {
if (this.intervals.messages) {
clearInterval(this.intervals.messages);
this.intervals.messages = null;
}
if (settings.messages.active) {
this.intervals.messages = setInterval(() => this.updateMessages(), Math.max(5, settings.messages.interval) * 1000);
}
}
} }

View File

@ -12,3 +12,4 @@ export * from './trip'
export * from './ui' export * from './ui'
export * from './settings' export * from './settings'
export { Departures } from "../store"; export { Departures } from "../store";
export { Messages } from "../store";

View File

@ -1,18 +1,26 @@
import Vue from 'vue'; import Vue from 'vue';
import { Component } from "vue-property-decorator"; import { Component } from "vue-property-decorator";
import { Message } from "../model/message"; import { Message } from "../model/message";
import { namespace } from 'vuex-class'; import store, { Messages, MessagesSettings } from '../store'
import store from '../store'
const { State } = namespace('messages');
@Component({ template: require("../../components/messages.html"), store }) @Component({ template: require("../../components/messages.html"), store })
export class MessagesComponent extends Vue { export class MessagesComponent extends Vue {
@State messages: Message[]; @Messages.State('messages')
public allMessages: Message[];
public icon(message: Message) { @MessagesSettings.State
switch (message.type) { public displayedEntriesCount: number;
}
public showAll: boolean = false;
get messages() {
return this.showAll
? this.allMessages
: this.allMessages.slice(0, this.displayedEntriesCount);
}
get nonDisplayedCount(): number {
return Math.max(this.allMessages.length - this.displayedEntriesCount, 0);
} }
public type(message: Message) { public type(message: Message) {

View File

@ -1 +1,2 @@
export * from "./departures" export * from "./departures"
export * from "./messages"

View File

@ -0,0 +1,21 @@
import { Component } from "vue-property-decorator";
import store, { MessagesSettings } from "../../store";
import Vue from "vue";
import { MessagesSettingsState } from "../../store/settings/messages";
@Component({template: require("../../../components/settings/messages.html"), store})
export class SettingsMessages extends Vue {
@MessagesSettings.State
public autorefresh: boolean;
@MessagesSettings.State
public autorefreshInterval: number;
@MessagesSettings.State
public displayedEntriesCount: number;
@MessagesSettings.Mutation
public update: (state: Partial<MessagesSettingsState>) => void;
}
Vue.component('SettingsMessages', SettingsMessages);

View File

@ -1,11 +1,10 @@
import { RootState, SavedState } from "./root"; import { RootState } from "./root";
import { Module, Plugin, Store } from "vuex"; import { Module } from "vuex";
import * as utils from "../utils";
import { Stop } from "../model"; import { Stop } from "../model";
export interface Favourite { export interface Favourite {
id: string; id: string;
name: string; name: string;
stops: Stop[]; stops: Stop[];
} }
@ -28,12 +27,4 @@ const favourites: Module<FavouritesState, RootState> = {
} }
}; };
export const localStorageSaver = (path: string, key: string): Plugin<any> => (store: Store<any>) => {
utils.set(store.state, path, JSON.parse(window.localStorage.getItem(key) || '[]'));
store.subscribe((mutation, state) => {
window.localStorage.setItem(key, JSON.stringify(utils.get(state, path)));
})
};
export default favourites; export default favourites;

View File

@ -2,21 +2,24 @@ import Vuex from 'vuex';
import messages, { MessagesState } from './messages'; import messages, { MessagesState } from './messages';
import departures, { DeparturesState } from './departures' import departures, { DeparturesState } from './departures'
import favourites, { FavouritesState, localStorageSaver } from './favourites' import favourites, { FavouritesState } from './favourites'
import departureSettings, { DeparturesSettingsState } from "./settings/departures";
import messagesSettings, { MessagesSettingsState } from "./settings/messages";
import { actions, mutations, RootState, state } 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;
departures: DeparturesState; departures: DeparturesState;
favourites: FavouritesState; favourites: FavouritesState;
"departures-settings": DeparturesSettingsState,
"messages-settings": MessagesSettingsState,
} & RootState; } & RootState;
const localStoragePersist = new VuexPersistence<State>({ const localStoragePersist = new VuexPersistence<State>({
modules: ['favourites', 'departures-settings'], modules: ['favourites', 'departures-settings', 'messages-settings'],
}); });
const sessionStoragePersist = new VuexPersistence<State>({ const sessionStoragePersist = new VuexPersistence<State>({
@ -24,17 +27,16 @@ const sessionStoragePersist = new VuexPersistence<State>({
storage: window.sessionStorage storage: window.sessionStorage
}); });
const store = new Vuex.Store({ const store = new Vuex.Store<RootState>({
state, mutations, actions, state, mutations, actions,
modules: { modules: {
messages, messages,
departures, departures,
favourites, favourites,
'departures-settings': departureSettings 'departures-settings': departureSettings,
'messages-settings': messagesSettings,
}, },
plugins: [ plugins: [
// todo: remove after some time
localStorageSaver('favourites.favourites', 'favourites'),
localStoragePersist.plugin, localStoragePersist.plugin,
sessionStoragePersist.plugin, sessionStoragePersist.plugin,
] ]
@ -44,4 +46,6 @@ export default store;
export const Favourites = namespace('favourites'); export const Favourites = namespace('favourites');
export const DeparturesSettings = namespace('departures-settings'); export const DeparturesSettings = namespace('departures-settings');
export const MessagesSettings = namespace('messages-settings');
export const Departures = namespace('departures'); export const Departures = namespace('departures');
export const Messages = namespace('messages');

View File

@ -0,0 +1,24 @@
import { Module } from "vuex";
import { RootState } from "../root";
export type MessagesSettingsState = {
autorefresh: boolean;
autorefreshInterval?: number;
displayedEntriesCount?: number;
}
const messagesSettings: Module<MessagesSettingsState, RootState> = {
namespaced: true,
state: {
autorefresh: true,
autorefreshInterval: 60,
displayedEntriesCount: 2
},
mutations: {
update(state: MessagesSettingsState, patch: Partial<MessagesSettingsState>) {
Object.assign(state, patch);
}
}
};
export default messagesSettings;

View File

@ -29,25 +29,7 @@
<portal to="popups"> <portal to="popups">
<popper reference="settings-messages" v-if="visibility.messages" arrow placement="left-start" @leave="visibility.messages = false"> <popper reference="settings-messages" v-if="visibility.messages" arrow placement="left-start" @leave="visibility.messages = false">
<h3 class="popper__heading flex"> <settings-messages></settings-messages>
<label class="text" for="messages-auto-refresh">
<ui-icon icon="refresh" fixed-width></ui-icon>
autoodświeżanie
</label>
<ui-switch id="messages-auto-refresh" v-model="autorefresh.messages.active" class="flex-space-left"></ui-switch>
</h3>
<div class="flex" v-if="autorefresh.messages.active">
<label for="messages-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="messages-auto-refresh-interval" v-model="autorefresh.messages.interval"/>
<div class="input-group-append">
<span class="input-group-text" aria-label="sekund">s</span>
</div>
</div>
</div>
</popper> </popper>
</portal> </portal>
</header> </header>