import * as api from "./api"; import journey_wrapper from "./types/wrapper"; import { migrator } from "./types/migration"; import { getGeoLine } from "./types/geom"; Vue.component("l-map", window.Vue2Leaflet.LMap); Vue.component("l-tile-layer", window.Vue2Leaflet.LTileLayer); Vue.component("l-marker", window.Vue2Leaflet.LMarker); Vue.component("l-icon", window.Vue2Leaflet.LIcon); Vue.component("l-popup", window.Vue2Leaflet.LPopup); Vue.component("l-tooltip", window.Vue2Leaflet.LTooltip); Vue.component("l-polyline", window.Vue2Leaflet.LPolyline); Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale); const app = new Vue({ el: "#app", data: { edit_active: ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), map_override: { active: false, elements: [] }, query: { type: "", res: [], load: false, sub: false, note: false, drawer: false, }, leg_nav: { scrollInterval: null, scrollDir: null }, impexp: "", lang: { format: "ddd D MMM", formatLocale: { firstDayOfWeek: 1, }, monthBeforeYear: true, }, }, methods: { 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) { if (index < 0 || index >= list.length) return 0; const c0 = list[(index == 0) ? index : (index - 1)] const c1 = list[(index == list.length - 1) ? index : (index + 1)] const brng = Math.atan2(c1[1] - c0[1], c1[0] - c0[0]); return `rotate:${brng - Math.PI / 2}rad`; }, generate_marker: function (item, fcolor) { return `
` }, generate_icon: function (item, fcolor = "", styling = "", classes = "") { return ``; }, import_data: function () { this.journey.data = Object.assign( {}, JSON.parse(this.impexp.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]); } }); }, export_data: function () { this.impexp = JSON.stringify(this.journey.data).toEncoded(); }, filter_selected: function (list, step) { return list.filter((e) => step ? e.step == this.journey.sel_day : e.step >= 0, ); }, filter_unselected: function (list) { return list.filter((e) => e.step == undefined || e.step < 0); }, remove_item: function (list, idx) { list[idx].step = -1; list.splice(idx, 1); }, log: function (e) { console.log(e); }, place_delete: function (f, idx) { switch (f) { case "hotel": return this.journey.leg_get().hotel = null; case "restaurant": return this.journey.leg_get().places.restaurants.splice(idx, 1); case "activities": return this.journey.leg_get().places.activities.splice(idx, 1); case "other": return; case "flight": return this.journey.leg_get().travel.splice(idx, 1); default: return true; } }, get_filter: function (f) { switch (f) { case "hotel": return api.is_hotel_type; case "restaurant": return api.is_restauration_type; case "place": return api.is_attraction_type; case "other": default: return () => true; } }, search_nominatim: function (f) { return (q) => api.query_nominatim(q, this.compute_bb(), this.get_filter(f)).catch((_err) => []).then((r) => { r.forEach((rr) => { rr.latlon = [parseFloat(rr.lat), parseFloat(rr.lon)]; rr.sname = rr.display_name.split(",")[0]; }); r = r.filter(e => { if (this.journey.leg_get().hotel && this.journey.leg_get().hotel.osm_id == e.osm_id) return false; if (this.journey.leg_get().places.restaurants.find(i => i.osm_id == e.osm_id)) return false; if (this.journey.leg_get().places.activities.find(i => i.osm_id == e.osm_id)) return false; return true }) this.query.load = false; this.query.res = r; return r }); }, search_travel: function (f) { return (q) => api.query_flight(q).then((r) => { r.forEach(el => { el.path = getGeoLine( { lat: el.from_geo.lat, lng: el.from_geo.lon }, { lat: el.to_geo.lat, lng: el.to_geo.lon }, { dist: 2_500_000 }).map(v => [v.lat, v.lng]) el.type = "flight"; }); r = r.filter(e => { if (this.journey.leg_get().travel.find(i => `${i.from}->${i.to}` == `${e.from}->${e.to}`)) return false; return true }) this.query.load = false; this.query.res = r; return r; }); }, 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.query.res = []; this.query.note = false; this.query.type = null; this.query.drawer = item ? true : false; setTimeout(() => this.$refs.map.mapObject.invalidateSize(), 500); this.query.sub = false; this.drawer_hover_item() if (item) { item.step = -1; switch (tpe) { case 'hotel': return this.journey.leg_get().hotel = item; case 'restaurant': return this.journey.leg_get().places.restaurants.push(item); case 'place': return this.journey.leg_get().places.activities.push(item); case 'other': return; case 'flight': return this.journey.leg_get().travel.push(item); } } }, search_active: function (q) { const txt = q.target.value this.query.load = true; switch (this.query.type) { case 'hotel': return this.search_hotel(txt); case 'restaurant': return this.search_restaurant(txt); case 'place': return this.search_place(txt); case 'other': return this.search_other(txt); case 'flight': return this.search_flight(txt); } }, search_enable: function (f) { this.query.drawer = true; setTimeout(() => this.$refs.map.mapObject.invalidateSize(), 500); if (f == "notes") { this.query.note = true; this.query.type = null; const query_in = document.getElementById('query_note') setTimeout(() => query_in.focus(), 500); return; } this.query.note = false; this.query.type = f; const query_in = document.getElementById('query_input') setTimeout(() => query_in.focus(), 500); this.search_active({ target: query_in }) }, sideScroll: function (element, direction, speed, step) { this.leg_nav.scrollDir = direction if (direction == 'none') return; this.leg_nav.scrollInterval = setInterval(() => { element.scrollLeft += (direction == 'left') ? -step : step; }, speed); }, keyboardEvent(e) { if (e.which === 13) { } }, nav_mousemove(e) { const c = document.querySelector('.scroll-content') const left = e.pageX - c.getBoundingClientRect().left; const newDir = left < c.offsetWidth * 0.1 ? 'left' : (left > c.offsetWidth * 0.9 ? 'right' : 'none') if (!this.leg_nav.scrollInterval || this.leg_nav.scrollDir != newDir) { if (this.leg_nav.scrollInterval) clearInterval(this.leg_nav.scrollInterval) this.sideScroll(c, newDir, 25, 10); } }, nav_mouseleave(e) { clearInterval(this.leg_nav.scrollInterval); this.leg_nav.scrollDir = 'none' this.leg_nav.scrollInterval = null }, refreshTextAreaHeight(event) { console.log("AAA", event.target.scrollHeight, event.target) event.target.style['height'] = 'auto'; event.target.style['height'] = event.target.scrollHeight + 'px'; event.target.style['max-height'] = "100%"; }, }, created: function () { this.search_hotel = api.throttle(this.search_nominatim("hotel"), 1000) this.search_restaurant = api.throttle(this.search_nominatim("restaurant"), 1000) this.search_place = api.throttle(this.search_nominatim("place"), 1000) this.save_data = api.throttle(() => { this.impexp = JSON.stringify(this.journey.data).toEncoded(); api.save(this.journey.id, this.journey.data); }, 1000); this.search_flight = api.throttle(this.search_travel("flight"), 2000) window.addEventListener("keydown", (e) => { switch (e.key) { case "ArrowLeft": this.journey.day_prev(); break; case "ArrowRight": this.journey.day_next(); break; default: console.log(e.key); } }); api.load(this.journey.id).then((r) => { app.journey.data = migrator(r) }); }, watch: { journey: { handler: function (ndata, odata) { if (this.edit_active) this.save_data(); }, deep: true, }, }, });