Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a2303c215e | ||
|
43dfc87546 | ||
7e0157880b | |||
74f681390a | |||
021f410a67 | |||
1bf9dd90b1 | |||
220088478e | |||
4537653465 | |||
45791e9c7f | |||
a9a947f81b | |||
bd371e432e | |||
38b110db0d | |||
e547df866f | |||
2ddc4a113c | |||
1c72e31ea8 | |||
5f80723fe9 | |||
b5918a47cb | |||
c8118fabe4 | |||
4a33222e82 |
@ -75,9 +75,7 @@ type NominatimResult = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const is_restauration_type = (e: NominatimResult) =>
|
export const is_restauration_type = (e: NominatimResult) =>
|
||||||
["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].indexOf(
|
["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].includes(e.type);
|
||||||
e.type
|
|
||||||
) != -1;
|
|
||||||
export const is_attraction_type = (e: NominatimResult): boolean =>
|
export const is_attraction_type = (e: NominatimResult): boolean =>
|
||||||
[
|
[
|
||||||
"tourism",
|
"tourism",
|
||||||
@ -88,18 +86,18 @@ export const is_attraction_type = (e: NominatimResult): boolean =>
|
|||||||
"historic",
|
"historic",
|
||||||
"natural",
|
"natural",
|
||||||
"waterway",
|
"waterway",
|
||||||
].indexOf(e.category) != -1 ||
|
].includes(e.category) ||
|
||||||
[
|
[
|
||||||
"place_of_worship",
|
"place_of_worship",
|
||||||
"national_park",
|
"national_park",
|
||||||
"nature_reserve",
|
"nature_reserve",
|
||||||
"protected_area",
|
"protected_area",
|
||||||
].indexOf(e.type) != -1 || is_travel_type(e);
|
].includes(e.type) || is_travel_type(e);
|
||||||
|
|
||||||
export const is_hotel_type = (e: NominatimResult): boolean =>
|
export const is_hotel_type = (e: NominatimResult): boolean =>
|
||||||
["hotel", "hostel", "guest_house"].indexOf(e.type) != -1
|
["hotel", "hostel", "guest_house"].includes(e.type)
|
||||||
export const is_travel_type = (e: NominatimResult): boolean =>
|
export const is_travel_type = (e: NominatimResult): boolean =>
|
||||||
["bus_stop", "tram_stop", "station", , "aerodrome", "parking"].indexOf(e.type) != -1
|
["bus_stop", "tram_stop", "station", , "aerodrome", "parking"].includes(e.type)
|
||||||
|
|
||||||
|
|
||||||
export const icon_type = (item: string | NominatimResult): string => {
|
export const icon_type = (item: string | NominatimResult): string => {
|
||||||
@ -141,12 +139,17 @@ export const icon_type = (item: string | NominatimResult): string => {
|
|||||||
"nature_reserve",
|
"nature_reserve",
|
||||||
],
|
],
|
||||||
"dice-five": ["water_park", "theme_park", "casino"],
|
"dice-five": ["water_park", "theme_park", "casino"],
|
||||||
|
"arrow-right": ["other"],
|
||||||
|
"train": ["train"],
|
||||||
|
"car-side":["car"],
|
||||||
|
"bycicle":["bike"],
|
||||||
|
"plane":["plane", "flight"],
|
||||||
"": ["?", "neighbourhood", "quarter", "highway", "place"],
|
"": ["?", "neighbourhood", "quarter", "highway", "place"],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let k in types) {
|
for (let k in types)
|
||||||
if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) return k;
|
if (types[k].includes(t) || types[k].includes(c)) return k;
|
||||||
}
|
|
||||||
console.log(item.display_name, item.category, item.type);
|
console.log(item.display_name, item.category, item.type);
|
||||||
return "question";
|
return "question";
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,6 @@ const filter_existing = function (
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
case "travel":
|
case "travel":
|
||||||
console.log(r);
|
|
||||||
return r.filter((e) => {
|
return r.filter((e) => {
|
||||||
if (
|
if (
|
||||||
leg.travel.find(
|
leg.travel.find(
|
||||||
@ -44,9 +43,8 @@ const process_results = function (tpe: "nominatim" | "travel", r: geoloc[]) {
|
|||||||
return rr;
|
return rr;
|
||||||
});
|
});
|
||||||
case "travel":
|
case "travel":
|
||||||
console.log(r);
|
|
||||||
return r.map((el) => {
|
return r.map((el) => {
|
||||||
(el as any).path = getGeoLine(
|
el.path = getGeoLine(
|
||||||
{
|
{
|
||||||
lat: (el as any).from_geo.lat,
|
lat: (el as any).from_geo.lat,
|
||||||
lng: (el as any).from_geo.lon,
|
lng: (el as any).from_geo.lon,
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import journey_wrapper from './types/wrapper';
|
|
||||||
|
|
||||||
/* LIST HELPERS */
|
|
||||||
export const filter_selected = function (journey: journey_wrapper, list: geoloc[], step: boolean) {
|
|
||||||
return list.filter((e) =>
|
|
||||||
step ? e.step == journey.sel_day : e.step >= 0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const filter_unselected = function (list: geoloc[]) {
|
|
||||||
return list.filter((e) => e.step == undefined || e.step < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const remove_item = function (list: geoloc[], idx: number) {
|
|
||||||
list[idx].step = -1;
|
|
||||||
list.splice(idx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* JOURNEY ADD/RM ITEM HELPER */
|
|
||||||
export const journey_add_place = function (journey: journey_wrapper, tpe: String, item: geoloc) {
|
|
||||||
switch (tpe) {
|
|
||||||
case 'hotel': return journey.leg_get().hotel = item;
|
|
||||||
case 'restaurant': return journey.leg_get().places.restaurants.push(item);
|
|
||||||
case 'place': return journey.leg_get().places.activities.push(item);
|
|
||||||
case 'other': return;
|
|
||||||
case 'flight': return journey.leg_get().travel.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const journey_del_place = function (journey: journey_wrapper, tpe: String, idx: number) {
|
|
||||||
console.log(tpe)
|
|
||||||
switch (tpe) {
|
|
||||||
case "hotel": return journey.leg_get().hotel = null;
|
|
||||||
case "restaurants": return journey.leg_get().places.restaurants.splice(idx, 1);
|
|
||||||
case "activities": return journey.leg_get().places.activities.splice(idx, 1);
|
|
||||||
case "other": return;
|
|
||||||
case "flight": return journey.leg_get().travel.splice(idx, 1);
|
|
||||||
default: return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,27 +6,24 @@ var nav = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const sideScroll = function (element: Element, direction: 'left' | 'right' | 'none', speed: number, step: number) {
|
const sideScroll = function (element: Element, direction: 'left' | 'right' | 'none', speed: number = 25, step: number = 15) {
|
||||||
nav.scrollDir = direction
|
nav.scrollDir = direction
|
||||||
if (direction == 'none') return;
|
if (direction == 'none') return;
|
||||||
nav.scrollInterval = setInterval(() => {
|
(nav as any).scrollInterval = setInterval(() => {
|
||||||
element.scrollLeft += (direction == 'left') ? -step : step;
|
element.scrollLeft += (direction == 'left') ? -step : step;
|
||||||
}, speed);
|
}, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const focus_leg = function (journey: journey_wrapper, idx: number | null = null) {
|
export const focus_leg = function (journey: journey_wrapper, idx: number | null = null) {
|
||||||
const c = document.querySelector('.scroll-content.nav-leg')!!
|
const c = document.querySelector('.scroll-content.nav-leg')!!
|
||||||
console.log(idx, c, journey)
|
|
||||||
const item = c.children[(idx != null ? idx : journey.sel_leg) + 1];
|
const item = c.children[(idx != null ? idx : journey.sel_leg) + 1];
|
||||||
c.scrollLeft = (item as any).offsetLeft + ((item as any).offsetWidth / 2) - (c as any).offsetWidth / 2
|
c.scrollLeft = (item as any).offsetLeft + ((item as any).offsetWidth / 2) - (c as any).offsetWidth / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
export const focus_day = function (journey: journey_wrapper, idx: number | null = null) {
|
export const focus_day = function (journey: journey_wrapper, idx: number | null = null) {
|
||||||
const c = document.querySelector('.scroll-content.nav-day')!!
|
const c = document.querySelector('.scroll-content.nav-day')!!
|
||||||
console.log(idx, c, journey)
|
|
||||||
const item = c.children[(idx != null ? idx : journey.sel_day) + 1];
|
const item = c.children[(idx != null ? idx : journey.sel_day) + 1];
|
||||||
c.scrollLeft = (item as any).offsetLeft + ((item as any).offsetWidth / 2) - (c as any).offsetWidth / 2;
|
c.scrollLeft = (item as any).offsetLeft + ((item as any).offsetWidth / 2) - (c as any).offsetWidth / 2;
|
||||||
//focus_leg(journey) // We dont render both navs anymore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nav_mousemove = function (e: PointerEvent) {
|
export const nav_mousemove = function (e: PointerEvent) {
|
||||||
@ -38,7 +35,7 @@ export const nav_mousemove = function (e: PointerEvent) {
|
|||||||
(left > c.offsetWidth * 0.9 ? 'right' : 'none')
|
(left > c.offsetWidth * 0.9 ? 'right' : 'none')
|
||||||
if (!nav.scrollInterval || nav.scrollDir != newDir) {
|
if (!nav.scrollInterval || nav.scrollDir != newDir) {
|
||||||
if (nav.scrollInterval) clearInterval(nav.scrollInterval)
|
if (nav.scrollInterval) clearInterval(nav.scrollInterval)
|
||||||
sideScroll(c, newDir, 25, 10);
|
sideScroll(c, newDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const nav_mouseleave = function (_e: PointerEvent) {
|
export const nav_mouseleave = function (_e: PointerEvent) {
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import journey_wrapper from "./types/wrapper";
|
import journey_wrapper from "./types/wrapper";
|
||||||
import { migrator } from "./types/migration";
|
import { migrator } from "./types/migration";
|
||||||
import { journey_add_place, journey_del_place } from "./helper/journey";
|
|
||||||
import { search_nominatim, search_flight } from "./helper/api";
|
|
||||||
import { focus_day, focus_leg, nav_mouseleave, nav_mousemove } from "./helper/nav";
|
import { focus_day, focus_leg, nav_mouseleave, nav_mousemove } from "./helper/nav";
|
||||||
import { set_search_set_results } from "./helper/api";
|
import { set_search_set_results } from "./helper/api";
|
||||||
|
import toast from "./types/toast";
|
||||||
|
import search_drawer from "./types/search_drawer";
|
||||||
|
import { to_xy } from "./types/geom";
|
||||||
|
|
||||||
Vue.component("l-map", window.Vue2Leaflet.LMap);
|
Vue.component("l-map", window.Vue2Leaflet.LMap);
|
||||||
Vue.component("l-tile-layer", window.Vue2Leaflet.LTileLayer);
|
Vue.component("l-tile-layer", window.Vue2Leaflet.LTileLayer);
|
||||||
@ -19,22 +20,10 @@ Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale);
|
|||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
el: "#app",
|
el: "#app",
|
||||||
data: {
|
data: {
|
||||||
edit_active: ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1,
|
journey: new journey_wrapper(),
|
||||||
journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)),
|
search_drawer: new search_drawer(),
|
||||||
map_override: { active: false, elements: [] },
|
|
||||||
query: {
|
|
||||||
type: "", query: "", res: [], load: false, sub: false, note: false, drawer: false, addmarker: false,
|
|
||||||
},
|
|
||||||
useDay: false,
|
useDay: false,
|
||||||
toast: {
|
toast: new toast(),
|
||||||
show: false,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
special: '',
|
|
||||||
acceptText: '',
|
|
||||||
cancelText: '',
|
|
||||||
func: () => { },
|
|
||||||
},
|
|
||||||
lang: {
|
lang: {
|
||||||
format: "ddd D MMM",
|
format: "ddd D MMM",
|
||||||
formatLocale: {
|
formatLocale: {
|
||||||
@ -46,18 +35,14 @@ const app = new Vue({
|
|||||||
methods: {
|
methods: {
|
||||||
start_journey: function () { window.location.href = "/" + this.journey.id },
|
start_journey: function () { window.location.href = "/" + this.journey.id },
|
||||||
|
|
||||||
compute_bb: function () {
|
|
||||||
if (!this.$refs.map) return undefined
|
|
||||||
const bounds = this.$refs.map.mapObject.getBounds();
|
|
||||||
return [[bounds.getSouthWest().lng, bounds.getSouthWest().lat],
|
|
||||||
[bounds.getNorthEast().lng, bounds.getNorthEast().lat]]
|
|
||||||
},
|
|
||||||
generate_rotation: function (index, list) {
|
generate_rotation: function (index, list) {
|
||||||
if (index < 0 || index >= list.length) return 0;
|
if (index < 0 || index >= list.length) return 0;
|
||||||
const c0 = list[(index == 0) ? index : (index - 1)]
|
const c0 = to_xy(list[(index == 0) ? index : (index - 1)])
|
||||||
const c1 = list[(index == list.length - 1) ? index : (index + 1)]
|
const c1 = to_xy(list[(index == (list.length - 1)) ? index : (index + 1)])
|
||||||
const brng = Math.atan2(c1[1] - c0[1], c1[0] - c0[0]);
|
const brng = Math.atan2(c1[1] - c0[1], c1[0] - c0[0])- Math.PI / 2;
|
||||||
return `rotate:${brng - Math.PI / 2}rad`;
|
const flip = (brng>-Math.PI/2)?'transform: scale(1,1);': 'transform: scale(1, -1);';
|
||||||
|
const rot = `rotate:${brng}rad;`
|
||||||
|
return `${rot}${flip}`;
|
||||||
|
|
||||||
},
|
},
|
||||||
generate_marker: function (item, fcolor) {
|
generate_marker: function (item, fcolor) {
|
||||||
@ -72,106 +57,6 @@ const app = new Vue({
|
|||||||
return `<i class="fa fa-${api.icon_type(item) || "star"} fa-2x ${classes}" style="${styling}; color:${fcolor || "white"}; text-align:center; align-content:center;"></i>`;
|
return `<i class="fa fa-${api.icon_type(item) || "star"} fa-2x ${classes}" style="${styling}; color:${fcolor || "white"}; text-align:center; align-content:center;"></i>`;
|
||||||
},
|
},
|
||||||
|
|
||||||
import_data: function (v) {
|
|
||||||
this.journey.data = Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(v.toDecoded()),
|
|
||||||
);
|
|
||||||
this.journey.data.main.forEach((e) => {
|
|
||||||
if (e.date_range) {
|
|
||||||
e.date_range[0] = new Date(e.date_range[0]);
|
|
||||||
e.date_range[1] = new Date(e.date_range[1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
toast_reset: function () {
|
|
||||||
this.toast.show = false;
|
|
||||||
this.toast.title = '';
|
|
||||||
this.toast.desc = ''
|
|
||||||
this.toast.special = '';
|
|
||||||
this.toast.acceptText = ''
|
|
||||||
this.toast.cancelText = ''
|
|
||||||
this.toast.func = () => { }
|
|
||||||
},
|
|
||||||
|
|
||||||
toast_impexp: function (is_import) {
|
|
||||||
this.toast.show = true;
|
|
||||||
this.toast.title = is_import ? 'Import' : 'Export';
|
|
||||||
this.toast.desc = ''
|
|
||||||
this.toast.special = JSON.stringify(this.journey.data).toEncoded();
|
|
||||||
this.toast.acceptText = is_import ? 'load' : ''
|
|
||||||
this.toast.cancelText = 'cancel'
|
|
||||||
this.toast.func = () => { this.import_data(this.toast.special); this.toast_reset(); }
|
|
||||||
},
|
|
||||||
|
|
||||||
search_set_results(r) {
|
|
||||||
this.query.load = false;
|
|
||||||
this.query.res = r;
|
|
||||||
return r
|
|
||||||
},
|
|
||||||
search_set_clear(keep_drawer) {
|
|
||||||
this.query.res = [];
|
|
||||||
this.query.note = false;
|
|
||||||
this.query.type = null;
|
|
||||||
this.query.addmarker = false;
|
|
||||||
this.query.sub = false;
|
|
||||||
this.query.drawer = keep_drawer;
|
|
||||||
setTimeout(() => this.$refs.map.mapObject.invalidateSize(), 500);
|
|
||||||
},
|
|
||||||
search_set_active: function (is_notes, tpe) {
|
|
||||||
this.query.drawer = true;
|
|
||||||
this.query.note = is_notes;
|
|
||||||
this.query.type = !is_notes ? tpe : null;
|
|
||||||
this.query.load = !is_notes;
|
|
||||||
setTimeout(() => this.$refs.map.mapObject.invalidateSize(), 500);
|
|
||||||
},
|
|
||||||
|
|
||||||
drawer_hover_item: function (item) {
|
|
||||||
if (item) {
|
|
||||||
this.map_override.active = true
|
|
||||||
if (item.type == 'flight') {
|
|
||||||
this.map_override.elements = [[item.from_geo.lat, item.from_geo.lon], [item.to_geo.lat, item.to_geo.lon]]
|
|
||||||
} else {
|
|
||||||
this.map_override.elements = [[item.lat, item.lon]]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.map_override.active = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
drawer_click_item: function (item) {
|
|
||||||
const tpe = this.query.type
|
|
||||||
this.search_set_clear(item ? true : false);
|
|
||||||
this.drawer_hover_item();
|
|
||||||
if (item) {
|
|
||||||
item.step = -1;
|
|
||||||
journey_add_place(this.journey, tpe, item)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
search_active: function (_e) {
|
|
||||||
const tpe = this.query.type;
|
|
||||||
const query = this.query.query;
|
|
||||||
switch (tpe) {
|
|
||||||
case 'hotel':
|
|
||||||
case 'restaurant': ;
|
|
||||||
case 'place':
|
|
||||||
case 'other':
|
|
||||||
return search_nominatim(tpe, query, this.compute_bb(), this.journey.leg_get())
|
|
||||||
|
|
||||||
case 'flight':
|
|
||||||
return search_flight(tpe, query, this.journey.leg_get());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
search_enable: function (f) {
|
|
||||||
const is_notes = f == 'notes';
|
|
||||||
this.search_set_active(is_notes, f)
|
|
||||||
setTimeout(() => document.getElementById(is_notes ? 'query_note' : 'query_input').focus(), 500);
|
|
||||||
if (!is_notes) this.search_active()
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshTextAreaHeight: function (e) {
|
refreshTextAreaHeight: function (e) {
|
||||||
e.target.style['height'] = 'auto';
|
e.target.style['height'] = 'auto';
|
||||||
e.target.style['height'] = e.target.scrollHeight + 'px';
|
e.target.style['height'] = e.target.scrollHeight + 'px';
|
||||||
@ -179,53 +64,62 @@ const app = new Vue({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onMapClick(e) {
|
onMapClick(e) {
|
||||||
if (this.query.addmarker) {
|
if (this.search_drawer.query.addmarker) {
|
||||||
const newMarker = {
|
const newMarker = {
|
||||||
latlon: [e.latlng.lat, e.latlng.lng],
|
latlon: [e.latlng.lat, e.latlng.lng],
|
||||||
sname: this.query.query,
|
sname: this.search_drawer.query.query,
|
||||||
type: this.query.type,
|
type: this.search_drawer.query.type,
|
||||||
};
|
};
|
||||||
this.drawer_click_item(newMarker)
|
this.search_drawer.click_item(this.journey,newMarker)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
set_search_set_results(this.search_set_results);
|
set_search_set_results((r) => { this.search_drawer.results(r); });
|
||||||
this.nav_mouseleave = nav_mouseleave;
|
this.nav_mouseleave = nav_mouseleave;
|
||||||
this.nav_mousemove = nav_mousemove;
|
this.nav_mousemove = nav_mousemove;
|
||||||
this.focus_day = focus_day;
|
this.focus_day = focus_day;
|
||||||
this.focus_leg = focus_leg;
|
this.focus_leg = focus_leg;
|
||||||
this.place_delete = (tpe, idx) => journey_del_place(this.journey, tpe, idx);
|
|
||||||
|
|
||||||
this.save_data = api.throttle(() => {
|
this.save_data = api.throttle(() => {
|
||||||
api.save(this.journey.id, this.journey.data);
|
api.save(this.journey.id, this.journey.data);
|
||||||
}, 1000);
|
}, 2000);
|
||||||
|
|
||||||
this.pressed_prev = api.throttle(() => {
|
this.pressed_prev_next = api.throttle((dir_prev) => {
|
||||||
if (this.useDay) this.journey.day_prev();
|
if (this.useDay && dir_prev) return this.journey.day_prev();
|
||||||
else this.journey.leg_prev();
|
if (!this.useDay && dir_prev) return this.journey.leg_prev();
|
||||||
}, 250)
|
if (this.useDay && !dir_prev) return this.journey.day_next();
|
||||||
this.pressed_next = api.throttle(() => {
|
if (!this.useDay && !dir_prev) return this.journey.leg_next();
|
||||||
if (this.useDay) this.journey.day_next();
|
|
||||||
else this.journey.leg_next();
|
|
||||||
}, 250)
|
}, 250)
|
||||||
|
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case "ArrowLeft": return this.pressed_prev()
|
case "ArrowLeft": return this.pressed_prev_next(true)
|
||||||
case "ArrowRight": return this.pressed_next()
|
case "ArrowRight": return this.pressed_prev_next(false)
|
||||||
default: return console.log(e.key);
|
default: return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.load(this.journey.id).then((r) => {
|
api.load(this.journey.id).then((r) => {
|
||||||
app.journey.data = migrator(r)
|
app.journey.data = migrator(r)
|
||||||
|
setTimeout(() => focus_leg(this.journey) && focus_day(this.journey) && this.$refs.map.mapObject.keyboard.disable(), 50);
|
||||||
|
|
||||||
|
;
|
||||||
|
this.search_drawer.refresh_map = () => { this.$refs.map.mapObject.invalidateSize() }
|
||||||
|
this.search_drawer.get_leg = () => { return this.journey.leg_get() }
|
||||||
|
this.search_drawer.get_bb = () => {
|
||||||
|
if (!this.$refs.map) return []
|
||||||
|
const bounds = this.$refs.map.mapObject.getBounds();
|
||||||
|
return [[bounds.getSouthWest().lng, bounds.getSouthWest().lat],
|
||||||
|
[bounds.getNorthEast().lng, bounds.getNorthEast().lat]]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
journey: {
|
journey: {
|
||||||
handler: function (ndata, odata) {
|
handler: function (ndata, odata) {
|
||||||
if (this.edit_active) this.save_data();
|
if (this.journey.edit) this.save_data();
|
||||||
|
window.location.hash = `#${this.journey.sel_leg}_${this.journey.sel_day}`
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
|
@ -7,10 +7,12 @@ declare global {
|
|||||||
}
|
}
|
||||||
interface geoloc {
|
interface geoloc {
|
||||||
title: string
|
title: string
|
||||||
osm_id: number
|
|
||||||
latlon: [number, number]
|
|
||||||
notes: string
|
notes: string
|
||||||
step: -1
|
type?: string
|
||||||
|
osm_id?: number
|
||||||
|
latlon?: [number, number]
|
||||||
|
step?: -1
|
||||||
|
path?: number[][]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface map {
|
interface map {
|
||||||
|
@ -160,6 +160,15 @@ function recursiveMidPoint(src: LatLng, dst: LatLng, opt: { step?: number, dist?
|
|||||||
return geom;
|
return geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getGeoLine(src: LatLng, dst: LatLng, opt: { step?: number, dist?: number }) {
|
export function to_xy(point: number[]){
|
||||||
|
const R = 6378137; // Earth's radius in meters (WGS84 standard)
|
||||||
|
const lon =((point[0] + 180) % 360 + 360) % 360 - 180;
|
||||||
|
const lat = ((point[1] + 90) % 180 + 180) % 180 - 90;
|
||||||
|
const x = R * (lon* Math.PI / 180);
|
||||||
|
const y = R * Math.log(Math.tan((Math.PI / 4) + (lat * Math.PI / 360)));
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGeoLine(src: LatLng, dst: LatLng, opt: { step?: number, dist?: number }): LatLng[] {
|
||||||
return recursiveMidPoint(src, dst, opt, 1)
|
return recursiveMidPoint(src, dst, opt, 1)
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ function migrate_A_to_0(e: journey): journey {
|
|||||||
v.day_title = v.day_title || (v as any).step_title;
|
v.day_title = v.day_title || (v as any).step_title;
|
||||||
v.places.activities = v.places.activities || (v as any).places.places;
|
v.places.activities = v.places.activities || (v as any).places.places;
|
||||||
v.travel = v.travel || [];
|
v.travel = v.travel || [];
|
||||||
v.day_title = typeof (v.day_title) == "string" ? [v.day_title] : []
|
v.day_title = typeof (v.day_title) == "string" ? [v.day_title] : [];
|
||||||
})
|
})
|
||||||
console.log(e)
|
console.log(e)
|
||||||
return e;
|
return e;
|
||||||
|
150
src/client/types/search_drawer.ts
Normal file
150
src/client/types/search_drawer.ts
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import { search_flight, search_nominatim } from "../helper/api";
|
||||||
|
import { leg_template } from "./format";
|
||||||
|
import journey_wrapper from "./wrapper";
|
||||||
|
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
type query_type = "hotel" | "restaurant" | "place" | "flight"
|
||||||
|
type note_type = "notes"
|
||||||
|
type sub_type = "travel" | "other"
|
||||||
|
|
||||||
|
interface query {
|
||||||
|
type: query_type | note_type | "",
|
||||||
|
sub: sub_type | "",
|
||||||
|
query: string,
|
||||||
|
res: any[],
|
||||||
|
load: boolean,
|
||||||
|
/* DELETE BELOW IF POSIBLE */
|
||||||
|
addmarker: Boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface map_override {
|
||||||
|
active: Boolean,
|
||||||
|
elements: number[][]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class search_drawer {
|
||||||
|
map_override: map_override = { active: false, elements: [] };
|
||||||
|
multipath : any[]=[];
|
||||||
|
|
||||||
|
query: query = {
|
||||||
|
type: "", query: "", sub: "", res: [], load: false, addmarker: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
resfresh_map: () => void = () => { }
|
||||||
|
get_bb: () => any[] = () => []
|
||||||
|
get_leg: () => leg = () => leg_template
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
show_drawer() {
|
||||||
|
return this.is_note() || this.is_query()
|
||||||
|
}
|
||||||
|
|
||||||
|
is_note() {
|
||||||
|
return ["notes"].includes(this.query.type)
|
||||||
|
}
|
||||||
|
is_place(){
|
||||||
|
return ["hotel", "restaurant", "place"].includes(this.query.type)
|
||||||
|
}
|
||||||
|
is_query() {
|
||||||
|
return this.is_place()|| this.is_flight() || this.is_multipath()
|
||||||
|
}
|
||||||
|
is_sub_travel() {
|
||||||
|
return ["travel"].includes(this.query.sub)
|
||||||
|
}
|
||||||
|
is_multipath(){
|
||||||
|
return ["flight", "train", "car","bike", "other"].includes(this.query.type)
|
||||||
|
}
|
||||||
|
is_flight(){
|
||||||
|
return ["flight"].includes(this.query.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
results(r: any[]) {
|
||||||
|
this.query.load = false;
|
||||||
|
this.query.res = r;
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
reset() {
|
||||||
|
this.query.res = [];
|
||||||
|
this.multipath = [];
|
||||||
|
this.map_override.elements = []
|
||||||
|
this.query.type = "";
|
||||||
|
this.query.addmarker = false;
|
||||||
|
setTimeout(() => this.resfresh_map(), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
active(tpe: query_type) {
|
||||||
|
this.query.type = tpe;
|
||||||
|
this.query.load = this.is_query();
|
||||||
|
setTimeout(() => this.resfresh_map(), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(_e = null) {
|
||||||
|
const tpe = this.query.type;
|
||||||
|
const query = this.query.query;
|
||||||
|
switch (tpe) {
|
||||||
|
case 'flight':
|
||||||
|
return search_flight(tpe, query, this.get_leg());
|
||||||
|
default:
|
||||||
|
return search_nominatim(tpe, query, this.get_bb(), this.get_leg())
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enable(f: query_type) {
|
||||||
|
this.active(f)
|
||||||
|
setTimeout(() => document.getElementById(this.is_note() ? 'query_note' : 'query_input')?.focus(), 500);
|
||||||
|
if (this.is_query()) this.search()
|
||||||
|
}
|
||||||
|
|
||||||
|
hover_item (item?:any) {
|
||||||
|
if (item) {
|
||||||
|
this.map_override.active = true
|
||||||
|
if (item.type == 'flight') {
|
||||||
|
this.map_override.elements.push([item.from_geo.lat, item.from_geo.lon])
|
||||||
|
this.map_override.elements.push([item.to_geo.lat, item.to_geo.lon])
|
||||||
|
} else {
|
||||||
|
this.map_override.elements.push([item.lat, item.lon])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.map_override.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
click_item (journey: journey_wrapper, item?:any) {
|
||||||
|
const tpe = this.query.type
|
||||||
|
if(this.is_multipath()){
|
||||||
|
if(this.query.addmarker){
|
||||||
|
if(item){
|
||||||
|
this.map_override.active = true
|
||||||
|
this.map_override.elements.push(item.latlon? item.latlon: [item.lat,item.lon])
|
||||||
|
this.multipath.push(item)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
let new_item :geoloc = {
|
||||||
|
type: (tpe as string),
|
||||||
|
path: this.map_override.elements,
|
||||||
|
title: '-',
|
||||||
|
notes: "",
|
||||||
|
}
|
||||||
|
this.map_override.active = false
|
||||||
|
journey.add_place(tpe, new_item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reset();
|
||||||
|
this.hover_item();
|
||||||
|
if (item) {
|
||||||
|
item.step = -1;
|
||||||
|
journey.add_place(tpe, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default search_drawer;
|
62
src/client/types/toast.ts
Normal file
62
src/client/types/toast.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import journey_wrapper from "./wrapper";
|
||||||
|
import { focus_leg } from "../helper/nav";
|
||||||
|
|
||||||
|
interface toaster {
|
||||||
|
show: boolean,
|
||||||
|
title: String,
|
||||||
|
desc: String,
|
||||||
|
special: String,
|
||||||
|
acceptText: String,
|
||||||
|
cancelText: String,
|
||||||
|
func: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const default_toaster = {
|
||||||
|
show: false,
|
||||||
|
title: ' ',
|
||||||
|
desc: ' ',
|
||||||
|
special: ' ',
|
||||||
|
acceptText: ' ',
|
||||||
|
cancelText: ' ',
|
||||||
|
func: () => { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class toast {
|
||||||
|
data: toaster = default_toaster;
|
||||||
|
|
||||||
|
reset = function (): void {
|
||||||
|
this.data.show = false
|
||||||
|
this.data.title = ' '
|
||||||
|
this.data.desc = ' '
|
||||||
|
this.data.special = ' '
|
||||||
|
this.data.acceptText = ' '
|
||||||
|
this.data.cancelText = ' '
|
||||||
|
this.data.func = () => { };
|
||||||
|
}
|
||||||
|
constructor() {
|
||||||
|
this.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
impexp = function (is_import: boolean, journey: journey_wrapper): void {
|
||||||
|
this.data.show = true;
|
||||||
|
this.data.title = is_import ? 'Import' : 'Export';
|
||||||
|
this.data.desc = ''
|
||||||
|
this.data.special = JSON.stringify(journey.data).toEncoded();
|
||||||
|
this.data.acceptText = is_import ? 'load' : ''
|
||||||
|
this.data.cancelText = 'cancel'
|
||||||
|
this.data.func = () => { journey.import_data(JSON.parse(this.data.special.toDecoded().toString())); this.reset(toast); }
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_leg = function (v: number, journey: journey_wrapper): void {
|
||||||
|
this.data.show = true;
|
||||||
|
this.data.title = `Delete Leg`;
|
||||||
|
this.data.desc = `Remove leg <${journey.leg_get(v).title || v}>`
|
||||||
|
this.data.special = '';
|
||||||
|
this.data.acceptText = 'delete'
|
||||||
|
this.data.cancelText = 'cancel'
|
||||||
|
this.data.func = () => { journey.rm_leg(v); focus_leg(journey); this.reset(toast); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default toast;
|
@ -6,12 +6,16 @@ const date_day_diff = (d0: Date, d1: Date): number =>
|
|||||||
|
|
||||||
class journey_wrapper {
|
class journey_wrapper {
|
||||||
id: String
|
id: String
|
||||||
|
edit: Boolean = true
|
||||||
data: journey = journey_template;
|
data: journey = journey_template;
|
||||||
sel_leg: number = 0;
|
sel_leg: number = 0;
|
||||||
sel_day: number = 0;
|
sel_day: number = 0;
|
||||||
|
|
||||||
constructor(id: String) {
|
constructor(id: String | undefined) {
|
||||||
this.id = id;
|
if (id)
|
||||||
|
this.id = id;
|
||||||
|
else
|
||||||
|
this.from_url()
|
||||||
}
|
}
|
||||||
|
|
||||||
leg_first = () => this.data.main[0]
|
leg_first = () => this.data.main[0]
|
||||||
@ -61,6 +65,9 @@ class journey_wrapper {
|
|||||||
day_sel(idx: number): void {
|
day_sel(idx: number): void {
|
||||||
this.sel_day = idx;
|
this.sel_day = idx;
|
||||||
}
|
}
|
||||||
|
day_count(): number {
|
||||||
|
return this.leg_len();
|
||||||
|
}
|
||||||
day_next() {
|
day_next() {
|
||||||
this.sel_day += 1
|
this.sel_day += 1
|
||||||
if (this.sel_day > this.leg_len() - 1) {
|
if (this.sel_day > this.leg_len() - 1) {
|
||||||
@ -151,6 +158,50 @@ class journey_wrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import_data(v: any) {
|
||||||
|
this.data = Object.assign({}, v);
|
||||||
|
this.data.main.forEach((e) => {
|
||||||
|
if (e.date_range) {
|
||||||
|
e.date_range[0] = new Date(e.date_range[0]);
|
||||||
|
e.date_range[1] = new Date(e.date_range[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_place(tpe: String, item: geoloc) {
|
||||||
|
switch (tpe) {
|
||||||
|
case 'hotel': return this.leg_get().hotel = item;
|
||||||
|
case 'restaurant': return this.leg_get().places.restaurants.push(item);
|
||||||
|
case 'place': return this.leg_get().places.activities.push(item);
|
||||||
|
case 'other':
|
||||||
|
case 'train':
|
||||||
|
case 'car':
|
||||||
|
case 'bike':
|
||||||
|
case 'flight': return this.leg_get().travel.push(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
del_place(tpe: String, idx: number) {
|
||||||
|
switch (tpe) {
|
||||||
|
case "hotel": return this.leg_get().hotel = null;
|
||||||
|
case "restaurants": return this.leg_get().places.restaurants.splice(idx, 1);
|
||||||
|
case "activities": return this.leg_get().places.activities.splice(idx, 1);
|
||||||
|
case "other": return;
|
||||||
|
case "flight": return this.leg_get().travel.splice(idx, 1);
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_url() {
|
||||||
|
const path = window.location.pathname.slice(1).split('/')
|
||||||
|
const hash = window.location.hash.slice(1).split('_')
|
||||||
|
this.id = path.at(-1) || String.gen_id(16).toString()
|
||||||
|
this.sel_leg = parseInt(hash.at(0) || '0')
|
||||||
|
this.sel_day = parseInt(hash.at(1) || '0')
|
||||||
|
this.edit = !["view", "short"].includes(path.at(0) || "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default journey_wrapper;
|
export default journey_wrapper;
|
@ -13,8 +13,8 @@ interface FlightData {
|
|||||||
|
|
||||||
function clean_times(s: string): string | null {
|
function clean_times(s: string): string | null {
|
||||||
if (s == "—" || s == "Scheduled") return null
|
if (s == "—" || s == "Scheduled") return null
|
||||||
if (s.indexOf("Estimated departure") == 0) return null
|
if (s.startsWith("Estimated departure")) return null
|
||||||
if (s.indexOf("Landed") == 0) return s.replace("Landed ", "")
|
if (s.startsWith("Landed")) return s.replace("Landed ", "")
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,49 +2,86 @@
|
|||||||
.input.w-100.text-dark
|
.input.w-100.text-dark
|
||||||
input#query_input(
|
input#query_input(
|
||||||
type="search"
|
type="search"
|
||||||
@input="search_active"
|
@input="search_drawer.search()"
|
||||||
@focus="search_active"
|
@focus="search_drawer.search()"
|
||||||
placeholder="Search ... "
|
placeholder="Search ... "
|
||||||
style="width:85%;"
|
style="width:85%;"
|
||||||
:disabled="query.note"
|
:disabled="search_drawer.is_note()"
|
||||||
v-model="query.query"
|
v-model="search_drawer.query.query"
|
||||||
)
|
)
|
||||||
.spinner(v-if="query.load")
|
.spinner(v-if="search_drawer.query.load")
|
||||||
|
|
||||||
div(v-if="['hotel', 'restaurant', 'place','other', 'travel'].indexOf(query.type)>=0")
|
div(v-if="search_drawer.is_query()")
|
||||||
template(v-for="(item, idx) in query.res" )
|
div(v-if="search_drawer.is_flight()")
|
||||||
|
template(v-for="(item, idx) in search_drawer.query.res" )
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
:key="'q'+idx"
|
||||||
|
@mouseover="search_drawer.hover_item(item)"
|
||||||
|
@mouseleave="search_drawer.hover_item()"
|
||||||
|
@click="search_drawer.click_item(journey,item)" )
|
||||||
|
div( v-html="generate_icon('plane', 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| {{ item.from }} => {{item.to}}
|
||||||
|
.bg-dark.divider(
|
||||||
|
:key="'qdiv'+idx" style="height:1px" )
|
||||||
.query-result.col-12.bg-white.text-dark(
|
.query-result.col-12.bg-white.text-dark(
|
||||||
:key="'q'+idx"
|
v-if="!search_drawer.query.addmarker"
|
||||||
@mouseover="drawer_hover_item(item)"
|
@click="search_drawer.query.addmarker=true" )
|
||||||
@mouseleave="drawer_hover_item()"
|
div( v-html="generate_icon('star', 'var(--dark)')")
|
||||||
@click="drawer_click_item(item)" )
|
|
||||||
div( v-html="generate_icon(item, 'var(--dark)')")
|
|
||||||
.col-10()
|
.col-10()
|
||||||
| {{ item.name }}
|
| Start custom
|
||||||
.bg-dark.divider(
|
.query-result.col-12.bg-white.text-dark(
|
||||||
:key="'qdiv'+idx" style="height:1px" )
|
v-else
|
||||||
.query-result.col-12.bg-white.text-dark(
|
@click="search_drawer.click_item(journey)" )
|
||||||
v-if="query.load==false && query.res.length>=0 && query.query!=''"
|
div( v-html="generate_icon('star', 'var(--dark)')")
|
||||||
@click="query.addmarker=true" )
|
.col-10()
|
||||||
div( v-html="generate_icon('star', 'var(--dark)')")
|
| Finish
|
||||||
.col-10()
|
div(v-else-if="search_drawer.is_multipath()")
|
||||||
| Add custom
|
template(v-for="(item, idx) in search_drawer.query.res" )
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
:key="'q'+idx"
|
||||||
|
@mouseover="search_drawer.hover_item(item)"
|
||||||
|
@mouseleave="search_drawer.hover_item()"
|
||||||
|
@click="search_drawer.click_item(journey,item)" )
|
||||||
|
div( v-html="generate_icon('plane', 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| {{ item.from }} => {{item.to}}
|
||||||
|
.bg-dark.divider(
|
||||||
|
:key="'qdiv'+idx" style="height:1px" )
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
v-if="!search_drawer.query.addmarker"
|
||||||
|
@click="search_drawer.query.addmarker=true" )
|
||||||
|
div( v-html="generate_icon('star', 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| Start custom
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
v-else
|
||||||
|
@click="search_drawer.click_item(journey)" )
|
||||||
|
div( v-html="generate_icon('star', 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| Finish
|
||||||
|
div(v-else-if="true")
|
||||||
|
template(v-for="(item, idx) in search_drawer.query.res" )
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
:key="'q'+idx"
|
||||||
|
@mouseover="search_drawer.hover_item(item)"
|
||||||
|
@mouseleave="search_drawer.hover_item()"
|
||||||
|
@click="search_drawer.click_item(journey,item)" )
|
||||||
|
div( v-html="generate_icon(item, 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| {{ item.name }}
|
||||||
|
.bg-dark.divider(
|
||||||
|
:key="'qdiv'+idx" style="height:1px" )
|
||||||
|
.query-result.col-12.bg-white.text-dark(
|
||||||
|
v-if="!search_drawer.query.load && search_drawer.query.res && search_drawer.is_query()"
|
||||||
|
@click="search_drawer.query.addmarker=true" )
|
||||||
|
div( v-html="generate_icon('star', 'var(--dark)')")
|
||||||
|
.col-10()
|
||||||
|
| Add custom
|
||||||
|
|
||||||
.col-12.text-white.text-center(
|
.col-12.text-white.text-center(
|
||||||
) {{query.load? `Loading ...` : `Found ${query.res.length} results`}}
|
) {{search_drawer.query.load? `Loading ...` : `Found ${search_drawer.query.res.length} results`}}
|
||||||
div(v-else-if="['flight'].indexOf(query.type)>=0")
|
div(v-else)
|
||||||
template(v-for="(item, idx) in query.res" )
|
template()
|
||||||
.query-result.col-12.bg-white.text-dark(
|
.query-result.col-12.bg-white.text-dark()
|
||||||
:key="'q'+idx"
|
| Unsuppored Query type {{search_drawer.query.type}}
|
||||||
@mouseover="drawer_hover_item(item)"
|
|
||||||
@mouseleave="drawer_hover_item()"
|
|
||||||
@click="drawer_click_item(item)" )
|
|
||||||
div( v-html="generate_icon('plane', 'var(--dark)')")
|
|
||||||
.col-10()
|
|
||||||
| {{ item.from }} => {{item.to}}
|
|
||||||
.bg-dark.divider(
|
|
||||||
:key="'qdiv'+idx" style="height:1px" )
|
|
||||||
div(v-else)
|
|
||||||
template()
|
|
||||||
.query-result.col-12.bg-white.text-dark()
|
|
||||||
| Unsuppored Query type {{query.type}}
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
.text {{ element.title || "Leg "+idx}}
|
.text {{ element.title || "Leg "+idx}}
|
||||||
i.fa.fa-times.text-small.fright(
|
i.fa.fa-times.text-small.fright(
|
||||||
style="top: 2px; right: 2px; position: absolute",
|
style="top: 2px; right: 2px; position: absolute",
|
||||||
@click="journey.rm_leg(idx); focus_leg(journey);"
|
@click="toast.delete_leg(idx, journey)"
|
||||||
)
|
)
|
||||||
.list-group-item.bg-white.text-white.show.placeholder-right(
|
.list-group-item.bg-white.text-white.show.placeholder-right(
|
||||||
:class="journey.sel_leg < journey.data.main.length-1? '': 'bg-dark'"
|
:class="journey.sel_leg < journey.data.main.length-1? '': 'bg-dark'"
|
||||||
|
@ -16,10 +16,10 @@ include smallbar.pug
|
|||||||
template(v-else)
|
template(v-else)
|
||||||
include leg/top_leg.pug
|
include leg/top_leg.pug
|
||||||
.row(style="aspect-ratio:1.25;min-height:432px;max-height:calc(100vh - 125px);width:calc(100% + 24px);")
|
.row(style="aspect-ratio:1.25;min-height:432px;max-height:calc(100vh - 125px);width:calc(100% + 24px);")
|
||||||
.map-container(:class=" { 'col-2 col-sm-5 col-md-8': query.type, 'col-2 col-sm-5 col-md-6': query.note , 'col-12': (!query.type && !query.note) }" )
|
.map-container(:class=" { 'col-2 col-sm-5 col-md-8': search_drawer.is_query(), 'col-2 col-sm-5 col-md-6': search_drawer.is_note() , 'col-12': (!search_drawer.is_query() && !search_drawer.is_note()) }" )
|
||||||
include map.pug
|
include map.pug
|
||||||
.row.drawer-container(:class="{ 'col-10 col-sm-7 col-md-4': query.type, 'col-10 col-sm-7 col-md-6': query.note, 'col-0': (!query.type && !query.note) }")
|
.row.drawer-container(:class="{ 'col-10 col-sm-7 col-md-4': search_drawer.is_query(), 'col-10 col-sm-7 col-md-6': search_drawer.is_note(), 'col-0': (!search_drawer.is_query() && !search_drawer.is_note()) }")
|
||||||
.h-100(:class="{ 'w-100 ': query.type, 'w-0': !query.type }")
|
.h-100(:class="{ 'w-100 ': search_drawer.is_query(), 'w-0': !search_drawer.is_query() }")
|
||||||
include leg/drawer.pug
|
include leg/drawer.pug
|
||||||
.h-100(:class="{ 'w-100': query.note, 'w-0': !query.note }")
|
.h-100(:class="{ 'w-100': search_drawer.is_note(), 'w-0': !search_drawer.is_note() }")
|
||||||
include leg/drawer-notes.pug
|
include leg/drawer-notes.pug
|
||||||
|
@ -4,7 +4,11 @@ l-map(
|
|||||||
@click="onMapClick"
|
@click="onMapClick"
|
||||||
style="height:100%"
|
style="height:100%"
|
||||||
no-blocking-animations=true
|
no-blocking-animations=true
|
||||||
:style="query.addmarker?'cursor:crosshair':''"
|
:max-bounds="[[-90, -180],[90, 180]]"
|
||||||
|
:max-bounds-viscosity="1.0"
|
||||||
|
:world-copy-jump="true"
|
||||||
|
:no-wrap="true"
|
||||||
|
:style="search_drawer.query.addmarker?'cursor:crosshair':''"
|
||||||
ref="map"
|
ref="map"
|
||||||
)
|
)
|
||||||
l-tile-layer(
|
l-tile-layer(
|
||||||
@ -19,5 +23,5 @@ l-map(
|
|||||||
include map/restaurants.pug
|
include map/restaurants.pug
|
||||||
|
|
||||||
include map/travel.pug
|
include map/travel.pug
|
||||||
template(v-if="edit_active")
|
template(v-if="journey.edit")
|
||||||
include map/right_menu.pug
|
include map/right_menu.pug
|
@ -19,19 +19,19 @@ mixin map_marker(place, color_sel_c, color_sel_o, color_else)
|
|||||||
:options="{maxWidth:400, minWidth:300}")
|
:options="{maxWidth:400, minWidth:300}")
|
||||||
h1.row.text-medium.text-center {{ place.sname }}
|
h1.row.text-medium.text-center {{ place.sname }}
|
||||||
span.row.text-small.text-gray {{ place.display_name }}
|
span.row.text-small.text-gray {{ place.display_name }}
|
||||||
span(v-if="edit_active")
|
span(v-if="journey.edit")
|
||||||
.row.input()
|
.row.input()
|
||||||
textarea.col-12.col-sm-12.text-small(
|
textarea.col-12.col-sm-12.text-small(
|
||||||
placeholder="",
|
placeholder="",
|
||||||
v-model="place.notes",
|
v-model="place.notes",
|
||||||
)
|
)
|
||||||
.leaflet-popup-button-group(v-if="edit_active")
|
.leaflet-popup-button-group(v-if="journey.edit")
|
||||||
a.text-gray(
|
a.text-gray(
|
||||||
v-on:click.prevent="place.step = ((place.step==journey.sel_day)?-1:journey.sel_day)"
|
v-on:click.prevent="place.step = ((place.step==journey.sel_day)?-1:journey.sel_day)"
|
||||||
v-html="generate_icon(((place.step==journey.sel_day)?'calendar-xmark':'calendar-plus'), 'NA')"
|
v-html="generate_icon(((place.step==journey.sel_day)?'calendar-xmark':'calendar-plus'), 'NA')"
|
||||||
)
|
)
|
||||||
a.text-gray(
|
a.text-gray(
|
||||||
v-on:click.prevent="place_delete(\""+place+"\",index)"
|
v-on:click.prevent="journey.del_place(\""+place+"\",index)"
|
||||||
v-html="generate_icon('trash', 'NA')"
|
v-html="generate_icon('trash', 'NA')"
|
||||||
)
|
)
|
||||||
span.row.text-small.text-dark(v-else) {{ place.notes }}
|
span.row.text-small.text-dark(v-else) {{ place.notes }}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
l-marker(
|
l-marker(
|
||||||
v-if="map_override.active",
|
v-if="search_drawer.map_override.active",
|
||||||
v-for="(el, idx) in map_override.elements"
|
v-for="(el, idx) in search_drawer.map_override.elements"
|
||||||
:key="'ovr'+idx"
|
:key="'ovr'+idx"
|
||||||
:lat-lng="el"
|
:lat-lng="el"
|
||||||
)
|
)
|
||||||
l-icon(v-html="generate_marker('plus', 'darkgreen')")
|
l-icon(v-html="generate_marker('plus', 'darkgreen')")
|
||||||
l-polyline(
|
l-polyline(
|
||||||
v-if="map_override.active && map_override.elements.length>1"
|
v-if="search_drawer.map_override.active && search_drawer.map_override.elements.length>1"
|
||||||
:lat-lngs="map_override.elements" :color="'darkgreen'"
|
:lat-lngs="search_drawer.map_override.elements" :color="'darkgreen'"
|
||||||
)
|
)
|
@ -1,21 +1,21 @@
|
|||||||
.map-menu.map-menu-top
|
.map-menu.map-menu-top
|
||||||
div(v-if="query.type" @click="drawer_click_item()" )
|
div(v-if="search_drawer.is_query()" @click="search_drawer.click_item(journey)" )
|
||||||
.map-menu-item(v-html="generate_icon('close')")
|
.map-menu-item(v-html="generate_icon('close')")
|
||||||
div(v-if="!query.type" @click="search_enable('hotel')")
|
div(v-if="!search_drawer.is_query()" @click="search_drawer.enable('hotel')")
|
||||||
.map-menu-item( v-html="generate_icon('bed')")
|
.map-menu-item( v-html="generate_icon('bed')")
|
||||||
div(v-if="!query.type" @click="search_enable('restaurant')")
|
div(v-if="!search_drawer.is_query()" @click="search_drawer.enable('restaurant')")
|
||||||
.map-menu-item( v-html="generate_icon('utensils')")
|
.map-menu-item( v-html="generate_icon('utensils')")
|
||||||
div(v-if="!query.type" @click="search_enable('place')")
|
div(v-if="!search_drawer.is_query()" @click="search_drawer.enable('place')")
|
||||||
.map-menu-item( v-html="generate_icon('star')")
|
.map-menu-item( v-html="generate_icon('star')")
|
||||||
.map-menu-sub(v-if="!query.type" @mouseenter="query.sub=true" @mouseleave="query.sub=false" )
|
.map-menu-sub(v-if="!search_drawer.is_query()" @mouseenter="search_drawer.query.sub='travel'" @mouseleave="search_drawer.query.sub=''" )
|
||||||
.map-menu-item(v-html="generate_icon('route')")
|
.map-menu-item(@click="search_drawer.enable('other')" v-html="generate_icon('route')")
|
||||||
.map-menu-item(v-if="query.sub" @click="search_enable('flight')" v-html="generate_icon('plane')")
|
.map-menu-item(v-if="search_drawer.is_sub_travel()" @click="search_drawer.enable('flight')" v-html="generate_icon('plane')")
|
||||||
.map-menu-item(v-if="query.sub" @click="search_enable('train')" v-html="generate_icon('train')")
|
.map-menu-item(v-if="search_drawer.is_sub_travel()" @click="search_drawer.enable('train')" v-html="generate_icon('train')")
|
||||||
.map-menu-item(v-if="query.sub" @click="search_enable('car')" v-html="generate_icon('car')")
|
.map-menu-item(v-if="search_drawer.is_sub_travel()" @click="search_drawer.enable('car')" v-html="generate_icon('car')")
|
||||||
.map-menu-item(v-if="query.sub" @click="search_enable('other')" v-html="generate_icon('person-biking')")
|
.map-menu-item(v-if="search_drawer.is_sub_travel()" @click="search_drawer.enable('bike')" v-html="generate_icon('person-biking')")
|
||||||
|
|
||||||
.map-menu.map-menu-center
|
.map-menu.map-menu-center
|
||||||
div(v-if="query.note" @click="drawer_click_item()" )
|
div(v-if="search_drawer.is_note()" @click="search_drawer.click_item(journey)" )
|
||||||
.map-menu-item(v-html="generate_icon('close')")
|
.map-menu-item(v-html="generate_icon('close')")
|
||||||
div(v-if="!query.note" @click="search_enable('notes')")
|
div(v-if="!search_drawer.is_note()" @click="search_drawer.enable('notes')")
|
||||||
.map-menu-item( v-html="generate_icon('pencil')")
|
.map-menu-item( v-html="generate_icon('pencil')")
|
@ -3,18 +3,18 @@ mixin flight_popup()
|
|||||||
:options="{maxWidth:400, minWidth:300}"
|
:options="{maxWidth:400, minWidth:300}"
|
||||||
)
|
)
|
||||||
h1.row.text-medium.text-center.text-uppercase {{ travel.id }}
|
h1.row.text-medium.text-center.text-uppercase {{ travel.id }}
|
||||||
span.row.text-small.text-gray {{ travel.from }} - {{travel.to}}
|
span.row.text-small.text-gray {{ travel.title? travel.title:`${travel.from||'?'}-${travel.to||'?'}` }}
|
||||||
span(v-if="edit_active")
|
span(v-if="journey.edit")
|
||||||
.row.input(style="margin-bottom:0")
|
.row.input(style="margin-bottom:0")
|
||||||
textarea.col-12.col-sm-12.text-small(
|
textarea.col-12.col-sm-12.text-small(
|
||||||
placeholder="",
|
placeholder="",
|
||||||
v-model="travel.notes",
|
v-model="travel.notes",
|
||||||
)
|
)
|
||||||
span.row.text-small.text-dark(v-else) {{ travel.notes }}
|
span.row.text-small.text-dark(v-else) {{ travel.notes }}
|
||||||
span(v-if="edit_active")
|
span(v-if="journey.edit")
|
||||||
.leaflet-popup-button-group(v-if="edit_active")
|
.leaflet-popup-button-group()
|
||||||
a.text-gray(
|
a.text-gray(
|
||||||
v-on:click.prevent="place_delete('flight',idx)"
|
v-on:click.prevent="journey.del_place('flight',idx)"
|
||||||
v-html="generate_icon('trash', 'NA')"
|
v-html="generate_icon('trash', 'NA')"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,9 +24,10 @@ div(v-for= "(travel, idx) in journey.leg_get().travel")
|
|||||||
|
|
||||||
l-marker(
|
l-marker(
|
||||||
v-for="(place, index) in travel.path"
|
v-for="(place, index) in travel.path"
|
||||||
:key="'plane'+index"
|
:key="'trvl'+index"
|
||||||
:lat-lng="place"
|
:lat-lng="place"
|
||||||
|
style="margin-left:0;"
|
||||||
)
|
)
|
||||||
l-icon(v-html="generate_icon('plane', travel.color || 'gray', generate_rotation(index,travel.path), 'travel-path-icon')"
|
l-icon(v-html="generate_icon(travel, travel.color || 'gray', generate_rotation(index,travel.path)+'margin:-6px -6px; position:absolute', 'travel-path-icon')"
|
||||||
)
|
)
|
||||||
+flight_popup()
|
+flight_popup()
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
.tooltip-text Editor
|
.tooltip-text Editor
|
||||||
.col-1
|
.col-1
|
||||||
.col-1
|
.col-1
|
||||||
a.text-white.tooltip(v-on:click.prevent="toast_impexp(true)")
|
a.text-white.tooltip(v-on:click.prevent="toast.impexp(true, journey)")
|
||||||
i.fas.fa-file-import
|
i.fas.fa-file-import
|
||||||
.tooltip-text Import
|
.tooltip-text Import
|
||||||
.col-1
|
.col-1
|
||||||
a.text-white.tooltip(v-on:click.prevent="toast_impexp(false)")
|
a.text-white.tooltip(v-on:click.prevent="toast.impexp(false, journey)")
|
||||||
i.fas.fa-file-export
|
i.fas.fa-file-export
|
||||||
.tooltip-text Export
|
.tooltip-text Export
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
template
|
template
|
||||||
.overlay.text-dark(v-if="toast.show" @click="")
|
.overlay.text-dark(v-if="toast.data.show" @click="")
|
||||||
.popup.bg-white(@click.stop)
|
.popup.bg-white(@click.stop)
|
||||||
.row
|
.row
|
||||||
.col-auto.text-huge {{ toast.title }}
|
.col-auto.text-huge {{ toast.data.title }}
|
||||||
.row(v-if="toast.desc")
|
.row(v-if="toast.data.desc")
|
||||||
.col-auto.text-medium {{ toast.desc }}
|
.col-auto.text-medium {{ toast.data.desc }}
|
||||||
.row(v-if="toast.special")
|
.row(v-if="toast.data.special")
|
||||||
.col-auto.text-medium
|
.col-auto.text-medium
|
||||||
.input
|
.input
|
||||||
input(v-model="toast.special")
|
input(v-model="toast.data.special")
|
||||||
.row.align
|
.row.align
|
||||||
button.button.bg-white(@click="toast.func" v-if="toast.acceptText") {{ toast.acceptText }}
|
button.button.bg-white(@click="toast.data.func" v-if="toast.data.acceptText") {{ toast.data.acceptText }}
|
||||||
button.button.bg-white(@click="toast.show=false;" v-if="toast.cancelText") {{ toast.cancelText }}
|
button.button.bg-white(@click="toast.data.show=false;" v-if="toast.data.cancelText") {{ toast.data.cancelText }}
|
Loading…
x
Reference in New Issue
Block a user