history of added stops
This commit is contained in:
parent
c2b959a9da
commit
75c0c98c8d
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<div v-if="filter.length < 3" class="mt-2">
|
<div v-if="filter.length < 3" class="mt-2">
|
||||||
<favourites />
|
<favourites />
|
||||||
|
<stop-history />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="state === 'fetching'" class="text-center p-4">
|
<div v-if="state === 'fetching'" class="text-center p-4">
|
||||||
@ -22,9 +23,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="stop-group__stops list-underlined">
|
<ul class="stop-group__stops list-underlined">
|
||||||
<li v-for="stop in group" :key="stop.id" class="d-flex">
|
<li v-for="stop in group" :key="stop.id" class="d-flex">
|
||||||
<picker-stop :stop="stop" class="flex-grow-1">
|
<picker-stop :stop="stop" class="flex-grow-1 finder__stop">
|
||||||
<template v-slot:primary-action>
|
<template v-slot:primary-action>
|
||||||
<button @click="select(stop, $event)" class="btn btn-action">
|
<button @click="select(stop, $event)" class="btn btn-action stretched-link">
|
||||||
<tooltip>dodaj przystanek</tooltip>
|
<tooltip>dodaj przystanek</tooltip>
|
||||||
<ui-icon icon="add" />
|
<ui-icon icon="add" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
<div class="finder__stop">
|
<div>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<slot name="primary-action" />
|
<div class="d-flex position-relative" style="min-width: 0">
|
||||||
<div class="overflow-hidden align-self-center">
|
<slot name="primary-action" />
|
||||||
<stop :stop="stop" />
|
<div class="overflow-hidden align-self-center">
|
||||||
<div class="stop__destinations" v-if="destinations && destinations.length > 0">
|
<stop :stop="stop" />
|
||||||
<ul class="ml-1">
|
<div class="stop__destinations" v-if="destinations && destinations.length > 0">
|
||||||
<li class="stop__destination destination" v-for="destination in destinations" :key="destination.stop.id">
|
<ul>
|
||||||
<ul class="destination__lines">
|
<li class="stop__destination destination" v-for="destination in destinations" :key="destination.stop.id">
|
||||||
<li v-for="line in destination.lines">
|
<ul class="destination__lines">
|
||||||
<line-symbol :line="line" :key="line.symbol" simple/>
|
<li v-for="line in destination.lines">
|
||||||
</li>
|
<line-symbol :line="line" :key="line.symbol" simple/>
|
||||||
</ul>
|
</li>
|
||||||
<span class="destination__name ml-1">{{ destination.stop.name }}</span>
|
</ul>
|
||||||
</li>
|
<span class="destination__name ml-1">{{ destination.stop.name }}</span>
|
||||||
</ul>
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stop__actions flex-space-left">
|
<div class="stop__actions">
|
||||||
<slot name="actions">
|
<slot name="actions">
|
||||||
<button class="btn btn-action" ref="action-info" @click="details = !details">
|
<button class="btn btn-action" ref="action-info" @click="details = !details">
|
||||||
<tooltip>dodatkowe informacje</tooltip>
|
<tooltip>dodatkowe informacje</tooltip>
|
||||||
|
11
resources/components/stop/history.html
Normal file
11
resources/components/stop/history.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<ul class="list-underlined history" v-if="all.length > 0">
|
||||||
|
<li v-for="entry in all" class="history__entry">
|
||||||
|
<picker-stop :stop="entry.stop" class="flex-grow-1 finder__stop">
|
||||||
|
<template v-slot:primary-action>
|
||||||
|
<button @click="select(entry.stop, $event)" class="btn btn-action stretched-link">
|
||||||
|
<ui-icon icon="history" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</picker-stop>
|
||||||
|
</li>
|
||||||
|
</ul>
|
@ -76,8 +76,12 @@
|
|||||||
.stop-group__header {
|
.stop-group__header {
|
||||||
@extend .section__title;
|
@extend .section__title;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 !important;
|
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
margin: -.5rem -.75rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stop-group__name {
|
.stop-group__name {
|
||||||
|
13
resources/ts/components/history.ts
Normal file
13
resources/ts/components/history.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Component from "vue-class-component";
|
||||||
|
import Vue from "vue";
|
||||||
|
import { History } from "../store";
|
||||||
|
import { HistoryEntry } from "../store/history";
|
||||||
|
import { Mutation } from "vuex-class";
|
||||||
|
import { Stop } from "../model";
|
||||||
|
|
||||||
|
@Component({ template: require('../../components/stop/history.html' )})
|
||||||
|
export class StopHistory extends Vue {
|
||||||
|
@History.Getter all: HistoryEntry[];
|
||||||
|
|
||||||
|
@Mutation("add") select: (stops: Stop[]) => void;
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
import Component from "vue-class-component";
|
import Component from "vue-class-component";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { Destination, Line, StopWithDestinations as Stop, StopGroup, StopGroups } from "../model";
|
import { Line, StopGroup, StopGroups, StopWithDestinations as Stop } from "../model";
|
||||||
import { Prop, Watch } from "vue-property-decorator";
|
import { Prop, Watch } from "vue-property-decorator";
|
||||||
import { FetchingState, filter, map, match, unique } from "../utils";
|
import { FetchingState, filter, map, match, unique } from "../utils";
|
||||||
import { debounce } from "../decorators";
|
import { debounce } from "../decorators";
|
||||||
import urls from '../urls';
|
import urls from '../urls';
|
||||||
|
import { Mutation } from "vuex-class";
|
||||||
|
import { HistoryEntry } from "../store/history";
|
||||||
|
import { StopHistory } from "./history";
|
||||||
|
|
||||||
@Component({ template: require('../../components/picker/stop.html') })
|
@Component({ template: require('../../components/picker/stop.html') })
|
||||||
export class PickerStopComponent extends Vue {
|
export class PickerStopComponent extends Vue {
|
||||||
@ -49,7 +52,8 @@ export class PickerStopComponent extends Vue {
|
|||||||
@Component({
|
@Component({
|
||||||
template: require('../../components/finder.html'),
|
template: require('../../components/finder.html'),
|
||||||
components: {
|
components: {
|
||||||
"PickerStop": PickerStopComponent
|
"PickerStop": PickerStopComponent,
|
||||||
|
"StopHistory": StopHistory,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class FinderComponent extends Vue {
|
export class FinderComponent extends Vue {
|
||||||
@ -61,6 +65,8 @@ export class FinderComponent extends Vue {
|
|||||||
@Prop({default: [], type: Array})
|
@Prop({default: [], type: Array})
|
||||||
public blacklist: Stop[];
|
public blacklist: Stop[];
|
||||||
|
|
||||||
|
@Mutation('history/push') pushToHistory: (entry: HistoryEntry) => void;
|
||||||
|
|
||||||
get filtered(): StopGroups {
|
get filtered(): StopGroups {
|
||||||
const groups = map(
|
const groups = map(
|
||||||
this.found,
|
this.found,
|
||||||
@ -91,6 +97,11 @@ export class FinderComponent extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private select(stop) {
|
private select(stop) {
|
||||||
|
this.pushToHistory({
|
||||||
|
date: this.$moment(),
|
||||||
|
stop: stop,
|
||||||
|
})
|
||||||
|
|
||||||
this.$emit('select', stop);
|
this.$emit('select', stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
faClock,
|
faClock,
|
||||||
faCog,
|
faCog,
|
||||||
faExclamationTriangle,
|
faExclamationTriangle,
|
||||||
|
faHistory,
|
||||||
faHourglassHalf,
|
faHourglassHalf,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faMapMarkerAlt,
|
faMapMarkerAlt,
|
||||||
@ -97,6 +98,7 @@ const definitions = {
|
|||||||
{ icon: faSolidExclamationTriangle, transform: "shrink-5 down-4 right-6" }
|
{ icon: faSolidExclamationTriangle, transform: "shrink-5 down-4 right-6" }
|
||||||
]),
|
]),
|
||||||
'close': simple(faTimes),
|
'close': simple(faTimes),
|
||||||
|
'history': simple(faHistory),
|
||||||
...lineTypeIcons,
|
...lineTypeIcons,
|
||||||
...messageTypeIcons,
|
...messageTypeIcons,
|
||||||
};
|
};
|
||||||
|
66
resources/ts/store/history.ts
Normal file
66
resources/ts/store/history.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Stop } from "../model";
|
||||||
|
import { Module } from "vuex";
|
||||||
|
import { RootState } from "./root";
|
||||||
|
import * as moment from "moment";
|
||||||
|
import { Moment } from "moment";
|
||||||
|
import { Jsonified } from "../utils";
|
||||||
|
|
||||||
|
export interface HistoryEntry {
|
||||||
|
stop: Stop,
|
||||||
|
date: Moment,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistorySettings {
|
||||||
|
maxEntries: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryState {
|
||||||
|
entries: Jsonified<HistoryEntry>[],
|
||||||
|
settings: HistorySettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serializeHistoryEntry(entry: HistoryEntry): Jsonified<HistoryEntry> {
|
||||||
|
return {
|
||||||
|
...entry,
|
||||||
|
date: entry.date.toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deserializeHistoryEntry(serialized: Jsonified<HistoryEntry>): HistoryEntry {
|
||||||
|
return {
|
||||||
|
...serialized,
|
||||||
|
date: moment(serialized.date),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const history: Module<HistoryState, RootState> = {
|
||||||
|
namespaced: true,
|
||||||
|
state: {
|
||||||
|
entries: [],
|
||||||
|
settings: {
|
||||||
|
maxEntries: 10,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
clear(state: HistoryState) {
|
||||||
|
state.entries = [];
|
||||||
|
},
|
||||||
|
push(state: HistoryState, entry: HistoryEntry) {
|
||||||
|
state.entries = state.entries.filter(cur => cur.stop.id != entry.stop.id);
|
||||||
|
state.entries.unshift(serializeHistoryEntry(entry));
|
||||||
|
|
||||||
|
if (state.entries.length > state.settings.maxEntries) {
|
||||||
|
state.entries = state.entries.slice(0, state.settings.maxEntries);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveSettings(state: HistoryState, settings: Partial<HistorySettings>) {
|
||||||
|
Object.assign(state.settings, settings);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
all: ({ entries, settings }) => entries.slice(0, settings.maxEntries).map(deserializeHistoryEntry),
|
||||||
|
latest: ({ entries }) => n => entries.slice(0, n).map(deserializeHistoryEntry),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default history;
|
@ -3,6 +3,7 @@ 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 } from './favourites'
|
import favourites, { FavouritesState } from './favourites'
|
||||||
|
import history, { HistoryState } from "./history";
|
||||||
import departureSettings, { DeparturesSettingsState } from "./settings/departures";
|
import departureSettings, { DeparturesSettingsState } from "./settings/departures";
|
||||||
import messagesSettings, { MessagesSettingsState } from "./settings/messages";
|
import messagesSettings, { MessagesSettingsState } from "./settings/messages";
|
||||||
|
|
||||||
@ -14,12 +15,13 @@ export type State = {
|
|||||||
messages: MessagesState;
|
messages: MessagesState;
|
||||||
departures: DeparturesState;
|
departures: DeparturesState;
|
||||||
favourites: FavouritesState;
|
favourites: FavouritesState;
|
||||||
"departures-settings": DeparturesSettingsState,
|
"departures-settings": DeparturesSettingsState;
|
||||||
"messages-settings": MessagesSettingsState,
|
"messages-settings": MessagesSettingsState;
|
||||||
|
history: HistoryState;
|
||||||
} & RootState;
|
} & RootState;
|
||||||
|
|
||||||
const localStoragePersist = new VuexPersistence<State>({
|
const localStoragePersist = new VuexPersistence<State>({
|
||||||
modules: ['favourites', 'departures-settings', 'messages-settings'],
|
modules: ['favourites', 'departures-settings', 'messages-settings', 'history'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const sessionStoragePersist = new VuexPersistence<State>({
|
const sessionStoragePersist = new VuexPersistence<State>({
|
||||||
@ -35,6 +37,7 @@ const store = new Vuex.Store<RootState>({
|
|||||||
favourites,
|
favourites,
|
||||||
'departures-settings': departureSettings,
|
'departures-settings': departureSettings,
|
||||||
'messages-settings': messagesSettings,
|
'messages-settings': messagesSettings,
|
||||||
|
history,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
localStoragePersist.plugin,
|
localStoragePersist.plugin,
|
||||||
@ -49,3 +52,4 @@ export const DeparturesSettings = namespace('departures-settings');
|
|||||||
export const MessagesSettings = namespace('messages-settings');
|
export const MessagesSettings = namespace('messages-settings');
|
||||||
export const Departures = namespace('departures');
|
export const Departures = namespace('departures');
|
||||||
export const Messages = namespace('messages');
|
export const Messages = namespace('messages');
|
||||||
|
export const History = namespace('history');
|
||||||
|
@ -86,8 +86,8 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<ul class="picker__stops list-underlined">
|
<ul class="picker__stops list-underlined">
|
||||||
<li v-for="stop in stops" :key="stop.id" class="d-flex align-items-center">
|
<li v-for="stop in stops" :key="stop.id" class="picker__stop">
|
||||||
<picker-stop :stop="stop" class="flex-grow-1">
|
<picker-stop :stop="stop">
|
||||||
<template v-slot:primary-action>
|
<template v-slot:primary-action>
|
||||||
<button @click="remove(stop)" class="btn btn-action">
|
<button @click="remove(stop)" class="btn btn-action">
|
||||||
<tooltip>usuń przystanek</tooltip>
|
<tooltip>usuń przystanek</tooltip>
|
||||||
|
Loading…
Reference in New Issue
Block a user