new choosing layout
This commit is contained in:
parent
12fb18d902
commit
4221fab3d1
@ -1,5 +1,5 @@
|
|||||||
<div class="finder">
|
<div class="finder">
|
||||||
<input class="form-control" v-model="filter" />
|
<input class="form-control" v-model="filter" placeholder="Zacznij pisać nazwę aby szukać..."/>
|
||||||
|
|
||||||
<div v-if="state === 'fetching'">
|
<div v-if="state === 'fetching'">
|
||||||
<fa icon="spinner-third" pulse/>
|
<fa icon="spinner-third" pulse/>
|
||||||
@ -30,8 +30,4 @@
|
|||||||
<fa :icon="['far', 'exclamation-triangle']"></fa>
|
<fa :icon="['far', 'exclamation-triangle']"></fa>
|
||||||
Nie znaleziono więcej przystanków, spełniających te kryteria.
|
Nie znaleziono więcej przystanków, spełniających te kryteria.
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-info" v-else>
|
|
||||||
<fa :icon="['far', 'search']"></fa>
|
|
||||||
Wprowadź zapytanie powyżej, aby wyszukać przystanek.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
@ -1,12 +0,0 @@
|
|||||||
<div class="picker">
|
|
||||||
<ul class="picker__stops list-underlined">
|
|
||||||
<li v-for="stop in stops" :key="stop.id" class="d-flex align-items-center">
|
|
||||||
<button @click="remove(stop)" class="btn btn-action">
|
|
||||||
<fa :icon="['fal', 'times']" />
|
|
||||||
</button>
|
|
||||||
<stop :stop="stop" class="flex-grow-1"></stop>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<stop-finder @select="add" :blacklist="stops"/>
|
|
||||||
</div>
|
|
@ -79,8 +79,7 @@
|
|||||||
|
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding-top: .5rem;
|
padding: .5rem .75rem;
|
||||||
padding-bottom: .5rem;
|
|
||||||
|
|
||||||
line-height: $btn-line-height;
|
line-height: $btn-line-height;
|
||||||
|
|
||||||
|
@ -25,103 +25,11 @@ Vue.use(Vuex);
|
|||||||
import('bootstrap'),
|
import('bootstrap'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// here goes "public" API
|
|
||||||
window['czydojade'] = Object.assign({}, window['czydojade'], {
|
|
||||||
components
|
|
||||||
});
|
|
||||||
|
|
||||||
store.dispatch('messages/update');
|
store.dispatch('messages/update');
|
||||||
store.dispatch('load', window['czydojade'].state);
|
store.dispatch('load', window['czydojade'].state);
|
||||||
|
|
||||||
let intervals = { messages: null, departures: null };
|
// here goes "public" API
|
||||||
|
window['czydojade'] = Object.assign({}, window['czydojade'], {
|
||||||
window['app'] = new Vue({
|
components, application: new components.Application({ el: '#app' })
|
||||||
el: '#app',
|
|
||||||
store: store,
|
|
||||||
data: {
|
|
||||||
sections: {
|
|
||||||
messages: true
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
messages: false,
|
|
||||||
departures: false
|
|
||||||
},
|
|
||||||
autorefresh: {
|
|
||||||
messages: {
|
|
||||||
active: true,
|
|
||||||
interval: 60
|
|
||||||
},
|
|
||||||
departures: {
|
|
||||||
active: true,
|
|
||||||
interval: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
messages(this: any) {
|
|
||||||
return {
|
|
||||||
count: this.$store.getters['messages/count'],
|
|
||||||
counts: this.$store.getters['messages/counts'],
|
|
||||||
state: this.$store.state.messages.state
|
|
||||||
};
|
|
||||||
},
|
|
||||||
departures(this: any) {
|
|
||||||
return {
|
|
||||||
state: this.$store.state.departures.state
|
|
||||||
};
|
|
||||||
},
|
|
||||||
stops: {
|
|
||||||
get(this: Vue) {
|
|
||||||
return this.$store.state.stops;
|
|
||||||
},
|
|
||||||
set(this: Vue, value) {
|
|
||||||
this.$store.commit('updateStops', value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
stops(this: any, stops) {
|
|
||||||
this.updateDepartures({ stops });
|
|
||||||
},
|
|
||||||
autorefresh: {
|
|
||||||
immediate: true,
|
|
||||||
deep: true,
|
|
||||||
handler(this: any, settings) {
|
|
||||||
if (intervals.messages) {
|
|
||||||
clearInterval(intervals.messages);
|
|
||||||
intervals.messages = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intervals.departures) {
|
|
||||||
clearInterval(intervals.departures);
|
|
||||||
intervals.messages = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.messages.active) {
|
|
||||||
intervals.messages = setInterval(() => this.updateMessages(), Math.max(5, settings.messages.interval) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.departures.active) {
|
|
||||||
intervals.departures = setInterval(() => this.updateDepartures({ stops: this.stops }), Math.max(5, settings.departures.interval) * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions({
|
|
||||||
updateMessages: 'messages/update',
|
|
||||||
updateDepartures: 'departures/update'
|
|
||||||
}),
|
|
||||||
...mapMutations({
|
|
||||||
updateStops: 'updateStops'
|
|
||||||
}),
|
|
||||||
save(this: Vue) {
|
|
||||||
this.$store.dispatch('save').then(x => console.log(x));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$el.classList.remove('not-ready');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -1,5 +1,94 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import store from '../store'
|
||||||
|
import { Component, Watch } from "vue-property-decorator";
|
||||||
|
import { Mutation, Action } from 'vuex-class'
|
||||||
|
import { ObtainPayload } from "../store/departures";
|
||||||
|
import { Stop } from "../model";
|
||||||
|
|
||||||
|
@Component({ store })
|
||||||
export class Application extends Vue {
|
export class Application extends Vue {
|
||||||
private messages: boolean = true;
|
private sections = {
|
||||||
|
messages: true
|
||||||
|
};
|
||||||
|
|
||||||
|
private settings = {
|
||||||
|
messages: false,
|
||||||
|
departures: false
|
||||||
|
};
|
||||||
|
|
||||||
|
private autorefresh = {
|
||||||
|
messages: {
|
||||||
|
active: true,
|
||||||
|
interval: 60
|
||||||
|
},
|
||||||
|
departures: {
|
||||||
|
active: true,
|
||||||
|
interval: 10
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private intervals = { messages: null, departures: null };
|
||||||
|
|
||||||
|
get messages() {
|
||||||
|
return {
|
||||||
|
count: this.$store.getters['messages/count'],
|
||||||
|
counts: this.$store.getters['messages/counts'],
|
||||||
|
state: this.$store.state.messages.state
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get departures() {
|
||||||
|
return {
|
||||||
|
state: this.$store.state.departures.state
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get stops() {
|
||||||
|
return this.$store.state.stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
set stops(value) {
|
||||||
|
this.$store.commit('updateStops', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$el.classList.remove('not-ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Action('messages/update') updateMessages: () => void;
|
||||||
|
@Action('departures/update') updateDepartures: (payload: ObtainPayload) => void;
|
||||||
|
|
||||||
|
@Mutation add: (stops: Stop[]) => void;
|
||||||
|
@Mutation remove: (stop: Stop) => void;
|
||||||
|
@Mutation clear: () => void;
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.$store.dispatch('save').then(x => console.log(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Watch('stops')
|
||||||
|
onStopUpdate(this: any, stops) {
|
||||||
|
this.updateDepartures({ stops });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Watch('settings', { immediate: true, deep: true })
|
||||||
|
onAutorefreshUpdate(settings) {
|
||||||
|
if (this.intervals.messages) {
|
||||||
|
clearInterval(this.intervals.messages);
|
||||||
|
this.intervals.messages = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.intervals.departures) {
|
||||||
|
clearInterval(this.intervals.departures);
|
||||||
|
this.intervals.messages = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.messages.active) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,3 +5,4 @@ export * from './departures'
|
|||||||
export * from './stop'
|
export * from './stop'
|
||||||
export * from './messages'
|
export * from './messages'
|
||||||
export * from './map'
|
export * from './map'
|
||||||
|
export * from './app'
|
@ -6,20 +6,6 @@ import { ensureArray, FetchingState, filter, map } from "../utils";
|
|||||||
import { debounce } from "../decorators";
|
import { debounce } from "../decorators";
|
||||||
import urls from '../urls';
|
import urls from '../urls';
|
||||||
|
|
||||||
@Component({ template: require("../../components/picker.html") })
|
|
||||||
export class PickerComponent extends Vue {
|
|
||||||
@Prop({ default: () => [], type: Array })
|
|
||||||
protected stops?: Stop[];
|
|
||||||
|
|
||||||
private remove(stop: Stop) {
|
|
||||||
this.$emit('update:stops', this.stops.filter(s => s != stop));
|
|
||||||
}
|
|
||||||
|
|
||||||
private add(stop: Stop|Stop[]) {
|
|
||||||
this.$emit('update:stops', [...this.stops, ...ensureArray(stop)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({ template: require('../../components/finder.html') })
|
@Component({ template: require('../../components/finder.html') })
|
||||||
export class FinderComponent extends Vue {
|
export class FinderComponent extends Vue {
|
||||||
protected found?: StopGroups = {};
|
protected found?: StopGroups = {};
|
||||||
@ -64,5 +50,4 @@ export class FinderComponent extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.component('StopPicker', PickerComponent);
|
|
||||||
Vue.component('StopFinder', FinderComponent);
|
Vue.component('StopFinder', FinderComponent);
|
||||||
|
@ -33,13 +33,15 @@ Vue.directive('hover', {
|
|||||||
el.addEventListener('focusout', deactivate);
|
el.addEventListener('focusout', deactivate);
|
||||||
},
|
},
|
||||||
unbind(el, binding) {
|
unbind(el, binding) {
|
||||||
const { activate, deactivate, keyboard } = binding['events'];
|
if (typeof binding['events'] !== 'undefined') {
|
||||||
|
const { activate, deactivate, keyboard } = binding['events'];
|
||||||
|
|
||||||
el.removeEventListener('mouseenter', activate);
|
el.removeEventListener('mouseenter', activate);
|
||||||
el.removeEventListener('click', activate);
|
el.removeEventListener('click', activate);
|
||||||
el.removeEventListener('keydown', keyboard);
|
el.removeEventListener('keydown', keyboard);
|
||||||
el.removeEventListener('mouseleave', deactivate);
|
el.removeEventListener('mouseleave', deactivate);
|
||||||
el.removeEventListener('focusout', deactivate);
|
el.removeEventListener('focusout', deactivate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -72,6 +74,8 @@ Vue.directive('responsive', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
unbind(el, binding) {
|
unbind(el, binding) {
|
||||||
window.removeEventListener('resize', binding['resize']);
|
if (typeof binding['resize'] !== 'undefined') {
|
||||||
|
window.removeEventListener('resize', binding['resize']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ export interface DeparturesState extends CommonState {
|
|||||||
departures: Departure[],
|
departures: Departure[],
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ObtainPayload {
|
export interface ObtainPayload {
|
||||||
stops: Stop[]
|
stops: Stop[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Stop } from "../model";
|
import { Stop } from "../model";
|
||||||
import { ActionTree, MutationTree } from "vuex";
|
import { ActionTree, MutationTree } from "vuex";
|
||||||
import urls from "../urls";
|
import urls from "../urls";
|
||||||
|
import { ensureArray } from "../utils";
|
||||||
|
|
||||||
export interface RootState {
|
export interface RootState {
|
||||||
stops: Stop[],
|
stops: Stop[],
|
||||||
@ -16,7 +17,9 @@ export const state: RootState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const mutations: MutationTree<RootState> = {
|
export const mutations: MutationTree<RootState> = {
|
||||||
updateStops: (state, stops) => state.stops = stops,
|
add: (state, stops) => state.stops = [...state.stops, ...ensureArray(stops)],
|
||||||
|
remove: (state, stop) => state.stops = state.stops.filter(s => s != stop),
|
||||||
|
clear: (state) => state.stops = [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actions: ActionTree<RootState, undefined> = {
|
export const actions: ActionTree<RootState, undefined> = {
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
<fa :icon="['fal', 'clock']" fixed-width></fa>
|
<fa :icon="['fal', 'clock']" fixed-width></fa>
|
||||||
<span class="text">Odjazdy</span>
|
<span class="text">Odjazdy</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<button class="btn btn-action flex-space-left" ref="settings-departures" v-hover="settings.departures">
|
<button class="btn btn-action flex-space-left" ref="settings-departures" v-hover="settings.departures">
|
||||||
<fa :icon="['fal', 'cog']" fixed-width></fa>
|
<fa :icon="['fal', 'cog']" fixed-width></fa>
|
||||||
</button>
|
</button>
|
||||||
@ -77,12 +78,32 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 order-md-first">
|
<div class="col-md-4 order-md-first">
|
||||||
|
<section class="section picker" v-if="stops.length > 0">
|
||||||
|
<header class="section__title flex">
|
||||||
|
<h2>
|
||||||
|
<fa :icon="['fal', 'sign']" fixed-width></fa>
|
||||||
|
<span class="text">Przystanki</span>
|
||||||
|
</h2>
|
||||||
|
<button class="btn btn-action flex-space-left" @click="clear">
|
||||||
|
<fa :icon="['fal', 'trash-alt']" fixed-width></fa>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<ul class="picker__stops list-underlined">
|
||||||
|
<li v-for="stop in stops" :key="stop.id" class="d-flex align-items-center">
|
||||||
|
<button @click="remove(stop)" class="btn btn-action">
|
||||||
|
<fa :icon="['fal', 'times']"></fa>
|
||||||
|
</button>
|
||||||
|
<stop :stop="stop" class="flex-grow-1"></stop>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
<section class="section picker">
|
<section class="section picker">
|
||||||
<h2 class="section__title">
|
<h2 class="section__title">
|
||||||
<fa :icon="['fal', 'sign']" fixed-width></fa>
|
<fa :icon="['fal', 'search']" fixed-width></fa>
|
||||||
Przystanki
|
Wybierz przystanki
|
||||||
</h2>
|
</h2>
|
||||||
<stop-picker :stops.sync="stops"></stop-picker>
|
<stop-finder @select="add" :blacklist="stops"/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user