wip
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
soraefir 2025-03-11 00:15:10 +01:00
parent 7e0157880b
commit 43dfc87546
Signed by: sora
GPG Key ID: A362EA0491E2EEA0
11 changed files with 3066 additions and 1926 deletions

View File

@ -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 => {
@ -144,9 +142,9 @@ export const icon_type = (item: string | NominatimResult): string => {
"": ["?", "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";
}; };

View File

@ -1,52 +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;
}
}
export const journey_from_url = function () {
const path = window.location.pathname.slice(1).split('/')
const hash = window.location.hash.slice(1).split('_')
return {
edit: ["view", "short"].indexOf(path.at(0) || "") == -1,
id: path.at(-1) || String.gen_id(16).toString(),
leg: parseInt(hash.at(0) || '0'),
day: parseInt(hash.at(1) || '0')
}
}

View File

@ -9,24 +9,21 @@ var nav = {
const sideScroll = function (element: Element, direction: 'left' | 'right' | 'none', speed: number = 25, step: number = 15) { 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) {

View File

@ -2,7 +2,6 @@
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_from_url } from "./helper/journey";
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 toast from "./types/toast";
@ -16,13 +15,11 @@ Vue.component("l-popup", window.Vue2Leaflet.LPopup);
Vue.component("l-tooltip", window.Vue2Leaflet.LTooltip); Vue.component("l-tooltip", window.Vue2Leaflet.LTooltip);
Vue.component("l-polyline", window.Vue2Leaflet.LPolyline); Vue.component("l-polyline", window.Vue2Leaflet.LPolyline);
Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale); Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale);
const journey_base = journey_from_url()
const app = new Vue({ const app = new Vue({
el: "#app", el: "#app",
data: { data: {
edit_active: journey_base.edit, journey: new journey_wrapper(),
journey: new journey_wrapper(journey_base.id),
search_drawer: new search_drawer(), search_drawer: new search_drawer(),
useDay: false, useDay: false,
toast: new toast(), toast: new toast(),
@ -40,9 +37,9 @@ const app = new Vue({
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 = list[(index == 0) ? index : (index - 1)]
const c1 = list[(index == list.length - 1) ? 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]); const brng = Math.atan2(c1[1] - c0[1], c1[0] - c0[0]);
return `rotate:${brng - 0 * Math.PI / 2}rad`; return `rotate:${brng - Math.PI / 2}rad`;
}, },
generate_marker: function (item, fcolor) { generate_marker: function (item, fcolor) {
@ -107,7 +104,7 @@ const app = new Vue({
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_next = api.throttle((dir_prev) => { this.pressed_prev_next = api.throttle((dir_prev) => {
if (this.useDay && dir_prev) return this.journey.day_prev(); if (this.useDay && dir_prev) return this.journey.day_prev();
@ -126,11 +123,9 @@ const app = new Vue({
api.load(this.journey.id).then((r) => { api.load(this.journey.id).then((r) => {
app.journey.data = migrator(r) app.journey.data = migrator(r)
app.journey.sel_leg = Math.min(app.journey.leg_count() - 1, journey_base.leg); setTimeout(() => focus_leg(this.journey) && focus_day(this.journey) && this.$refs.map.mapObject.keyboard.disable(), 25);
app.journey.sel_day = Math.min(app.journey.day_count() - 1, journey_base.day);
setTimeout(() => focus_leg(this.journey) && focus_day(this.journey), 25);
this.$refs.map.mapObject.keyboard.disable(); ;
this.search_drawer.refresh_map = () => { this.$refs.map.mapObject.invalidateSize() } this.search_drawer.refresh_map = () => { this.$refs.map.mapObject.invalidateSize() }
this.search_drawer.get_leg = () => { return this.journey.leg_get() } this.search_drawer.get_leg = () => { return this.journey.leg_get() }
this.search_drawer.get_bb = () => { this.search_drawer.get_bb = () => {
@ -144,7 +139,7 @@ const app = new Vue({
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}` window.location.hash = `#${this.journey.sel_leg}_${this.journey.sel_day}`
}, },
deep: true, deep: true,

View File

@ -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]
@ -164,6 +168,36 @@ class journey_wrapper {
} }
}); });
} }
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': return;
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;

View File

@ -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
} }

View File

@ -19,5 +19,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

View File

@ -19,13 +19,13 @@ 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')"

View File

@ -4,15 +4,15 @@ mixin flight_popup()
) )
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.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(journey,'flight',idx)" v-on:click.prevent="place_delete(journey,'flight',idx)"
v-html="generate_icon('trash', 'NA')" v-html="generate_icon('trash', 'NA')"

4842
yarn.lock

File diff suppressed because it is too large Load Diff