From 8a46f473ebe029a0810da09d9f19eaaa24973f70 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:12:04 +0100 Subject: [PATCH 01/95] Update package.json --- package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 019efc2..46ffec5 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "esbuild src/app.ts --bundle --outfile=public/main.js --bundle --minify --sourcemap --tsconfig=tsconfig.json", + "build": "esbuild src/app.ts --bundle --outfile=public/main.js --tree-shaking=true --bundle --minify --sourcemap --tsconfig=tsconfig.json", "start": "node server.js", - "demon": "nodemon -e ts,pug --watch src --exec \"yarn build && yarn start\"" + "demon": "nodemon -e ts,js,pug --watch src --watch template --watch router --exec \"yarn build && yarn start\"" }, "repository": { "type": "git", @@ -21,11 +21,9 @@ "@fastify/view": "^10.0.0", "@prettier/plugin-pug": "^3.0.0", "@types/node": "^22.13.5", - "axios": "^1.7.9", "esbuild": "^0.25.0", "fastify": "^5.0.0", "nodemon": "^3.0.1", - "pretier": "^0.0.1", "prettier": "^3.5.2", "pug": "^3.0.2" } -- 2.47.2 From 1e10109bbe90f9a3da23a7939f0a53ea2baf62f9 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:12:46 +0100 Subject: [PATCH 02/95] Update router/api.js --- router/api.js | 84 +++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/router/api.js b/router/api.js index 1d8e13a..1a8dfe3 100644 --- a/router/api.js +++ b/router/api.js @@ -1,37 +1,23 @@ -const axios = require("axios"); - module.exports = (fastify, opts, done) => { fastify.get("/flight/:id", async (req, reply) => { - const ENDPOINT = "https://www.flightradar24.com/v1/search/web/find"; - const FORMAT = "-"; if (req.params.id) { - axios - .get(ENDPOINT, { - params: { - format: FORMAT, - query: req.params.id, - limit: 16, - type: "schedule", - }, - }) - .then((res) => reply.send(res.data)); + const url = new URL("https://www.flightradar24.com/v1/search/web/find"); + url.searchParams.append('format', '-') + url.searchParams.append('query', req.params.id) + url.searchParams.append('limit', 16) + url.searchParams.append('type', 'schedule') + fetch(url).then((res) => reply.send(res.data)); } else { return reply.send([]); } return reply; }); fastify.get("/place/:id", async (req, reply) => { - const ENDPOINT = "https://nominatim.openstreetmap.org/"; - const FORMAT = "jsonv2"; if (req.params.id) { - axios - .get(ENDPOINT, { - params: { - format: FORMAT, - q: req.params.id, - }, - }) - .then((res) => reply.send(res.data)); + const url = new URL("https://nominatim.openstreetmap.org/"); + url.searchParams.append('format', 'jsonv2') + url.searchParams.append('q', req.params.id) + fetch(url).then((res) => reply.send(res.data)); } else { return reply.send([]); } @@ -40,33 +26,33 @@ module.exports = (fastify, opts, done) => { fastify.get("/gpx/:id", async (req, reply) => { if (req.params.id == undefined) - return reply.code(400).send({ error: "No ID query parameter" }); + return reply.code(400).send({ error: "No ID query parameter" }); - fastify.level.db.get(req.params.id, (err, val) => { - if (err) { - console.warn(err); - reply.code(500).send(); - } else { - let file = '' - const data = JSON.parse(val); - const gen_wpt = (name,desc,latlon,icon="Flag") => `0${name}-${desc}${icon}` - const esc_str = (str) => (str||"Undefined").replace('"',""").replace("'","'").replace("<","<").replace(">",">").replace("&","&").replace("\n","...") - data.main.forEach(a => { - file+= gen_wpt(esc_str(a.hotel.name), esc_str(a.hotel.notes), a.hotel.latlon, icon="Hotel"); - a.places.restaurants.forEach(b => { - file+= gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon="Restaurant"); + fastify.level.db.get(req.params.id, (err, val) => { + if (err) { + console.warn(err); + reply.code(500).send(); + } else { + let file = '' + const data = JSON.parse(val); + const gen_wpt = (name, desc, latlon, icon = "Flag") => `0${name}-${desc}${icon}` + const esc_str = (str) => (str || "Undefined").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">").replace("&", "&").replace("\n", "...") + data.main.forEach(a => { + file += gen_wpt(esc_str(a.hotel.name), esc_str(a.hotel.notes), a.hotel.latlon, icon = "Hotel"); + a.places.restaurants.forEach(b => { + file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon = "Restaurant"); + }); + a.places.activities.forEach(b => { + file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon = "Tree"); + }); }); - a.places.activities.forEach(b => { - file+= gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon="Tree"); - }); - }); - file+=""; - reply.header('Content-Type', 'application/gpx+xml'); - reply.header('Content-Disposition', `attachment; filename=${req.params.id}.gpx`); - reply.send(file); - } - }); - return reply; + file += ""; + reply.header('Content-Type', 'application/gpx+xml'); + reply.header('Content-Disposition', `attachment; filename=${req.params.id}.gpx`); + reply.send(file); + } + }); + return reply; }); fastify.get("/:id", async (req, reply) => { -- 2.47.2 From 9f88d80b68322658db475e99906f1e6d72674dd9 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:13:02 +0100 Subject: [PATCH 03/95] Update src/api.ts --- src/api.ts | 127 ++++++++++++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 69 deletions(-) diff --git a/src/api.ts b/src/api.ts index f13157f..5d4747f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,41 +1,59 @@ -import axios from "axios"; +export const throttle = (func: () => void, wait: number) => { + let lastTime = 0; + let timeoutId: ReturnType | undefined; + let lastArgs: any[]; + + return function (...args: any[]) { + const now = Date.now(); + lastArgs = args; + + if (now - lastTime >= wait) { + lastTime = now; + func.apply(this, lastArgs); + } else { + if (timeoutId) clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + lastTime = Date.now(); + func.apply(this, lastArgs); + }, wait - (now - lastTime)); + } + }; +} export const load = (id: string) => - axios.get("/api/" + id).then((response) => { - if (response.data == "") throw "Invalid Journey Data Received"; - let res = response.data; - + fetch("/api/" + id).then(res => { + if (!res.ok) throw new Error('Error ' + res.statusText); + return res.json(); + }).then((res) => { for (let e of res.main) { - if (e.dateRange) { - e.dateRange[0] = new Date(e.dateRange[0]); - e.dateRange[1] = new Date(e.dateRange[1]); + if (e.date_range) { + e.date_range[0] = new Date(e.date_range[0]); + e.date_range[1] = new Date(e.date_range[1]); } e.step_title = e.step_title || []; } return res; - }); + }) -export const save = (id: string, v: string) => - axios - .post("/api/" + id, v) - .then((response) => { +export const save = (id: string, v: journey) => + fetch("/api/" + id, { method: "post", body: JSON.stringify(v) }) + .then(res => { + if (!res.ok) throw new Error('Error ' + res.statusText); + return res.json(); + }).then((_res) => { console.log("Saved..."); }) - .catch((error) => { - console.warn("Error! Could not reach the API."); - }); export const query_nominatim = ( q: string, f: (v: string) => Boolean = () => true, ) => - axios - .get("/api/place/" + q) - .then((res) => res.data) + fetch("/api/place/" + q) + .then((res) => (res.status == 200) ? res.json() : []) .then((res) => res.filter(f)); export const query_flight = (q: string) => - axios.get("/api/flight/" + q).then((res) => res.data); + fetch("/api/flight/" + q).then((res) => res.json()); type NominatimResult = { type: string; @@ -69,54 +87,25 @@ export const is_attraction_type = (e: NominatimResult): boolean => export const icon_type = (item: NominatimResult): string => { let t = item.type; let c = item.category; - const arr = ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"]; - if (arr.indexOf(t) != -1) { - return "utensils"; - } else if (t == "hotel" || t == "hostel" || t == "guest_house") { - return "bed"; - } else if (t == "museum" || c == "historic" || t == "place_of_worship") { - return "landmark"; - } else if (t == "peak" || t == "viewpoint") { - return "mountain"; - } else if (t == "parking") { - return "parking"; - } else if ( - t == "water" || - t == "river" || - t == "lake" || - t == "torrent" || - t == "aquarium" - ) { - return "water"; - } else if (t == "community_centre" || t == "locality") { - return "building"; - } else if (t == "attraction") { - return "landmark"; - } else if (t == "information" || t == "university") { - return "landmark"; - } else if (t == "bridge") { - return "archway"; - } else if ( - t == "woodland" || - t == "shieling" || - t == "national_park" || - t == "zoo" || - t == "park" || - t == "garden" || - 0 - ) { - return "tree"; - } else if (t == "water_park" || t == "theme_park") { - return "dice-five"; - } else if ( - t == "?" || - t == "neighbourhood" || - t == "quarter" || - c == "highway" - ) { - return ""; - } else { - console.log(item.display_name, item.category, item.type); - return "question"; + let types = { + "utensils": ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"], + "bed": ["hotel", "hostel", "guest_house"], + "landmark": ["museum", "historic", "place_of_worship", "attraction", "information", "university"], + "mountain": ["peak", "viewpoint"], + "parking": ["parking"], + "water": ["water", "river", "lake", "torrent", "aquarium"], + "building": ["community_center", "locality"], + "archway": ["bridge"], + "tree": ["woodland", "shieling", "national_park", "park", "zoo", "garden"], + "dice-five": ["water_park", "theme_park", "casino"], + "": ["?", "neighbourhood", "quarter", "highway"], } + + for (let k in types) { + if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) + return k; + } + + console.log(item.display_name, item.category, item.type); + return "question"; }; -- 2.47.2 From d6890940d0ddefcbc75c4da504759b5649a64aa3 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:13:16 +0100 Subject: [PATCH 04/95] Update src/app.ts --- src/app.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/app.ts b/src/app.ts index 524306e..10b982f 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,13 +1,4 @@ import "./types/ext"; +import "./types/format"; import "./api"; import "./old.js"; - -console.log("TEST"); - -if (false) { - console.log("B"); -} - -function test() { - console.log("CC"); -} -- 2.47.2 From ef00ba536d3abe11b3183e5593ff03dfa4743632 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:13:35 +0100 Subject: [PATCH 05/95] Update src/old.js --- src/old.js | 225 ++++++----------------------------------------------- 1 file changed, 25 insertions(+), 200 deletions(-) diff --git a/src/old.js b/src/old.js index 07049a7..1796bd4 100644 --- a/src/old.js +++ b/src/old.js @@ -1,4 +1,6 @@ + import * as api from "./api"; +import journey_wrapper from "./types/wrapper"; Vue.component("l-map", window.Vue2Leaflet.LMap); Vue.component("l-tile-layer", window.Vue2Leaflet.LTileLayer); @@ -15,13 +17,7 @@ const app = new Vue({ data: { journey_edit: ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, - journey_id: window.location.pathname.split("/").pop() || String.gen_id(16), - - journey_step_data: { day: 1, section: 0 }, - journey_data: { - name: "New Journey", - main: [], - }, + journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), query: { hotel: [], flight: [], nominatim: [] }, querying: { hotel: false, flight: false, place: false, food: false }, @@ -35,185 +31,14 @@ const app = new Vue({ }, }, methods: { - start_journey: function (event) { - window.location.href = "/" + this.journey_id; - }, - add_section: function (event) { - if (this.journey_data.main == undefined) this.journey_data.main = []; - this.journey_data.main.push({ - title: "?", - step_title: [], - map: { zoom: 2 }, - hotel: { latlon: [0, 0] }, - places: { restaurants: [], places: [] }, - }); - }, - step_len: function (idx) { - return this.journey_data.main[idx].dateRange - ? (this.journey_data.main[idx].dateRange[1] - - this.journey_data.main[idx].dateRange[0]) / - (1000 * 60 * 60 * 24) + - 1 - : 1; - }, - next_step: function () { - this.journey_step_data.day += 1; - let s = this.journey_step_data.section; - let cd = this.step_len(s); + start_journey: () => window.location.href = "/" + this.journey.id, - if (this.journey_step_data.day > cd) { - this.journey_step_data.section += 1; - if (this.journey_step_data.section >= this.journey_data.main.length) { - this.journey_step_data.section = this.journey_data.main.length - 1; - this.journey_step_data.day = cd; - } else { - this.journey_step_data.day = 1; - } - } - }, - prev_step: function () { - this.journey_step_data.day -= 1; - if (this.journey_step_data.day <= 0) { - this.journey_step_data.section -= 1; - if (this.journey_step_data.section < 0) { - this.first_step(); - } else { - let s = this.journey_step_data.section; - - let cd = this.step_len(s); - this.journey_step_data.day = cd; - } - } - }, - nextnext_step: function () { - this.journey_step_data.section += 1; - this.journey_step_data.day = 1; - if (this.journey_step_data.section >= this.journey_data.main.length) - this.first_step(); - }, - prevprev_step: function () { - this.journey_step_data.section -= 1; - this.journey_step_data.day = 1; - if (this.journey_step_data.section < 0) this.first_step(); - }, - first_step: function () { - this.journey_step_data.section = 0; - this.journey_step_data.day = 1; - }, - - active_date: function () { - if (this.journey_step_data.day < 0) return "?"; - if (!this.journey_data.main[this.journey_step_data.section].dateRange) - return "?"; - var date = new Date( - this.journey_data.main[this.journey_step_data.section].dateRange[0], - ); - date.setDate(date.getDate() + this.journey_step_data.day - 1); - return this.format_date(date); - }, - format_date: function (d) { - return ( - ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d.getDay()] + - " " + - d.getDate() + - " " + - [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ][d.getMonth()] - ); - }, - - total_days: function () { - if (this.journey_data.main.length == 0) return 0; - try { - return ( - (this.journey_data.main[this.journey_data.main.length - 1] - .dateRange[1] - - this.journey_data.main[0].dateRange[0]) / - (1000 * 60 * 60 * 24) - ); - } catch { - return "?"; - } - }, - total_date: function () { - if (this.journey_data.main.length == 0) return ""; - try { - return `${this.format_date( - this.journey_data.main[0].dateRange[0], - )} - ${this.format_date( - this.journey_data.main[this.journey_data.main.length - 1] - .dateRange[1], - )}`; - } catch { - return "?"; - } - }, - update_date: function (idx) { - let dateRange = this.journey_data.main[idx].dateRange; - let start_end = [0, 0]; - let step_len = 0; - - let last_start = dateRange[0]; - for (let i = idx - 1; i >= 0; --i) { - step_len = this.step_len(i) - 1; - if (this.journey_data.main[i].dateRange) { - start_end = [last_start.getDate() - step_len, last_start.getDate()]; - } else { - this.journey_data.main[i].dateRange = [new Date(), new Date()]; - start_end = [last_start.getDate() - step_len, last_start.getDate()]; - } - this.journey_data.main[i].dateRange[0].setTime(last_start.getTime()); - this.journey_data.main[i].dateRange[0].setDate(start_end[0]); - this.journey_data.main[i].dateRange[1].setTime(last_start.getTime()); - this.journey_data.main[i].dateRange[1].setDate(start_end[1]); - last_start = this.journey_data.main[i].dateRange[0]; - } - - let last_end = dateRange[1]; - for (let i = idx + 1; i < this.journey_data.main.length; ++i) { - step_len = this.step_len(i) - 1; - if (this.journey_data.main[i].dateRange) { - start_end = [last_end.getDate(), last_end.getDate() + step_len]; - } else { - this.journey_data.main[i].dateRange = [new Date(), new Date()]; - start_end = [last_end.getDate(), last_end.getDate() + step_len]; - } - this.journey_data.main[i].dateRange[0].setTime(last_end.getTime()); - this.journey_data.main[i].dateRange[0].setDate(start_end[0]); - this.journey_data.main[i].dateRange[1].setTime(last_end.getTime()); - this.journey_data.main[i].dateRange[1].setDate(start_end[1]); - last_end = this.journey_data.main[i].dateRange[1]; - } - }, - - rm_section: function (idx) { - this.journey_data.main.splice(idx, 1); - if (this.journey_step_data.section == idx) { - this.prevprev_step(); - } - }, - sel_section: function (idx) { - this.journey_step_data.section = idx; - this.journey_step_data.day = 1; - }, search_nominatim: function (txt, f) { if (txt == "") { this.query.nominatim = []; return Promise.resolve([]); } - return query_nominatim(txt, f).then((results) => { + return api.query_nominatim(txt, f).catch((err) => []).then((results) => { results.forEach((r) => { r.latlon = [parseFloat(r.lat), parseFloat(r.lon)]; r.sname = r.display_name.split(",")[0]; @@ -224,7 +49,7 @@ const app = new Vue({ search_flight: function (txt) { if (txt == "") return; this.querying.flight = true; - query_flight(txt.replace(" ", "")).then((results) => { + api.query_flight(txt.replace(" ", "")).then((results) => { if (results.results == "") { this.query.flight = []; this.querying.flight = false; @@ -243,27 +68,27 @@ const app = new Vue({ }, save_data: function () { - this.impexp = JSON.stringify(this.journey_data).toEncoded(); - api.save(this.journey_id, this.journey_data); + this.impexp = JSON.stringify(this.journey.data).toEncoded(); + api.save(this.journey.id, this.journey.data); }, import_data: function () { - this.journey_data = Object.assign( + this.journey.data = Object.assign( {}, JSON.parse(this.impexp.toDecoded()), ); - this.journey_data.main.forEach((e) => { - if (e.dateRange) { - e.dateRange[0] = new Date(e.dateRange[0]); - e.dateRange[1] = new Date(e.dateRange[1]); + 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(); + this.impexp = JSON.stringify(this.journey.data).toEncoded(); }, filter_selected: function (list, step) { return list.filter((e) => - step ? e.step == this.journey_step_data.day : e.step >= 0, + step ? e.step == this.journey.sel_day : e.step >= 0, ); }, filter_unselected: function (list) { @@ -286,21 +111,21 @@ const app = new Vue({ window.addEventListener("keydown", (e) => { switch (e.key) { case "ArrowLeft": - this.prev_step(); + this.journey.day_prev(); break; case "ArrowRight": - this.next_step(); + this.journey.day_next(); break; default: console.log(e.key); } }); - api.load(this.journey_id).then((r) => (app.journey_data = r)); + api.load(this.journey.id).then((r) => (app.journey.data = r)); - this.debounceSave = _.debounce(this.save_data, 500); + this.debounceSave = api.throttle(this.save_data, 500); this.debounceSearch = { - hotel: _.debounce((q) => { + hotel: api.throttle((q) => { this.querying.hotel = true; this.search_nominatim( q, @@ -310,7 +135,7 @@ const app = new Vue({ this.querying.hotel = false; }); }, 500), - restaurants: _.debounce((q) => { + restaurants: api.throttle((q) => { this.querying.food = true; this.search_nominatim(q, (r) => api.is_restauration_type(r)).then( (r) => { @@ -318,23 +143,23 @@ const app = new Vue({ }, ); }, 500), - places: _.debounce((q) => { + places: api.throttle((q) => { this.querying.place = true; this.search_nominatim(q, (r) => api.is_attraction_type(r)).then((r) => { this.querying.place = false; }); }, 500), - other: _.debounce((q) => { + other: api.throttle((q) => { this.querying.any = true; this.search_nominatim(q, (r) => true).then((r) => { this.querying.any = false; }); }, 500), - flight: _.debounce((q) => this.search_flight(q), 500), + flight: api.throttle((q) => this.search_flight(q), 500), }; }, watch: { - journey_data: { + journey: { handler: function (ndata, odata) { this.debounceSave(); }, -- 2.47.2 From d295c1550433c201e6e293ff36cb88c15ff9030a Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:13:53 +0100 Subject: [PATCH 06/95] Update src/types/ext.ts --- src/types/ext.ts | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/types/ext.ts b/src/types/ext.ts index cddb2b8..c13aa39 100644 --- a/src/types/ext.ts +++ b/src/types/ext.ts @@ -2,8 +2,10 @@ declare global { interface Date { toJSONLocal: () => string; + toLocal: () => string; } } + Date.prototype.toJSONLocal = function () { function addZ(n: number): string { return n <= 9 ? `0${n}` : `${n}`; @@ -13,7 +15,27 @@ Date.prototype.toJSONLocal = function () { addZ(this.getMonth() + 1), addZ(this.getDate()), ].join("-"); -}; +} + +Date.prototype.toLocal = function () { + return [["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][this.getDay()], + this.getDate(), + [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ][this.getMonth()]].join(" ") + ; +} // ARRAY EXTENTION declare global { @@ -76,4 +98,4 @@ String.gen_id = function (length) { .join(""); }; -export {}; +export { }; -- 2.47.2 From c4537ca1b01c63f8bf9556bb06dc669b768c1eea Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:14:19 +0100 Subject: [PATCH 07/95] Add src/types/format.ts --- src/types/format.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/types/format.ts diff --git a/src/types/format.ts b/src/types/format.ts new file mode 100644 index 0000000..ab7b6b1 --- /dev/null +++ b/src/types/format.ts @@ -0,0 +1,54 @@ +declare global { + interface map { + zoom: number + center: { + lat: number + lng: number + } + } + + interface geoloc { + latlon: [number, number] + notes: string + } + + interface leg { + title: string + step_title: string[] + date_range: [Date, Date] | null + map: map + travel: unknown[] + hotel: geoloc | null + places: { + restaurants: geoloc[] + places: geoloc[] + } + notes: string + } + + interface journey { + title: string + name: string | null + main: leg[] + } +} + +const journey_template: journey = { + title: "New Journey", + name: null, + main: [], +} + +const leg_template: leg = { + title: "New Leg", + step_title: [], + map: { zoom: 2, center: { lng: 0, lat: 0 } }, + travel: [], + hotel: null, + places: { restaurants: [], places: [] }, + notes: "", + date_range: null +} + +export { map, geoloc, leg, journey } +export { journey_template, leg_template } \ No newline at end of file -- 2.47.2 From b8e71cd6faa9fb1fac0adbaecb88719075c35bd5 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:14:38 +0100 Subject: [PATCH 08/95] Add src/types/wrapper.ts --- src/types/wrapper.ts | 138 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/types/wrapper.ts diff --git a/src/types/wrapper.ts b/src/types/wrapper.ts new file mode 100644 index 0000000..faf74ec --- /dev/null +++ b/src/types/wrapper.ts @@ -0,0 +1,138 @@ +import { journey_template, leg_template } from "./format" + +const date_day_diff = (d0: Date, d1: Date): number => + (d1.getTime() - d0.getTime()) / (1000 * 60 * 60 * 24) + +class journey_wrapper { + id: string + data: journey = journey_template; + sel_leg: number = 0; + sel_day: number = 0; + + constructor(id: string) { + this.id = id; + } + + leg_first = () => this.data.main[0] + leg_last = () => this.data.main[this.leg_count() - 1] + leg_count(): number { + return this.data.main.length; + } + leg_len(idx: number = null): number { + let d = this.leg_get(idx == null ? this.sel_leg : idx).date_range; + return d ? date_day_diff(d[0], d[1]) + 1 : 1; + } + add_leg(): void { + if (this.data.main == undefined) this.data.main = []; + this.data.main.push(leg_template); + } + rm_leg(idx: number): void { + this.data.main.splice(idx, 1); + if (this.sel_leg == idx) this.leg_prev(); + } + tot_len(): number | "?" { + if (this.leg_count() == 0) return 0; + try { + let d0 = this.leg_first().date_range[0] + let d1 = this.leg_last().date_range[1] + return date_day_diff(d0, d1); + } catch { + return "?"; + } + } + leg_sel(idx: number): void { + this.sel_leg = idx; + this.sel_day = 1; + } + leg_get(idx: number = null): leg { + return this.data.main[idx == null ? this.sel_leg : idx] + } + leg_next(): void { + this.sel_leg = Math.min(this.sel_leg + 1, this.leg_count() - 1); + this.sel_day = 0; + } + leg_prev(): void { + this.sel_leg = Math.max(this.sel_leg - 1, 0); + this.sel_day = 0; + } + day_next() { + this.sel_day += 1 + if (this.sel_day > this.leg_len() - 1) { + if (this.sel_leg < this.leg_count() - 1) { + this.leg_next() + this.sel_day = 0; + } else { + this.sel_day = this.leg_len() - 1; + } + } + } + day_prev() { + this.sel_day -= 1 + if (this.sel_day < 0) { + if (this.sel_leg > 0) { + this.leg_prev() + this.sel_day = this.leg_len() - 1; + } else { + this.sel_day = 0; + } + } + } + date_sel(): string { + if (this.sel_day < 0) return "?"; + if (!this.leg_get().date_range) + return "?"; + var date = new Date( + this.leg_get().date_range[0], + ); + date.setDate(date.getDate() + this.sel_day); + return date.toLocal(); + } + date_tot() { + if (this.leg_count() == 0) return ""; + try { + return `${this.leg_first().date_range[0].toLocal()} - ${this.leg_last().date_range[1].toLocal()}`; + } catch { + return "?"; + } + } + + date_update(idx: number) { + let date_range = this.leg_get(idx).date_range; + let start_end = [0, 0]; + let step_len = 0; + + let last_start = date_range[0]; + for (let i = idx - 1; i >= 0; --i) { + step_len = this.leg_len(i) - 1; + if (this.leg_get(i).date_range) { + start_end = [last_start.getDate() - step_len, last_start.getDate()]; + } else { + this.leg_get(i).date_range = [new Date(), new Date()]; + start_end = [last_start.getDate() - step_len, last_start.getDate()]; + } + this.leg_get(i).date_range[0].setTime(last_start.getTime()); + this.leg_get(i).date_range[0].setDate(start_end[0]); + this.leg_get(i).date_range[1].setTime(last_start.getTime()); + this.leg_get(i).date_range[1].setDate(start_end[1]); + last_start = this.leg_get(i).date_range[0]; + } + + let last_end = date_range[1]; + for (let i = idx + 1; i < this.leg_count(); ++i) { + step_len = this.leg_len(i) - 1; + if (this.leg_get(i).date_range) { + start_end = [last_end.getDate(), last_end.getDate() + step_len]; + } else { + this.leg_get(i).date_range = [new Date(), new Date()]; + start_end = [last_end.getDate(), last_end.getDate() + step_len]; + } + this.leg_get(i).date_range[0].setTime(last_end.getTime()); + this.leg_get(i).date_range[0].setDate(start_end[0]); + this.leg_get(i).date_range[1].setTime(last_end.getTime()); + this.leg_get(i).date_range[1].setDate(start_end[1]); + last_end = this.leg_get(i).date_range[1]; + } + } +} + +export default journey_wrapper; \ No newline at end of file -- 2.47.2 From c72416780329dee62649e0a74fde99e75ec4d810 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:14:54 +0100 Subject: [PATCH 09/95] Update template/home.pug --- template/home.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/home.pug b/template/home.pug index 41087ea..9de3b59 100644 --- a/template/home.pug +++ b/template/home.pug @@ -69,7 +69,7 @@ main#app | Select and plan the varying elements of your journey .aligner.aligner--contentEnd .input - input#journey_id(v-model="journey_id", placeholder="ID", type="text") + input#journey.id(v-model="journey.id", placeholder="ID", type="text") button.button.button--primary.button--mobileFull( v-on:click="start_journey" ) Start the journey -- 2.47.2 From 6f96bff5b50958f3a98347fca2806f1af4a7a350 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:15:06 +0100 Subject: [PATCH 10/95] Update template/short.pug --- template/short.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/short.pug b/template/short.pug index e06e6cb..f4fdd09 100644 --- a/template/short.pug +++ b/template/short.pug @@ -3,7 +3,7 @@ include module/head.pug main#app(v-cloak) include module/nav_pub.pug div( - v-for="(item, idx) in journey_data.main", + v-for="(item, idx) in journey.data.main", :class="idx % 2 === 0 ? 'bg-dark text-white' : ''" ) include module/short_sec.pug -- 2.47.2 From 0949635148807509ace8b12cd22ba94577f745d5 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:15:17 +0100 Subject: [PATCH 11/95] Update template/view.pug --- template/view.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/view.pug b/template/view.pug index a80f3a6..7230689 100644 --- a/template/view.pug +++ b/template/view.pug @@ -1,6 +1,6 @@ doctype html include module/head.pug main#app(v-cloak) - div(v-if="journey_data.main[journey_step_data.section] != undefined") + div(v-if="journey.data.main[journey.sel_leg] != undefined") include module/view_step.pug include module/foot.pug -- 2.47.2 From 17cfcc77da36b54f169dd492e3414d30d56e57c2 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:15:35 +0100 Subject: [PATCH 12/95] Update template/module/foot.pug --- template/module/foot.pug | 2 -- 1 file changed, 2 deletions(-) diff --git a/template/module/foot.pug b/template/module/foot.pug index 9c2437c..4863aed 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -1,7 +1,5 @@ script(src="https://unpkg.com/leaflet") script(src="https://unpkg.com/leaflet.awesome-markers") -//- script(src="https://unpkg.com/axios") -script(src="https://unpkg.com/lodash") script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vue@2") -- 2.47.2 From 63eb47f8556abb35c3884a3c4a4ac005cd9f8475 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:15:49 +0100 Subject: [PATCH 13/95] Update template/module/journey_sec.pug --- template/module/journey_sec.pug | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/template/module/journey_sec.pug b/template/module/journey_sec.pug index 4b5640e..5b8fd78 100644 --- a/template/module/journey_sec.pug +++ b/template/module/journey_sec.pug @@ -1,20 +1,20 @@ draggable.list-group.bg-dark( tag="div", - :list="journey_data.main", + :list="journey.data.main", handle=".handle" ) .list-group-item.handle( - v-for="(element, idx) in journey_data.main", + v-for="(element, idx) in journey.data.main", :key="idx", - @click="sel_section(idx)", - :class="journey_step_data.section == idx ? 'bg-primary' : 'bg-white'" + @click="journey.leg_sel(idx)", + :class="journey.sel_leg == idx ? 'bg-primary' : 'bg-white'" ) .text {{ element.title }} i.fa.fa-times.close.fright( style="top: 2px; right: 2px; position: absolute", - @click="rm_section(idx)" + @click="journey.rm_leg(idx)" ) - .list-group-item.bg-white(@click="add_section()") + .list-group-item.bg-white(@click="journey.add_leg()") .text Add Section i.fa.fa-plus.add(style="top: 12px; right: 5px; position: absolute") -- 2.47.2 From 923263e27f2ecb5137c8b551bb117479976021b2 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:15:59 +0100 Subject: [PATCH 14/95] Update template/module/journey_step.pug --- template/module/journey_step.pug | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/template/module/journey_step.pug b/template/module/journey_step.pug index 10281da..94e06da 100644 --- a/template/module/journey_step.pug +++ b/template/module/journey_step.pug @@ -1,19 +1,19 @@ -div(v-for="(e, idx) in journey_data.main", :key="idx") - .bg-dark.text-white(v-if="journey_step_data.section == idx") +div(v-for="(e, idx) in journey.data.main", :key="idx") + .bg-dark.text-white(v-if="journey.sel_leg == idx") .container.section .row.text-center .input.col-sm-2 - input(v-model="journey_data.main[idx].title") + input(v-model="journey.leg_get(idx).title") .input.col-sm-2 input( placeholder="Day title", - v-model="journey_data.main[idx].step_title[journey_step_data.day]" + v-model="journey.leg_get(idx).step_title[journey.sel_day]" ) .col-sm-3 .right.input.col-sm-2 input( disabled="", - :value="active_date() + ' (' + journey_step_data.day + ')'" + :value="journey.date_sel() + ' (' + journey.sel_day + ')'" ) .row .col-9.col-ssm-12 @@ -21,21 +21,21 @@ div(v-for="(e, idx) in journey_data.main", :key="idx") .col-3.col-ssm-12 .row.text-center div - label Date Range ({{ step_len(idx) }}) + label Date Range ({{ journey.leg_len(idx) }}) .input.text-dark date-picker( :lang="lang", - v-model="journey_data.main[idx].dateRange", + v-model="journey.data.main[idx].date_range", range="", format="ddd D MMM", placeholder="Date Range", - v-on:change="update_date(idx)" + v-on:change="journey.date_update(idx)" ) .row.text-center div label Hotel multiselect#ajax( - v-model="journey_data.main[idx].hotel", + v-model="journey.data.main[idx].hotel", label="sname", track-by="place_id", placeholder="Type to search", @@ -54,7 +54,7 @@ div(v-for="(e, idx) in journey_data.main", :key="idx") div label Restoration multiselect#ajax( - v-model="journey_data.main[idx].places.restaurants", + v-model="journey.data.main[idx].places.restaurants", label="sname", track-by="place_id", placeholder="Type to search", @@ -74,7 +74,7 @@ div(v-for="(e, idx) in journey_data.main", :key="idx") div label Activities multiselect#ajax( - v-model="journey_data.main[idx].places.activities", + v-model="journey.data.main[idx].places.activities", label="sname", track-by="place_id", placeholder="Type to search", @@ -95,7 +95,7 @@ div(v-for="(e, idx) in journey_data.main", :key="idx") label Notes .input.text-dark(style="width: 100%") textarea-autosize.text-small( - v-model="journey_data.main[idx].notes", + v-model="journey.data.main[idx].notes", placeholder="Notes", :min-height="30", :max-height="350" -- 2.47.2 From b3867d42b37d111fa0655d9aef2fa46bc7b65be0 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:16:11 +0100 Subject: [PATCH 15/95] Update template/module/map.pug --- template/module/map.pug | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/template/module/map.pug b/template/module/map.pug index 34f6e83..0987112 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -1,6 +1,6 @@ l-map( - :zoom.sync="journey_data.main[idx].map.zoom", - :center.sync="journey_data.main[idx].map.center", + :zoom.sync="journey.data.main[idx].map.zoom", + :center.sync="journey.data.main[idx].map.center", style="padding-top: 100%" ) l-tile-layer( @@ -9,30 +9,30 @@ l-map( ) l-control-scale(position="topright", :imperial="false", :metric="true") l-marker( - v-if="journey_data.main[idx].hotel", - :lat-lng="journey_data.main[idx].hotel.latlon" + v-if="journey.data.main[idx].hotel", + :lat-lng="journey.data.main[idx].hotel.latlon" ) l-icon - div(v-html="generate_icon(journey_data.main[idx].hotel, 'darkblue')") + div(v-html="generate_icon(journey.data.main[idx].hotel, 'darkblue')") l-popup - h1.row.text-medium.text-center {{ journey_data.main[idx].hotel.sname }} - span.row.text-small.text-gray {{ journey_data.main[idx].hotel.display_name }} + h1.row.text-medium.text-center {{ journey.data.main[idx].hotel.sname }} + span.row.text-small.text-gray {{ journey.data.main[idx].hotel.display_name }} span(v-if="journey_edit") .row.input textarea-autosize.col-12.col-sm-12.text-small( placeholder="Notes", - v-model="journey_data.main[idx].hotel.notes", + v-model="journey.data.main[idx].hotel.notes", :min-height="30", :max-height="350" ) - span.row.text-small.text-white(v-else) {{ journey_data.main[idx].hotel.notes }} + span.row.text-small.text-white(v-else) {{ journey.data.main[idx].hotel.notes }} l-marker( - v-for="place in journey_data.main[idx].places.activities", + v-for="place in journey.data.main[idx].places.activities", :lat-lng="place.latlon" ) l-icon div( - v-if="place.step == journey_step_data.day", + v-if="place.step == journey.sel_day", v-html="generate_icon(place)" ) div( @@ -60,12 +60,12 @@ l-map( a.leaflet-popup-close-button.text-gray( style="right: 16px; visibility: visible", href="#ad", - v-on:click.prevent="place.step = journey_step_data.day" + v-on:click.prevent="place.step = journey.sel_day" ) + span.row.text-small.text-dark(v-else) {{ place.notes }} l-marker( - v-for="place in journey_data.main[idx].places.restaurants", + v-for="place in journey.data.main[idx].places.restaurants", :lat-lng.sync="place.latlon" ) l-icon -- 2.47.2 From 8e547fd0cfd061645672a502546b6c890ac5449b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:16:21 +0100 Subject: [PATCH 16/95] Update template/module/nav_pub.pug --- template/module/nav_pub.pug | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/template/module/nav_pub.pug b/template/module/nav_pub.pug index 49af761..ab88fb2 100644 --- a/template/module/nav_pub.pug +++ b/template/module/nav_pub.pug @@ -8,11 +8,11 @@ header.header ) span.hide-small HOTM .input.input-invis - input.small(:value="journey_data.name", type="text", disabled="") + input.small(:value="journey.data.name", type="text", disabled="") .row.header-nav.text-big(style="margin-bottom: 0") .col-sm-3 - a(:href="'/short/' + journey_id") + a(:href="'/short/' + journey.id") i.fas.fa-file-contract .col-sm-3 - a(:href="'/view/' + journey_id") + a(:href="'/view/' + journey.id") i.fas.fa-camera -- 2.47.2 From 6048b30a18b5c7aaf49562190c73cb2a99090f44 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:16:36 +0100 Subject: [PATCH 17/95] Update template/module/nav.pug --- template/module/nav.pug | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/template/module/nav.pug b/template/module/nav.pug index c7173f1..96eb3f7 100644 --- a/template/module/nav.pug +++ b/template/module/nav.pug @@ -8,31 +8,31 @@ header.header ) span.hide-small OTM .input.input-invis.row - input.col-6.small(v-model="journey_data.name", type="text") + input.col-6.small(v-model="journey.data.name", type="text") input.col-6.small( disabled, type="text", - :placeholder="total_date() + ' (' + total_days() + ')'" + :placeholder="journey.date_tot() + ' (' + journey.tot_len() + ')'" ) .row.header-nav.text-big(style="margin-bottom: 0") .col-sm-2 - a(:href="'/short/' + journey_id") + a(:href="'/short/' + journey.id") i.fas.fa-file-contract .col-sm-2 - a(:href="'/view/' + journey_id") + a(:href="'/view/' + journey.id") i.fas.fa-camera .col-sm-2 a(href="#main", v-on:click.prevent="first_step") i.fas.fa-tools .col-sm-1.text-small - a(href="#prevprev", v-on:click.prevent="prevprev_step") + a(href="#prevprev", v-on:click.prevent="journey.leg_prev()") i.fas.fa-angle-double-left .col-sm-1 - a(href="#prev", v-on:click.prevent="prev_step") + a(href="#prev", v-on:click.prevent="journey.day_prev()") i.fas.fa-angle-left .col-sm-1 - a(href="#next", v-on:click.prevent="next_step") + a(href="#next", v-on:click.prevent="journey.day_next()") i.fas.fa-angle-right .col-sm-1.text-small - a(href="#nextnext", v-on:click.prevent="nextnext_step") + a(href="#nextnext", v-on:click.prevent="journey.leg_next()") i.fas.fa-angle-double-right -- 2.47.2 From 9d9e79b07ded3f65f82897cc5edf04ef5b39e037 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:16:48 +0100 Subject: [PATCH 18/95] Update template/module/short_sec.pug --- template/module/short_sec.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/module/short_sec.pug b/template/module/short_sec.pug index 3bfe2bf..bc005b0 100644 --- a/template/module/short_sec.pug +++ b/template/module/short_sec.pug @@ -6,7 +6,7 @@ input( disabled="", placeholder="No Dates", - :value="item.dateRange ? format_date(item.dateRange[0]) + ' - ' + format_date(item.dateRange[1]) : ''" + :value="item.date_range ? format_date(item.date_range[0]) + ' - ' + format_date(item.date_range[1]) : ''" ) .input.col-sm-2 input(disabled="", placeholder="No Hotel", :value="item.hotel.sname") -- 2.47.2 From cc527bc1abefbf2bbd3e77550a29df2781361ce2 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 15:16:59 +0100 Subject: [PATCH 19/95] Update template/module/view_step.pug --- template/module/view_step.pug | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/template/module/view_step.pug b/template/module/view_step.pug index 6540d3e..7ee9e2d 100644 --- a/template/module/view_step.pug +++ b/template/module/view_step.pug @@ -1,13 +1,13 @@ -div(v-for="(e, idx) in journey_data.main", :key="idx") - .bg-dark.text-white(v-if="journey_step_data.section == idx") +div(v-for="(e, idx) in journey.data.main", :key="idx") + .bg-dark.text-white(v-if="journey.sel_leg == idx") .container.section .aligner.text-center.text-white.text-huge(style="margin-bottom: 5px") .aligner--itemTop.fleft a(href="#prev", v-on:click.prevent="prev_step") i.fas.fa-angle-left span.container - span.small {{ journey_data.main[idx].title }} {{ journey_step_data.day }} - .text-big.text-gray {{ journey_data.main[idx].step_title[journey_step_data.day] }} + span.small {{ journey.data.main[idx].title }} {{ journey.sel_day }} + .text-big.text-gray {{ journey.data.main[idx].step_title[journey.sel_day] }} .aligner--itemEnd.fright a(href="#next", v-on:click.prevent="next_step") i.fas.fa-angle-right -- 2.47.2 From 059dfec50d763212cec0f4e76ced8489fd9d0683 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 16:45:49 +0100 Subject: [PATCH 20/95] Update router/api.js --- router/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/api.js b/router/api.js index 1a8dfe3..3366236 100644 --- a/router/api.js +++ b/router/api.js @@ -74,7 +74,7 @@ module.exports = (fastify, opts, done) => { if (req.params.id == undefined) return reply.code(400).send({ error: "No ID query parameter" }); - fastify.level.db.put(req.params.id, JSON.stringify(req.body), (err) => { + fastify.level.db.put(req.params.id, req.body, (err) => { if (err) { console.warn(err); reply.code(500).send({ error: "Error with DB" }); -- 2.47.2 From d689ceb5116d2fff2f5b1c9cb6ab63c36e1bf9da Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 16:46:11 +0100 Subject: [PATCH 21/95] Update src/api.ts --- src/api.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/api.ts b/src/api.ts index 5d4747f..8717b9c 100644 --- a/src/api.ts +++ b/src/api.ts @@ -96,7 +96,7 @@ export const icon_type = (item: NominatimResult): string => { "water": ["water", "river", "lake", "torrent", "aquarium"], "building": ["community_center", "locality"], "archway": ["bridge"], - "tree": ["woodland", "shieling", "national_park", "park", "zoo", "garden"], + "tree": ["woodland", "shieling", "national_park", "park", "zoo", "garden", "nature_reserve"], "dice-five": ["water_park", "theme_park", "casino"], "": ["?", "neighbourhood", "quarter", "highway"], } @@ -105,7 +105,6 @@ export const icon_type = (item: NominatimResult): string => { if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) return k; } - console.log(item.display_name, item.category, item.type); return "question"; }; -- 2.47.2 From ecc9e8336988f5560869a63823cbb006346fb23f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 16:46:22 +0100 Subject: [PATCH 22/95] Update src/types/ext.ts --- src/types/ext.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/types/ext.ts b/src/types/ext.ts index c13aa39..0344b70 100644 --- a/src/types/ext.ts +++ b/src/types/ext.ts @@ -56,27 +56,20 @@ Array.prototype.foldl = function (f: (x: T, acc: B) => B, acc: B): B { // STRING EXTENTION declare global { interface String { - btoa: () => String; toEncoded: () => String; toDecoded: () => String; } } -String.prototype.btoa = function () { - return window.btoa(this); -}; - String.prototype.toEncoded = function () { - return window.btoa( - Array.from(this as string, (c) => c.charCodeAt(0)).foldl( - (e, v) => v + String.fromCharCode(e), - "", - ), - ); + return window.btoa(encodeURIComponent(Array.from(this as string, (c) => c.charCodeAt(0)).foldl( + (e, v) => v + String.fromCharCode(e), + "", + ))) }; String.prototype.toDecoded = function () { - return Array.from(window.atob(this), (c) => c.charCodeAt(0)).foldl( + return Array.from(decodeURIComponent(window.atob(this as string)), (c) => c.charCodeAt(0)).foldl( (e, v) => v + String.fromCharCode(e), "", ); -- 2.47.2 From f3bed6d21c9f34f632d0881e196aeccaa3ae0f13 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 16:46:42 +0100 Subject: [PATCH 23/95] Update template/module/view_step.pug --- template/module/view_step.pug | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/module/view_step.pug b/template/module/view_step.pug index 7ee9e2d..bcb4d82 100644 --- a/template/module/view_step.pug +++ b/template/module/view_step.pug @@ -3,13 +3,13 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") .container.section .aligner.text-center.text-white.text-huge(style="margin-bottom: 5px") .aligner--itemTop.fleft - a(href="#prev", v-on:click.prevent="prev_step") + a(href="#prev", v-on:click.prevent="journey.day_prev()") i.fas.fa-angle-left span.container span.small {{ journey.data.main[idx].title }} {{ journey.sel_day }} .text-big.text-gray {{ journey.data.main[idx].step_title[journey.sel_day] }} .aligner--itemEnd.fright - a(href="#next", v-on:click.prevent="next_step") + a(href="#next", v-on:click.prevent="journey.day_next()") i.fas.fa-angle-right .row .col-12.col-sm-12 -- 2.47.2 From c2d1858e68fc4315500b7fad6a867407e62bec71 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 17:31:02 +0100 Subject: [PATCH 24/95] Update src/old.js --- src/old.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/old.js b/src/old.js index 1796bd4..3a9435d 100644 --- a/src/old.js +++ b/src/old.js @@ -1,6 +1,7 @@ import * as api from "./api"; import journey_wrapper from "./types/wrapper"; +import { migrator } from "./types/migration"; Vue.component("l-map", window.Vue2Leaflet.LMap); Vue.component("l-tile-layer", window.Vue2Leaflet.LTileLayer); @@ -8,6 +9,7 @@ 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); Vue.component("multiselect", window.VueMultiselect.default); Vue.use(window.VueTextareaAutosize); @@ -29,6 +31,10 @@ const app = new Vue({ }, monthBeforeYear: true, }, + polyline: { + latlngs: [[47.334852, -1.509485], [47.342596, -1.328731], [47.241487, -1.190568], [47.234787, -1.358337]], + color: 'green' + } }, methods: { start_journey: () => window.location.href = "/" + this.journey.id, @@ -121,7 +127,7 @@ const app = new Vue({ } }); - api.load(this.journey.id).then((r) => (app.journey.data = r)); + api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); this.debounceSave = api.throttle(this.save_data, 500); this.debounceSearch = { -- 2.47.2 From a13b3acbe53d073ef2ca506bd651ca03110ba79b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 17:31:15 +0100 Subject: [PATCH 25/95] Update src/types/format.ts --- src/types/format.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/types/format.ts b/src/types/format.ts index ab7b6b1..0693e03 100644 --- a/src/types/format.ts +++ b/src/types/format.ts @@ -14,7 +14,7 @@ declare global { interface leg { title: string - step_title: string[] + day_title: string[] date_range: [Date, Date] | null map: map travel: unknown[] @@ -27,6 +27,7 @@ declare global { } interface journey { + fmt_ver: number title: string name: string | null main: leg[] @@ -34,6 +35,7 @@ declare global { } const journey_template: journey = { + fmt_ver: 1, title: "New Journey", name: null, main: [], @@ -41,7 +43,7 @@ const journey_template: journey = { const leg_template: leg = { title: "New Leg", - step_title: [], + day_title: [], map: { zoom: 2, center: { lng: 0, lat: 0 } }, travel: [], hotel: null, -- 2.47.2 From 97f2a5ebb8fb0fd99b0d63ca430e3c84ecf35e28 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 17:31:32 +0100 Subject: [PATCH 26/95] Add src/types/migration.ts --- src/types/migration.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/types/migration.ts diff --git a/src/types/migration.ts b/src/types/migration.ts new file mode 100644 index 0000000..c4760b7 --- /dev/null +++ b/src/types/migration.ts @@ -0,0 +1,22 @@ +const FMT_VER_0 = 0 +const FMT_VER_LATEST = FMT_VER_0 + +function migrate_A_to_0(e: journey): journey { + e.title = e.name; + e.main.forEach((v) => { + v.date_range = v.date_range || (v as any).dateRange; + v.day_title = v.day_title || (v as any).step_title; + v.travel; + }) + console.log(e) + return e; +} + +export const migrator = (e: journey): journey => { + if (e.fmt_ver == FMT_VER_LATEST) return e; + switch (e.fmt_ver) { + case FMT_VER_0: break; // Update when FMT_VER_1 releases + default: + return migrate_A_to_0(e) + } +} \ No newline at end of file -- 2.47.2 From b554eba76c0ade0d83ca39baa8a3e822156d6210 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Mon, 24 Feb 2025 17:31:48 +0100 Subject: [PATCH 27/95] Update template/module/map.pug --- template/module/map.pug | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/template/module/map.pug b/template/module/map.pug index 0987112..51a08db 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -63,7 +63,6 @@ l-map( v-on:click.prevent="place.step = journey.sel_day" ) + span.row.text-small.text-dark(v-else) {{ place.notes }} - l-marker( v-for="place in journey.data.main[idx].places.restaurants", :lat-lng.sync="place.latlon" @@ -82,3 +81,5 @@ l-map( :max-height="350" ) span.row.text-small.text-dark(v-else) {{ place.notes }} + + l-polyline(:lat-lngs="polyline.latlngs" :color="polyline.color") \ No newline at end of file -- 2.47.2 From 0cc9d235ed74bdf3347fbcf3515fef46fcd245b2 Mon Sep 17 00:00:00 2001 From: soraefir Date: Tue, 25 Feb 2025 01:38:34 +0100 Subject: [PATCH 28/95] Better nominatim --- router/api.js | 16 ++- src/api.ts | 208 ++++++++++++++++++------------- src/old.js | 15 ++- template/module/journey_step.pug | 2 +- template/module/map.pug | 1 + template/module/view_step.pug | 2 +- yarn.lock | 100 --------------- 7 files changed, 149 insertions(+), 195 deletions(-) diff --git a/router/api.js b/router/api.js index 3366236..c7c421a 100644 --- a/router/api.js +++ b/router/api.js @@ -6,7 +6,7 @@ module.exports = (fastify, opts, done) => { url.searchParams.append('query', req.params.id) url.searchParams.append('limit', 16) url.searchParams.append('type', 'schedule') - fetch(url).then((res) => reply.send(res.data)); + fetch(url).then((res) => reply.send(res.json())); } else { return reply.send([]); } @@ -14,10 +14,20 @@ module.exports = (fastify, opts, done) => { }); fastify.get("/place/:id", async (req, reply) => { if (req.params.id) { - const url = new URL("https://nominatim.openstreetmap.org/"); + const url = new URL("https://nominatim.openstreetmap.org/search"); url.searchParams.append('format', 'jsonv2') url.searchParams.append('q', req.params.id) - fetch(url).then((res) => reply.send(res.data)); + + let bb = JSON.parse(req.query.bb) + if(bb){ + url.searchParams.append('viewbox', `${bb[0][0]},${bb[0][1]},${bb[1][0]},${bb[1][1]}`) + url.searchParams.append('bounded', 1) + } + fetch(url).then((res) => { + if( !res.ok) throw new Error("Nominatim Error") + return res.json() + }).then(res=>{ + reply.send(res)}); } else { return reply.send([]); } diff --git a/src/api.ts b/src/api.ts index 8717b9c..26b5689 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,110 +1,142 @@ export const throttle = (func: () => void, wait: number) => { - let lastTime = 0; - let timeoutId: ReturnType | undefined; - let lastArgs: any[]; + let lastTime = 0; + let timeoutId: ReturnType | undefined; + let lastArgs: any[]; - return function (...args: any[]) { - const now = Date.now(); - lastArgs = args; + return function (...args: any[]) { + const now = Date.now(); + lastArgs = args; - if (now - lastTime >= wait) { - lastTime = now; - func.apply(this, lastArgs); - } else { - if (timeoutId) clearTimeout(timeoutId); - timeoutId = setTimeout(() => { - lastTime = Date.now(); - func.apply(this, lastArgs); - }, wait - (now - lastTime)); - } - }; -} + if (now - lastTime >= wait) { + lastTime = now; + func.apply(this, lastArgs); + } else { + if (timeoutId) clearTimeout(timeoutId); + timeoutId = setTimeout( + () => { + lastTime = Date.now(); + func.apply(this, lastArgs); + }, + wait - (now - lastTime) + ); + } + }; +}; export const load = (id: string) => - fetch("/api/" + id).then(res => { - if (!res.ok) throw new Error('Error ' + res.statusText); - return res.json(); - }).then((res) => { - for (let e of res.main) { - if (e.date_range) { - e.date_range[0] = new Date(e.date_range[0]); - e.date_range[1] = new Date(e.date_range[1]); - } - e.step_title = e.step_title || []; - } - return res; - }) + fetch("/api/" + id) + .then((res) => { + if (!res.ok) throw new Error("Error " + res.statusText); + return res.json(); + }) + .then((res) => { + for (let e of res.main) { + if (e.date_range) { + e.date_range[0] = new Date(e.date_range[0]); + e.date_range[1] = new Date(e.date_range[1]); + } + e.day_title = e.day_title || []; + } + return res; + }); export const save = (id: string, v: journey) => - fetch("/api/" + id, { method: "post", body: JSON.stringify(v) }) - .then(res => { - if (!res.ok) throw new Error('Error ' + res.statusText); - return res.json(); - }).then((_res) => { - console.log("Saved..."); - }) + fetch("/api/" + id, { method: "post", body: JSON.stringify(v) }) + .then((res) => { + if (!res.ok) throw new Error("Error " + res.statusText); + return res.json(); + }) + .then((_res) => { + console.log("Saved..."); + }); export const query_nominatim = ( - q: string, - f: (v: string) => Boolean = () => true, -) => - fetch("/api/place/" + q) - .then((res) => (res.status == 200) ? res.json() : []) - .then((res) => res.filter(f)); + q: string, + bb: any, + f: (v: string) => Boolean = () => true +) => { + let url = new URL("/api/place/" + q, window.location.origin); + url.searchParams.append("id", q); + url.searchParams.append("bb", JSON.stringify(bb)); + return fetch(url) + .then((res) => (res.status == 200 ? res.json() : [])) + .then((res) => res.filter(f)); +}; export const query_flight = (q: string) => - fetch("/api/flight/" + q).then((res) => res.json()); + fetch("/api/flight/" + q).then((res) => res.json()); type NominatimResult = { - type: string; - category: string; - display_name: string; // DEBUG ONLY + type: string; + category: string; + display_name: string; // DEBUG ONLY }; export const is_restauration_type = (e: NominatimResult) => - ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].indexOf( - e.type, - ) != -1; + ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].indexOf( + e.type + ) != -1; export const is_attraction_type = (e: NominatimResult): boolean => - [ - "tourism", - "leisure", - "place", - "amenity", - "highway", - "historic", - "natural", - "waterway", - ].indexOf(e.category) != -1 || - [ - "place_of_worship", - "national_park", - "nature_reserve", - "protected_area", - ].indexOf(e.type) != -1; + [ + "tourism", + "leisure", + "place", + "amenity", + "highway", + "historic", + "natural", + "waterway", + ].indexOf(e.category) != -1 || + [ + "place_of_worship", + "national_park", + "nature_reserve", + "protected_area", + ].indexOf(e.type) != -1; export const icon_type = (item: NominatimResult): string => { - let t = item.type; - let c = item.category; - let types = { - "utensils": ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"], - "bed": ["hotel", "hostel", "guest_house"], - "landmark": ["museum", "historic", "place_of_worship", "attraction", "information", "university"], - "mountain": ["peak", "viewpoint"], - "parking": ["parking"], - "water": ["water", "river", "lake", "torrent", "aquarium"], - "building": ["community_center", "locality"], - "archway": ["bridge"], - "tree": ["woodland", "shieling", "national_park", "park", "zoo", "garden", "nature_reserve"], - "dice-five": ["water_park", "theme_park", "casino"], - "": ["?", "neighbourhood", "quarter", "highway"], - } + let t = item.type; + let c = item.category; + let types = { + utensils: [ + "restaurant", + "cafe", + "pub", + "bar", + "fast_food", + "food_court", + ], + bed: ["hotel", "hostel", "guest_house"], + landmark: [ + "museum", + "historic", + "place_of_worship", + "attraction", + "information", + "university", + ], + mountain: ["peak", "viewpoint"], + parking: ["parking"], + water: ["water", "river", "lake", "torrent", "aquarium"], + building: ["community_center", "locality"], + archway: ["bridge"], + tree: [ + "woodland", + "shieling", + "national_park", + "park", + "zoo", + "garden", + "nature_reserve", + ], + "dice-five": ["water_park", "theme_park", "casino"], + "": ["?", "neighbourhood", "quarter", "highway"], + }; - for (let k in types) { - if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) - return k; - } - console.log(item.display_name, item.category, item.type); - return "question"; + for (let k in types) { + if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) return k; + } + console.log(item.display_name, item.category, item.type); + return "question"; }; diff --git a/src/old.js b/src/old.js index 3a9435d..9e4d8e4 100644 --- a/src/old.js +++ b/src/old.js @@ -37,14 +37,25 @@ const app = new Vue({ } }, methods: { - start_journey: () => window.location.href = "/" + this.journey.id, + start_journey: function(){ window.location.href = "/" + this.journey.id}, + + compute_bb: function(){ + const map = this.$refs.map[0].mapObject; + var bounds = map.getBounds(); + var minLng = bounds.getSouthWest().lng; + var minLat = bounds.getSouthWest().lat; + var maxLng = bounds.getNorthEast().lng; + var maxLat = bounds.getNorthEast().lat; + return [[minLng,minLat],[maxLng,maxLat]] + }, search_nominatim: function (txt, f) { if (txt == "") { this.query.nominatim = []; return Promise.resolve([]); } - return api.query_nominatim(txt, f).catch((err) => []).then((results) => { + let bb = this.journey.leg_get(); + return api.query_nominatim(txt,this.compute_bb(), f).catch((err) => []).then((results) => { results.forEach((r) => { r.latlon = [parseFloat(r.lat), parseFloat(r.lon)]; r.sname = r.display_name.split(",")[0]; diff --git a/template/module/journey_step.pug b/template/module/journey_step.pug index 94e06da..c3498c1 100644 --- a/template/module/journey_step.pug +++ b/template/module/journey_step.pug @@ -7,7 +7,7 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") .input.col-sm-2 input( placeholder="Day title", - v-model="journey.leg_get(idx).step_title[journey.sel_day]" + v-model="journey.leg_get(idx).day_title[journey.sel_day]" ) .col-sm-3 .right.input.col-sm-2 diff --git a/template/module/map.pug b/template/module/map.pug index 51a08db..b7da2cf 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -2,6 +2,7 @@ l-map( :zoom.sync="journey.data.main[idx].map.zoom", :center.sync="journey.data.main[idx].map.center", style="padding-top: 100%" + ref="map" ) l-tile-layer( url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", diff --git a/template/module/view_step.pug b/template/module/view_step.pug index bcb4d82..90daa75 100644 --- a/template/module/view_step.pug +++ b/template/module/view_step.pug @@ -7,7 +7,7 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") i.fas.fa-angle-left span.container span.small {{ journey.data.main[idx].title }} {{ journey.sel_day }} - .text-big.text-gray {{ journey.data.main[idx].step_title[journey.sel_day] }} + .text-big.text-gray {{ journey.data.main[idx].day_title[journey.sel_day] }} .aligner--itemEnd.fright a(href="#next", v-on:click.prevent="journey.day_next()") i.fas.fa-angle-right diff --git a/yarn.lock b/yarn.lock index 3d1e226..9d38d61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -527,13 +527,6 @@ __metadata: languageName: node linkType: hard -"asynckit@npm:^0.4.0": - version: 0.4.0 - resolution: "asynckit@npm:0.4.0" - checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d - languageName: node - linkType: hard - "atomic-sleep@npm:^1.0.0": version: 1.0.0 resolution: "atomic-sleep@npm:1.0.0" @@ -551,17 +544,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.7.9": - version: 1.7.9 - resolution: "axios@npm:1.7.9" - dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 10c0/b7a41e24b59fee5f0f26c1fc844b45b17442832eb3a0fb42dd4f1430eb4abc571fe168e67913e8a1d91c993232bd1d1ab03e20e4d1fee8c6147649b576fc1b0b - languageName: node - linkType: hard - "babel-walk@npm:3.0.0-canary-5": version: 3.0.0-canary-5 resolution: "babel-walk@npm:3.0.0-canary-5" @@ -728,15 +710,6 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.8": - version: 1.0.8 - resolution: "combined-stream@npm:1.0.8" - dependencies: - delayed-stream: "npm:~1.0.0" - checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -803,13 +776,6 @@ __metadata: languageName: node linkType: hard -"delayed-stream@npm:~1.0.0": - version: 1.0.0 - resolution: "delayed-stream@npm:1.0.0" - checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 - languageName: node - linkType: hard - "depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -921,18 +887,6 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af - languageName: node - linkType: hard - "esbuild@npm:^0.25.0": version: 0.25.0 resolution: "esbuild@npm:0.25.0" @@ -1143,16 +1097,6 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.15.6": - version: 1.15.9 - resolution: "follow-redirects@npm:1.15.9" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/5829165bd112c3c0e82be6c15b1a58fa9dcfaede3b3c54697a82fe4a62dd5ae5e8222956b448d2f98e331525f05d00404aba7d696de9e761ef6e42fdc780244f - languageName: node - linkType: hard - "foreground-child@npm:^3.1.0": version: 3.3.0 resolution: "foreground-child@npm:3.3.0" @@ -1163,18 +1107,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.0": - version: 4.0.2 - resolution: "form-data@npm:4.0.2" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - mime-types: "npm:^2.1.12" - checksum: 10c0/e534b0cf025c831a0929bf4b9bbe1a9a6b03e273a8161f9947286b9b13bf8fb279c6944aae0070c4c311100c6d6dbb815cd955dc217728caf73fad8dc5b8ee9c - languageName: node - linkType: hard - "fs-minipass@npm:^3.0.0": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" @@ -1698,22 +1630,6 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0": - version: 1.52.0 - resolution: "mime-db@npm:1.52.0" - checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa - languageName: node - linkType: hard - -"mime-types@npm:^2.1.12": - version: 2.1.35 - resolution: "mime-types@npm:2.1.35" - dependencies: - mime-db: "npm:1.52.0" - checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 - languageName: node - linkType: hard - "mime@npm:^3": version: 3.0.0 resolution: "mime@npm:3.0.0" @@ -2032,13 +1948,6 @@ __metadata: languageName: node linkType: hard -"pretier@npm:^0.0.1": - version: 0.0.1 - resolution: "pretier@npm:0.0.1" - checksum: 10c0/206f5b353c32a9ad0e38243ad2caf7c8859ef43c975514e1c725088e4925d8b1480f73b96ebfd5ceaa1a563a77a3b8c893db7bb3642585bfa0c635f7ee149885 - languageName: node - linkType: hard - "prettier@npm:^3.5.2": version: 3.5.2 resolution: "prettier@npm:3.5.2" @@ -2081,13 +1990,6 @@ __metadata: languageName: node linkType: hard -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b - languageName: node - linkType: hard - "pstree.remy@npm:^1.1.8": version: 1.1.8 resolution: "pstree.remy@npm:1.1.8" @@ -2676,11 +2578,9 @@ __metadata: "@fastify/view": "npm:^10.0.0" "@prettier/plugin-pug": "npm:^3.0.0" "@types/node": "npm:^22.13.5" - axios: "npm:^1.7.9" esbuild: "npm:^0.25.0" fastify: "npm:^5.0.0" nodemon: "npm:^3.0.1" - pretier: "npm:^0.0.1" prettier: "npm:^3.5.2" pug: "npm:^3.0.2" languageName: unknown -- 2.47.2 From 5bb1622a0bbe89bec5c3ec4bbce01b233062488e Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:05:00 +0100 Subject: [PATCH 29/95] Update src/client/api.ts --- src/{ => client}/api.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => client}/api.ts (100%) diff --git a/src/api.ts b/src/client/api.ts similarity index 100% rename from src/api.ts rename to src/client/api.ts -- 2.47.2 From a782f61e0b2d83e902e41b543b40890be85096ef Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:05:22 +0100 Subject: [PATCH 30/95] Update src/client/main.ts --- src/{app.ts => client/main.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{app.ts => client/main.ts} (100%) diff --git a/src/app.ts b/src/client/main.ts similarity index 100% rename from src/app.ts rename to src/client/main.ts -- 2.47.2 From ca2e2c11d2a050d46466020b929cf823891055bd Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:05:37 +0100 Subject: [PATCH 31/95] Update src/client/old.js --- src/{ => client}/old.js | 1 - 1 file changed, 1 deletion(-) rename src/{ => client}/old.js (99%) diff --git a/src/old.js b/src/client/old.js similarity index 99% rename from src/old.js rename to src/client/old.js index 9e4d8e4..9843eeb 100644 --- a/src/old.js +++ b/src/client/old.js @@ -1,4 +1,3 @@ - import * as api from "./api"; import journey_wrapper from "./types/wrapper"; import { migrator } from "./types/migration"; -- 2.47.2 From aacefdce949866a0eec270a0c27bcc5ad653b15b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:06:20 +0100 Subject: [PATCH 32/95] Update src/client/types/ext.ts --- src/{ => client}/types/ext.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => client}/types/ext.ts (100%) diff --git a/src/types/ext.ts b/src/client/types/ext.ts similarity index 100% rename from src/types/ext.ts rename to src/client/types/ext.ts -- 2.47.2 From 4083c4268f6f1441b7c790cf5f4fb0ce0b73db99 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:06:36 +0100 Subject: [PATCH 33/95] Update src/client/types/format.ts --- src/{ => client}/types/format.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => client}/types/format.ts (100%) diff --git a/src/types/format.ts b/src/client/types/format.ts similarity index 100% rename from src/types/format.ts rename to src/client/types/format.ts -- 2.47.2 From 25a6fcf90dab46459df743f238c36f0a43391fd0 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:07:04 +0100 Subject: [PATCH 34/95] Update src/client/types/migration.ts --- src/{ => client}/types/migration.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename src/{ => client}/types/migration.ts (92%) diff --git a/src/types/migration.ts b/src/client/types/migration.ts similarity index 92% rename from src/types/migration.ts rename to src/client/types/migration.ts index c4760b7..c6dfd9f 100644 --- a/src/types/migration.ts +++ b/src/client/types/migration.ts @@ -2,7 +2,7 @@ const FMT_VER_0 = 0 const FMT_VER_LATEST = FMT_VER_0 function migrate_A_to_0(e: journey): journey { - e.title = e.name; + e.title = (e as any).name; e.main.forEach((v) => { v.date_range = v.date_range || (v as any).dateRange; v.day_title = v.day_title || (v as any).step_title; @@ -19,4 +19,5 @@ export const migrator = (e: journey): journey => { default: return migrate_A_to_0(e) } + return e; } \ No newline at end of file -- 2.47.2 From 8e8ab398c95e7206d1040e7248b9c61df946f1ef Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:08:00 +0100 Subject: [PATCH 35/95] Update src/client/types/format.ts --- src/client/types/format.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/client/types/format.ts b/src/client/types/format.ts index 0693e03..1d4fcf2 100644 --- a/src/client/types/format.ts +++ b/src/client/types/format.ts @@ -29,7 +29,6 @@ declare global { interface journey { fmt_ver: number title: string - name: string | null main: leg[] } } @@ -37,7 +36,6 @@ declare global { const journey_template: journey = { fmt_ver: 1, title: "New Journey", - name: null, main: [], } -- 2.47.2 From 3568de823d4f7c735a7df2a5c1ad8960bbf365e8 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:08:18 +0100 Subject: [PATCH 36/95] Update src/client/types/wrapper.ts --- src/{ => client}/types/wrapper.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => client}/types/wrapper.ts (100%) diff --git a/src/types/wrapper.ts b/src/client/types/wrapper.ts similarity index 100% rename from src/types/wrapper.ts rename to src/client/types/wrapper.ts -- 2.47.2 From bfd13fd782f7b31591383ea6d4dbfb495f4e882d Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:08:53 +0100 Subject: [PATCH 37/95] Update package.json --- package.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 46ffec5..ea3c71d 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "name": "volp", "version": "1.0.0", "description": "Open Travel Mapper", - "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "esbuild src/app.ts --bundle --outfile=public/main.js --tree-shaking=true --bundle --minify --sourcemap --tsconfig=tsconfig.json", - "start": "node server.js", + "build": "yarn build-server && yarn build-client", + "build-client": "esbuild src/client/main.ts --outfile=public/main.js --tree-shaking=true --bundle --minify --sourcemap --tsconfig=tsconfig-client.json", + "build-server": "esbuild src/server/**/*.ts --outdir=build --platform=node --format=cjs", + "start": "node build/main.js", "demon": "nodemon -e ts,js,pug --watch src --watch template --watch router --exec \"yarn build && yarn start\"" }, "repository": { @@ -22,9 +23,11 @@ "@prettier/plugin-pug": "^3.0.0", "@types/node": "^22.13.5", "esbuild": "^0.25.0", - "fastify": "^5.0.0", + "fastify": "^5.2.1", + "jsdom": "^26.0.0", "nodemon": "^3.0.1", "prettier": "^3.5.2", - "pug": "^3.0.2" + "pug": "^3.0.2", + "undici": "^7.3.0" } -} +} \ No newline at end of file -- 2.47.2 From b995cd45f0d09808ff1713b76ed9b996b49c36ae Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:09:16 +0100 Subject: [PATCH 38/95] Update tsconfig-client.json --- tsconfig.json => tsconfig-client.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tsconfig.json => tsconfig-client.json (100%) diff --git a/tsconfig.json b/tsconfig-client.json similarity index 100% rename from tsconfig.json rename to tsconfig-client.json -- 2.47.2 From e8f0516ccb183e8a6957d366ff4e0b43f41b3b37 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:09:39 +0100 Subject: [PATCH 39/95] Update src/server/api.js --- {router => src/server}/api.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {router => src/server}/api.js (100%) diff --git a/router/api.js b/src/server/api.js similarity index 100% rename from router/api.js rename to src/server/api.js -- 2.47.2 From 7fdd467c8c446ea14233c4d57cbde08211af8643 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:10:01 +0100 Subject: [PATCH 40/95] Update src/server/main.ts --- server.js | 35 ----------------------------------- src/server/main.ts | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 35 deletions(-) delete mode 100644 server.js create mode 100644 src/server/main.ts diff --git a/server.js b/server.js deleted file mode 100644 index bffdc7c..0000000 --- a/server.js +++ /dev/null @@ -1,35 +0,0 @@ -const fastify = require("fastify")(); //{ logger: true }); -const path = require("path"); - -fastify.register(require("@fastify/static"), { - root: path.join(__dirname, "public"), - prefix: "/public/", -}); - -fastify.register( - require("@fastify/leveldb"), - { - name: "db", - }, - (err) => { - if (err) throw err; - } -); - -fastify.register(require("@fastify/view"), { - engine: { - pug: require("pug"), - }, -}); - -fastify.register(require("./router/api"), { prefix: "/api" }); - -fastify.get("/", (req, reply) => reply.view("/template/home.pug")); -fastify.get("/:id", (req, reply) => reply.view("/template/journey.pug")); -fastify.get("/view/:id", (req, reply) => reply.view("/template/view.pug")); -fastify.get("/short/:id", (req, reply) => reply.view("/template/short.pug")); - -fastify.listen({ port: 8080, host: "0.0.0.0" }, (err, address) => { - if (err) throw err; - console.log("Listening on", address); -}); diff --git a/src/server/main.ts b/src/server/main.ts new file mode 100644 index 0000000..dd32624 --- /dev/null +++ b/src/server/main.ts @@ -0,0 +1,36 @@ +import fastify from 'fastify' +import fastify_static from '@fastify/static' +import fastify_db from '@fastify/leveldb' +import fastify_view from '@fastify/view'; +import pug from 'pug' +import { join as pathJoin } from "path"; + +import api from "./router/api" + +const server = fastify(); //{ logger: true }); + +server.register(fastify_static, { + root: pathJoin(__dirname, "public"), + prefix: "/public/", +}); + +server.register( + fastify_db as any, + { name: "db" } +); + +server.register(fastify_view, { + engine: { pug: pug }, +}); + +server.register(api, { prefix: "/api" }); + +server.get("/", (req, reply) => reply.view("/template/home.pug")); +server.get("/:id", (req, reply) => reply.view("/template/journey.pug")); +server.get("/view/:id", (req, reply) => reply.view("/template/view.pug")); +server.get("/short/:id", (req, reply) => reply.view("/template/short.pug")); + +server.listen({ port: 8080, host: "0.0.0.0" }, (err, address) => { + if (err) throw err; + console.log("Listening on", address); +}); -- 2.47.2 From 5a45dcb1b99295328d18d7da075dc065c6d64a00 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:10:18 +0100 Subject: [PATCH 41/95] Update src/server/api.ts --- src/server/{api.js => api.ts} | 70 ++++++++++++++--------------------- 1 file changed, 27 insertions(+), 43 deletions(-) rename src/server/{api.js => api.ts} (57%) diff --git a/src/server/api.js b/src/server/api.ts similarity index 57% rename from src/server/api.js rename to src/server/api.ts index c7c421a..afe855b 100644 --- a/src/server/api.js +++ b/src/server/api.ts @@ -1,44 +1,28 @@ -module.exports = (fastify, opts, done) => { - fastify.get("/flight/:id", async (req, reply) => { - if (req.params.id) { - const url = new URL("https://www.flightradar24.com/v1/search/web/find"); - url.searchParams.append('format', '-') - url.searchParams.append('query', req.params.id) - url.searchParams.append('limit', 16) - url.searchParams.append('type', 'schedule') - fetch(url).then((res) => reply.send(res.json())); - } else { - return reply.send([]); - } - return reply; - }); - fastify.get("/place/:id", async (req, reply) => { - if (req.params.id) { - const url = new URL("https://nominatim.openstreetmap.org/search"); - url.searchParams.append('format', 'jsonv2') - url.searchParams.append('q', req.params.id) +import { FastifyInstance } from 'fastify/types/instance'; +import { ProxyAgent, setGlobalDispatcher } from 'undici'; - let bb = JSON.parse(req.query.bb) - if(bb){ - url.searchParams.append('viewbox', `${bb[0][0]},${bb[0][1]},${bb[1][0]},${bb[1][1]}`) - url.searchParams.append('bounded', 1) - } - fetch(url).then((res) => { - if( !res.ok) throw new Error("Nominatim Error") - return res.json() - }).then(res=>{ - reply.send(res)}); - } else { - return reply.send([]); - } - return reply; - }); +import { flight_get_data } from './api_flight' +import { nominatim_get_data } from './api_nominatim'; - fastify.get("/gpx/:id", async (req, reply) => { +setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY as string)); + + +export default function (server, opts, done) { + server.get("/flight/:id", async (req, reply) => + flight_get_data(req.params.id) + .then(res => reply.send(res)) + ); + + server.get("/place/:id", async (req, reply) => + nominatim_get_data(req.params.id, JSON.parse(req.query.bb)) + .then(res => reply.send(res)) + ); + + server.get("/gpx/:id", async (req, reply) => { if (req.params.id == undefined) return reply.code(400).send({ error: "No ID query parameter" }); - fastify.level.db.get(req.params.id, (err, val) => { + server.level.db.get(req.params.id, (err, val) => { if (err) { console.warn(err); reply.code(500).send(); @@ -48,12 +32,12 @@ module.exports = (fastify, opts, done) => { const gen_wpt = (name, desc, latlon, icon = "Flag") => `0${name}-${desc}${icon}` const esc_str = (str) => (str || "Undefined").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">").replace("&", "&").replace("\n", "...") data.main.forEach(a => { - file += gen_wpt(esc_str(a.hotel.name), esc_str(a.hotel.notes), a.hotel.latlon, icon = "Hotel"); + file += gen_wpt(esc_str(a.hotel.name), esc_str(a.hotel.notes), a.hotel.latlon, "Hotel"); a.places.restaurants.forEach(b => { - file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon = "Restaurant"); + file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, "Restaurant"); }); a.places.activities.forEach(b => { - file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, icon = "Tree"); + file += gen_wpt(esc_str(b.name), esc_str(b.notes), b.latlon, "Tree"); }); }); file += ""; @@ -65,11 +49,11 @@ module.exports = (fastify, opts, done) => { return reply; }); - fastify.get("/:id", async (req, reply) => { + server.get("/:id", async (req, reply) => { if (req.params.id == undefined) return reply.code(400).send({ error: "No ID query parameter" }); - fastify.level.db.get(req.params.id, (err, val) => { + server.level.db.get(req.params.id, (err, val) => { if (err) { console.warn(err); reply.code(500).send(); @@ -80,11 +64,11 @@ module.exports = (fastify, opts, done) => { return reply; }); - fastify.post("/:id", async (req, reply) => { + server.post("/:id", async (req, reply) => { if (req.params.id == undefined) return reply.code(400).send({ error: "No ID query parameter" }); - fastify.level.db.put(req.params.id, req.body, (err) => { + server.level.db.put(req.params.id, req.body, (err) => { if (err) { console.warn(err); reply.code(500).send({ error: "Error with DB" }); -- 2.47.2 From ca9edace2f6958adebbf9f27bdc839aad087dada Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:10:41 +0100 Subject: [PATCH 42/95] Add src/server/api_flight.ts --- src/server/api_flight.ts | 86 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/server/api_flight.ts diff --git a/src/server/api_flight.ts b/src/server/api_flight.ts new file mode 100644 index 0000000..ac1e0c8 --- /dev/null +++ b/src/server/api_flight.ts @@ -0,0 +1,86 @@ +import { JSDOM } from 'jsdom'; + +interface FlightData { + id: string; + date: string; + from: string; + to: string; + std: string; + atd: string | string[] | null; + sta: string; + ata: string | string[] | null; +} + +function clean_times(s: string): string | null { + if (s == "—" || s == "Scheduled") return null + if (s.indexOf("Estimated departure") == 0) return null + if (s.indexOf("Landed") == 0) return s.replace("Landed ", "") + return s +} + +export function flight_get_data(flightId: string): Promise { + const url = new URL(`https://www.flightradar24.com/data/flights/${flightId}`); + return fetch(url).then(res => res.text()).then(res => new JSDOM(res)).then(dom => { + const rows = dom.window.document.querySelectorAll('table tbody tr'); + const flightData: FlightData[] = []; + rows.forEach(row => { + const columns = row.querySelectorAll('td'); + /* + * 2/6 = Date/Duration + * 3/4 = From/To + * 7/8 = STD/ATD + * 9/11 = STA/ATA + */ + const flight: FlightData = { + id: flightId, + date: columns[2].textContent.trim(), + from: columns[3].textContent.trim(), + to: columns[4].textContent.trim(), + std: columns[7].textContent.trim(), + atd: clean_times(columns[8].textContent.trim()), + sta: columns[9].textContent.trim(), + ata: clean_times(columns[11].textContent.trim()) + }; + flightData.push(flight); + }); + + return groupByPair(flightData).map(v => groupByFrequency(v)); + }) +} + +function groupByPair(flightData: FlightData[]): FlightData[][] { + const flightMap: { [key: string]: FlightData[] } = {}; + flightData.forEach(flight => { + const key = `${flight.from}-${flight.to}`; + if (!flightMap[key]) + flightMap[key] = []; + flightMap[key].push(flight); + }); + return Object.values(flightMap); +} + +function groupByFrequency(flightData: FlightData[]): FlightData { + let data = 'OOOOOOO'; // Initialize with no flights + const atdArray: string[] = []; + const ataArray: string[] = []; + + flightData.forEach(flight => { + const dayOfWeek = (new Date(flight.date).getDay() + 6) % 7; + data = data.substring(0, dayOfWeek) + 'X' + data.substring(dayOfWeek + 1); + if (flight.atd) + atdArray.push(flight.atd as string); + if (flight.ata) + ataArray.push(flight.ata as string); + }); + + return { + id: flightData[0].id, + date: data, + from: flightData[0].from, + to: flightData[0].to, + std: flightData[0].std, + sta: flightData[0].sta, + atd: atdArray, + ata: ataArray + }; +}; -- 2.47.2 From e0ec2c0f46aa2e2213eee959ae37eb00b846232b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:10:57 +0100 Subject: [PATCH 43/95] Add src/server/api_nominatim.ts --- src/server/api_nominatim.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/server/api_nominatim.ts diff --git a/src/server/api_nominatim.ts b/src/server/api_nominatim.ts new file mode 100644 index 0000000..f264130 --- /dev/null +++ b/src/server/api_nominatim.ts @@ -0,0 +1,16 @@ + +export function nominatim_get_data(id: string, bb: string[][] | null = null): Promise { + if (!id) return Promise.resolve([]) + + const url = new URL("https://nominatim.openstreetmap.org/search"); + url.searchParams.append('format', 'jsonv2') + url.searchParams.append('q', id) + if (bb) { + url.searchParams.append('viewbox', `${bb[0][0]},${bb[0][1]},${bb[1][0]},${bb[1][1]}`) + url.searchParams.append('bounded', `1`) + } + return fetch(url).then((res) => { + if (!res.ok) throw new Error("Nominatim Error") + return res.json() + }) +} -- 2.47.2 From 1df6f14f1a8faefb000f10b0984ef02f4d1bbd62 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 16:11:34 +0100 Subject: [PATCH 44/95] Update src/server/main.ts --- src/server/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/main.ts b/src/server/main.ts index dd32624..6085405 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -5,7 +5,7 @@ import fastify_view from '@fastify/view'; import pug from 'pug' import { join as pathJoin } from "path"; -import api from "./router/api" +import api from "./api" const server = fastify(); //{ logger: true }); -- 2.47.2 From c307dd0a22041edc40a7e59fd3dde79711508775 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:02:19 +0100 Subject: [PATCH 45/95] Update src/client/old.js --- src/client/old.js | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/client/old.js b/src/client/old.js index 9843eeb..ae82cc2 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -1,3 +1,4 @@ + import * as api from "./api"; import journey_wrapper from "./types/wrapper"; import { migrator } from "./types/migration"; @@ -31,21 +32,21 @@ const app = new Vue({ monthBeforeYear: true, }, polyline: { - latlngs: [[47.334852, -1.509485], [47.342596, -1.328731], [47.241487, -1.190568], [47.234787, -1.358337]], + latlngs: [], color: 'green' } }, methods: { - start_journey: function(){ window.location.href = "/" + this.journey.id}, + start_journey: function () { window.location.href = "/" + this.journey.id }, - compute_bb: function(){ - const map = this.$refs.map[0].mapObject; - var bounds = map.getBounds(); - var minLng = bounds.getSouthWest().lng; - var minLat = bounds.getSouthWest().lat; - var maxLng = bounds.getNorthEast().lng; - var maxLat = bounds.getNorthEast().lat; - return [[minLng,minLat],[maxLng,maxLat]] + compute_bb: function () { + const map = this.$refs.map[0].mapObject; + var bounds = map.getBounds(); + var minLng = bounds.getSouthWest().lng; + var minLat = bounds.getSouthWest().lat; + var maxLng = bounds.getNorthEast().lng; + var maxLat = bounds.getNorthEast().lat; + return [[minLng, minLat], [maxLng, maxLat]] }, search_nominatim: function (txt, f) { @@ -54,7 +55,7 @@ const app = new Vue({ return Promise.resolve([]); } let bb = this.journey.leg_get(); - return api.query_nominatim(txt,this.compute_bb(), f).catch((err) => []).then((results) => { + return api.query_nominatim(txt, this.compute_bb(), f).catch((err) => []).then((results) => { results.forEach((r) => { r.latlon = [parseFloat(r.lat), parseFloat(r.lon)]; r.sname = r.display_name.split(",")[0]; @@ -65,7 +66,7 @@ const app = new Vue({ search_flight: function (txt) { if (txt == "") return; this.querying.flight = true; - api.query_flight(txt.replace(" ", "")).then((results) => { + api.query_flight(txt).then((results) => { if (results.results == "") { this.query.flight = []; this.querying.flight = false; @@ -139,6 +140,14 @@ const app = new Vue({ api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); + + api.query_flight("qf1").then(r => { + console.log(r) + this.polyline.latlngs = L.geodesic([ + new L.LatLng(r[0].from_geo.lat, r[0].from_geo.lon), + new L.LatLng(r[0].to_geo.lat, r[0].to_geo.lon)], {})._latlngs + }) + this.debounceSave = api.throttle(this.save_data, 500); this.debounceSearch = { hotel: api.throttle((q) => { -- 2.47.2 From dc23d5ba830fe965adcf066a60a620ef2c661823 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:02:38 +0100 Subject: [PATCH 46/95] Update src/server/main.ts --- src/server/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/main.ts b/src/server/main.ts index 6085405..f955c66 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -5,12 +5,12 @@ import fastify_view from '@fastify/view'; import pug from 'pug' import { join as pathJoin } from "path"; -import api from "./api" +import api from "./router/api" const server = fastify(); //{ logger: true }); server.register(fastify_static, { - root: pathJoin(__dirname, "public"), + root: pathJoin(__dirname, "../public"), prefix: "/public/", }); -- 2.47.2 From 58c6eaa8689694dea73621ff91a6dcc9c937c61b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:02:48 +0100 Subject: [PATCH 47/95] Update src/server/api_flight.ts --- src/server/api_flight.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api_flight.ts b/src/server/api_flight.ts index ac1e0c8..14f5977 100644 --- a/src/server/api_flight.ts +++ b/src/server/api_flight.ts @@ -51,7 +51,7 @@ export function flight_get_data(flightId: string): Promise { function groupByPair(flightData: FlightData[]): FlightData[][] { const flightMap: { [key: string]: FlightData[] } = {}; flightData.forEach(flight => { - const key = `${flight.from}-${flight.to}`; + const key = `${flight.from}-${flight.to}-${flight.std}`; if (!flightMap[key]) flightMap[key] = []; flightMap[key].push(flight); -- 2.47.2 From d63845ed9abe36608e9ca34940b5e773ce7fa1bb Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:02:57 +0100 Subject: [PATCH 48/95] Update src/server/api_nominatim.ts --- src/server/api_nominatim.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/server/api_nominatim.ts b/src/server/api_nominatim.ts index f264130..58a48f6 100644 --- a/src/server/api_nominatim.ts +++ b/src/server/api_nominatim.ts @@ -1,4 +1,14 @@ +function drop_fields(results) { + results.forEach(e => { + delete e.licence; + delete e.place_rank; + delete e.importance; + delete e.boundingbox; + }); + return results +} + export function nominatim_get_data(id: string, bb: string[][] | null = null): Promise { if (!id) return Promise.resolve([]) @@ -11,6 +21,6 @@ export function nominatim_get_data(id: string, bb: string[][] | null = null): Pr } return fetch(url).then((res) => { if (!res.ok) throw new Error("Nominatim Error") - return res.json() + return res.json().then(r => drop_fields(r)) }) } -- 2.47.2 From 6ec4d426c9571f3b186dde2fb3923d001d58134b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:03:07 +0100 Subject: [PATCH 49/95] Update src/server/api.ts --- src/server/api.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/api.ts b/src/server/api.ts index afe855b..88de4d6 100644 --- a/src/server/api.ts +++ b/src/server/api.ts @@ -10,6 +10,14 @@ setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY as string)); export default function (server, opts, done) { server.get("/flight/:id", async (req, reply) => flight_get_data(req.params.id) + .then(res => { + let wait_for_all: Promise[] = [] + res.forEach(r => { + wait_for_all.push(nominatim_get_data(r.from).then(geo => (r as any).from_geo = geo[0])); + wait_for_all.push(nominatim_get_data(r.to).then(geo => (r as any).to_geo = geo[0])); + }); + return Promise.all(wait_for_all).then(_ => res) + }) .then(res => reply.send(res)) ); -- 2.47.2 From 60508b99ae9311a165da15f7ac63287276ccd688 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Tue, 25 Feb 2025 18:03:22 +0100 Subject: [PATCH 50/95] Update template/module/foot.pug --- template/module/foot.pug | 1 + 1 file changed, 1 insertion(+) diff --git a/template/module/foot.pug b/template/module/foot.pug index 4863aed..991d48e 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -1,5 +1,6 @@ script(src="https://unpkg.com/leaflet") script(src="https://unpkg.com/leaflet.awesome-markers") +script(src="https://unpkg.com/leaflet.geodesic") script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vue@2") -- 2.47.2 From ad420b45280adc6443d6ced1e47fc7e5631289b1 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:55:29 +0100 Subject: [PATCH 51/95] Update src/client/api.ts --- src/client/api.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/client/api.ts b/src/client/api.ts index 26b5689..674d920 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -1,17 +1,18 @@ export const throttle = (func: () => void, wait: number) => { - let lastTime = 0; - let timeoutId: ReturnType | undefined; - let lastArgs: any[]; + var lastTime = 0; + var timeoutId: ReturnType | undefined; + var lastArgs: any[]; return function (...args: any[]) { const now = Date.now(); lastArgs = args; + if (timeoutId) clearTimeout(timeoutId); + timeoutId = undefined; if (now - lastTime >= wait) { lastTime = now; func.apply(this, lastArgs); } else { - if (timeoutId) clearTimeout(timeoutId); timeoutId = setTimeout( () => { lastTime = Date.now(); @@ -55,6 +56,7 @@ export const query_nominatim = ( bb: any, f: (v: string) => Boolean = () => true ) => { + if (q.length == 0) return Promise.resolve([]) let url = new URL("/api/place/" + q, window.location.origin); url.searchParams.append("id", q); url.searchParams.append("bb", JSON.stringify(bb)); @@ -95,7 +97,13 @@ export const is_attraction_type = (e: NominatimResult): boolean => "protected_area", ].indexOf(e.type) != -1; -export const icon_type = (item: NominatimResult): string => { +export const is_hotel_type = (e: NominatimResult): boolean => + ["hotel", "hostel", "guest_house"].indexOf(e.type) != -1 + +export const icon_type = (item: string | NominatimResult): string => { + if (typeof (item) == "string") { + return item + } let t = item.type; let c = item.category; let types = { -- 2.47.2 From a69d334782364f370c1880da552810d3ad602dad Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:55:50 +0100 Subject: [PATCH 52/95] Update src/client/old.js --- src/client/old.js | 163 +++++++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 74 deletions(-) diff --git a/src/client/old.js b/src/client/old.js index ae82cc2..d92a4d4 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -2,6 +2,7 @@ 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); @@ -21,8 +22,11 @@ const app = new Vue({ ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), - query: { hotel: [], flight: [], nominatim: [] }, - querying: { hotel: false, flight: false, place: false, food: false }, + query: { + type: "", + act: false, + res: [], + }, impexp: "", lang: { format: "ddd D MMM", @@ -49,44 +53,44 @@ const app = new Vue({ return [[minLng, minLat], [maxLng, maxLat]] }, - search_nominatim: function (txt, f) { - if (txt == "") { - this.query.nominatim = []; - return Promise.resolve([]); - } - let bb = this.journey.leg_get(); - return api.query_nominatim(txt, this.compute_bb(), f).catch((err) => []).then((results) => { - results.forEach((r) => { - r.latlon = [parseFloat(r.lat), parseFloat(r.lon)]; - r.sname = r.display_name.split(",")[0]; - }); - this.query.nominatim = results; - }); - }, - search_flight: function (txt) { - if (txt == "") return; - this.querying.flight = true; - api.query_flight(txt).then((results) => { - if (results.results == "") { - this.query.flight = []; - this.querying.flight = false; - return; - } - this.query.flight = results.results; - this.querying.flight = false; - }); - }, - generate_icon: function (item, fcolor) { + generate_marker: function (item, fcolor) { return L.AwesomeMarkers.icon({ + iconAnchor: [12, 36], icon: api.icon_type(item) || "star", prefix: "fa", markerColor: fcolor || item.color || "blue", }).createIcon().outerHTML; }, + generate_rotation: function (index, list) { + if (index < 0 || index >= list.length) return 0; + let c0, c1; + if (index == 0) { + c0 = list[index] + c1 = list[index + 1] + } else if (index == list.length - 1) { + c0 = list[index - 1] + c1 = list[index] + } else { + c0 = list[index - 1]; + c1 = list[index + 1]; + } + const dx = c1[0] - c0[0]; + const dy = c1[1] - c0[1]; + const brng = Math.atan2(dy, dx); + return `rotate:${brng - Math.PI / 2}rad`;// * (180 / Math.PI); // Convert from radians to degrees + + }, + + generate_icon: function (item, fcolor, styling = "") { + return ``; + }, + save_data: function () { - this.impexp = JSON.stringify(this.journey.data).toEncoded(); - api.save(this.journey.id, this.journey.data); + api.throttle(() => { + this.impexp = JSON.stringify(this.journey.data).toEncoded(); + api.save(this.journey.id, this.journey.data); + }, 1000); }, import_data: function () { this.journey.data = Object.assign( @@ -119,12 +123,58 @@ const app = new Vue({ console.log(e); }, + 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) => { + this.query.act = true; + this.query.type = f; + return 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]; + }); + this.query.res = r; + this.query.act = false; + }); + } + }, + // break; + // case "flight": { + // return api.query_flight(q).then((r) => { + // // r.path = r.map(el => getGeoLine( + // // new L.LatLng(el.from_geo.lat, el.from_geo.lon), + // // new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 10_000_000 }).map(v => [v.lat, v.lng])); + // this.query.res = r; + // this.query.actt = false; + // }); + // } break; + // default: + // console.log(`Query not yet setup: ${k}`) + // } + // } + // }, + keyboardEvent(e) { if (e.which === 13) { } }, }, 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.search_flight = api.throttle(this.search_travel(), 2000) + window.addEventListener("keydown", (e) => { switch (e.key) { case "ArrowLeft": @@ -140,53 +190,18 @@ const app = new Vue({ api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); + // api.query_flight("qf1").then(r => { + // this.polyline.latlngs = r.map(el => getGeoLine( + // new L.LatLng(el.from_geo.lat, el.from_geo.lon), + // new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); + // console.log(this.polyline.latlngs) + // }); - api.query_flight("qf1").then(r => { - console.log(r) - this.polyline.latlngs = L.geodesic([ - new L.LatLng(r[0].from_geo.lat, r[0].from_geo.lon), - new L.LatLng(r[0].to_geo.lat, r[0].to_geo.lon)], {})._latlngs - }) - - this.debounceSave = api.throttle(this.save_data, 500); - this.debounceSearch = { - hotel: api.throttle((q) => { - this.querying.hotel = true; - this.search_nominatim( - q, - (r) => - r.type == "hotel" || r.type == "hostel" || r.type == "guest_house", - ).then((r) => { - this.querying.hotel = false; - }); - }, 500), - restaurants: api.throttle((q) => { - this.querying.food = true; - this.search_nominatim(q, (r) => api.is_restauration_type(r)).then( - (r) => { - this.querying.food = false; - }, - ); - }, 500), - places: api.throttle((q) => { - this.querying.place = true; - this.search_nominatim(q, (r) => api.is_attraction_type(r)).then((r) => { - this.querying.place = false; - }); - }, 500), - other: api.throttle((q) => { - this.querying.any = true; - this.search_nominatim(q, (r) => true).then((r) => { - this.querying.any = false; - }); - }, 500), - flight: api.throttle((q) => this.search_flight(q), 500), - }; }, watch: { journey: { handler: function (ndata, odata) { - this.debounceSave(); + this.save_data(); }, deep: true, }, -- 2.47.2 From d184068ae2c0d701463f8cb80605e555da1adc66 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:56:10 +0100 Subject: [PATCH 53/95] Add src/client/types/geoms.ts --- src/client/types/geoms.ts | 177 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 src/client/types/geoms.ts diff --git a/src/client/types/geoms.ts b/src/client/types/geoms.ts new file mode 100644 index 0000000..628c61b --- /dev/null +++ b/src/client/types/geoms.ts @@ -0,0 +1,177 @@ +// import L from "leaflet" + +const ellipsoid = { + a: 6378137, + b: 6356752.3142, + f: 1 / 298.257223563 +}; + +function mod(n: number, p: number): number { + const r = n % p; + return r < 0 ? r + p : r; +} + +function wrap(degrees: number, max = 360) { + if (-max <= degrees && degrees <= max) { + return degrees; + } else { + return mod(degrees + max, 2 * max) - max; + } +} + +function dist(src, dst, itr = 100, mit = true): number { + const p1 = src, + p2 = dst; + const φ1 = toRadians(p1.lat), + λ1 = toRadians(p1.lng); + const φ2 = toRadians(p2.lat), + λ2 = toRadians(p2.lng); + const π = Math.PI; + const ε = Number.EPSILON; + + // allow alternative ellipsoid to be specified + const { a, b, f } = ellipsoid; + + const dL = λ2 - λ1; // L = difference in longitude, U = reduced latitude, defined by tan U = (1-f)·tanφ. + const tanU1 = (1 - f) * Math.tan(φ1), + cosU1 = 1 / Math.sqrt(1 + tanU1 * tanU1), + sinU1 = tanU1 * cosU1; + const tanU2 = (1 - f) * Math.tan(φ2), + cosU2 = 1 / Math.sqrt(1 + tanU2 * tanU2), + sinU2 = tanU2 * cosU2; + + const antipodal = Math.abs(dL) > π / 2 || Math.abs(φ2 - φ1) > π / 2; + + let λ = dL, + sinλ: number | null = null, + cosλ: number | null = null; // λ = difference in longitude on an auxiliary sphere + let σ = antipodal ? π : 0, + sinσ = 0, + cosσ = antipodal ? -1 : 1, + sinSqσ: number | null = null; // σ = angular distance P₁ P₂ on the sphere + let cos2σₘ = 1; // σₘ = angular distance on the sphere from the equator to the midpoint of the line + let sinα: number | null = null, + cosSqα = 1; // α = azimuth of the geodesic at the equator + let C: number | null = null; + + let λʹ: number | null = null, + iterations = 0; + do { + sinλ = Math.sin(λ); + cosλ = Math.cos(λ); + sinSqσ = + cosU2 * sinλ * (cosU2 * sinλ) + + (cosU1 * sinU2 - sinU1 * cosU2 * cosλ) * (cosU1 * sinU2 - sinU1 * cosU2 * cosλ); + if (Math.abs(sinSqσ) < ε) { + break; // co-incident/antipodal points (falls back on λ/σ = L) + } + sinσ = Math.sqrt(sinSqσ); + cosσ = sinU1 * sinU2 + cosU1 * cosU2 * cosλ; + σ = Math.atan2(sinσ, cosσ); + sinα = (cosU1 * cosU2 * sinλ) / sinσ; + cosSqα = 1 - sinα * sinα; + cos2σₘ = cosSqα !== 0 ? cosσ - (2 * sinU1 * sinU2) / cosSqα : 0; // on equatorial line cos²α = 0 (§6) + C = (f / 16) * cosSqα * (4 + f * (4 - 3 * cosSqα)); + λʹ = λ; + λ = dL + (1 - C) * f * sinα * (σ + C * sinσ * (cos2σₘ + C * cosσ * (-1 + 2 * cos2σₘ * cos2σₘ))); + const iterationCheck = antipodal ? Math.abs(λ) - π : Math.abs(λ); + if (iterationCheck > π) { + throw new EvalError("λ > π"); + } + } while (Math.abs(λ - λʹ) > 1e-12 && ++iterations < itr); + + if (iterations >= itr) { + if (mit) { + return dist( + src, + new L.LatLng(dst.lat, dst.lng - 0.01), + itr, + mit + ); + } else { + throw new EvalError(`Inverse vincenty formula failed to converge after ${itr} iterations + (start=${src.lat}/${src.lng}; dest=${dst.lat}/${dst.lng})`); + } + } + const uSq = (cosSqα * (a * a - b * b)) / (b * b); + const A = 1 + (uSq / 16384) * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))); + const B = (uSq / 1024) * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))); + const Δσ = + B * + sinσ * + (cos2σₘ + + (B / 4) * + (cosσ * (-1 + 2 * cos2σₘ * cos2σₘ) - + (B / 6) * cos2σₘ * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σₘ * cos2σₘ))); + + const s = b * A * (σ - Δσ); // s = length of the geodesic + return s + +} + +function pointDistance(src: L.LatLng, dst: L.LatLng): number { + return dist( + new L.LatLng(src.lat, wrap(src.lng, 180)), + new L.LatLng(dst.lat, wrap(dst.lng, 180)) + ); +} + +function toRadians(degree: number): number { + return (degree * Math.PI) / 180; +} + +function toDegrees(radians: number): number { + return (radians * 180) / Math.PI; +} + +function midpoint(src: L.LatLng, dst: L.LatLng): L.LatLng { + // φm = atan2( sinφ1 + sinφ2, √( (cosφ1 + cosφ2⋅cosΔλ)² + cos²φ2⋅sin²Δλ ) ) + // λm = λ1 + atan2(cosφ2⋅sinΔλ, cosφ1 + cosφ2⋅cosΔλ) + // midpoint is sum of vectors to two points: mathforum.org/library/drmath/view/51822.html + + const φ1 = toRadians(src.lat); + const λ1 = toRadians(src.lng); + const φ2 = toRadians(dst.lat); + const Δλ = toRadians(dst.lng - src.lng); + + // get cartesian coordinates for the two points + const A = { x: Math.cos(φ1), y: 0, z: Math.sin(φ1) }; // place point A on prime meridian y=0 + const B = { x: Math.cos(φ2) * Math.cos(Δλ), y: Math.cos(φ2) * Math.sin(Δλ), z: Math.sin(φ2) }; + + // vector to midpoint is sum of vectors to two points (no need to normalise) + const C = { x: A.x + B.x, y: A.y + B.y, z: A.z + B.z }; + + const φm = Math.atan2(C.z, Math.sqrt(C.x * C.x + C.y * C.y)); + const λm = λ1 + Math.atan2(C.y, C.x); + + return new L.LatLng(toDegrees(φm), toDegrees(λm)); +} + +function recursiveMidPoint(src: L.LatLng, dst: L.LatLng, opt: { step?: number, dist?: number }): L.LatLng[] { + const geom: L.LatLng[] = [src, dst]; + const mp = midpoint(src, dst); + + if (opt.step != undefined) { + if (opt.step > 0) { + geom.splice(0, 1, ...recursiveMidPoint(src, mp, { step: opt.step - 1 })); + geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, { step: opt.step - 1 })); + } else { + geom.splice(1, 0, mp); + } + } else if (opt.dist != undefined) { + // console.log(src, dst, pointDistance(src, dst)) + if (pointDistance(src, dst) > opt.dist) { + geom.splice(0, 1, ...recursiveMidPoint(src, mp, { dist: opt.dist })); + geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, { dist: opt.dist })); + } else { + geom.splice(1, 0, mp); + } + } + console.log(geom) + return geom; +} + +export function getGeoLine(src: L.LatLng, dst: L.LatLng, opt: { step: number, dist: number }) { + + return recursiveMidPoint(src, dst, opt) +} \ No newline at end of file -- 2.47.2 From cbaaf4de5bb480a20b3887e68a5e985bf30b52da Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:56:21 +0100 Subject: [PATCH 54/95] Update src/client/types/wrapper.ts --- src/client/types/wrapper.ts | 59 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/client/types/wrapper.ts b/src/client/types/wrapper.ts index faf74ec..4a84a63 100644 --- a/src/client/types/wrapper.ts +++ b/src/client/types/wrapper.ts @@ -18,8 +18,8 @@ class journey_wrapper { leg_count(): number { return this.data.main.length; } - leg_len(idx: number = null): number { - let d = this.leg_get(idx == null ? this.sel_leg : idx).date_range; + leg_len(idx?: number): number { + let d = this.leg_get(idx == undefined ? this.sel_leg : idx).date_range; return d ? date_day_diff(d[0], d[1]) + 1 : 1; } add_leg(): void { @@ -32,20 +32,20 @@ class journey_wrapper { } tot_len(): number | "?" { if (this.leg_count() == 0) return 0; - try { - let d0 = this.leg_first().date_range[0] - let d1 = this.leg_last().date_range[1] + let lf = this.leg_first(), ll = this.leg_last(); + if (lf.date_range && ll.date_range) { + let d0 = lf.date_range[0] + let d1 = ll.date_range[1] return date_day_diff(d0, d1); - } catch { - return "?"; } + return "?"; } leg_sel(idx: number): void { this.sel_leg = idx; this.sel_day = 1; } - leg_get(idx: number = null): leg { - return this.data.main[idx == null ? this.sel_leg : idx] + leg_get(idx?: number): leg { + return this.data.main[idx != undefined ? idx : this.sel_leg] } leg_next(): void { this.sel_leg = Math.min(this.sel_leg + 1, this.leg_count() - 1); @@ -79,25 +79,26 @@ class journey_wrapper { } date_sel(): string { if (this.sel_day < 0) return "?"; - if (!this.leg_get().date_range) + let leg = this.leg_get() + if (!leg.date_range) return "?"; var date = new Date( - this.leg_get().date_range[0], + leg.date_range[0], ); date.setDate(date.getDate() + this.sel_day); return date.toLocal(); } date_tot() { if (this.leg_count() == 0) return ""; - try { - return `${this.leg_first().date_range[0].toLocal()} - ${this.leg_last().date_range[1].toLocal()}`; - } catch { - return "?"; - } + let lf = this.leg_first(), ll = this.leg_last(); + if (lf.date_range && ll.date_range) + return `${lf.date_range[0].toLocal()} - ${ll[1].toLocal()}`; + return "?"; } date_update(idx: number) { let date_range = this.leg_get(idx).date_range; + if (!date_range) return; let start_end = [0, 0]; let step_len = 0; @@ -110,11 +111,14 @@ class journey_wrapper { this.leg_get(i).date_range = [new Date(), new Date()]; start_end = [last_start.getDate() - step_len, last_start.getDate()]; } - this.leg_get(i).date_range[0].setTime(last_start.getTime()); - this.leg_get(i).date_range[0].setDate(start_end[0]); - this.leg_get(i).date_range[1].setTime(last_start.getTime()); - this.leg_get(i).date_range[1].setDate(start_end[1]); - last_start = this.leg_get(i).date_range[0]; + let leg = this.leg_get(i) + if (leg.date_range) { + leg.date_range[0].setTime(last_start.getTime()); + leg.date_range[0].setDate(start_end[0]); + leg.date_range[1].setTime(last_start.getTime()); + leg.date_range[1].setDate(start_end[1]); + last_start = leg.date_range[0]; + } } let last_end = date_range[1]; @@ -126,11 +130,14 @@ class journey_wrapper { this.leg_get(i).date_range = [new Date(), new Date()]; start_end = [last_end.getDate(), last_end.getDate() + step_len]; } - this.leg_get(i).date_range[0].setTime(last_end.getTime()); - this.leg_get(i).date_range[0].setDate(start_end[0]); - this.leg_get(i).date_range[1].setTime(last_end.getTime()); - this.leg_get(i).date_range[1].setDate(start_end[1]); - last_end = this.leg_get(i).date_range[1]; + let leg = this.leg_get(i) + if (leg.date_range) { + leg.date_range[0].setTime(last_end.getTime()); + leg.date_range[0].setDate(start_end[0]); + leg.date_range[1].setTime(last_end.getTime()); + leg.date_range[1].setDate(start_end[1]); + last_end = leg.date_range[1]; + } } } } -- 2.47.2 From 38f1300095729fe4fabed9860d630de9c649aad1 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:56:53 +0100 Subject: [PATCH 55/95] Update src/server/api_nominatim.ts -- 2.47.2 From 951172ede33c309d11c8bf57698119acf8d0a677 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:57:27 +0100 Subject: [PATCH 56/95] Update src/server/main.ts --- src/server/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/main.ts b/src/server/main.ts index f955c66..91ba4d3 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -5,7 +5,7 @@ import fastify_view from '@fastify/view'; import pug from 'pug' import { join as pathJoin } from "path"; -import api from "./router/api" +import api from "./api" const server = fastify(); //{ logger: true }); -- 2.47.2 From be46114dd3d04a42e33fa6daa01c81827cca962b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:58:11 +0100 Subject: [PATCH 57/95] Update template/module/journey_step.pug --- template/module/journey_step.pug | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/template/module/journey_step.pug b/template/module/journey_step.pug index c3498c1..f8b5652 100644 --- a/template/module/journey_step.pug +++ b/template/module/journey_step.pug @@ -40,15 +40,15 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") track-by="place_id", placeholder="Type to search", open-direction="bottom", - :options="query.nominatim", + :options="query.res", :searchable="true", - :loading="querying.hotel", + :loading="query.act && query.type=='hotel'", :internal-search="false", :clear-on-select="false", :options-limit="50", :limit="1", :max-height="600", - @search-change="debounceSearch.hotel" + @search-change="search_hotel" ) .row.text-center div @@ -60,15 +60,15 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") placeholder="Type to search", open-direction="bottom", :multiple="true", - :options="query.nominatim", + :options="query.res", :searchable="true", - :loading="querying.food", + :loading="query.act && query.type == 'restaurant'", :internal-search="false", :clear-on-select="false", :options-limit="50", :limit="10", :max-height="600", - @search-change="debounceSearch.restaurants" + @search-change="search_restaurant" ) .row.text-center div @@ -80,15 +80,15 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") placeholder="Type to search", open-direction="bottom", :multiple="true", - :options="query.nominatim", + :options="query.res", :searchable="true", - :loading="querying.place", + :loading="query.act && query.type=='place'", :internal-search="false", :clear-on-select="false", :options-limit="50", :limit="10", :max-height="600", - @search-change="debounceSearch.places" + @search-change="search_place" ) .row.text-center div -- 2.47.2 From f5b9ad05c7fcdd5fdb36a445d745f3bcf695ff27 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 16:58:21 +0100 Subject: [PATCH 58/95] Update template/module/map.pug --- template/module/map.pug | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/template/module/map.pug b/template/module/map.pug index b7da2cf..dc43d7f 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -14,7 +14,7 @@ l-map( :lat-lng="journey.data.main[idx].hotel.latlon" ) l-icon - div(v-html="generate_icon(journey.data.main[idx].hotel, 'darkblue')") + div(v-html="generate_marker(journey.data.main[idx].hotel, 'darkblue')") l-popup h1.row.text-medium.text-center {{ journey.data.main[idx].hotel.sname }} span.row.text-small.text-gray {{ journey.data.main[idx].hotel.display_name }} @@ -34,13 +34,13 @@ l-map( l-icon div( v-if="place.step == journey.sel_day", - v-html="generate_icon(place)" + v-html="generate_marker(place)" ) div( v-else-if="place.step == -1 || place.step == undefined", - v-html="generate_icon(place, 'gray')" + v-html="generate_marker(place, 'gray')" ) - div(v-else-if="journey_edit", v-html="generate_icon(place, 'lightgray')") + div(v-else-if="journey_edit", v-html="generate_marker(place, 'lightgray')") div(v-else) l-popup h1.row.text-medium.text-center {{ place.sname }} @@ -66,10 +66,10 @@ l-map( span.row.text-small.text-dark(v-else) {{ place.notes }} l-marker( v-for="place in journey.data.main[idx].places.restaurants", - :lat-lng.sync="place.latlon" + :lat-lng="place.latlon" ) l-icon - div(v-html="generate_icon(place, 'cadetblue')") + div(v-html="generate_marker(place, 'cadetblue')") l-popup h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} @@ -83,4 +83,11 @@ l-map( ) span.row.text-small.text-dark(v-else) {{ place.notes }} - l-polyline(:lat-lngs="polyline.latlngs" :color="polyline.color") \ No newline at end of file + div(v-for= "latlngs in polyline.latlngs") + l-polyline(:lat-lngs="polyline.latlngs" :color="polyline.color") + l-marker( + v-for="(place, index) in latlngs", + :lat-lng="place" + ) + l-icon + div(v-html="generate_icon('plane', polyline.color, generate_rotation(index,latlngs))") \ No newline at end of file -- 2.47.2 From b7b87507e3dbf534c67b900f5e91a7ccfe31dd6f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Wed, 26 Feb 2025 17:01:07 +0100 Subject: [PATCH 59/95] Update src/client/types/geom.ts --- src/client/types/{geoms.ts => geom.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/client/types/{geoms.ts => geom.ts} (100%) diff --git a/src/client/types/geoms.ts b/src/client/types/geom.ts similarity index 100% rename from src/client/types/geoms.ts rename to src/client/types/geom.ts -- 2.47.2 From f1c702bc14b088af2012820744bc5140296591a1 Mon Sep 17 00:00:00 2001 From: soraefir Date: Thu, 27 Feb 2025 00:55:37 +0100 Subject: [PATCH 60/95] Wip --- .gitignore | 1 + package.json | 9 +- public/css/index.css | 247 +++++++++++++++-- src/client/main.ts | 2 +- src/client/old.js | 332 +++++++++++------------ src/client/types/geom.ts | 3 - src/client/types/wrapper.ts | 2 +- src/client/vue.ts | 192 ++++++++++++++ src/server/api.ts | 5 +- template/module/foot.pug | 12 +- template/module/map.pug | 33 ++- tsconfig-client.json | 19 +- yarn.lock | 510 +++++++++++++++++++++++++++++++++++- 13 files changed, 1126 insertions(+), 241 deletions(-) create mode 100644 src/client/vue.ts diff --git a/.gitignore b/.gitignore index 9d3debb..b60d94f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ db/ public/*.js public/*.map .yarnrc.yml +build/ \ No newline at end of file diff --git a/package.json b/package.json index ea3c71d..9aeb0f2 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,14 @@ "esbuild": "^0.25.0", "fastify": "^5.2.1", "jsdom": "^26.0.0", + "leaflet": "^1.9.4", "nodemon": "^3.0.1", "prettier": "^3.5.2", "pug": "^3.0.2", - "undici": "^7.3.0" + "undici": "^7.3.0", + "vue": "2", + "vue-multiselect": "2", + "vue-textarea-autosize": "^1.1.1", + "vue2-leaflet": "^2.7.1" } -} \ No newline at end of file +} diff --git a/public/css/index.css b/public/css/index.css index a04cbc2..73a2fcb 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -253,7 +253,7 @@ } } -.section + .section { +.section+.section { padding-top: 0; } @@ -424,10 +424,10 @@ a:focus { margin-bottom: 0 !important; } -.text-withSubtitle + .text-huge, -.text-withSubtitle + .text-big, -.text-withSubtitle + .text-medium, -.text-withSubtitle + .text-small { +.text-withSubtitle+.text-huge, +.text-withSubtitle+.text-big, +.text-withSubtitle+.text-medium, +.text-withSubtitle+.text-small { margin-top: 0.5em; } @@ -858,7 +858,7 @@ input:-webkit-autofill { display: none; } -.checkbox input[type="checkbox"]:checked + label::after { +.checkbox input[type="checkbox"]:checked+label::after { -webkit-animation: checkboxAndRadioAnimation 0.25s; animation: checkboxAndRadioAnimation 0.25s; content: ""; @@ -866,7 +866,7 @@ input:-webkit-autofill { transform: scale(1) rotate(45deg); } -.checkbox input[type="checkbox"] + label { +.checkbox input[type="checkbox"]+label { display: block; overflow: hidden; padding-left: 30px; @@ -874,7 +874,7 @@ input:-webkit-autofill { white-space: nowrap; } -.checkbox input[type="checkbox"] + label::before { +.checkbox input[type="checkbox"]+label::before { background-color: #eceff1; border: 1px solid #d5d9db; border-radius: 3px; @@ -888,7 +888,7 @@ input:-webkit-autofill { width: 20px; } -.checkbox input[type="checkbox"] + label::after { +.checkbox input[type="checkbox"]+label::after { border-bottom: 3px solid #03a9f4; border-right: 3px solid #03a9f4; display: block; @@ -911,7 +911,7 @@ input:-webkit-autofill { display: none; } -.radio input[type="radio"]:checked + label::after { +.radio input[type="radio"]:checked+label::after { -webkit-animation: checkboxAndRadioAnimation 0.25s; animation: checkboxAndRadioAnimation 0.25s; content: ""; @@ -919,7 +919,7 @@ input:-webkit-autofill { transform: scale(1) rotate(45deg); } -.radio input[type="radio"] + label { +.radio input[type="radio"]+label { display: block; overflow: hidden; padding-left: 30px; @@ -927,7 +927,7 @@ input:-webkit-autofill { white-space: nowrap; } -.radio input[type="radio"] + label::before { +.radio input[type="radio"]+label::before { background-color: #eceff1; border: 1px solid #d5d9db; border-radius: 20px; @@ -941,7 +941,7 @@ input:-webkit-autofill { width: 20px; } -.radio input[type="radio"] + label::after { +.radio input[type="radio"]+label::after { background-color: #03a9f4; border-radius: 20px; display: block; @@ -960,10 +960,12 @@ input:-webkit-autofill { -webkit-transform: scale(0) rotate(45deg); transform: scale(0) rotate(45deg); } + 50% { -webkit-transform: scale(1.5) rotate(45deg); transform: scale(1.5) rotate(45deg); } + 100% { -webkit-transform: scale(1) rotate(45deg); transform: scale(1) rotate(45deg); @@ -975,10 +977,12 @@ input:-webkit-autofill { -webkit-transform: scale(0) rotate(45deg); transform: scale(0) rotate(45deg); } + 50% { -webkit-transform: scale(1.5) rotate(45deg); transform: scale(1.5) rotate(45deg); } + 100% { -webkit-transform: scale(1) rotate(45deg); transform: scale(1) rotate(45deg); @@ -1140,18 +1144,23 @@ input:-webkit-autofill { left: -300px; width: 30%; } + 50% { width: 30%; } + 70% { width: 70%; } + 80% { left: 50%; } + 95% { left: 120%; } + to { left: 100%; } @@ -1162,18 +1171,23 @@ input:-webkit-autofill { left: -300px; width: 30%; } + 50% { width: 30%; } + 70% { width: 70%; } + 80% { left: 50%; } + 95% { left: 120%; } + to { left: 100%; } @@ -1254,18 +1268,22 @@ input:-webkit-autofill { -webkit-transform: rotate(0); transform: rotate(0); } + 25% { -webkit-transform: rotate(90deg); transform: rotate(90deg); } + 50% { -webkit-transform: rotate(180deg); transform: rotate(180deg); } + 75% { -webkit-transform: rotate(270deg); transform: rotate(270deg); } + 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); @@ -1277,18 +1295,22 @@ input:-webkit-autofill { -webkit-transform: rotate(0); transform: rotate(0); } + 25% { -webkit-transform: rotate(90deg); transform: rotate(90deg); } + 50% { -webkit-transform: rotate(180deg); transform: rotate(180deg); } + 75% { -webkit-transform: rotate(270deg); transform: rotate(270deg); } + 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); @@ -1300,10 +1322,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(4.5px, 4.5px, 0); transform: translate3d(4.5px, 4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1315,10 +1339,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(4.5px, 4.5px, 0); transform: translate3d(4.5px, 4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1330,10 +1356,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(-4.5px, 4.5px, 0); transform: translate3d(-4.5px, 4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1345,10 +1373,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(-4.5px, 4.5px, 0); transform: translate3d(-4.5px, 4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1360,10 +1390,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(-4.5px, -4.5px, 0); transform: translate3d(-4.5px, -4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1375,10 +1407,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(-4.5px, -4.5px, 0); transform: translate3d(-4.5px, -4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1390,10 +1424,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(4.5px, -4.5px, 0); transform: translate3d(4.5px, -4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1405,10 +1441,12 @@ input:-webkit-autofill { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + 50% { -webkit-transform: translate3d(4.5px, -4.5px, 0); transform: translate3d(4.5px, -4.5px, 0); } + 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); @@ -1641,6 +1679,7 @@ input:-webkit-autofill { } @media (min-width: 576px) { + .table--responsive th, .table--responsive td { border-top: 1px solid #d5d9db; @@ -1797,8 +1836,8 @@ input:-webkit-autofill { margin-right: 0; } -.no-gutters > .col, -.no-gutters > [class*="col-"] { +.no-gutters>.col, +.no-gutters>[class*="col-"] { padding-left: 0; padding-right: 0; } @@ -2054,131 +2093,169 @@ input:-webkit-autofill { flex-grow: 1; max-width: 100%; } + .col-sm-auto { flex: 0 0 auto; width: auto; max-width: none; } + .col-sm-1 { flex: 0 0 8.33333%; max-width: 8.33333%; } + .col-sm-2 { flex: 0 0 16.66667%; max-width: 16.66667%; } + .col-sm-3 { flex: 0 0 25%; max-width: 25%; } + .col-sm-4 { flex: 0 0 33.33333%; max-width: 33.33333%; } + .col-sm-5 { flex: 0 0 41.66667%; max-width: 41.66667%; } + .col-sm-6 { flex: 0 0 50%; max-width: 50%; } + .col-sm-7 { flex: 0 0 58.33333%; max-width: 58.33333%; } + .col-sm-8 { flex: 0 0 66.66667%; max-width: 66.66667%; } + .col-sm-9 { flex: 0 0 75%; max-width: 75%; } + .col-sm-10 { flex: 0 0 83.33333%; max-width: 83.33333%; } + .col-sm-11 { flex: 0 0 91.66667%; max-width: 91.66667%; } + .col-sm-12 { flex: 0 0 100%; max-width: 100%; } + .order-sm-first { order: -1; } + .order-sm-1 { order: 1; } + .order-sm-2 { order: 2; } + .order-sm-3 { order: 3; } + .order-sm-4 { order: 4; } + .order-sm-5 { order: 5; } + .order-sm-6 { order: 6; } + .order-sm-7 { order: 7; } + .order-sm-8 { order: 8; } + .order-sm-9 { order: 9; } + .order-sm-10 { order: 10; } + .order-sm-11 { order: 11; } + .order-sm-12 { order: 12; } + .offset-sm-0 { margin-left: 0; } + .offset-sm-1 { margin-left: 8.33333%; } + .offset-sm-2 { margin-left: 16.66667%; } + .offset-sm-3 { margin-left: 25%; } + .offset-sm-4 { margin-left: 33.33333%; } + .offset-sm-5 { margin-left: 41.66667%; } + .offset-sm-6 { margin-left: 50%; } + .offset-sm-7 { margin-left: 58.33333%; } + .offset-sm-8 { margin-left: 66.66667%; } + .offset-sm-9 { margin-left: 75%; } + .offset-sm-10 { margin-left: 83.33333%; } + .offset-sm-11 { margin-left: 91.66667%; } @@ -2190,131 +2267,169 @@ input:-webkit-autofill { flex-grow: 1; max-width: 100%; } + .col-md-auto { flex: 0 0 auto; width: auto; max-width: none; } + .col-md-1 { flex: 0 0 8.33333%; max-width: 8.33333%; } + .col-md-2 { flex: 0 0 16.66667%; max-width: 16.66667%; } + .col-md-3 { flex: 0 0 25%; max-width: 25%; } + .col-md-4 { flex: 0 0 33.33333%; max-width: 33.33333%; } + .col-md-5 { flex: 0 0 41.66667%; max-width: 41.66667%; } + .col-md-6 { flex: 0 0 50%; max-width: 50%; } + .col-md-7 { flex: 0 0 58.33333%; max-width: 58.33333%; } + .col-md-8 { flex: 0 0 66.66667%; max-width: 66.66667%; } + .col-md-9 { flex: 0 0 75%; max-width: 75%; } + .col-md-10 { flex: 0 0 83.33333%; max-width: 83.33333%; } + .col-md-11 { flex: 0 0 91.66667%; max-width: 91.66667%; } + .col-md-12 { flex: 0 0 100%; max-width: 100%; } + .order-md-first { order: -1; } + .order-md-1 { order: 1; } + .order-md-2 { order: 2; } + .order-md-3 { order: 3; } + .order-md-4 { order: 4; } + .order-md-5 { order: 5; } + .order-md-6 { order: 6; } + .order-md-7 { order: 7; } + .order-md-8 { order: 8; } + .order-md-9 { order: 9; } + .order-md-10 { order: 10; } + .order-md-11 { order: 11; } + .order-md-12 { order: 12; } + .offset-md-0 { margin-left: 0; } + .offset-md-1 { margin-left: 8.33333%; } + .offset-md-2 { margin-left: 16.66667%; } + .offset-md-3 { margin-left: 25%; } + .offset-md-4 { margin-left: 33.33333%; } + .offset-md-5 { margin-left: 41.66667%; } + .offset-md-6 { margin-left: 50%; } + .offset-md-7 { margin-left: 58.33333%; } + .offset-md-8 { margin-left: 66.66667%; } + .offset-md-9 { margin-left: 75%; } + .offset-md-10 { margin-left: 83.33333%; } + .offset-md-11 { margin-left: 91.66667%; } @@ -2326,131 +2441,169 @@ input:-webkit-autofill { flex-grow: 1; max-width: 100%; } + .col-lg-auto { flex: 0 0 auto; width: auto; max-width: none; } + .col-lg-1 { flex: 0 0 8.33333%; max-width: 8.33333%; } + .col-lg-2 { flex: 0 0 16.66667%; max-width: 16.66667%; } + .col-lg-3 { flex: 0 0 25%; max-width: 25%; } + .col-lg-4 { flex: 0 0 33.33333%; max-width: 33.33333%; } + .col-lg-5 { flex: 0 0 41.66667%; max-width: 41.66667%; } + .col-lg-6 { flex: 0 0 50%; max-width: 50%; } + .col-lg-7 { flex: 0 0 58.33333%; max-width: 58.33333%; } + .col-lg-8 { flex: 0 0 66.66667%; max-width: 66.66667%; } + .col-lg-9 { flex: 0 0 75%; max-width: 75%; } + .col-lg-10 { flex: 0 0 83.33333%; max-width: 83.33333%; } + .col-lg-11 { flex: 0 0 91.66667%; max-width: 91.66667%; } + .col-lg-12 { flex: 0 0 100%; max-width: 100%; } + .order-lg-first { order: -1; } + .order-lg-1 { order: 1; } + .order-lg-2 { order: 2; } + .order-lg-3 { order: 3; } + .order-lg-4 { order: 4; } + .order-lg-5 { order: 5; } + .order-lg-6 { order: 6; } + .order-lg-7 { order: 7; } + .order-lg-8 { order: 8; } + .order-lg-9 { order: 9; } + .order-lg-10 { order: 10; } + .order-lg-11 { order: 11; } + .order-lg-12 { order: 12; } + .offset-lg-0 { margin-left: 0; } + .offset-lg-1 { margin-left: 8.33333%; } + .offset-lg-2 { margin-left: 16.66667%; } + .offset-lg-3 { margin-left: 25%; } + .offset-lg-4 { margin-left: 33.33333%; } + .offset-lg-5 { margin-left: 41.66667%; } + .offset-lg-6 { margin-left: 50%; } + .offset-lg-7 { margin-left: 58.33333%; } + .offset-lg-8 { margin-left: 66.66667%; } + .offset-lg-9 { margin-left: 75%; } + .offset-lg-10 { margin-left: 83.33333%; } + .offset-lg-11 { margin-left: 91.66667%; } @@ -2462,131 +2615,169 @@ input:-webkit-autofill { flex-grow: 1; max-width: 100%; } + .col-xl-auto { flex: 0 0 auto; width: auto; max-width: none; } + .col-xl-1 { flex: 0 0 8.33333%; max-width: 8.33333%; } + .col-xl-2 { flex: 0 0 16.66667%; max-width: 16.66667%; } + .col-xl-3 { flex: 0 0 25%; max-width: 25%; } + .col-xl-4 { flex: 0 0 33.33333%; max-width: 33.33333%; } + .col-xl-5 { flex: 0 0 41.66667%; max-width: 41.66667%; } + .col-xl-6 { flex: 0 0 50%; max-width: 50%; } + .col-xl-7 { flex: 0 0 58.33333%; max-width: 58.33333%; } + .col-xl-8 { flex: 0 0 66.66667%; max-width: 66.66667%; } + .col-xl-9 { flex: 0 0 75%; max-width: 75%; } + .col-xl-10 { flex: 0 0 83.33333%; max-width: 83.33333%; } + .col-xl-11 { flex: 0 0 91.66667%; max-width: 91.66667%; } + .col-xl-12 { flex: 0 0 100%; max-width: 100%; } + .order-xl-first { order: -1; } + .order-xl-1 { order: 1; } + .order-xl-2 { order: 2; } + .order-xl-3 { order: 3; } + .order-xl-4 { order: 4; } + .order-xl-5 { order: 5; } + .order-xl-6 { order: 6; } + .order-xl-7 { order: 7; } + .order-xl-8 { order: 8; } + .order-xl-9 { order: 9; } + .order-xl-10 { order: 10; } + .order-xl-11 { order: 11; } + .order-xl-12 { order: 12; } + .offset-xl-0 { margin-left: 0; } + .offset-xl-1 { margin-left: 8.33333%; } + .offset-xl-2 { margin-left: 16.66667%; } + .offset-xl-3 { margin-left: 25%; } + .offset-xl-4 { margin-left: 33.33333%; } + .offset-xl-5 { margin-left: 41.66667%; } + .offset-xl-6 { margin-left: 50%; } + .offset-xl-7 { margin-left: 58.33333%; } + .offset-xl-8 { margin-left: 66.66667%; } + .offset-xl-9 { margin-left: 75%; } + .offset-xl-10 { margin-left: 83.33333%; } + .offset-xl-11 { margin-left: 91.66667%; } @@ -2643,10 +2834,12 @@ body { } @media screen and (max-width: 550px) { + .example1, .example2 { max-width: 100%; } + .example1 img, .example2 img { width: 100% !important; @@ -2657,7 +2850,7 @@ body { font-size: 14px; } -:not(pre) > code[class*="language-"], +:not(pre)>code[class*="language-"], pre[class*="language-"] { background-color: #eceff1 !important; } @@ -2926,3 +3119,25 @@ li { display: block; padding: 0.5rem 1.5rem; } + + + + +.custom-pin { + position: relative; + width: 32px; + height: 32px; + background-color: #ff5733; + border-radius: 50%; +} + +.custom-pin::after { + content: ""; + position: absolute; + bottom: -10px; + left: 50%; + transform: translateX(-50%); + border-left: 10px solid transparent; + border-right: 10px solid transparent; + background-color: 15px solid #ff5733; +} \ No newline at end of file diff --git a/src/client/main.ts b/src/client/main.ts index 10b982f..a443417 100644 --- a/src/client/main.ts +++ b/src/client/main.ts @@ -1,4 +1,4 @@ import "./types/ext"; import "./types/format"; import "./api"; -import "./old.js"; +import "./vue"; diff --git a/src/client/old.js b/src/client/old.js index d92a4d4..42cb379 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -16,194 +16,172 @@ Vue.component("multiselect", window.VueMultiselect.default); Vue.use(window.VueTextareaAutosize); const app = new Vue({ - el: "#app", - data: { - journey_edit: - ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, - journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), + el: "#app", + data: { + journey_edit: + ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, + journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), - query: { - type: "", - act: false, - res: [], - }, - impexp: "", - lang: { - format: "ddd D MMM", - formatLocale: { - firstDayOfWeek: 1, - }, - monthBeforeYear: true, - }, - polyline: { - latlngs: [], - color: 'green' - } - }, - methods: { - start_journey: function () { window.location.href = "/" + this.journey.id }, + query: { + type: "", + act: false, + res: [], + }, + impexp: "", + lang: { + format: "ddd D MMM", + formatLocale: { + firstDayOfWeek: 1, + }, + monthBeforeYear: true, + }, + polyline: { + latlngs: [], + color: 'green' + } + }, + methods: { + start_journey: function () { window.location.href = "/" + this.journey.id }, - compute_bb: function () { - const map = this.$refs.map[0].mapObject; - var bounds = map.getBounds(); - var minLng = bounds.getSouthWest().lng; - var minLat = bounds.getSouthWest().lat; - var maxLng = bounds.getNorthEast().lng; - var maxLat = bounds.getNorthEast().lat; - return [[minLng, minLat], [maxLng, maxLat]] - }, + compute_bb: function () { + const bounds = this.$refs.map[0].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 L.AwesomeMarkers.icon({ - iconAnchor: [12, 36], - icon: api.icon_type(item) || "star", - prefix: "fa", - markerColor: fcolor || item.color || "blue", - }).createIcon().outerHTML; - }, + }, + generate_marker: function (item, fcolor) { + return ` +
+ + + + ` + }, + generate_icon: function (item, fcolor, styling = "") { + return ``; + }, - generate_rotation: function (index, list) { - if (index < 0 || index >= list.length) return 0; - let c0, c1; - if (index == 0) { - c0 = list[index] - c1 = list[index + 1] - } else if (index == list.length - 1) { - c0 = list[index - 1] - c1 = list[index] - } else { - c0 = list[index - 1]; - c1 = list[index + 1]; - } - const dx = c1[0] - c0[0]; - const dy = c1[1] - c0[1]; - const brng = Math.atan2(dy, dx); - return `rotate:${brng - Math.PI / 2}rad`;// * (180 / Math.PI); // Convert from radians to degrees - }, + 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); + }, - generate_icon: function (item, fcolor, styling = "") { - return ``; - }, + 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; + } + }, - save_data: function () { - api.throttle(() => { - this.impexp = JSON.stringify(this.journey.data).toEncoded(); - api.save(this.journey.id, this.journey.data); - }, 1000); - }, - 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); - }, + search_nominatim: function (f) { + return (q) => { + this.query.act = true; + this.query.type = f; + return 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]; + }); + this.query.res = r; + this.query.act = false; + return r + }); + } + }, + search_travel: function (f) { + return (q) => { + this.query.act = true; + this.query.type = f; + return api.query_flight(q).then((r) => { + r.forEach(el => el.path = getGeoLine( + new L.LatLng(el.from_geo.lat, el.from_geo.lon), + new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); + this.query.res = r; + this.query.act = false; + return r; + }); + } + }, - 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; - } - }, + keyboardEvent(e) { + if (e.which === 13) { + } + }, + }, + created: function () { - search_nominatim: function (f) { - return (q) => { - this.query.act = true; - this.query.type = f; - return 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]; - }); - this.query.res = r; - this.query.act = false; - }); - } - }, - // break; - // case "flight": { - // return api.query_flight(q).then((r) => { - // // r.path = r.map(el => getGeoLine( - // // new L.LatLng(el.from_geo.lat, el.from_geo.lon), - // // new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 10_000_000 }).map(v => [v.lat, v.lng])); - // this.query.res = r; - // this.query.actt = false; - // }); - // } break; - // default: - // console.log(`Query not yet setup: ${k}`) - // } - // } - // }, + 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) - keyboardEvent(e) { - if (e.which === 13) { - } - }, - }, - created: function () { + 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); + } + }); - 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.search_flight = api.throttle(this.search_travel(), 2000) + api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); - 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); - } - }); + this.search_travel("flight")("qf1").then(r => { + this.polyline.latlngs = r.map(e => e.path) + }); - api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); - - // api.query_flight("qf1").then(r => { - // this.polyline.latlngs = r.map(el => getGeoLine( - // new L.LatLng(el.from_geo.lat, el.from_geo.lon), - // new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); - // console.log(this.polyline.latlngs) - // }); - - }, - watch: { - journey: { - handler: function (ndata, odata) { - this.save_data(); - }, - deep: true, - }, - }, + }, + watch: { + journey: { + handler: function (ndata, odata) { + this.save_data(); + }, + deep: true, + }, + }, }); diff --git a/src/client/types/geom.ts b/src/client/types/geom.ts index 628c61b..99fb18d 100644 --- a/src/client/types/geom.ts +++ b/src/client/types/geom.ts @@ -159,7 +159,6 @@ function recursiveMidPoint(src: L.LatLng, dst: L.LatLng, opt: { step?: number, d geom.splice(1, 0, mp); } } else if (opt.dist != undefined) { - // console.log(src, dst, pointDistance(src, dst)) if (pointDistance(src, dst) > opt.dist) { geom.splice(0, 1, ...recursiveMidPoint(src, mp, { dist: opt.dist })); geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, { dist: opt.dist })); @@ -167,11 +166,9 @@ function recursiveMidPoint(src: L.LatLng, dst: L.LatLng, opt: { step?: number, d geom.splice(1, 0, mp); } } - console.log(geom) return geom; } export function getGeoLine(src: L.LatLng, dst: L.LatLng, opt: { step: number, dist: number }) { - return recursiveMidPoint(src, dst, opt) } \ No newline at end of file diff --git a/src/client/types/wrapper.ts b/src/client/types/wrapper.ts index 4a84a63..486f6e4 100644 --- a/src/client/types/wrapper.ts +++ b/src/client/types/wrapper.ts @@ -9,7 +9,7 @@ class journey_wrapper { sel_leg: number = 0; sel_day: number = 0; - constructor(id: string) { + constructor(id: String) { this.id = id; } diff --git a/src/client/vue.ts b/src/client/vue.ts new file mode 100644 index 0000000..731f8fe --- /dev/null +++ b/src/client/vue.ts @@ -0,0 +1,192 @@ + +import * as api from "./api"; +import journey_wrapper from "./types/wrapper"; +import { migrator } from "./types/migration"; +import { getGeoLine } from "./types/geom"; + +import Vue from "vue"; +import { LMap, LTileLayer, LMarker, LIcon, LPopup, LTooltip, LPolyline, LControlScale } from "vue2-leaflet"; +import Multiselect from 'vue-multiselect' +import TextareaAutosize from 'vue-textarea-autosize' + +Vue.component("l-map", LMap); +Vue.component("l-tile-layer", LTileLayer); +Vue.component("l-marker", LMarker); +Vue.component("l-icon", LIcon); +Vue.component("l-popup", LPopup); +Vue.component("l-tooltip", LTooltip); +Vue.component("l-polyline", LPolyline); +Vue.component("l-control-scale", LControlScale); +Vue.component("multiselect", Multiselect); +Vue.use(TextareaAutosize); + +const app = new Vue({ + el: "#app", + data: { + journey_edit: + ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, + journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), + + query: { + type: "", + act: false, + res: [], + }, + impexp: "", + lang: { + format: "ddd D MMM", + formatLocale: { + firstDayOfWeek: 1, + }, + monthBeforeYear: true, + }, + polyline: { + latlngs: [], + color: 'green' + } + }, + methods: { + start_journey: function () { window.location.href = "/" + this.journey.id }, + + compute_bb: function () { + const bounds = this.$refs.map[0].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 = "") { + 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); + }, + + 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) => { + this.query.act = true; + this.query.type = f; + return 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]; + }); + this.query.res = r; + this.query.act = false; + return r + }); + } + }, + search_travel: function (f) { + return (q) => { + this.query.act = true; + this.query.type = f; + return api.query_flight(q).then((r) => { + r.forEach(el => el.path = getGeoLine( + new L.LatLng(el.from_geo.lat, el.from_geo.lon), + new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); + this.query.res = r; + this.query.act = false; + return r; + }); + } + }, + + keyboardEvent(e) { + if (e.which === 13) { + } + }, + }, + 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))); + + this.search_travel("flight")("qf1").then(r => { + this.polyline.latlngs = r.map(e => e.path) + }); + + }, + watch: { + journey: { + handler: function (ndata, odata) { + this.save_data(); + }, + deep: true, + }, + }, +}); diff --git a/src/server/api.ts b/src/server/api.ts index 88de4d6..9b8b531 100644 --- a/src/server/api.ts +++ b/src/server/api.ts @@ -1,10 +1,9 @@ -import { FastifyInstance } from 'fastify/types/instance'; -import { ProxyAgent, setGlobalDispatcher } from 'undici'; +//import { ProxyAgent, setGlobalDispatcher } from 'undici'; import { flight_get_data } from './api_flight' import { nominatim_get_data } from './api_nominatim'; -setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY as string)); +//setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY as string)); export default function (server, opts, done) { diff --git a/template/module/foot.pug b/template/module/foot.pug index 991d48e..c415501 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -1,13 +1,11 @@ script(src="https://unpkg.com/leaflet") -script(src="https://unpkg.com/leaflet.awesome-markers") -script(src="https://unpkg.com/leaflet.geodesic") script(src="https://unpkg.com/sortablejs") -script(src="https://unpkg.com/vue@2") -script(src="https://unpkg.com/vue2-datepicker") -script(src="https://unpkg.com/vue-textarea-autosize") -script(src="https://unpkg.com/vue-multiselect@2") -script(src="https://unpkg.com/vue2-leaflet") +//- script(src="https://unpkg.com/vue@2") +//- script(src="https://unpkg.com/vue2-datepicker") +//- script(src="https://unpkg.com/vue-textarea-autosize") +//- script(src="https://unpkg.com/vue-multiselect@2") +//- script(src="https://unpkg.com/vue2-leaflet") script(src="https://unpkg.com/vuedraggable") script(src="/public/main.js", type="text/javascript", charset="utf-8") footer.bg-dark diff --git a/template/module/map.pug b/template/module/map.pug index dc43d7f..4c62135 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -13,8 +13,7 @@ l-map( v-if="journey.data.main[idx].hotel", :lat-lng="journey.data.main[idx].hotel.latlon" ) - l-icon - div(v-html="generate_marker(journey.data.main[idx].hotel, 'darkblue')") + l-icon(v-html="generate_marker(journey.data.main[idx].hotel, 'darkblue')") l-popup h1.row.text-medium.text-center {{ journey.data.main[idx].hotel.sname }} span.row.text-small.text-gray {{ journey.data.main[idx].hotel.display_name }} @@ -28,20 +27,20 @@ l-map( ) span.row.text-small.text-white(v-else) {{ journey.data.main[idx].hotel.notes }} l-marker( - v-for="place in journey.data.main[idx].places.activities", + v-for="(place, index) in journey.data.main[idx].places.activities", + :key="'activities'+index", :lat-lng="place.latlon" ) - l-icon - div( + l-icon( v-if="place.step == journey.sel_day", v-html="generate_marker(place)" ) - div( + l-icon( v-else-if="place.step == -1 || place.step == undefined", v-html="generate_marker(place, 'gray')" ) - div(v-else-if="journey_edit", v-html="generate_marker(place, 'lightgray')") - div(v-else) + l-icon(v-else-if="journey_edit", v-html="generate_marker(place, 'lightgray')") + l-icon(v-else) l-popup h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} @@ -65,20 +64,20 @@ l-map( ) + span.row.text-small.text-dark(v-else) {{ place.notes }} l-marker( - v-for="place in journey.data.main[idx].places.restaurants", + v-for="(place, index) in journey.data.main[idx].places.restaurants", + :key="'restaurants'+index" :lat-lng="place.latlon" ) - l-icon - div(v-html="generate_marker(place, 'cadetblue')") + l-icon(v-html="generate_marker(place, 'cadetblue')") l-popup h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} span(v-if="journey_edit") .row.input textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", - v-model="place.notes", - :min-height="30", + placeholder="Notes" + v-model="place.notes" + :min-height="30" :max-height="350" ) span.row.text-small.text-dark(v-else) {{ place.notes }} @@ -86,8 +85,8 @@ l-map( div(v-for= "latlngs in polyline.latlngs") l-polyline(:lat-lngs="polyline.latlngs" :color="polyline.color") l-marker( - v-for="(place, index) in latlngs", + v-for="(place, index) in latlngs" + :key="'plane'+index" :lat-lng="place" ) - l-icon - div(v-html="generate_icon('plane', polyline.color, generate_rotation(index,latlngs))") \ No newline at end of file + l-icon(v-html="generate_icon('plane', polyline.color, generate_rotation(index,latlngs))") \ No newline at end of file diff --git a/tsconfig-client.json b/tsconfig-client.json index 6a54986..04b8e7b 100644 --- a/tsconfig-client.json +++ b/tsconfig-client.json @@ -1,12 +1,17 @@ { - "compilerOptions": { "target": "esnext", - "typeRoots": ["./node_modules/@types", "./types/ext"], - "lib": ["esnext", "DOM"], - "noEmit": true, // Disable emitting output (use esbuild to handle this) - "skipLibCheck": true, // Skip type checking of all declaration files (*.d.ts) - "strict": false, // Disable strict type checks if needed + "typeRoots": [ + "./node_modules/@types", + "./types/ext" + ], + "lib": [ + "esnext", + "DOM" + ], + "noEmit": true, // Disable emitting output (use esbuild to handle this) + "skipLibCheck": true, // Skip type checking of all declaration files (*.d.ts) + "strict": false, // Disable strict type checks if needed "moduleResolution": "node", } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9d38d61..8bc6ed8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,19 @@ __metadata: version: 8 cacheKey: 10c0 +"@asamuzakjp/css-color@npm:^2.8.2": + version: 2.8.3 + resolution: "@asamuzakjp/css-color@npm:2.8.3" + dependencies: + "@csstools/css-calc": "npm:^2.1.1" + "@csstools/css-color-parser": "npm:^3.0.7" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + lru-cache: "npm:^10.4.3" + checksum: 10c0/e108c92ee5de6d8510c9aaca8375c0aeab730dc9b6d4bd287aea2a0379cfbaa09f0814dcacb3e2ddc5c79d7deedf3f82ec8d1ce0effd4a8fac8415b1fe553798 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-string-parser@npm:7.25.9" @@ -19,7 +32,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": +"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": version: 7.26.9 resolution: "@babel/parser@npm:7.26.9" dependencies: @@ -40,6 +53,52 @@ __metadata: languageName: node linkType: hard +"@csstools/color-helpers@npm:^5.0.2": + version: 5.0.2 + resolution: "@csstools/color-helpers@npm:5.0.2" + checksum: 10c0/bebaddb28b9eb58b0449edd5d0c0318fa88f3cb079602ee27e88c9118070d666dcc4e09a5aa936aba2fde6ba419922ade07b7b506af97dd7051abd08dfb2959b + languageName: node + linkType: hard + +"@csstools/css-calc@npm:^2.1.1, @csstools/css-calc@npm:^2.1.2": + version: 2.1.2 + resolution: "@csstools/css-calc@npm:2.1.2" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/34ced30553968ef5d5f9e00e3b90b48c47480cf130e282e99d57ec9b09f803aab8bc06325683e72a1518b5e7180a3da8b533f1b462062757c21989a53b482e1a + languageName: node + linkType: hard + +"@csstools/css-color-parser@npm:^3.0.7": + version: 3.0.8 + resolution: "@csstools/css-color-parser@npm:3.0.8" + dependencies: + "@csstools/color-helpers": "npm:^5.0.2" + "@csstools/css-calc": "npm:^2.1.2" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/90722c5a62ca94e9d578ddf59be604a76400b932bd3d4bd23cb1ae9b7ace8fcf83c06995d2b31f96f4afef24a7cefba79beb11ed7ee4999d7ecfec3869368359 + languageName: node + linkType: hard + +"@csstools/css-parser-algorithms@npm:^3.0.4": + version: 3.0.4 + resolution: "@csstools/css-parser-algorithms@npm:3.0.4" + peerDependencies: + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/d411f07765e14eede17bccc6bd4f90ff303694df09aabfede3fd104b2dfacfd4fe3697cd25ddad14684c850328f3f9420ebfa9f78380892492974db24ae47dbd + languageName: node + linkType: hard + +"@csstools/css-tokenizer@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/css-tokenizer@npm:3.0.3" + checksum: 10c0/c31bf410e1244b942e71798e37c54639d040cb59e0121b21712b40015fced2b0fb1ffe588434c5f8923c9cd0017cfc1c1c8f3921abc94c96edf471aac2eba5e5 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.25.0": version: 0.25.0 resolution: "@esbuild/aix-ppc64@npm:0.25.0" @@ -403,6 +462,21 @@ __metadata: languageName: node linkType: hard +"@vue/compiler-sfc@npm:2.7.16": + version: 2.7.16 + resolution: "@vue/compiler-sfc@npm:2.7.16" + dependencies: + "@babel/parser": "npm:^7.23.5" + postcss: "npm:^8.4.14" + prettier: "npm:^1.18.2 || ^2.0.0" + source-map: "npm:^0.6.1" + dependenciesMeta: + prettier: + optional: true + checksum: 10c0/eaeeef054c939e6cd7591199e2b998ae33d0afd65dc1b5675b54361f0c657c08ae82945791a1a8ca76762e1c1f8e69a00595daf280b854cbc3370ed5c5a34bcd + languageName: node + linkType: hard + "abbrev@npm:^3.0.0": version: 3.0.0 resolution: "abbrev@npm:3.0.0" @@ -527,6 +601,13 @@ __metadata: languageName: node linkType: hard +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d + languageName: node + linkType: hard + "atomic-sleep@npm:^1.0.0": version: 1.0.0 resolution: "atomic-sleep@npm:1.0.0" @@ -710,6 +791,15 @@ __metadata: languageName: node linkType: hard +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: "npm:~1.0.0" + checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -743,6 +833,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^2.6.5": + version: 2.6.12 + resolution: "core-js@npm:2.6.12" + checksum: 10c0/00128efe427789120a06b819adc94cc72b96955acb331cb71d09287baf9bd37bebd191d91f1ee4939c893a050307ead4faea08876f09115112612b6a05684b63 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -754,6 +851,33 @@ __metadata: languageName: node linkType: hard +"cssstyle@npm:^4.2.1": + version: 4.2.1 + resolution: "cssstyle@npm:4.2.1" + dependencies: + "@asamuzakjp/css-color": "npm:^2.8.2" + rrweb-cssom: "npm:^0.8.0" + checksum: 10c0/02ba8c47c0caaab57acadacb3eb6c0f5f009000f55d61f6563670e07d389b26edefeed497e6c1847fcd2e6bbe0b6974c2d4291f97fa0c6ec6add13a7fa926d84 + languageName: node + linkType: hard + +"csstype@npm:^3.1.0": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 + languageName: node + linkType: hard + +"data-urls@npm:^5.0.0": + version: 5.0.0 + resolution: "data-urls@npm:5.0.0" + dependencies: + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^14.0.0" + checksum: 10c0/1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad + languageName: node + linkType: hard + "debug@npm:4, debug@npm:^4, debug@npm:^4.3.4": version: 4.4.0 resolution: "debug@npm:4.4.0" @@ -766,6 +890,13 @@ __metadata: languageName: node linkType: hard +"decimal.js@npm:^10.4.3": + version: 10.5.0 + resolution: "decimal.js@npm:10.5.0" + checksum: 10c0/785c35279df32762143914668df35948920b6c1c259b933e0519a69b7003fc0a5ed2a766b1e1dda02574450c566b21738a45f15e274b47c2ac02072c0d1f3ac3 + languageName: node + linkType: hard + "deferred-leveldown@npm:^7.0.0": version: 7.0.0 resolution: "deferred-leveldown@npm:7.0.0" @@ -776,6 +907,13 @@ __metadata: languageName: node linkType: hard +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 + languageName: node + linkType: hard + "depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -850,6 +988,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.5.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -887,6 +1032,18 @@ __metadata: languageName: node linkType: hard +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af + languageName: node + linkType: hard + "esbuild@npm:^0.25.0": version: 0.25.0 resolution: "esbuild@npm:0.25.0" @@ -1045,7 +1202,7 @@ __metadata: languageName: node linkType: hard -"fastify@npm:^5.0.0": +"fastify@npm:^5.2.1": version: 5.2.1 resolution: "fastify@npm:5.2.1" dependencies: @@ -1107,6 +1264,18 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^4.0.1": + version: 4.0.2 + resolution: "form-data@npm:4.0.2" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + mime-types: "npm:^2.1.12" + checksum: 10c0/e534b0cf025c831a0929bf4b9bbe1a9a6b03e273a8161f9947286b9b13bf8fb279c6944aae0070c4c311100c6d6dbb815cd955dc217728caf73fad8dc5b8ee9c + languageName: node + linkType: hard + "fs-minipass@npm:^3.0.0": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" @@ -1257,6 +1426,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^4.0.0": + version: 4.0.0 + resolution: "html-encoding-sniffer@npm:4.0.0" + dependencies: + whatwg-encoding: "npm:^3.1.1" + checksum: 10c0/523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -1277,7 +1455,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^7.0.0": +"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" dependencies: @@ -1287,7 +1465,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6": version: 7.0.6 resolution: "https-proxy-agent@npm:7.0.6" dependencies: @@ -1297,7 +1475,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -1416,6 +1594,13 @@ __metadata: languageName: node linkType: hard +"is-potential-custom-element-name@npm:^1.0.1": + version: 1.0.1 + resolution: "is-potential-custom-element-name@npm:1.0.1" + checksum: 10c0/b73e2f22bc863b0939941d369486d308b43d7aef1f9439705e3582bfccaa4516406865e32c968a35f97a99396dac84e2624e67b0a16b0a15086a785e16ce7db9 + languageName: node + linkType: hard + "is-promise@npm:^2.0.0": version: 2.2.2 resolution: "is-promise@npm:2.2.2" @@ -1485,6 +1670,40 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^26.0.0": + version: 26.0.0 + resolution: "jsdom@npm:26.0.0" + dependencies: + cssstyle: "npm:^4.2.1" + data-urls: "npm:^5.0.0" + decimal.js: "npm:^10.4.3" + form-data: "npm:^4.0.1" + html-encoding-sniffer: "npm:^4.0.0" + http-proxy-agent: "npm:^7.0.2" + https-proxy-agent: "npm:^7.0.6" + is-potential-custom-element-name: "npm:^1.0.1" + nwsapi: "npm:^2.2.16" + parse5: "npm:^7.2.1" + rrweb-cssom: "npm:^0.8.0" + saxes: "npm:^6.0.0" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^5.0.0" + w3c-xmlserializer: "npm:^5.0.0" + webidl-conversions: "npm:^7.0.0" + whatwg-encoding: "npm:^3.1.1" + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^14.1.0" + ws: "npm:^8.18.0" + xml-name-validator: "npm:^5.0.0" + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10c0/e48725ba4027edcfc9bca5799eaec72c6561ecffe3675a8ff87fe9c3541ca4ff9f82b4eff5b3d9c527302da0d859b2f60e9364347a5d42b77f5c76c436c569dc + languageName: node + linkType: hard + "json-schema-ref-resolver@npm:^2.0.0": version: 2.0.1 resolution: "json-schema-ref-resolver@npm:2.0.1" @@ -1511,6 +1730,13 @@ __metadata: languageName: node linkType: hard +"leaflet@npm:^1.9.4": + version: 1.9.4 + resolution: "leaflet@npm:1.9.4" + checksum: 10c0/f639441dbb7eb9ae3fcd29ffd7d3508f6c6106892441634b0232fafb9ffb1588b05a8244ec7085de2c98b5ed703894df246898477836cfd0ce5b96d4717b5ca1 + languageName: node + linkType: hard + "level-codec@npm:^10.0.0": version: 10.0.0 resolution: "level-codec@npm:10.0.0" @@ -1590,7 +1816,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0, lru-cache@npm:^10.4.3": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb @@ -1630,6 +1856,22 @@ __metadata: languageName: node linkType: hard +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + "mime@npm:^3": version: 3.0.0 resolution: "mime@npm:3.0.0" @@ -1759,6 +2001,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.8": + version: 3.3.8 + resolution: "nanoid@npm:3.3.8" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/4b1bb29f6cfebf3be3bc4ad1f1296fb0a10a3043a79f34fbffe75d1621b4318319211cd420549459018ea3592f0d2f159247a6f874911d6d26eaaadda2478120 + languageName: node + linkType: hard + "napi-macros@npm:~2.0.0": version: 2.0.0 resolution: "napi-macros@npm:2.0.0" @@ -1842,6 +2093,13 @@ __metadata: languageName: node linkType: hard +"nwsapi@npm:^2.2.16": + version: 2.2.16 + resolution: "nwsapi@npm:2.2.16" + checksum: 10c0/0aa0637f4d51043d0183d994e08336bae996b03b42984381bf09ebdf3ff4909c018eda6b2a8aba0a08f3ea8303db8a0dad0608b38dc0bff15fd87017286ae21a + languageName: node + linkType: hard + "object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -1870,6 +2128,15 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^7.2.1": + version: 7.2.1 + resolution: "parse5@npm:7.2.1" + dependencies: + entities: "npm:^4.5.0" + checksum: 10c0/829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80 + languageName: node + linkType: hard + "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -1904,6 +2171,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -1948,6 +2222,26 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.14": + version: 8.5.3 + resolution: "postcss@npm:8.5.3" + dependencies: + nanoid: "npm:^3.3.8" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3 + languageName: node + linkType: hard + +"prettier@npm:^1.18.2 || ^2.0.0": + version: 2.8.8 + resolution: "prettier@npm:2.8.8" + bin: + prettier: bin-prettier.js + checksum: 10c0/463ea8f9a0946cd5b828d8cf27bd8b567345cf02f56562d5ecde198b91f47a76b7ac9eae0facd247ace70e927143af6135e8cf411986b8cb8478784a4d6d724a + languageName: node + linkType: hard + "prettier@npm:^3.5.2": version: 3.5.2 resolution: "prettier@npm:3.5.2" @@ -2124,6 +2418,13 @@ __metadata: languageName: node linkType: hard +"punycode@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.3": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -2237,6 +2538,13 @@ __metadata: languageName: node linkType: hard +"rrweb-cssom@npm:^0.8.0": + version: 0.8.0 + resolution: "rrweb-cssom@npm:0.8.0" + checksum: 10c0/56f2bfd56733adb92c0b56e274c43f864b8dd48784d6fe946ef5ff8d438234015e59ad837fc2ad54714b6421384141c1add4eb569e72054e350d1f8a50b8ac7b + languageName: node + linkType: hard + "safe-buffer@npm:5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -2267,6 +2575,15 @@ __metadata: languageName: node linkType: hard +"saxes@npm:^6.0.0": + version: 6.0.0 + resolution: "saxes@npm:6.0.0" + dependencies: + xmlchars: "npm:^2.2.0" + checksum: 10c0/3847b839f060ef3476eb8623d099aa502ad658f5c40fd60c105ebce86d244389b0d76fcae30f4d0c728d7705ceb2f7e9b34bb54717b6a7dbedaf5dad2d9a4b74 + languageName: node + linkType: hard + "secure-json-parse@npm:^3.0.1": version: 3.0.2 resolution: "secure-json-parse@npm:3.0.2" @@ -2366,6 +2683,20 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf + languageName: node + linkType: hard + +"source-map@npm:^0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 + languageName: node + linkType: hard + "split2@npm:^4.0.0": version: 4.2.0 resolution: "split2@npm:4.2.0" @@ -2461,6 +2792,13 @@ __metadata: languageName: node linkType: hard +"symbol-tree@npm:^3.2.4": + version: 3.2.4 + resolution: "symbol-tree@npm:3.2.4" + checksum: 10c0/dfbe201ae09ac6053d163578778c53aa860a784147ecf95705de0cd23f42c851e1be7889241495e95c37cabb058edb1052f141387bef68f705afc8f9dd358509 + languageName: node + linkType: hard + "tar@npm:^7.4.3": version: 7.4.3 resolution: "tar@npm:7.4.3" @@ -2484,6 +2822,24 @@ __metadata: languageName: node linkType: hard +"tldts-core@npm:^6.1.78": + version: 6.1.78 + resolution: "tldts-core@npm:6.1.78" + checksum: 10c0/aea5e664da879cd862ccf5df9286531ddf4c34a9ca832480188bf6cd165cd45654f5b0a0f0f5315e16203ebfb87d52f8630b9419e729b3cfe5eff073c398693e + languageName: node + linkType: hard + +"tldts@npm:^6.1.32": + version: 6.1.78 + resolution: "tldts@npm:6.1.78" + dependencies: + tldts-core: "npm:^6.1.78" + bin: + tldts: bin/cli.js + checksum: 10c0/966f3f5a63405db6abb49b479784baa677510993f21ffbd67571f3d819451d70a603f1246b13f1c309a7573c4d9fbe0241aca6ff6e8399cbe7d2dd70b7ee4052 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -2523,6 +2879,24 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^5.0.0": + version: 5.1.1 + resolution: "tough-cookie@npm:5.1.1" + dependencies: + tldts: "npm:^6.1.32" + checksum: 10c0/84fe18b7c28ce273c916d95028c00ffff58c285d58e90fbd44eb9380dd1bc21892c675cd1bbd4bfbc95108fe833c406b285844757d41636248bfe264655a6ef8 + languageName: node + linkType: hard + +"tr46@npm:^5.0.0": + version: 5.0.0 + resolution: "tr46@npm:5.0.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10c0/1521b6e7bbc8adc825c4561480f9fe48eb2276c81335eed9fa610aa4c44a48a3221f78b10e5f18b875769eb3413e30efbf209ed556a17a42aa8d690df44b7bee + languageName: node + linkType: hard + "undefsafe@npm:^2.0.5": version: 2.0.5 resolution: "undefsafe@npm:2.0.5" @@ -2537,6 +2911,13 @@ __metadata: languageName: node linkType: hard +"undici@npm:^7.3.0": + version: 7.3.0 + resolution: "undici@npm:7.3.0" + checksum: 10c0/62c5e335725cadb02e19950932c7823fc330cbfd80106e6836daa6db1379aa727510b77de0a4e6f912087b288ded93f7daf4b8c154ad36fd5c9c4b96b26888b8 + languageName: node + linkType: hard + "unique-filename@npm:^4.0.0": version: 4.0.0 resolution: "unique-filename@npm:4.0.0" @@ -2579,13 +2960,99 @@ __metadata: "@prettier/plugin-pug": "npm:^3.0.0" "@types/node": "npm:^22.13.5" esbuild: "npm:^0.25.0" - fastify: "npm:^5.0.0" + fastify: "npm:^5.2.1" + jsdom: "npm:^26.0.0" + leaflet: "npm:^1.9.4" nodemon: "npm:^3.0.1" prettier: "npm:^3.5.2" pug: "npm:^3.0.2" + undici: "npm:^7.3.0" + vue: "npm:2" + vue-multiselect: "npm:2" + vue-textarea-autosize: "npm:^1.1.1" + vue2-leaflet: "npm:^2.7.1" languageName: unknown linkType: soft +"vue-multiselect@npm:2": + version: 2.1.9 + resolution: "vue-multiselect@npm:2.1.9" + checksum: 10c0/baecfbb97b4b225bd2e2054f2eed640917b47f448a76a43f084d344764c813a58e825ea2131f6803c125e6e8d4e0b4edb5712da49dd1b8a082f29ac845cc7c2b + languageName: node + linkType: hard + +"vue-textarea-autosize@npm:^1.1.1": + version: 1.1.1 + resolution: "vue-textarea-autosize@npm:1.1.1" + dependencies: + core-js: "npm:^2.6.5" + checksum: 10c0/22614d412b7e592b68c9b127cfc4257985058571d185ef1885acd3666b77381c87a2006b5084d5687b5e3729ad5b8c53ff962eaf43bbefa1dc5ae0e58cada9db + languageName: node + linkType: hard + +"vue2-leaflet@npm:^2.7.1": + version: 2.7.1 + resolution: "vue2-leaflet@npm:2.7.1" + peerDependencies: + "@types/leaflet": ^1.5.7 + leaflet: ^1.3.4 + vue: ^2.5.17 + checksum: 10c0/34ae5cc4b78deaf3ee7f73a210b2e45f9d80b92860d5ac5d831d74fd8a94d06983845f01e6203b4e61bad7f6385715f0ea3cd23b2e39fb6c8ce912fe4d096af6 + languageName: node + linkType: hard + +"vue@npm:2": + version: 2.7.16 + resolution: "vue@npm:2.7.16" + dependencies: + "@vue/compiler-sfc": "npm:2.7.16" + csstype: "npm:^3.1.0" + checksum: 10c0/15bf536c131a863d03c42386a4bbc82316262129421ef70e88d1758bcf951446ef51edeff42e3b27d026015330fe73d90155fca270eb5eadd30b0290735f2c3e + languageName: node + linkType: hard + +"w3c-xmlserializer@npm:^5.0.0": + version: 5.0.0 + resolution: "w3c-xmlserializer@npm:5.0.0" + dependencies: + xml-name-validator: "npm:^5.0.0" + checksum: 10c0/8712774c1aeb62dec22928bf1cdfd11426c2c9383a1a63f2bcae18db87ca574165a0fbe96b312b73652149167ac6c7f4cf5409f2eb101d9c805efe0e4bae798b + languageName: node + linkType: hard + +"webidl-conversions@npm:^7.0.0": + version: 7.0.0 + resolution: "webidl-conversions@npm:7.0.0" + checksum: 10c0/228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4 + languageName: node + linkType: hard + +"whatwg-encoding@npm:^3.1.1": + version: 3.1.1 + resolution: "whatwg-encoding@npm:3.1.1" + dependencies: + iconv-lite: "npm:0.6.3" + checksum: 10c0/273b5f441c2f7fda3368a496c3009edbaa5e43b71b09728f90425e7f487e5cef9eb2b846a31bd760dd8077739c26faf6b5ca43a5f24033172b003b72cf61a93e + languageName: node + linkType: hard + +"whatwg-mimetype@npm:^4.0.0": + version: 4.0.0 + resolution: "whatwg-mimetype@npm:4.0.0" + checksum: 10c0/a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df + languageName: node + linkType: hard + +"whatwg-url@npm:^14.0.0, whatwg-url@npm:^14.1.0": + version: 14.1.1 + resolution: "whatwg-url@npm:14.1.1" + dependencies: + tr46: "npm:^5.0.0" + webidl-conversions: "npm:^7.0.0" + checksum: 10c0/de1e9cc2f04cb000f232c839d4999384ba41b680ef8a89e7c61c9bc40354ba8593c775d068faaf0819f5866e4d6ca3e7b9b386e2123aa475bfd33da02316f476 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -2642,6 +3109,35 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.18.0": + version: 8.18.1 + resolution: "ws@npm:8.18.1" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/e498965d6938c63058c4310ffb6967f07d4fa06789d3364829028af380d299fe05762961742971c764973dce3d1f6a2633fe8b2d9410c9b52e534b4b882a99fa + languageName: node + linkType: hard + +"xml-name-validator@npm:^5.0.0": + version: 5.0.0 + resolution: "xml-name-validator@npm:5.0.0" + checksum: 10c0/3fcf44e7b73fb18be917fdd4ccffff3639373c7cb83f8fc35df6001fecba7942f1dbead29d91ebb8315e2f2ff786b508f0c9dc0215b6353f9983c6b7d62cb1f5 + languageName: node + linkType: hard + +"xmlchars@npm:^2.2.0": + version: 2.2.0 + resolution: "xmlchars@npm:2.2.0" + checksum: 10c0/b64b535861a6f310c5d9bfa10834cf49127c71922c297da9d4d1b45eeaae40bf9b4363275876088fbe2667e5db028d2cd4f8ee72eed9bede840a67d57dab7593 + languageName: node + linkType: hard + "yallist@npm:^4.0.0": version: 4.0.0 resolution: "yallist@npm:4.0.0" -- 2.47.2 From 366ca8b97fb25fb5986bf981260f4a28981dfe6f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:30:33 +0100 Subject: [PATCH 61/95] Update src/client/main.ts --- src/client/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/main.ts b/src/client/main.ts index a443417..9c35ce8 100644 --- a/src/client/main.ts +++ b/src/client/main.ts @@ -1,4 +1,4 @@ import "./types/ext"; import "./types/format"; import "./api"; -import "./vue"; +import "./old"; -- 2.47.2 From 52b3d98feca237b24d779756576ff7ff49836d7f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:30:44 +0100 Subject: [PATCH 62/95] Update src/client/old.js --- src/client/old.js | 356 +++++++++++++++++++++++++++------------------- 1 file changed, 206 insertions(+), 150 deletions(-) diff --git a/src/client/old.js b/src/client/old.js index 42cb379..a81823a 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -16,172 +16,228 @@ Vue.component("multiselect", window.VueMultiselect.default); Vue.use(window.VueTextareaAutosize); const app = new Vue({ - el: "#app", - data: { - journey_edit: - ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, - journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), + el: "#app", + data: { + edit_active: ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, + drawer_active: "hotel", + journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), + map_override: { active: false, center: [0, 0] }, - query: { - type: "", - act: false, - res: [], - }, - impexp: "", - lang: { - format: "ddd D MMM", - formatLocale: { - firstDayOfWeek: 1, - }, - monthBeforeYear: true, - }, - polyline: { - latlngs: [], - color: 'green' - } - }, - methods: { - start_journey: function () { window.location.href = "/" + this.journey.id }, + query: { + type: "", res: [], + }, + impexp: "", + lang: { + format: "ddd D MMM", + formatLocale: { + firstDayOfWeek: 1, + }, + monthBeforeYear: true, + }, + polyline: { + latlngs: [], + color: 'green' + } + }, + methods: { + start_journey: function () { window.location.href = "/" + this.journey.id }, - compute_bb: function () { - const bounds = this.$refs.map[0].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`; + compute_bb: function () { + const bounds = this.$refs.map[0].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_marker: function (item, fcolor) { + return `
` - }, - generate_icon: function (item, fcolor, styling = "") { - return ``; - }, + }, + generate_icon: function (item, fcolor, styling = "") { + 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); - }, + 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); + }, - 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; - } - }, + 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) => { - this.query.act = true; - this.query.type = f; - return 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]; - }); - this.query.res = r; - this.query.act = false; - return r - }); - } - }, - search_travel: function (f) { - return (q) => { - this.query.act = true; - this.query.type = f; - return api.query_flight(q).then((r) => { - r.forEach(el => el.path = getGeoLine( - new L.LatLng(el.from_geo.lat, el.from_geo.lon), - new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); - this.query.res = r; - this.query.act = false; - return r; - }); - } - }, + search_nominatim: function (f) { + return (q) => { + this.query.type = f; + return 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]; + }); + this.query.res = r; + this.query.type = null; + return r + }); + } + }, + search_travel: function (f) { + return (q) => { + this.query.type = f; + return 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: 5_000_000 }).map(v => [v.lat, v.lng]) + el.type = "flight"; + }); + this.query.res = r; + this.query.type = null; + return r; + }); + } + }, - keyboardEvent(e) { - if (e.which === 13) { - } - }, - }, - created: function () { + drawer_hover_item: function (item) { + if (item) { + this.map_override.active = true + this.map_override.center = [item.lat, item.lon] + } else { + this.map_override.active = false + } + }, - 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) + drawer_click_item: function (item) { + console.log(item) + console.log(this.journey.leg_get()) + switch (this.drawer_active) { + 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.places.push(item); + case 'other': return; + case 'flight': return this.journey.leg_get().travel.push(item); + } + }, - 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); - } - }); + search_active: function (q) { + const txt = q.target.value + switch (this.drawer_active) { + 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); + } + }, - api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); + keyboardEvent(e) { + if (e.which === 13) { + } + }, + }, + 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) + this - this.search_travel("flight")("qf1").then(r => { - this.polyline.latlngs = r.map(e => e.path) - }); + 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); + } + }); - }, - watch: { - journey: { - handler: function (ndata, odata) { - this.save_data(); - }, - deep: true, - }, - }, + api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); + + // this.search_travel("flight")("qf1").then(r => { + // // this.polyline.latlngs = r.map(e => e.path) + // this.journey.data.main[this.journey.sel_leg].travel = r; + // }); + + }, + watch: { + journey: { + handler: function (ndata, odata) { + this.save_data(); + }, + deep: true, + }, + }, }); + +var scrollInterval = null; +var scrollDir = null; +document.querySelector('.scroll-content').addEventListener('mousemove', (e) => { + const c = document.querySelector('.scroll-content') + const newDir = + e.pageX < c.offsetWidth * 0.2 ? 'left' : + (e.pageX > c.offsetWidth * 0.8 ? 'right' : scrollDir) + if (!scrollInterval || scrollDir != newDir) { + if (scrollInterval) clearInterval(scrollInterval) + sideScroll(c, newDir, 25, 10); + } +}); +document.querySelector('.scroll-content').addEventListener('mouseleave', () => { + clearInterval(scrollInterval); + scrollInterval = null +}); +function sideScroll(element, direction, speed, step) { + scrollDir = direction + scrollInterval = setInterval(() => { + element.scrollLeft += (direction == 'left') ? -step : step; + }, speed); +} -- 2.47.2 From fe4190313be04de995c92bb4c4ecc17c2ad6713b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:30:58 +0100 Subject: [PATCH 63/95] Update src/client/types/format.ts --- src/client/types/format.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/client/types/format.ts b/src/client/types/format.ts index 1d4fcf2..ba75269 100644 --- a/src/client/types/format.ts +++ b/src/client/types/format.ts @@ -1,17 +1,21 @@ -declare global { - interface map { - zoom: number - center: { - lat: number - lng: number - } - } + +declare global { + interface LatLng { + lat: number + lng: number + } interface geoloc { latlon: [number, number] notes: string } + interface map { + zoom: number + center: LatLng + } + + interface leg { title: string day_title: string[] -- 2.47.2 From 1814a8a87d6431ee7fa4320f17a908d4f671a323 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:31:09 +0100 Subject: [PATCH 64/95] Update src/client/types/geom.ts --- src/client/types/geom.ts | 47 ++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/client/types/geom.ts b/src/client/types/geom.ts index 99fb18d..10a281a 100644 --- a/src/client/types/geom.ts +++ b/src/client/types/geom.ts @@ -1,5 +1,3 @@ -// import L from "leaflet" - const ellipsoid = { a: 6378137, b: 6356752.3142, @@ -19,7 +17,7 @@ function wrap(degrees: number, max = 360) { } } -function dist(src, dst, itr = 100, mit = true): number { +function dist(src: LatLng, dst: LatLng, itr = 100, mit = true): number { const p1 = src, p2 = dst; const φ1 = toRadians(p1.lat), @@ -84,7 +82,7 @@ function dist(src, dst, itr = 100, mit = true): number { if (mit) { return dist( src, - new L.LatLng(dst.lat, dst.lng - 0.01), + { lat: dst.lat, lng: dst.lng - 0.01 }, itr, mit ); @@ -109,10 +107,10 @@ function dist(src, dst, itr = 100, mit = true): number { } -function pointDistance(src: L.LatLng, dst: L.LatLng): number { +function pointDistance(src: LatLng, dst: LatLng): number { return dist( - new L.LatLng(src.lat, wrap(src.lng, 180)), - new L.LatLng(dst.lat, wrap(dst.lng, 180)) + { lat: src.lat, lng: wrap(src.lng, 180) }, + { lat: dst.lat, lng: wrap(dst.lng, 180) } ); } @@ -124,7 +122,7 @@ function toDegrees(radians: number): number { return (radians * 180) / Math.PI; } -function midpoint(src: L.LatLng, dst: L.LatLng): L.LatLng { +function midpoint(src: LatLng, dst: LatLng): LatLng { // φm = atan2( sinφ1 + sinφ2, √( (cosφ1 + cosφ2⋅cosΔλ)² + cos²φ2⋅sin²Δλ ) ) // λm = λ1 + atan2(cosφ2⋅sinΔλ, cosφ1 + cosφ2⋅cosΔλ) // midpoint is sum of vectors to two points: mathforum.org/library/drmath/view/51822.html @@ -144,31 +142,24 @@ function midpoint(src: L.LatLng, dst: L.LatLng): L.LatLng { const φm = Math.atan2(C.z, Math.sqrt(C.x * C.x + C.y * C.y)); const λm = λ1 + Math.atan2(C.y, C.x); - return new L.LatLng(toDegrees(φm), toDegrees(λm)); + return { lat: toDegrees(φm), lng: toDegrees(λm) }; } -function recursiveMidPoint(src: L.LatLng, dst: L.LatLng, opt: { step?: number, dist?: number }): L.LatLng[] { - const geom: L.LatLng[] = [src, dst]; +function recursiveMidPoint(src: LatLng, dst: LatLng, opt: { step?: number, dist?: number } = {}, curr = 0): LatLng[] { + const geom: LatLng[] = [src, dst]; const mp = midpoint(src, dst); - - if (opt.step != undefined) { - if (opt.step > 0) { - geom.splice(0, 1, ...recursiveMidPoint(src, mp, { step: opt.step - 1 })); - geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, { step: opt.step - 1 })); - } else { - geom.splice(1, 0, mp); - } - } else if (opt.dist != undefined) { - if (pointDistance(src, dst) > opt.dist) { - geom.splice(0, 1, ...recursiveMidPoint(src, mp, { dist: opt.dist })); - geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, { dist: opt.dist })); - } else { - geom.splice(1, 0, mp); - } + const split_step = (opt.step != undefined && (opt.step > 0 || curr == 0)) + const split_dist = (opt.dist != undefined && (pointDistance(src, dst) > opt.dist || curr == 0)) + const next_opt = split_step ? { step: (opt.step || 0) - 1 } : { dist: opt.dist }; + if (split_step || split_dist) { + geom.splice(0, 1, ...recursiveMidPoint(src, mp, next_opt, curr + 1)); + geom.splice(geom.length - 2, 2, ...recursiveMidPoint(mp, dst, next_opt, curr + 1)); + } else { + geom.splice(1, 0, mp); } return geom; } -export function getGeoLine(src: L.LatLng, dst: L.LatLng, opt: { step: number, dist: number }) { - return recursiveMidPoint(src, dst, opt) +export function getGeoLine(src: LatLng, dst: LatLng, opt: { step?: number, dist?: number }) { + return recursiveMidPoint(src, dst, opt, 0) } \ No newline at end of file -- 2.47.2 From 92032f60e9f83158719d06ce8e0009b37d04a876 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:31:19 +0100 Subject: [PATCH 65/95] Update src/client/types/wrapper.ts --- src/client/types/wrapper.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/client/types/wrapper.ts b/src/client/types/wrapper.ts index 486f6e4..66f84b3 100644 --- a/src/client/types/wrapper.ts +++ b/src/client/types/wrapper.ts @@ -4,7 +4,7 @@ const date_day_diff = (d0: Date, d1: Date): number => (d1.getTime() - d0.getTime()) / (1000 * 60 * 60 * 24) class journey_wrapper { - id: string + id: String data: journey = journey_template; sel_leg: number = 0; sel_day: number = 0; @@ -82,9 +82,7 @@ class journey_wrapper { let leg = this.leg_get() if (!leg.date_range) return "?"; - var date = new Date( - leg.date_range[0], - ); + var date = new Date(leg.date_range[0]); date.setDate(date.getDate() + this.sel_day); return date.toLocal(); } @@ -92,7 +90,7 @@ class journey_wrapper { if (this.leg_count() == 0) return ""; let lf = this.leg_first(), ll = this.leg_last(); if (lf.date_range && ll.date_range) - return `${lf.date_range[0].toLocal()} - ${ll[1].toLocal()}`; + return `${lf.date_range[0].toLocal()} - ${ll.date_range[1].toLocal()}`; return "?"; } -- 2.47.2 From 503ff92d5e81d2746184413ce03b86926ba332e3 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:31:54 +0100 Subject: [PATCH 66/95] Update template/module/foot.pug --- template/module/foot.pug | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/template/module/foot.pug b/template/module/foot.pug index c415501..39e7a65 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -1,11 +1,11 @@ script(src="https://unpkg.com/leaflet") script(src="https://unpkg.com/sortablejs") -//- script(src="https://unpkg.com/vue@2") -//- script(src="https://unpkg.com/vue2-datepicker") -//- script(src="https://unpkg.com/vue-textarea-autosize") -//- script(src="https://unpkg.com/vue-multiselect@2") -//- script(src="https://unpkg.com/vue2-leaflet") +script(src="https://unpkg.com/vue@2") +script(src="https://unpkg.com/vue2-datepicker") +script(src="https://unpkg.com/vue-textarea-autosize") +script(src="https://unpkg.com/vue-multiselect@2") +script(src="https://unpkg.com/vue2-leaflet") script(src="https://unpkg.com/vuedraggable") script(src="/public/main.js", type="text/javascript", charset="utf-8") footer.bg-dark -- 2.47.2 From f3381bf8f09f20272f78537f32d83720cd39a2eb Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:32:32 +0100 Subject: [PATCH 67/95] Update template/module/journey_nav.pug --- template/module/{journey_sec.pug => journey_nav.pug} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename template/module/{journey_sec.pug => journey_nav.pug} (89%) diff --git a/template/module/journey_sec.pug b/template/module/journey_nav.pug similarity index 89% rename from template/module/journey_sec.pug rename to template/module/journey_nav.pug index 5b8fd78..3a2ed78 100644 --- a/template/module/journey_sec.pug +++ b/template/module/journey_nav.pug @@ -1,4 +1,4 @@ -draggable.list-group.bg-dark( +draggable.scroll-content.list-group.bg-dark( tag="div", :list="journey.data.main", handle=".handle" @@ -16,5 +16,5 @@ draggable.list-group.bg-dark( ) .list-group-item.bg-white(@click="journey.add_leg()") - .text Add Section + .text Add Leg i.fa.fa-plus.add(style="top: 12px; right: 5px; position: absolute") -- 2.47.2 From 1f3db375a4be2ba368f29cd2f0e490e9d64ab0dc Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:32:45 +0100 Subject: [PATCH 68/95] Update template/module/journey_leg.pug --- .../{journey_step.pug => journey_leg.pug} | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) rename template/module/{journey_step.pug => journey_leg.pug} (79%) diff --git a/template/module/journey_step.pug b/template/module/journey_leg.pug similarity index 79% rename from template/module/journey_step.pug rename to template/module/journey_leg.pug index f8b5652..aee7a18 100644 --- a/template/module/journey_step.pug +++ b/template/module/journey_leg.pug @@ -16,8 +16,25 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") :value="journey.date_sel() + ' (' + journey.sel_day + ')'" ) .row - .col-9.col-ssm-12 + .map-container(:class="{ 'col-9': !drawer_active, 'col-7': drawer_active }") include map.pug + .drawer-container(:class="{ 'col-3': drawer_active, 'col-0': !drawer_active }") + .row.text-center + .input.text-dark(style="width: 100%") + input( + type="search" + @input="search_active" + placeholder="Search ... " + ) + ul + li( + v-for="item in query.res" + :key="item.id" + @mouseover="drawer_hover_item(item)" + @mouseleave="drawer_hover_item()" + @click="drawer_click_item(item)" ) + | {{ item.name }} + .col-3.col-ssm-12 .row.text-center div @@ -42,7 +59,7 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") open-direction="bottom", :options="query.res", :searchable="true", - :loading="query.act && query.type=='hotel'", + :loading="query.type=='hotel'", :internal-search="false", :clear-on-select="false", :options-limit="50", @@ -62,7 +79,7 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") :multiple="true", :options="query.res", :searchable="true", - :loading="query.act && query.type == 'restaurant'", + :loading="query.type == 'restaurant'", :internal-search="false", :clear-on-select="false", :options-limit="50", @@ -82,7 +99,7 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") :multiple="true", :options="query.res", :searchable="true", - :loading="query.act && query.type=='place'", + :loading="query.type=='place'", :internal-search="false", :clear-on-select="false", :options-limit="50", -- 2.47.2 From 50a98b9a310d2683acd1cabb1d581a625a2ddaef Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:32:59 +0100 Subject: [PATCH 69/95] Update template/module/map.pug --- template/module/map.pug | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/template/module/map.pug b/template/module/map.pug index 4c62135..19e4da8 100644 --- a/template/module/map.pug +++ b/template/module/map.pug @@ -1,6 +1,7 @@ l-map( - :zoom.sync="journey.data.main[idx].map.zoom", - :center.sync="journey.data.main[idx].map.center", + + :zoom.sync="journey.leg_get().map.zoom", + :center.sync="journey.leg_get().map.center", style="padding-top: 100%" ref="map" ) @@ -9,6 +10,12 @@ l-map( attribution="© OpenStreetMap contributors" ) l-control-scale(position="topright", :imperial="false", :metric="true") + l-marker( + v-if="map_override.active", + :lat-lng="map_override.center" + ) + l-icon(v-html="generate_marker('plus', 'darkgreen')") + l-marker( v-if="journey.data.main[idx].hotel", :lat-lng="journey.data.main[idx].hotel.latlon" @@ -17,8 +24,8 @@ l-map( l-popup h1.row.text-medium.text-center {{ journey.data.main[idx].hotel.sname }} span.row.text-small.text-gray {{ journey.data.main[idx].hotel.display_name }} - span(v-if="journey_edit") - .row.input + span(v-if="edit_active") + .row.input(style="margin-bottom:0;") textarea-autosize.col-12.col-sm-12.text-small( placeholder="Notes", v-model="journey.data.main[idx].hotel.notes", @@ -39,12 +46,12 @@ l-map( v-else-if="place.step == -1 || place.step == undefined", v-html="generate_marker(place, 'gray')" ) - l-icon(v-else-if="journey_edit", v-html="generate_marker(place, 'lightgray')") + l-icon(v-else-if="edit_active", v-html="generate_marker(place, 'lightgray')") l-icon(v-else) l-popup h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} - span(v-if="journey_edit") + span(v-if="edit_active") .row.input textarea-autosize.col-12.col-sm-12.text-small( placeholder="Notes", @@ -72,7 +79,7 @@ l-map( l-popup h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} - span(v-if="journey_edit") + span(v-if="edit_active") .row.input textarea-autosize.col-12.col-sm-12.text-small( placeholder="Notes" @@ -82,11 +89,11 @@ l-map( ) span.row.text-small.text-dark(v-else) {{ place.notes }} - div(v-for= "latlngs in polyline.latlngs") - l-polyline(:lat-lngs="polyline.latlngs" :color="polyline.color") + div(v-for= "travel in journey.data.main[idx].travel") + l-polyline(:lat-lngs="travel.path" :color="travel.color || 'gray'") l-marker( - v-for="(place, index) in latlngs" + v-for="(place, index) in travel.path" :key="'plane'+index" :lat-lng="place" ) - l-icon(v-html="generate_icon('plane', polyline.color, generate_rotation(index,latlngs))") \ No newline at end of file + l-icon(v-html="generate_icon('plane', travel.color || 'gray', generate_rotation(index,travel.path))") \ No newline at end of file -- 2.47.2 From 9060814609a77352edc3ed8b5041b70689a6f457 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Thu, 27 Feb 2025 17:33:19 +0100 Subject: [PATCH 70/95] Update template/journey.pug --- template/journey.pug | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/template/journey.pug b/template/journey.pug index 3d9a79c..7cdd77a 100644 --- a/template/journey.pug +++ b/template/journey.pug @@ -4,7 +4,7 @@ include module/head.pug main#app(v-cloak) include module/nav.pug - include module/journey_sec.pug - include module/journey_step.pug + include module/journey_nav.pug + include module/journey_leg.pug include module/importexport.pug include module/foot.pug -- 2.47.2 From 19600369800da55e0c18b72f66c90a08b4281c14 Mon Sep 17 00:00:00 2001 From: soraefir Date: Fri, 28 Feb 2025 01:05:10 +0100 Subject: [PATCH 71/95] wip --- .gitignore | 1 + public/css/index.css | 95 +++++++++ src/client/old.js | 71 +++---- src/client/types/wrapper.ts | 2 +- src/client/vue.ts | 192 ------------------ template/journey.pug | 4 +- template/module/foot.pug | 2 +- template/module/journey.pug | 3 + .../{importexport.pug => journey/impexp.pug} | 4 +- template/module/journey/leg.pug | 11 + template/module/journey/leg/drawer.pug | 15 ++ template/module/journey/leg/nav.pug | 23 +++ template/module/journey/leg/old_cfg.pug | 71 +++++++ template/module/journey/leg/top.pug | 29 +++ template/module/journey/map.pug | 20 ++ template/module/journey/map/activities.pug | 37 ++++ template/module/journey/map/hotel.pug | 18 ++ template/module/journey/map/override.pug | 5 + template/module/journey/map/restaurants.pug | 18 ++ template/module/journey/map/right_menu.pug | 6 + template/module/journey/map/travel.pug | 9 + template/module/journey_leg.pug | 119 ----------- template/module/journey_nav.pug | 20 -- template/module/map.pug | 99 --------- template/module/{nav_pub.pug => view/nav.pug} | 0 .../{short_sec.pug => view/short_leg.pug} | 0 .../{view_step.pug => view/view_day.pug} | 0 template/short.pug | 4 +- template/view.pug | 2 +- 29 files changed, 406 insertions(+), 474 deletions(-) delete mode 100644 src/client/vue.ts create mode 100644 template/module/journey.pug rename template/module/{importexport.pug => journey/impexp.pug} (93%) create mode 100644 template/module/journey/leg.pug create mode 100644 template/module/journey/leg/drawer.pug create mode 100644 template/module/journey/leg/nav.pug create mode 100644 template/module/journey/leg/old_cfg.pug create mode 100644 template/module/journey/leg/top.pug create mode 100644 template/module/journey/map.pug create mode 100644 template/module/journey/map/activities.pug create mode 100644 template/module/journey/map/hotel.pug create mode 100644 template/module/journey/map/override.pug create mode 100644 template/module/journey/map/restaurants.pug create mode 100644 template/module/journey/map/right_menu.pug create mode 100644 template/module/journey/map/travel.pug delete mode 100644 template/module/journey_leg.pug delete mode 100644 template/module/journey_nav.pug delete mode 100644 template/module/map.pug rename template/module/{nav_pub.pug => view/nav.pug} (100%) rename template/module/{short_sec.pug => view/short_leg.pug} (100%) rename template/module/{view_step.pug => view/view_day.pug} (100%) diff --git a/.gitignore b/.gitignore index b60d94f..fd98ac3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ db/ public/*.js public/*.map .yarnrc.yml +.pnp* build/ \ No newline at end of file diff --git a/public/css/index.css b/public/css/index.css index 73a2fcb..94c8fa1 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -3140,4 +3140,99 @@ li { border-left: 10px solid transparent; border-right: 10px solid transparent; background-color: 15px solid #ff5733; +} + +.leaflet-control-attribution { + display: none; +} + +.display-none { + display: none; +} + +.col-0 { + flex: 0 0 0%; + max-width: 100%; + overflow: hidden; +} + +.map-container, +.drawer-container { + transition: flex 0.5s ease-in-out, max-width 0.5s ease-in-out; +} + +.drawer-container { + right: 0; + top: 0; +} + +.map-menu { + position: absolute; + top: 0; + right: 0; + display: flex; + z-index: 500; + flex-direction: column; + gap: 10px; + margin: 5px; +} + +.map-menu-item { + background-color: darkslategrey; + padding: 5px; + border-radius: 50%; + cursor: pointer; +} + +.map-menu-item:hover { + filter: brightness(150%); +} + +.travel-path-icon { + margin-left: -12px; + margin-top: -32px; +} + +.spinner { + position: absolute; + right: 1px; + top: 1px; + width: 40px; + height: 38px; + background: #fff; + display: block +} + +.spinner:after, +.spinner:before { + position: absolute; + content: ""; + top: 50%; + left: 50%; + margin: -8px 0 0 -8px; + width: 16px; + height: 16px; + border-radius: 100%; + border: 2px solid transparent; + border-top-color: #41b883; + -webkit-box-shadow: 0 0 0 1px transparent; + box-shadow: 0 0 0 1px transparent +} + +.spinner:before { + -webkit-animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); + animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite +} + +.spinner:after { + -webkit-animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); + animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite +} + +.input .mx-input { + height: 40px; } \ No newline at end of file diff --git a/src/client/old.js b/src/client/old.js index a81823a..66f3eca 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -19,7 +19,6 @@ const app = new Vue({ el: "#app", data: { edit_active: ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, - drawer_active: "hotel", journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), map_override: { active: false, center: [0, 0] }, @@ -37,13 +36,17 @@ const app = new Vue({ polyline: { latlngs: [], color: 'green' + }, + leg_nav: { + scrollInterval: null, + scrollDir: null } }, methods: { start_journey: function () { window.location.href = "/" + this.journey.id }, compute_bb: function () { - const bounds = this.$refs.map[0].mapObject.getBounds(); + const bounds = this.$refs.map.mapObject.getBounds(); return [[bounds.getSouthWest().lng, bounds.getSouthWest().lat], [bounds.getNorthEast().lng, bounds.getNorthEast().lat]] }, @@ -63,8 +66,8 @@ const app = new Vue({ ` }, - generate_icon: function (item, fcolor, styling = "") { - return ``; + generate_icon: function (item, fcolor = "", styling = "", classes = "") { + return ``; }, @@ -118,7 +121,6 @@ const app = new Vue({ rr.sname = rr.display_name.split(",")[0]; }); this.query.res = r; - this.query.type = null; return r }); } @@ -134,7 +136,6 @@ const app = new Vue({ el.type = "flight"; }); this.query.res = r; - this.query.type = null; return r; }); } @@ -150,12 +151,14 @@ const app = new Vue({ }, drawer_click_item: function (item) { - console.log(item) - console.log(this.journey.leg_get()) - switch (this.drawer_active) { + const tpe = this.query.type; + this.query.res = []; + this.query.type = null; + this.drawer_hover_item() + 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.places.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); } @@ -163,7 +166,7 @@ const app = new Vue({ search_active: function (q) { const txt = q.target.value - switch (this.drawer_active) { + 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); @@ -172,10 +175,32 @@ const app = new Vue({ } }, + + sideScroll: function (element, direction, speed, step) { + this.leg_nav.scrollDir = direction + 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 newDir = + e.pageX < c.offsetWidth * 0.2 ? 'left' : + (e.pageX > c.offsetWidth * 0.8 ? 'right' : this.leg_nav.scrollDir) + 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.scrollInterval = null + }, }, created: function () { this.search_hotel = api.throttle(this.search_nominatim("hotel"), 1000) @@ -186,7 +211,6 @@ const app = new Vue({ api.save(this.journey.id, this.journey.data); }, 1000); this.search_flight = api.throttle(this.search_travel("flight"), 2000) - this window.addEventListener("keydown", (e) => { switch (e.key) { @@ -219,25 +243,4 @@ const app = new Vue({ }, }); -var scrollInterval = null; -var scrollDir = null; -document.querySelector('.scroll-content').addEventListener('mousemove', (e) => { - const c = document.querySelector('.scroll-content') - const newDir = - e.pageX < c.offsetWidth * 0.2 ? 'left' : - (e.pageX > c.offsetWidth * 0.8 ? 'right' : scrollDir) - if (!scrollInterval || scrollDir != newDir) { - if (scrollInterval) clearInterval(scrollInterval) - sideScroll(c, newDir, 25, 10); - } -}); -document.querySelector('.scroll-content').addEventListener('mouseleave', () => { - clearInterval(scrollInterval); - scrollInterval = null -}); -function sideScroll(element, direction, speed, step) { - scrollDir = direction - scrollInterval = setInterval(() => { - element.scrollLeft += (direction == 'left') ? -step : step; - }, speed); -} + diff --git a/src/client/types/wrapper.ts b/src/client/types/wrapper.ts index 66f84b3..db9923c 100644 --- a/src/client/types/wrapper.ts +++ b/src/client/types/wrapper.ts @@ -42,7 +42,7 @@ class journey_wrapper { } leg_sel(idx: number): void { this.sel_leg = idx; - this.sel_day = 1; + this.sel_day = 0; } leg_get(idx?: number): leg { return this.data.main[idx != undefined ? idx : this.sel_leg] diff --git a/src/client/vue.ts b/src/client/vue.ts deleted file mode 100644 index 731f8fe..0000000 --- a/src/client/vue.ts +++ /dev/null @@ -1,192 +0,0 @@ - -import * as api from "./api"; -import journey_wrapper from "./types/wrapper"; -import { migrator } from "./types/migration"; -import { getGeoLine } from "./types/geom"; - -import Vue from "vue"; -import { LMap, LTileLayer, LMarker, LIcon, LPopup, LTooltip, LPolyline, LControlScale } from "vue2-leaflet"; -import Multiselect from 'vue-multiselect' -import TextareaAutosize from 'vue-textarea-autosize' - -Vue.component("l-map", LMap); -Vue.component("l-tile-layer", LTileLayer); -Vue.component("l-marker", LMarker); -Vue.component("l-icon", LIcon); -Vue.component("l-popup", LPopup); -Vue.component("l-tooltip", LTooltip); -Vue.component("l-polyline", LPolyline); -Vue.component("l-control-scale", LControlScale); -Vue.component("multiselect", Multiselect); -Vue.use(TextareaAutosize); - -const app = new Vue({ - el: "#app", - data: { - journey_edit: - ["view", "short"].indexOf(window.location.pathname.split("/")[1]) == -1, - journey: new journey_wrapper(window.location.pathname.split("/").pop() || String.gen_id(16)), - - query: { - type: "", - act: false, - res: [], - }, - impexp: "", - lang: { - format: "ddd D MMM", - formatLocale: { - firstDayOfWeek: 1, - }, - monthBeforeYear: true, - }, - polyline: { - latlngs: [], - color: 'green' - } - }, - methods: { - start_journey: function () { window.location.href = "/" + this.journey.id }, - - compute_bb: function () { - const bounds = this.$refs.map[0].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 = "") { - 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); - }, - - 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) => { - this.query.act = true; - this.query.type = f; - return 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]; - }); - this.query.res = r; - this.query.act = false; - return r - }); - } - }, - search_travel: function (f) { - return (q) => { - this.query.act = true; - this.query.type = f; - return api.query_flight(q).then((r) => { - r.forEach(el => el.path = getGeoLine( - new L.LatLng(el.from_geo.lat, el.from_geo.lon), - new L.LatLng(el.to_geo.lat, el.to_geo.lon), { dist: 5_000_000 }).map(v => [v.lat, v.lng])); - this.query.res = r; - this.query.act = false; - return r; - }); - } - }, - - keyboardEvent(e) { - if (e.which === 13) { - } - }, - }, - 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))); - - this.search_travel("flight")("qf1").then(r => { - this.polyline.latlngs = r.map(e => e.path) - }); - - }, - watch: { - journey: { - handler: function (ndata, odata) { - this.save_data(); - }, - deep: true, - }, - }, -}); diff --git a/template/journey.pug b/template/journey.pug index 7cdd77a..0ca849f 100644 --- a/template/journey.pug +++ b/template/journey.pug @@ -4,7 +4,5 @@ include module/head.pug main#app(v-cloak) include module/nav.pug - include module/journey_nav.pug - include module/journey_leg.pug - include module/importexport.pug + include module/journey.pug include module/foot.pug diff --git a/template/module/foot.pug b/template/module/foot.pug index 39e7a65..0ee055f 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -1,11 +1,11 @@ script(src="https://unpkg.com/leaflet") -script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vue@2") script(src="https://unpkg.com/vue2-datepicker") script(src="https://unpkg.com/vue-textarea-autosize") script(src="https://unpkg.com/vue-multiselect@2") script(src="https://unpkg.com/vue2-leaflet") +script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vuedraggable") script(src="/public/main.js", type="text/javascript", charset="utf-8") footer.bg-dark diff --git a/template/module/journey.pug b/template/module/journey.pug new file mode 100644 index 0000000..ed370b3 --- /dev/null +++ b/template/module/journey.pug @@ -0,0 +1,3 @@ +.journey + include journey/leg.pug +include journey/impexp.pug \ No newline at end of file diff --git a/template/module/importexport.pug b/template/module/journey/impexp.pug similarity index 93% rename from template/module/importexport.pug rename to template/module/journey/impexp.pug index b66f61e..6e0c3a5 100644 --- a/template/module/importexport.pug +++ b/template/module/journey/impexp.pug @@ -1,4 +1,4 @@ -div +.impexp .container-medium.section .aligner .input.col-sm-4 @@ -10,4 +10,4 @@ div .col-sm-2 button.button.button--primary.button--mobileFull( v-on:click="export_data" - ) Export + ) Export \ No newline at end of file diff --git a/template/module/journey/leg.pug b/template/module/journey/leg.pug new file mode 100644 index 0000000..58eb20f --- /dev/null +++ b/template/module/journey/leg.pug @@ -0,0 +1,11 @@ +include leg/nav.pug +.bg-dark.text-white(v-if="journey && journey.leg_get()") + .container.section + include leg/top.pug + .row(style="aspect-ratio:1.25;") + .map-container(:class="{ 'col-9': query.type, 'col-12': !query.type }" ) + include map.pug + .drawer-container(:class="{ 'col-3': query.type, 'col-0': !query.type }") + include leg/drawer.pug + + include leg/old_cfg.pug \ No newline at end of file diff --git a/template/module/journey/leg/drawer.pug b/template/module/journey/leg/drawer.pug new file mode 100644 index 0000000..76b4b99 --- /dev/null +++ b/template/module/journey/leg/drawer.pug @@ -0,0 +1,15 @@ +.row.text-center + .input.text-dark(style="width: 100%") + input( + type="search" + @input="search_active" + placeholder="Search ... " + ) + ul + li( + v-for="item in query.res" + :key="item.id" + @mouseover="drawer_hover_item(item)" + @mouseleave="drawer_hover_item()" + @click="drawer_click_item(item)" ) + | {{ item.name }} \ No newline at end of file diff --git a/template/module/journey/leg/nav.pug b/template/module/journey/leg/nav.pug new file mode 100644 index 0000000..42fdebc --- /dev/null +++ b/template/module/journey/leg/nav.pug @@ -0,0 +1,23 @@ +.scroll-handler( + @mouveleave="nav_mouseleave" + @mousemove="nav_mousemove") + draggable.scroll-content.list-group.bg-dark( + tag="div", + :list="journey.data.main", + handle=".handle" + ) + .list-group-item.handle( + v-for="(element, idx) in journey.data.main", + :key="idx", + @click="journey.leg_sel(idx)", + :class="journey.sel_leg == idx ? 'bg-primary' : 'bg-white'" + ) + .text {{ element.title }} + i.fa.fa-times.close.fright( + style="top: 2px; right: 2px; position: absolute", + @click="journey.rm_leg(idx)" + ) + + .list-group-item.bg-white(@click="journey.add_leg()") + .text Add Leg + i.fa.fa-plus.add(style="top: 12px; right: 5px; position: absolute") diff --git a/template/module/journey/leg/old_cfg.pug b/template/module/journey/leg/old_cfg.pug new file mode 100644 index 0000000..027df9c --- /dev/null +++ b/template/module/journey/leg/old_cfg.pug @@ -0,0 +1,71 @@ +div + div + .row.text-center + div + label Hotel + multiselect#ajax( + v-model="journey.leg_get().hotel", + label="sname", + track-by="place_id", + placeholder="Type to search", + open-direction="bottom", + :options="query.res", + :searchable="true", + :loading="query.type=='hotel'", + :internal-search="false", + :clear-on-select="false", + :options-limit="50", + :limit="1", + :max-height="600", + @search-change="search_hotel" + ) + .row.text-center + div + label Restoration + multiselect#ajax( + v-model="journey.leg_get().places.restaurants", + label="sname", + track-by="place_id", + placeholder="Type to search", + open-direction="bottom", + :multiple="true", + :options="query.res", + :searchable="true", + :loading="query.type == 'restaurant'", + :internal-search="false", + :clear-on-select="false", + :options-limit="50", + :limit="10", + :max-height="600", + @search-change="search_restaurant" + ) + .row.text-center + div + label Activities + multiselect#ajax( + v-model="journey.leg_get().places.activities", + label="sname", + track-by="place_id", + placeholder="Type to search", + open-direction="bottom", + :multiple="true", + :options="query.res", + :searchable="true", + :loading="query.type=='place'", + :internal-search="false", + :clear-on-select="false", + :options-limit="50", + :limit="10", + :max-height="600", + @search-change="search_place" + ) + .row.text-center + div + label Notes + .input.text-dark(style="width: 100%") + textarea-autosize.text-small( + v-model="journey.leg_get().notes", + placeholder="Notes", + :min-height="30", + :max-height="350" + ) diff --git a/template/module/journey/leg/top.pug b/template/module/journey/leg/top.pug new file mode 100644 index 0000000..434f6af --- /dev/null +++ b/template/module/journey/leg/top.pug @@ -0,0 +1,29 @@ +.row.text-center + .col-sm-2 + .input + input(v-model="journey.leg_get().title") + .col-sm-2 + .input + input( + placeholder="Day title", + v-model="journey.leg_get().day_title[journey.sel_day]" + ) + + .col-sm-4 + .input + //- label Date Range ({{ journey.leg_len() }}) + date-picker( + :lang="lang", + v-model="journey.leg_get().date_range", + range="", + format="ddd D MMM", + placeholder="Date Range", + v-on:change="journey.date_update(journey.sel_leg)" + ) + .col-sm-1 + .right.col-sm-2 + .input + input( + disabled="", + :value="journey.date_sel() + ' (' + journey.sel_day + ')'" + ) \ No newline at end of file diff --git a/template/module/journey/map.pug b/template/module/journey/map.pug new file mode 100644 index 0000000..6acc613 --- /dev/null +++ b/template/module/journey/map.pug @@ -0,0 +1,20 @@ +l-map( + :zoom.sync="journey.leg_get().map.zoom", + :center.sync="journey.leg_get().map.center", + style="height:100%" + ref="map" +) + l-tile-layer( + url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", + attribution="© OpenStreetMap contributors" + ) + l-control-scale(position="bottomright", :imperial="false", :metric="true") + include map/override.pug + + include map/hotel.pug + include map/activities.pug + include map/restaurants.pug + + include map/travel.pug + + include map/right_menu.pug \ No newline at end of file diff --git a/template/module/journey/map/activities.pug b/template/module/journey/map/activities.pug new file mode 100644 index 0000000..e7d9f0d --- /dev/null +++ b/template/module/journey/map/activities.pug @@ -0,0 +1,37 @@ +l-marker( + v-for="(place, index) in journey.leg_get().places.activities", + :key="'activities'+index", + :lat-lng="place.latlon" + ) + l-icon( + v-if="place.step == journey.sel_day", + v-html="generate_marker(place)" + ) + l-icon( + v-else-if="place.step == -1 || place.step == undefined", + v-html="generate_marker(place, 'gray')" + ) + l-icon(v-else-if="edit_active", v-html="generate_marker(place, 'lightgray')") + l-icon(v-else) + l-popup + h1.row.text-medium.text-center {{ place.sname }} + span.row.text-small.text-gray {{ place.display_name }} + span(v-if="edit_active") + .row.input(style="margin-bottom:0") + textarea-autosize.col-12.col-sm-12.text-small( + placeholder="Notes", + v-model="place.notes", + :min-height="30", + :max-height="350" + ) + a.leaflet-popup-close-button.text-gray( + style="right: 0px; visibility: visible", + href="#rm", + v-on:click.prevent="place.step = -1" + ) - + a.leaflet-popup-close-button.text-gray( + style="right: 16px; visibility: visible", + href="#ad", + v-on:click.prevent="place.step = journey.sel_day" + ) + + span.row.text-small.text-dark(v-else) {{ place.notes }} diff --git a/template/module/journey/map/hotel.pug b/template/module/journey/map/hotel.pug new file mode 100644 index 0000000..d19bea4 --- /dev/null +++ b/template/module/journey/map/hotel.pug @@ -0,0 +1,18 @@ +l-marker( + v-if="journey.leg_get().hotel", + :lat-lng="journey.leg_get().hotel.latlon" + ) + l-icon(v-html="generate_marker(journey.leg_get().hotel, 'darkblue')") + l-popup + h1.row.text-medium.text-center {{ journey.leg_get().hotel.sname }} + span.row.text-small.text-gray {{ journey.leg_get().hotel.display_name }} + span(v-if="edit_active") + .row.input(style="margin-bottom:0;") + textarea-autosize.col-12.col-sm-12.text-small( + placeholder="Notes", + v-model="journey.leg_get().hotel.notes", + :min-height="30", + :max-height="350" + ) + span.row.text-small.text-white(v-else) {{ journey.leg_get().hotel.notes }} + \ No newline at end of file diff --git a/template/module/journey/map/override.pug b/template/module/journey/map/override.pug new file mode 100644 index 0000000..c03d5e7 --- /dev/null +++ b/template/module/journey/map/override.pug @@ -0,0 +1,5 @@ +l-marker( + v-if="map_override.active", + :lat-lng="map_override.center" + ) + l-icon(v-html="generate_marker('plus', 'darkgreen')") \ No newline at end of file diff --git a/template/module/journey/map/restaurants.pug b/template/module/journey/map/restaurants.pug new file mode 100644 index 0000000..02a9cfe --- /dev/null +++ b/template/module/journey/map/restaurants.pug @@ -0,0 +1,18 @@ +l-marker( + v-for="(place, index) in journey.leg_get().places.restaurants", + :key="'restaurants'+index" + :lat-lng="place.latlon" + ) + l-icon(v-html="generate_marker(place, 'cadetblue')") + l-popup + h1.row.text-medium.text-center {{ place.sname }} + span.row.text-small.text-gray {{ place.display_name }} + span(v-if="edit_active") + .row.input(style="margin-bottom:0") + textarea-autosize.col-12.col-sm-12.text-small( + placeholder="Notes" + v-model="place.notes" + :min-height="30" + :max-height="350" + ) + span.row.text-small.text-dark(v-else) {{ place.notes }} diff --git a/template/module/journey/map/right_menu.pug b/template/module/journey/map/right_menu.pug new file mode 100644 index 0000000..3601232 --- /dev/null +++ b/template/module/journey/map/right_menu.pug @@ -0,0 +1,6 @@ +.map-menu + .map-menu-item( v-if="query.type" @click="query.type=''" v-html="generate_icon('close')") + .map-menu-item(v-if="!query.type" @click="query.type='hotel'" v-html="generate_icon('bed')") + .map-menu-item(v-if="!query.type" @click="query.type='restaurant'" v-html="generate_icon('utensils')") + .map-menu-item(v-if="!query.type" @click="query.type='place'" v-html="generate_icon('star')") + .map-menu-item(v-if="!query.type" @click="query.type='flight'" v-html="generate_icon('plane')") \ No newline at end of file diff --git a/template/module/journey/map/travel.pug b/template/module/journey/map/travel.pug new file mode 100644 index 0000000..e3ee144 --- /dev/null +++ b/template/module/journey/map/travel.pug @@ -0,0 +1,9 @@ +div(v-for= "travel in journey.leg_get().travel") + l-polyline(:lat-lngs="travel.path" :color="travel.color || 'gray'") + l-marker( + v-for="(place, index) in travel.path" + :key="'plane'+index" + :lat-lng="place" + ) + l-icon(v-html="generate_icon('plane', travel.color || 'gray', generate_rotation(index,travel.path), 'travel-path-icon')" + ) \ No newline at end of file diff --git a/template/module/journey_leg.pug b/template/module/journey_leg.pug deleted file mode 100644 index aee7a18..0000000 --- a/template/module/journey_leg.pug +++ /dev/null @@ -1,119 +0,0 @@ -div(v-for="(e, idx) in journey.data.main", :key="idx") - .bg-dark.text-white(v-if="journey.sel_leg == idx") - .container.section - .row.text-center - .input.col-sm-2 - input(v-model="journey.leg_get(idx).title") - .input.col-sm-2 - input( - placeholder="Day title", - v-model="journey.leg_get(idx).day_title[journey.sel_day]" - ) - .col-sm-3 - .right.input.col-sm-2 - input( - disabled="", - :value="journey.date_sel() + ' (' + journey.sel_day + ')'" - ) - .row - .map-container(:class="{ 'col-9': !drawer_active, 'col-7': drawer_active }") - include map.pug - .drawer-container(:class="{ 'col-3': drawer_active, 'col-0': !drawer_active }") - .row.text-center - .input.text-dark(style="width: 100%") - input( - type="search" - @input="search_active" - placeholder="Search ... " - ) - ul - li( - v-for="item in query.res" - :key="item.id" - @mouseover="drawer_hover_item(item)" - @mouseleave="drawer_hover_item()" - @click="drawer_click_item(item)" ) - | {{ item.name }} - - .col-3.col-ssm-12 - .row.text-center - div - label Date Range ({{ journey.leg_len(idx) }}) - .input.text-dark - date-picker( - :lang="lang", - v-model="journey.data.main[idx].date_range", - range="", - format="ddd D MMM", - placeholder="Date Range", - v-on:change="journey.date_update(idx)" - ) - .row.text-center - div - label Hotel - multiselect#ajax( - v-model="journey.data.main[idx].hotel", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :options="query.res", - :searchable="true", - :loading="query.type=='hotel'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="1", - :max-height="600", - @search-change="search_hotel" - ) - .row.text-center - div - label Restoration - multiselect#ajax( - v-model="journey.data.main[idx].places.restaurants", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :multiple="true", - :options="query.res", - :searchable="true", - :loading="query.type == 'restaurant'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="10", - :max-height="600", - @search-change="search_restaurant" - ) - .row.text-center - div - label Activities - multiselect#ajax( - v-model="journey.data.main[idx].places.activities", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :multiple="true", - :options="query.res", - :searchable="true", - :loading="query.type=='place'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="10", - :max-height="600", - @search-change="search_place" - ) - .row.text-center - div - label Notes - .input.text-dark(style="width: 100%") - textarea-autosize.text-small( - v-model="journey.data.main[idx].notes", - placeholder="Notes", - :min-height="30", - :max-height="350" - ) diff --git a/template/module/journey_nav.pug b/template/module/journey_nav.pug deleted file mode 100644 index 3a2ed78..0000000 --- a/template/module/journey_nav.pug +++ /dev/null @@ -1,20 +0,0 @@ -draggable.scroll-content.list-group.bg-dark( - tag="div", - :list="journey.data.main", - handle=".handle" -) - .list-group-item.handle( - v-for="(element, idx) in journey.data.main", - :key="idx", - @click="journey.leg_sel(idx)", - :class="journey.sel_leg == idx ? 'bg-primary' : 'bg-white'" - ) - .text {{ element.title }} - i.fa.fa-times.close.fright( - style="top: 2px; right: 2px; position: absolute", - @click="journey.rm_leg(idx)" - ) - - .list-group-item.bg-white(@click="journey.add_leg()") - .text Add Leg - i.fa.fa-plus.add(style="top: 12px; right: 5px; position: absolute") diff --git a/template/module/map.pug b/template/module/map.pug deleted file mode 100644 index 19e4da8..0000000 --- a/template/module/map.pug +++ /dev/null @@ -1,99 +0,0 @@ -l-map( - - :zoom.sync="journey.leg_get().map.zoom", - :center.sync="journey.leg_get().map.center", - style="padding-top: 100%" - ref="map" -) - l-tile-layer( - url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", - attribution="© OpenStreetMap contributors" - ) - l-control-scale(position="topright", :imperial="false", :metric="true") - l-marker( - v-if="map_override.active", - :lat-lng="map_override.center" - ) - l-icon(v-html="generate_marker('plus', 'darkgreen')") - - l-marker( - v-if="journey.data.main[idx].hotel", - :lat-lng="journey.data.main[idx].hotel.latlon" - ) - l-icon(v-html="generate_marker(journey.data.main[idx].hotel, 'darkblue')") - l-popup - h1.row.text-medium.text-center {{ journey.data.main[idx].hotel.sname }} - span.row.text-small.text-gray {{ journey.data.main[idx].hotel.display_name }} - span(v-if="edit_active") - .row.input(style="margin-bottom:0;") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", - v-model="journey.data.main[idx].hotel.notes", - :min-height="30", - :max-height="350" - ) - span.row.text-small.text-white(v-else) {{ journey.data.main[idx].hotel.notes }} - l-marker( - v-for="(place, index) in journey.data.main[idx].places.activities", - :key="'activities'+index", - :lat-lng="place.latlon" - ) - l-icon( - v-if="place.step == journey.sel_day", - v-html="generate_marker(place)" - ) - l-icon( - v-else-if="place.step == -1 || place.step == undefined", - v-html="generate_marker(place, 'gray')" - ) - l-icon(v-else-if="edit_active", v-html="generate_marker(place, 'lightgray')") - l-icon(v-else) - l-popup - h1.row.text-medium.text-center {{ place.sname }} - span.row.text-small.text-gray {{ place.display_name }} - span(v-if="edit_active") - .row.input - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", - v-model="place.notes", - :min-height="30", - :max-height="350" - ) - a.leaflet-popup-close-button.text-gray( - style="right: 0px; visibility: visible", - href="#rm", - v-on:click.prevent="place.step = -1" - ) - - a.leaflet-popup-close-button.text-gray( - style="right: 16px; visibility: visible", - href="#ad", - v-on:click.prevent="place.step = journey.sel_day" - ) + - span.row.text-small.text-dark(v-else) {{ place.notes }} - l-marker( - v-for="(place, index) in journey.data.main[idx].places.restaurants", - :key="'restaurants'+index" - :lat-lng="place.latlon" - ) - l-icon(v-html="generate_marker(place, 'cadetblue')") - l-popup - h1.row.text-medium.text-center {{ place.sname }} - span.row.text-small.text-gray {{ place.display_name }} - span(v-if="edit_active") - .row.input - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes" - v-model="place.notes" - :min-height="30" - :max-height="350" - ) - span.row.text-small.text-dark(v-else) {{ place.notes }} - - div(v-for= "travel in journey.data.main[idx].travel") - l-polyline(:lat-lngs="travel.path" :color="travel.color || 'gray'") - l-marker( - v-for="(place, index) in travel.path" - :key="'plane'+index" - :lat-lng="place" - ) - l-icon(v-html="generate_icon('plane', travel.color || 'gray', generate_rotation(index,travel.path))") \ No newline at end of file diff --git a/template/module/nav_pub.pug b/template/module/view/nav.pug similarity index 100% rename from template/module/nav_pub.pug rename to template/module/view/nav.pug diff --git a/template/module/short_sec.pug b/template/module/view/short_leg.pug similarity index 100% rename from template/module/short_sec.pug rename to template/module/view/short_leg.pug diff --git a/template/module/view_step.pug b/template/module/view/view_day.pug similarity index 100% rename from template/module/view_step.pug rename to template/module/view/view_day.pug diff --git a/template/short.pug b/template/short.pug index f4fdd09..90390db 100644 --- a/template/short.pug +++ b/template/short.pug @@ -1,10 +1,10 @@ doctype html include module/head.pug main#app(v-cloak) - include module/nav_pub.pug + include module/view/nav.pug div( v-for="(item, idx) in journey.data.main", :class="idx % 2 === 0 ? 'bg-dark text-white' : ''" ) - include module/short_sec.pug + include module/view/short_leg.pug include module/foot.pug diff --git a/template/view.pug b/template/view.pug index 7230689..96c486d 100644 --- a/template/view.pug +++ b/template/view.pug @@ -2,5 +2,5 @@ doctype html include module/head.pug main#app(v-cloak) div(v-if="journey.data.main[journey.sel_leg] != undefined") - include module/view_step.pug + include module/view/view_day.pug include module/foot.pug -- 2.47.2 From 7af6d04dd1813d877d370fe88b0e44753e15f72d Mon Sep 17 00:00:00 2001 From: soraefir Date: Fri, 28 Feb 2025 01:43:32 +0100 Subject: [PATCH 72/95] wip --- public/css/index.css | 104 +++++++++++++++--------- src/client/old.js | 45 +++++----- template/module/foot.pug | 1 - template/module/head.pug | 8 -- template/module/journey/leg/drawer.pug | 4 +- template/module/journey/leg/old_cfg.pug | 80 +++++++++--------- 6 files changed, 128 insertions(+), 114 deletions(-) diff --git a/public/css/index.css b/public/css/index.css index 94c8fa1..2c167f6 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -1,3 +1,30 @@ +:root { + --black: #030B12; + --darkdark: #0C1D2E; + --dark: #203A53; + --lightdark: #425F7C; + --light: #93A9BE; + --lightlight: #B6C5D5; + --white: #F0F3F7; + --orange: ##F5B97D; + --yellow: #F5F57D; + --green: #B9F57D; + --turquoise: #7DF5B9; + --blue: #7DB9F5; + --purple: #B97DF5; + --pink: #F57DB9; + --red: #F57D7D; + + --pri: var(--blue); + --alt: var(--pink); + --valid: var(--green); + --error: var(--red); + --warn: var(--orange); + --info: var(--yellow); + --bg: var(--darkdark); + --fg: var(--white); +} + /** * SETTINGS */ @@ -8,66 +35,66 @@ * BACKGROUND */ .bg-primary { - background-color: #03a9f4; + background-color: var(--blue); } .bg-dark { - background-color: #18232f; + background-color: var(--darkdark); } .bg-secondary { - background-color: #e91e63; + background-color: var(--pink); } .bg-white { - background-color: #fff; + background-color: var(--white); } .bg-success { - background-color: #4caf50; + background-color: var(--green); } .bg-info { - background-color: #5bc0de; + background-color: var(--yellow); } .bg-warning { - background-color: #f0ad4e; + background-color: var(--orange); } .bg-error { - background-color: #e74c3c; + background-color: var(--red); } .bg-gray { - background-color: #969da6; + background-color: var(--lightdark); } .bg-gray-light { - background-color: #eceff1; + background-color: var(--lightlight); } /** * BORDER */ .border { - border: 1px solid #d5d9db; + border: 1px solid var(--white); } .border-bottom { - border-bottom: 1px solid #d5d9db; + border-bottom: 1px solid var(--white); } .border-left { - border-left: 1px solid #d5d9db; + border-left: 1px solid var(--white); } .border-right { - border-right: 1px solid #d5d9db; + border-right: 1px solid var(--white); } .border-top { - border-top: 1px solid #d5d9db; + border-top: 1px solid var(--white); } /** @@ -313,16 +340,16 @@ body { } a { - color: #03a9f4; + color: var(--blue); text-decoration: none; } a:hover { - color: rgba(3, 169, 244, 0.8); + color: color-mix(in srgb, var(--color-primary), #FFF 15%); } a:focus { - color: #03a9f4; + color: var(--blue); } .text-huge, @@ -647,7 +674,7 @@ button { .button--outlined { background-color: transparent; - border: 1px solid #d5d9db; + border: 1px solid var(--white); color: #03a9f4; } @@ -708,7 +735,7 @@ input:-webkit-autofill { .textarea, .input, .select { - border: 1px solid #d5d9db; + border: 1px solid var(--white); border-radius: 3px; box-shadow: none; display: inline-block; @@ -876,7 +903,7 @@ input:-webkit-autofill { .checkbox input[type="checkbox"]+label::before { background-color: #eceff1; - border: 1px solid #d5d9db; + border: 1px solid var(--white); border-radius: 3px; content: ""; display: inline-block; @@ -929,7 +956,7 @@ input:-webkit-autofill { .radio input[type="radio"]+label::before { background-color: #eceff1; - border: 1px solid #d5d9db; + border: 1px solid var(--white); border-radius: 20px; content: ""; display: inline-block; @@ -1580,7 +1607,7 @@ input:-webkit-autofill { */ .table { background-color: #eceff1; - border: 1px solid #d5d9db; + border: 1px solid var(--white); border-collapse: collapse; color: #272727; max-width: 100%; @@ -1589,13 +1616,13 @@ input:-webkit-autofill { .table th, .table td { - border-bottom: 1px solid #d5d9db; + border-bottom: 1px solid var(--white); padding: 8px; position: relative; } .table thead { - border-bottom: 1px solid #d5d9db; + border-bottom: 1px solid var(--white); } .table th { @@ -1670,7 +1697,7 @@ input:-webkit-autofill { } .table--responsive td:first-child { - border-top: 1px solid #d5d9db; + border-top: 1px solid var(--white); } .table--responsive th, @@ -1682,7 +1709,7 @@ input:-webkit-autofill { .table--responsive th, .table--responsive td { - border-top: 1px solid #d5d9db; + border-top: 1px solid var(--white); display: table-cell; } } @@ -1700,7 +1727,7 @@ input:-webkit-autofill { * */ .tabs { - border-bottom: 1px solid #d5d9db; + border-bottom: 1px solid var(--white); text-align: center; } @@ -3178,7 +3205,7 @@ li { } .map-menu-item { - background-color: darkslategrey; + background-color: var(--darkdark); padding: 5px; border-radius: 50%; cursor: pointer; @@ -3195,11 +3222,10 @@ li { .spinner { position: absolute; - right: 1px; - top: 1px; + right: 0; + top: 0; width: 40px; - height: 38px; - background: #fff; + height: 40px; display: block } @@ -3209,14 +3235,12 @@ li { content: ""; top: 50%; left: 50%; - margin: -8px 0 0 -8px; - width: 16px; - height: 16px; + margin: -12px 0 0 -12px; + width: 24px; + height: 24px; border-radius: 100%; - border: 2px solid transparent; - border-top-color: #41b883; - -webkit-box-shadow: 0 0 0 1px transparent; - box-shadow: 0 0 0 1px transparent + border: 3px solid transparent; + border-top-color: var(--blue); } .spinner:before { diff --git a/src/client/old.js b/src/client/old.js index 66f3eca..038991b 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -12,7 +12,7 @@ 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); -Vue.component("multiselect", window.VueMultiselect.default); +// Vue.component("multiselect", window.VueMultiselect.default); Vue.use(window.VueTextareaAutosize); const app = new Vue({ @@ -23,7 +23,7 @@ const app = new Vue({ map_override: { active: false, center: [0, 0] }, query: { - type: "", res: [], + type: "", res: [], load: false, }, impexp: "", lang: { @@ -113,32 +113,28 @@ const app = new Vue({ }, search_nominatim: function (f) { - return (q) => { - this.query.type = f; - return 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]; - }); - this.query.res = r; - return r + 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]; }); - } + this.query.load = false; + this.query.res = r; + return r + }); }, search_travel: function (f) { - return (q) => { - this.query.type = f; - return 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: 5_000_000 }).map(v => [v.lat, v.lng]) - el.type = "flight"; - }); - this.query.res = r; - return r; + 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: 5_000_000 }).map(v => [v.lat, v.lng]) + el.type = "flight"; }); - } + this.query.load = false; + this.query.res = r; + return r; + }); }, drawer_hover_item: function (item) { @@ -166,6 +162,7 @@ const app = new Vue({ 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); diff --git a/template/module/foot.pug b/template/module/foot.pug index 0ee055f..8580614 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -3,7 +3,6 @@ script(src="https://unpkg.com/leaflet") script(src="https://unpkg.com/vue@2") script(src="https://unpkg.com/vue2-datepicker") script(src="https://unpkg.com/vue-textarea-autosize") -script(src="https://unpkg.com/vue-multiselect@2") script(src="https://unpkg.com/vue2-leaflet") script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vuedraggable") diff --git a/template/module/head.pug b/template/module/head.pug index 6252ff0..f0ae469 100644 --- a/template/module/head.pug +++ b/template/module/head.pug @@ -11,15 +11,7 @@ head link(rel="stylesheet", href="/public/css/index.css") link(rel="stylesheet", href="https://unpkg.com/vue2-datepicker/index.css") - link( - rel="stylesheet", - href="https://unpkg.com/vue-multiselect@2/dist/vue-multiselect.min.css" - ) link(rel="stylesheet", href="https://unpkg.com/leaflet/dist/leaflet.css") - link( - rel="stylesheet", - href="https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.css" - ) link( rel="stylesheet", href="https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css" diff --git a/template/module/journey/leg/drawer.pug b/template/module/journey/leg/drawer.pug index 76b4b99..9a9a330 100644 --- a/template/module/journey/leg/drawer.pug +++ b/template/module/journey/leg/drawer.pug @@ -1,10 +1,12 @@ -.row.text-center +.row .input.text-dark(style="width: 100%") input( type="search" @input="search_active" placeholder="Search ... " + style="width:85%;" ) + .spinner(v-if="query.load") ul li( v-for="item in query.res" diff --git a/template/module/journey/leg/old_cfg.pug b/template/module/journey/leg/old_cfg.pug index 027df9c..8b9faa2 100644 --- a/template/module/journey/leg/old_cfg.pug +++ b/template/module/journey/leg/old_cfg.pug @@ -1,45 +1,45 @@ div div - .row.text-center - div - label Hotel - multiselect#ajax( - v-model="journey.leg_get().hotel", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :options="query.res", - :searchable="true", - :loading="query.type=='hotel'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="1", - :max-height="600", - @search-change="search_hotel" - ) - .row.text-center - div - label Restoration - multiselect#ajax( - v-model="journey.leg_get().places.restaurants", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :multiple="true", - :options="query.res", - :searchable="true", - :loading="query.type == 'restaurant'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="10", - :max-height="600", - @search-change="search_restaurant" - ) - .row.text-center + //- .row.text-center + //- div + //- label Hotel + //- multiselect#ajax( + //- v-model="journey.leg_get().hotel", + //- label="sname", + //- track-by="place_id", + //- placeholder="Type to search", + //- open-direction="bottom", + //- :options="query.res", + //- :searchable="true", + //- :loading="query.type=='hotel'", + //- :internal-search="false", + //- :clear-on-select="false", + //- :options-limit="50", + //- :limit="1", + //- :max-height="600", + //- @search-change="search_hotel" + //- ) + //- .row.text-center + //- div + //- label Restoration + //- multiselect#ajax( + //- v-model="journey.leg_get().places.restaurants", + //- label="sname", + //- track-by="place_id", + //- placeholder="Type to search", + //- open-direction="bottom", + //- :multiple="true", + //- :options="query.res", + //- :searchable="true", + //- :loading="query.type == 'restaurant'", + //- :internal-search="false", + //- :clear-on-select="false", + //- :options-limit="50", + //- :limit="10", + //- :max-height="600", + //- @search-change="search_restaurant" + //- ) + //- .row.text-center div label Activities multiselect#ajax( -- 2.47.2 From 62956dd4b19fe1c95c3e167f8f9c00b4e3c3adbe Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:49:41 +0100 Subject: [PATCH 73/95] Update src/client/api.ts --- src/client/api.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/client/api.ts b/src/client/api.ts index 674d920..8ac2945 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -78,14 +78,13 @@ export const is_restauration_type = (e: NominatimResult) => ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].indexOf( e.type ) != -1; - export const is_attraction_type = (e: NominatimResult): boolean => [ "tourism", "leisure", "place", "amenity", - "highway", + // "highway", "historic", "natural", "waterway", @@ -95,10 +94,13 @@ export const is_attraction_type = (e: NominatimResult): boolean => "national_park", "nature_reserve", "protected_area", - ].indexOf(e.type) != -1; + ].indexOf(e.type) != -1 || is_travel_type(e); export const is_hotel_type = (e: NominatimResult): boolean => ["hotel", "hostel", "guest_house"].indexOf(e.type) != -1 +export const is_travel_type = (e: NominatimResult): boolean => + ["bus_stop", "tram_stop", "station", , "aerodrome", "parking"].indexOf(e.type) != -1 + export const icon_type = (item: string | NominatimResult): string => { if (typeof (item) == "string") { @@ -122,7 +124,7 @@ export const icon_type = (item: string | NominatimResult): string => { "place_of_worship", "attraction", "information", - "university", + "university", "theatre", "opera" ], mountain: ["peak", "viewpoint"], parking: ["parking"], -- 2.47.2 From 3ea48d69ab926232b473e5dc96159ab414a20225 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:49:59 +0100 Subject: [PATCH 74/95] Update src/client/old.js --- src/client/old.js | 88 +++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/src/client/old.js b/src/client/old.js index 038991b..e845b5c 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -15,15 +15,20 @@ Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale); // Vue.component("multiselect", window.VueMultiselect.default); Vue.use(window.VueTextareaAutosize); +var first_boot = true + 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, center: [0, 0] }, - + map_override: { active: false, elements: [] }, query: { - type: "", res: [], load: false, + type: "", res: [], load: false, sub: false, + }, + leg_nav: { + scrollInterval: null, + scrollDir: null }, impexp: "", lang: { @@ -33,14 +38,6 @@ const app = new Vue({ }, monthBeforeYear: true, }, - polyline: { - latlngs: [], - color: 'green' - }, - leg_nav: { - scrollInterval: null, - scrollDir: null - } }, methods: { start_journey: function () { window.location.href = "/" + this.journey.id }, @@ -101,7 +98,16 @@ const app = new Vue({ 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; @@ -118,6 +124,12 @@ const app = new Vue({ 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 @@ -128,9 +140,13 @@ const app = new Vue({ 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: 5_000_000 }).map(v => [v.lat, v.lng]) + { 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; @@ -140,7 +156,11 @@ const app = new Vue({ drawer_hover_item: function (item) { if (item) { this.map_override.active = true - this.map_override.center = [item.lat, item.lon] + 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 } @@ -150,13 +170,17 @@ const app = new Vue({ const tpe = this.query.type; this.query.res = []; this.query.type = null; + this.query.sub = false; this.drawer_hover_item() - 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); + 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); + } } }, @@ -172,9 +196,18 @@ const app = new Vue({ } }, + search_enable: function (f) { + this.query.type = f; + const query_in = document.getElementById('query_input') + + query_in.focus() + 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); @@ -187,8 +220,8 @@ const app = new Vue({ nav_mousemove(e) { const c = document.querySelector('.scroll-content') const newDir = - e.pageX < c.offsetWidth * 0.2 ? 'left' : - (e.pageX > c.offsetWidth * 0.8 ? 'right' : this.leg_nav.scrollDir) + e.pageX < c.offsetWidth * 0.1 ? 'left' : + (e.pageX > 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); @@ -196,6 +229,7 @@ const app = new Vue({ }, nav_mouseleave(e) { clearInterval(this.leg_nav.scrollInterval); + this.leg_nav.scrollDir = 'none' this.leg_nav.scrollInterval = null }, }, @@ -222,13 +256,9 @@ const app = new Vue({ } }); - api.load(this.journey.id).then((r) => (app.journey.data = migrator(r))); - - // this.search_travel("flight")("qf1").then(r => { - // // this.polyline.latlngs = r.map(e => e.path) - // this.journey.data.main[this.journey.sel_leg].travel = r; - // }); - + api.load(this.journey.id).then((r) => { + app.journey.data = migrator(r) + }); }, watch: { journey: { -- 2.47.2 From b030286f9c1b53219b8dc54c815be195c1bafe47 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:50:21 +0100 Subject: [PATCH 75/95] Update src/client/types/format.ts --- src/client/types/format.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client/types/format.ts b/src/client/types/format.ts index ba75269..335f189 100644 --- a/src/client/types/format.ts +++ b/src/client/types/format.ts @@ -8,6 +8,7 @@ declare global { interface geoloc { latlon: [number, number] notes: string + step: -1 } interface map { @@ -25,7 +26,7 @@ declare global { hotel: geoloc | null places: { restaurants: geoloc[] - places: geoloc[] + activities: geoloc[] } notes: string } @@ -49,7 +50,7 @@ const leg_template: leg = { map: { zoom: 2, center: { lng: 0, lat: 0 } }, travel: [], hotel: null, - places: { restaurants: [], places: [] }, + places: { restaurants: [], activities: [] }, notes: "", date_range: null } -- 2.47.2 From 208bf1805ecc3d3b5ef9455317127e0384d5926a Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:50:32 +0100 Subject: [PATCH 76/95] Update src/client/types/geom.ts --- src/client/types/geom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/types/geom.ts b/src/client/types/geom.ts index 10a281a..23a864a 100644 --- a/src/client/types/geom.ts +++ b/src/client/types/geom.ts @@ -161,5 +161,5 @@ function recursiveMidPoint(src: LatLng, dst: LatLng, opt: { step?: number, dist? } export function getGeoLine(src: LatLng, dst: LatLng, opt: { step?: number, dist?: number }) { - return recursiveMidPoint(src, dst, opt, 0) + return recursiveMidPoint(src, dst, opt, 1) } \ No newline at end of file -- 2.47.2 From 6260d396e5364b4c3f418177181b9ccdbd58e035 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:50:51 +0100 Subject: [PATCH 77/95] Update src/client/types/migration.ts --- src/client/types/migration.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/types/migration.ts b/src/client/types/migration.ts index c6dfd9f..2ccf0c0 100644 --- a/src/client/types/migration.ts +++ b/src/client/types/migration.ts @@ -6,7 +6,8 @@ function migrate_A_to_0(e: journey): journey { e.main.forEach((v) => { v.date_range = v.date_range || (v as any).dateRange; v.day_title = v.day_title || (v as any).step_title; - v.travel; + v.places.activities = v.places.activities || (v as any).places.places; + v.travel = v.travel || []; }) console.log(e) return e; -- 2.47.2 From 0ece752fd46d9ac2385d6e2a8728b5924abbba04 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:51:32 +0100 Subject: [PATCH 78/95] Update template/module/journey/map.pug --- template/module/journey/map.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/module/journey/map.pug b/template/module/journey/map.pug index 6acc613..db88834 100644 --- a/template/module/journey/map.pug +++ b/template/module/journey/map.pug @@ -2,7 +2,7 @@ l-map( :zoom.sync="journey.leg_get().map.zoom", :center.sync="journey.leg_get().map.center", style="height:100%" - ref="map" + no-blocking-animations=true ) l-tile-layer( url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", -- 2.47.2 From d68a148b403907f7d812b4711498d81a5f45abb2 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:51:42 +0100 Subject: [PATCH 79/95] Update template/module/journey/leg/drawer.pug --- template/module/journey/leg/drawer.pug | 61 ++++++++++++++++++++------ 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/template/module/journey/leg/drawer.pug b/template/module/journey/leg/drawer.pug index 9a9a330..9deaa70 100644 --- a/template/module/journey/leg/drawer.pug +++ b/template/module/journey/leg/drawer.pug @@ -1,17 +1,50 @@ -.row - .input.text-dark(style="width: 100%") - input( - type="search" - @input="search_active" - placeholder="Search ... " - style="width:85%;" - ) - .spinner(v-if="query.load") - ul - li( - v-for="item in query.res" - :key="item.id" +.input.text-dark(style="width: 100%") + input#query_input( + type="search" + @input="search_active" + placeholder="Search ... " + style="width:85%;" + ) + .spinner(v-if="query.load") +div(style="width:100%" + v-if="['hotel', 'restaurant', 'place','other', 'travel'].indexOf(query.type)>=0") + template(v-for="(item, idx) in query.res" ) + .col-12.bg-white.text-dark( + style="display:flex;align-items:center; border-radius:3px;" + :key="'q'+idx" @mouseover="drawer_hover_item(item)" @mouseleave="drawer_hover_item()" @click="drawer_click_item(item)" ) - | {{ item.name }} \ No newline at end of file + div( v-html="generate_icon(item, 'var(--dark)')") + .col-10() + | {{ item.name }} + .bg-dark.divider( + :key="'qdiv'+idx" style="height:1px" ) + .col-12.bg-white.text-dark( + v-if="query.load==false && query.res.length==0" + style="display:flex;align-items:center; border-radius:3px;" ) + div( v-html="generate_icon('star', 'var(--dark)')") + .col-10() + | Add custom + + .col-12.text-white.text-center( + ) {{query.load? `Loading ...` : `Found ${query.res.length} results`}} +div(style="width:100%" + v-else-if="['flight'].indexOf(query.type)>=0") + template(v-for="(item, idx) in query.res" ) + .col-12.bg-white.text-dark( + style="display:flex;align-items:center; border-radius:3px;" + :key="'q'+idx" + @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(style="width:100%" v-else) + template() + .col-12.bg-white.text-dark( + style="display:flex;align-items:center; border-radius:3px;") + | Unsuppored Query type {{query.type}} \ No newline at end of file -- 2.47.2 From 4a10318b747cc55f4da701fb799297c4c84b578f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:52:03 +0100 Subject: [PATCH 80/95] Update template/module/journey/leg/nav.pug --- template/module/journey/leg/nav.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/module/journey/leg/nav.pug b/template/module/journey/leg/nav.pug index 42fdebc..94802f3 100644 --- a/template/module/journey/leg/nav.pug +++ b/template/module/journey/leg/nav.pug @@ -1,5 +1,5 @@ .scroll-handler( - @mouveleave="nav_mouseleave" + @mouseleave="nav_mouseleave" @mousemove="nav_mousemove") draggable.scroll-content.list-group.bg-dark( tag="div", -- 2.47.2 From 8820e4990a67a7f1b1651f2db7ed56938ccc43cc Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:52:14 +0100 Subject: [PATCH 81/95] Update template/module/journey/leg/old_cfg.pug --- template/module/journey/leg/old_cfg.pug | 59 ------------------------- 1 file changed, 59 deletions(-) diff --git a/template/module/journey/leg/old_cfg.pug b/template/module/journey/leg/old_cfg.pug index 8b9faa2..06b75f4 100644 --- a/template/module/journey/leg/old_cfg.pug +++ b/template/module/journey/leg/old_cfg.pug @@ -1,64 +1,5 @@ div div - //- .row.text-center - //- div - //- label Hotel - //- multiselect#ajax( - //- v-model="journey.leg_get().hotel", - //- label="sname", - //- track-by="place_id", - //- placeholder="Type to search", - //- open-direction="bottom", - //- :options="query.res", - //- :searchable="true", - //- :loading="query.type=='hotel'", - //- :internal-search="false", - //- :clear-on-select="false", - //- :options-limit="50", - //- :limit="1", - //- :max-height="600", - //- @search-change="search_hotel" - //- ) - //- .row.text-center - //- div - //- label Restoration - //- multiselect#ajax( - //- v-model="journey.leg_get().places.restaurants", - //- label="sname", - //- track-by="place_id", - //- placeholder="Type to search", - //- open-direction="bottom", - //- :multiple="true", - //- :options="query.res", - //- :searchable="true", - //- :loading="query.type == 'restaurant'", - //- :internal-search="false", - //- :clear-on-select="false", - //- :options-limit="50", - //- :limit="10", - //- :max-height="600", - //- @search-change="search_restaurant" - //- ) - //- .row.text-center - div - label Activities - multiselect#ajax( - v-model="journey.leg_get().places.activities", - label="sname", - track-by="place_id", - placeholder="Type to search", - open-direction="bottom", - :multiple="true", - :options="query.res", - :searchable="true", - :loading="query.type=='place'", - :internal-search="false", - :clear-on-select="false", - :options-limit="50", - :limit="10", - :max-height="600", - @search-change="search_place" - ) .row.text-center div label Notes -- 2.47.2 From 22f4cbda1893b50ca911ae26c85561d6b9e52bc4 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:52:24 +0100 Subject: [PATCH 82/95] Update template/module/journey/leg/top.pug --- template/module/journey/leg/top.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/module/journey/leg/top.pug b/template/module/journey/leg/top.pug index 434f6af..a42a692 100644 --- a/template/module/journey/leg/top.pug +++ b/template/module/journey/leg/top.pug @@ -20,7 +20,7 @@ placeholder="Date Range", v-on:change="journey.date_update(journey.sel_leg)" ) - .col-sm-1 + .col-sm-2 .right.col-sm-2 .input input( -- 2.47.2 From 828b2ae3cbd203c8b01ce71d7ef959df254cd92a Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:52:49 +0100 Subject: [PATCH 83/95] Update template/module/journey/map/activities.pug --- template/module/journey/map/activities.pug | 37 ++-------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/template/module/journey/map/activities.pug b/template/module/journey/map/activities.pug index e7d9f0d..a7bb1c5 100644 --- a/template/module/journey/map/activities.pug +++ b/template/module/journey/map/activities.pug @@ -1,37 +1,6 @@ -l-marker( +include mixin-marker.pug +div( v-for="(place, index) in journey.leg_get().places.activities", :key="'activities'+index", - :lat-lng="place.latlon" ) - l-icon( - v-if="place.step == journey.sel_day", - v-html="generate_marker(place)" - ) - l-icon( - v-else-if="place.step == -1 || place.step == undefined", - v-html="generate_marker(place, 'gray')" - ) - l-icon(v-else-if="edit_active", v-html="generate_marker(place, 'lightgray')") - l-icon(v-else) - l-popup - h1.row.text-medium.text-center {{ place.sname }} - span.row.text-small.text-gray {{ place.display_name }} - span(v-if="edit_active") - .row.input(style="margin-bottom:0") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", - v-model="place.notes", - :min-height="30", - :max-height="350" - ) - a.leaflet-popup-close-button.text-gray( - style="right: 0px; visibility: visible", - href="#rm", - v-on:click.prevent="place.step = -1" - ) - - a.leaflet-popup-close-button.text-gray( - style="right: 16px; visibility: visible", - href="#ad", - v-on:click.prevent="place.step = journey.sel_day" - ) + - span.row.text-small.text-dark(v-else) {{ place.notes }} + +map_marker("activities", "var(--lightdark)", "var(--light)", "var(--lightlight)") \ No newline at end of file -- 2.47.2 From 2fbf2ec3e91b391c0515acb7703f57f0cc6b5f82 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:52:59 +0100 Subject: [PATCH 84/95] Update template/module/journey/map/hotel.pug --- template/module/journey/map/hotel.pug | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/template/module/journey/map/hotel.pug b/template/module/journey/map/hotel.pug index d19bea4..42947f7 100644 --- a/template/module/journey/map/hotel.pug +++ b/template/module/journey/map/hotel.pug @@ -1,18 +1,7 @@ -l-marker( +include mixin-marker.pug +div( v-if="journey.leg_get().hotel", - :lat-lng="journey.leg_get().hotel.latlon" + v-for="(place, index) in [journey.leg_get().hotel]", + :key="'hotel'+index", ) - l-icon(v-html="generate_marker(journey.leg_get().hotel, 'darkblue')") - l-popup - h1.row.text-medium.text-center {{ journey.leg_get().hotel.sname }} - span.row.text-small.text-gray {{ journey.leg_get().hotel.display_name }} - span(v-if="edit_active") - .row.input(style="margin-bottom:0;") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", - v-model="journey.leg_get().hotel.notes", - :min-height="30", - :max-height="350" - ) - span.row.text-small.text-white(v-else) {{ journey.leg_get().hotel.notes }} - \ No newline at end of file + +map_marker("hotel", "var(--darkdark)", "var(--darkdark)", "var(--darkdark)") \ No newline at end of file -- 2.47.2 From 102b873e7905265351e0f59e4e1a96de97c1af07 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:53:12 +0100 Subject: [PATCH 85/95] Add template/module/journey/map/mixin-marker.pug --- template/module/journey/map/mixin-marker.pug | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 template/module/journey/map/mixin-marker.pug diff --git a/template/module/journey/map/mixin-marker.pug b/template/module/journey/map/mixin-marker.pug new file mode 100644 index 0000000..cc4ca6b --- /dev/null +++ b/template/module/journey/map/mixin-marker.pug @@ -0,0 +1,41 @@ + +mixin map_marker(place, color_sel_c, color_sel_o, color_else) + l-marker( + :lat-lng="place.latlon" + ) + l-icon( + v-if="(place.step == journey.sel_day)" + v-html="generate_marker(place, \""+color_sel_c+"\")" + ) + l-icon( + v-else-if="(place.step >=0)" + v-html="generate_marker(place, \""+color_sel_o+"\")" + ) + l-icon( + v-else + v-html="generate_marker(place, \""+color_else+"\")" + ) + l-popup() + h1.row.text-medium.text-center {{ place.sname }} + span.row.text-small.text-gray {{ place.display_name }} + span(v-if="edit_active") + .row.input(style="margin-bottom:0") + textarea-autosize.col-12.col-sm-12.text-small( + placeholder="Notes", + v-model="place.notes", + :min-height="30", + :max-height="350" + ) + a.leaflet-popup-close-button.text-gray( + style="right: 4px; visibility: visible", + href="#rm", + v-on:click.prevent="place_delete(\""+place+"\",index)" + v-html="generate_icon('trash', 'NA')" + ) + a.leaflet-popup-close-button.text-gray( + style="right: 20px; visibility: visible", + href="#toggle_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')" + ) + span.row.text-small.text-dark(v-else) {{ place.notes }} -- 2.47.2 From 832bfa485ba5b3958af8e0ad711eb775bb84203f Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:53:26 +0100 Subject: [PATCH 86/95] Update template/module/journey/map/override.pug --- template/module/journey/map/override.pug | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/template/module/journey/map/override.pug b/template/module/journey/map/override.pug index c03d5e7..5fe6755 100644 --- a/template/module/journey/map/override.pug +++ b/template/module/journey/map/override.pug @@ -1,5 +1,11 @@ l-marker( v-if="map_override.active", - :lat-lng="map_override.center" + v-for="(el, idx) in map_override.elements" + key="'ovr'+idx" + :lat-lng="el" ) - l-icon(v-html="generate_marker('plus', 'darkgreen')") \ No newline at end of file + l-icon(v-html="generate_marker('plus', 'darkgreen')") +l-polyline( + v-if="map_override.active && map_override.elements.length>1" + :lat-lngs="map_override.elements" :color="'darkgreen'" +) \ No newline at end of file -- 2.47.2 From 6f3b005c5c6aa15bcd9ec27b9158805d6d9a41e0 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:53:33 +0100 Subject: [PATCH 87/95] Update template/module/journey/map/restaurants.pug --- template/module/journey/map/restaurants.pug | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/template/module/journey/map/restaurants.pug b/template/module/journey/map/restaurants.pug index 02a9cfe..1685cd8 100644 --- a/template/module/journey/map/restaurants.pug +++ b/template/module/journey/map/restaurants.pug @@ -1,18 +1,6 @@ -l-marker( +include mixin-marker.pug +div( v-for="(place, index) in journey.leg_get().places.restaurants", - :key="'restaurants'+index" - :lat-lng="place.latlon" + :key="'restaurants'+index", ) - l-icon(v-html="generate_marker(place, 'cadetblue')") - l-popup - h1.row.text-medium.text-center {{ place.sname }} - span.row.text-small.text-gray {{ place.display_name }} - span(v-if="edit_active") - .row.input(style="margin-bottom:0") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes" - v-model="place.notes" - :min-height="30" - :max-height="350" - ) - span.row.text-small.text-dark(v-else) {{ place.notes }} + +map_marker("restaurants", "var(--dark)", "var(--dark)", "var(--dark)") \ No newline at end of file -- 2.47.2 From 48363040d36ac4aa43deb720bc5882b49ae7729b Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:53:42 +0100 Subject: [PATCH 88/95] Update template/module/journey/map/right_menu.pug --- template/module/journey/map/right_menu.pug | 41 +++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/template/module/journey/map/right_menu.pug b/template/module/journey/map/right_menu.pug index 3601232..b61174e 100644 --- a/template/module/journey/map/right_menu.pug +++ b/template/module/journey/map/right_menu.pug @@ -1,6 +1,37 @@ .map-menu - .map-menu-item( v-if="query.type" @click="query.type=''" v-html="generate_icon('close')") - .map-menu-item(v-if="!query.type" @click="query.type='hotel'" v-html="generate_icon('bed')") - .map-menu-item(v-if="!query.type" @click="query.type='restaurant'" v-html="generate_icon('utensils')") - .map-menu-item(v-if="!query.type" @click="query.type='place'" v-html="generate_icon('star')") - .map-menu-item(v-if="!query.type" @click="query.type='flight'" v-html="generate_icon('plane')") \ No newline at end of file + div( v-if="query.type" @click="drawer_click_item()" ) + .map-menu-item(v-html="generate_icon('close')") + div(v-if="!query.type" @click="search_enable('hotel')") + .map-menu-item( v-html="generate_icon('bed')") + div(v-if="!query.type" @click="search_enable('restaurant')") + .map-menu-item( v-html="generate_icon('utensils')") + div(v-if="!query.type" @click="search_enable('place')") + .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-item(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="query.sub" @click="search_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="query.sub" @click="search_enable('other')" v-html="generate_icon('person-biking')") + + +//- .map-menu-sub { +//- display: flex; +//- flex-direction: row-reverse; +//- gap: 5px; +//- } +//- .map-menu-item, +//- .map-menu-sub-item { +//- background-color: var(--darkdark); +//- padding: 5px; +//- border-radius: 50%; +//- cursor: pointer; +//- float: right; +//- height: fit-content; +//- } +//- .vue2leaflet-map { +//- border-radius: 3px; +//- } +//- .leaflet-popup-content { +//- margin: 10px 20px; +//- } \ No newline at end of file -- 2.47.2 From c98be7a4e63cec6f80120fab9ec1e59274ac8b39 Mon Sep 17 00:00:00 2001 From: sora-ext Date: Fri, 28 Feb 2025 17:53:58 +0100 Subject: [PATCH 89/95] Update template/module/journey/map/travel.pug --- template/module/journey/map/travel.pug | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/template/module/journey/map/travel.pug b/template/module/journey/map/travel.pug index e3ee144..dee910c 100644 --- a/template/module/journey/map/travel.pug +++ b/template/module/journey/map/travel.pug @@ -1,9 +1,32 @@ -div(v-for= "travel in journey.leg_get().travel") +mixin flight_popup() + l-popup() + h1.row.text-medium.text-center {{ travel.id.toUpperCase() }} + span.row.text-small.text-gray {{ travel.from }} - {{travel.to}} + span(v-if="edit_active") + .row.input(style="margin-bottom:0") + textarea-autosize.col-12.col-sm-12.text-small( + placeholder="Notes", + v-model="travel.notes", + :min-height="30", + :max-height="350" + ) + a.leaflet-popup-close-button.text-gray( + style="right: 4px; visibility: visible", + href="#rm", + v-on:click.prevent="place_delete('flight',idx)" + v-html="generate_icon('trash', 'NA')" + ) + span.row.text-small.text-dark(v-else) {{ travel.notes }} + +div(v-for= "(travel, idx) in journey.leg_get().travel") l-polyline(:lat-lngs="travel.path" :color="travel.color || 'gray'") + +flight_popup() + l-marker( v-for="(place, index) in travel.path" :key="'plane'+index" :lat-lng="place" ) l-icon(v-html="generate_icon('plane', travel.color || 'gray', generate_rotation(index,travel.path), 'travel-path-icon')" - ) \ No newline at end of file + ) + +flight_popup() -- 2.47.2 From 52ee73a4acb7890b67870db3ed26c513951d7d7c Mon Sep 17 00:00:00 2001 From: soraefir Date: Sat, 1 Mar 2025 23:40:45 +0100 Subject: [PATCH 90/95] wip --- package.json | 12 +- public/css/index.css | 1826 ++---------------- src/client/api.ts | 2 +- src/client/old.js | 35 +- src/client/types/format.ts | 14 +- src/client/types/wrapper.ts | 1 + src/server/api_nominatim.ts | 1 + template/home.pug | 87 +- template/journey.pug | 3 +- template/module/foot.pug | 13 +- template/module/journey.pug | 3 - template/module/journey/leg.pug | 11 - template/module/journey/leg/drawer-notes.pug | 8 + template/module/journey/leg/drawer.pug | 32 +- template/module/journey/leg/nav.pug | 51 +- template/module/journey/leg/old_cfg.pug | 12 - template/module/journey/leg/top.pug | 29 +- template/module/journey/main.pug | 31 + template/module/journey/map.pug | 3 +- template/module/journey/map/mixin-marker.pug | 26 +- template/module/journey/map/right_menu.pug | 30 +- template/module/journey/map/travel.pug | 24 +- template/module/nav.pug | 38 - template/module/view/nav.pug | 7 - template/module/view/short_leg.pug | 12 +- template/view.pug | 2 +- 26 files changed, 413 insertions(+), 1900 deletions(-) delete mode 100644 template/module/journey.pug delete mode 100644 template/module/journey/leg.pug create mode 100644 template/module/journey/leg/drawer-notes.pug delete mode 100644 template/module/journey/leg/old_cfg.pug create mode 100644 template/module/journey/main.pug delete mode 100644 template/module/nav.pug diff --git a/package.json b/package.json index 9aeb0f2..a94c2a2 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "build-client": "esbuild src/client/main.ts --outfile=public/main.js --tree-shaking=true --bundle --minify --sourcemap --tsconfig=tsconfig-client.json", "build-server": "esbuild src/server/**/*.ts --outdir=build --platform=node --format=cjs", "start": "node build/main.js", - "demon": "nodemon -e ts,js,pug --watch src --watch template --watch router --exec \"yarn build && yarn start\"" + "demon": "nodemon -e ts,js --watch src --watch template --watch router --exec \"yarn build && yarn start\"" }, "repository": { "type": "git", @@ -20,19 +20,13 @@ "@fastify/leveldb": "^6.0.0", "@fastify/static": "^8.0.0", "@fastify/view": "^10.0.0", - "@prettier/plugin-pug": "^3.0.0", "@types/node": "^22.13.5", "esbuild": "^0.25.0", "fastify": "^5.2.1", "jsdom": "^26.0.0", - "leaflet": "^1.9.4", "nodemon": "^3.0.1", "prettier": "^3.5.2", "pug": "^3.0.2", - "undici": "^7.3.0", - "vue": "2", - "vue-multiselect": "2", - "vue-textarea-autosize": "^1.1.1", - "vue2-leaflet": "^2.7.1" + "undici": "^7.3.0" } -} +} \ No newline at end of file diff --git a/public/css/index.css b/public/css/index.css index 2c167f6..1202b96 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -15,22 +15,9 @@ --pink: #F57DB9; --red: #F57D7D; - --pri: var(--blue); - --alt: var(--pink); - --valid: var(--green); - --error: var(--red); - --warn: var(--orange); - --info: var(--yellow); - --bg: var(--darkdark); - --fg: var(--white); + --border-radius: 3px; } -/** - * SETTINGS - */ -/** - * COMPONENTS - */ /** * BACKGROUND */ @@ -74,74 +61,16 @@ background-color: var(--lightlight); } -/** - * BORDER - */ -.border { - border: 1px solid var(--white); -} - -.border-bottom { - border-bottom: 1px solid var(--white); -} - -.border-left { - border-left: 1px solid var(--white); -} - -.border-right { - border-right: 1px solid var(--white); -} - -.border-top { - border-top: 1px solid var(--white); -} /** * ALIGNERS */ -.aligner { - display: flex; -} -.aligner--spaceBetween { - justify-content: space-between; - width: 100%; -} - -.aligner--spaceAround { - justify-content: space-around; - width: 100%; -} - -.aligner--centerVertical { +.align { align-items: center; -} - -.aligner--centerHoritzontal { justify-content: center; } -.aligner--contentStart { - justify-content: flex-start; -} - -.aligner--contentEnd { - justify-content: flex-end; -} - -.aligner--itemTop { - align-self: flex-start; -} - -.aligner--itemBottom { - align-self: flex-end; -} - -.flex-grow, -.aligner--grow { - flex-grow: 1; -} /** * FLOATS @@ -160,88 +89,6 @@ display: table; } -/** - * MARGINS - */ -.m-xsmall { - margin: 4px; -} - -.mb-xsmall { - margin-bottom: 4px; -} - -.m-small { - margin: 8px; -} - -.mb-small { - margin-bottom: 8px; -} - -.m-medium { - margin: 16px; -} - -.mb-medium { - margin-bottom: 16px; -} - -.m-big { - margin: 36px; -} - -.mb-big { - margin-bottom: 36px; -} - -.m-huge { - margin: 48px; -} - -.mb-huge { - margin-bottom: 48px; -} - -.m-none { - margin: 0 !important; -} - -/** - * PADDINGS - */ -.p-small { - padding: 4px; -} - -.pb-small { - padding-bottom: 4px; -} - -.p-medium { - padding: 8px; -} - -.pb-medium { - padding-bottom: 8px; -} - -.p-big { - padding: 16px; -} - -.pb-big { - padding-bottom: 16px; -} - -.p-huge { - padding: 36px; -} - -.pb-huge { - padding-bottom: 36px; -} - /** * OTHERS */ @@ -253,16 +100,8 @@ overflow: hidden; } -.opacity-low { - opacity: 0.5; -} - -.rounded-corners { - border-radius: 5px; -} - .rounded { - border-radius: 100%; + border-radius: var(--border-radius); } /** @@ -285,7 +124,6 @@ } .container { - background-color: transparent; margin: 0 auto; max-width: 1380px; padding-left: 12px; @@ -477,70 +315,6 @@ h4 { text-align: left; } -/** - * BADGE - * - * Markup: - * ------- - * - *
    - *
  • Badge 1
  • - *
  • Badge 1
  • - *
- * - */ -.badge { - background-color: #eceff1; - border-radius: 3px; - color: #272727; - display: inline-block; - line-height: 1.2em; - padding: 8px 16px; -} - -.badge--big { - font-size: 1.3em; -} - -.badge--small { - font-size: 0.7em; -} - -.badge--primary { - background-color: #03a9f4; - color: #fff; -} - -.badge--secondary { - background-color: #e91e63; - color: #fff; -} - -.badge--dark { - background-color: #18232f; - color: #fff; -} - -.badge--light { - background-color: #969da6; - color: #fff; -} - -.badge--success { - background-color: #4caf50; - color: #fff; -} - -.badge--error { - background-color: #e74c3c; - color: #fff; -} - -.badge--warning { - background-color: #f0ad4e; - color: #fff; -} - /** * BUTTON * @@ -567,7 +341,6 @@ button { font-size: 16px; font-weight: 600; line-height: 1.5em; - margin: 0 8px 16px 8px; padding: 8px 16px; text-align: center; text-decoration: none; @@ -721,6 +494,7 @@ textarea { -webkit-appearance: none; -moz-appearance: none; appearance: none; + resize: none; } label { @@ -736,11 +510,10 @@ input:-webkit-autofill { .input, .select { border: 1px solid var(--white); - border-radius: 3px; + border-radius: var(--border-radius); box-shadow: none; display: inline-block; font-weight: normal; - margin-bottom: 20px; overflow: hidden; } @@ -904,7 +677,7 @@ input:-webkit-autofill { .checkbox input[type="checkbox"]+label::before { background-color: #eceff1; border: 1px solid var(--white); - border-radius: 3px; + border-radius: var(--border-radius); content: ""; display: inline-block; height: 20px; @@ -1023,16 +796,15 @@ input:-webkit-autofill { } .input { - background-color: #eceff1; - margin-right: 10px; + background-color: var(--white); padding: 0; position: relative; } .input :focus, .input :active { - background-color: #fbfbfc; - border-radius: 3px; + background-color: var(--white); + border-radius: var(--border-radius); } .input input, @@ -1080,61 +852,6 @@ input:-webkit-autofill { width: 16px; } -.input-fullWidth { - display: block; - margin-left: 0; - margin-right: 0; - width: 100%; -} - -/** - * FORM COLLAPSED (items in row without gap between them) - * - * Markup: - * ------- - * - *
- *
- * - *
- *
- * - *
- * - *
- **/ -.formCollapsed { - display: flex; - margin-bottom: 20px; -} - -.formCollapsed-item { - border-radius: 0 !important; - margin: 0 !important; -} - -.formCollapsed-item:first-child { - border-bottom-left-radius: 3px !important; - border-top-left-radius: 3px !important; -} - -.formCollapsed-item:last-child { - border-bottom-right-radius: 3px !important; - border-top-right-radius: 3px !important; -} - -.formCollapsed-item:not(:last-child) { - border-right: 0; -} - -.formCollapsed-itemPrimary { - flex: 1; -} - /** * LOADING BAR * @@ -1220,596 +937,6 @@ input:-webkit-autofill { } } -/** - * LOADING SPINNER - * - * Markup: - * --------- - *
- * - * - * - * - *
- * - */ -.loadingSpinner { - -webkit-animation: rotateLoader 4s infinite; - animation: rotateLoader 4s infinite; - -webkit-animation-timing-function: ease-in-out; - animation-timing-function: ease-in-out; - display: block; - height: 30px; - left: 50%; - margin-left: -15px; - margin-top: -15px; - position: fixed; - top: 50%; - width: 30px; - z-index: 1000; -} - -.loadingSpinner-inner { - -webkit-animation-timing-function: ease-in-out; - animation-timing-function: ease-in-out; - background-color: #e91e63; - border-radius: 100%; - display: block; - height: 9px; - position: absolute; - width: 9px; -} - -.loadingSpinner-inner:nth-child(1) { - -webkit-animation: translateBall1 1s infinite; - animation: translateBall1 1s infinite; - left: 0; - top: 0; - -webkit-transform: translate3d(4.5px, 4.5px, 0); - transform: translate3d(4.5px, 4.5px, 0); -} - -.loadingSpinner-inner:nth-child(2) { - -webkit-animation: translateBall2 1s infinite; - animation: translateBall2 1s infinite; - right: 0; - top: 0; -} - -.loadingSpinner-inner:nth-child(3) { - -webkit-animation: translateBall3 1s infinite; - animation: translateBall3 1s infinite; - bottom: 0; - right: 0; -} - -.loadingSpinner-inner:nth-child(4) { - -webkit-animation: translateBall4 1s infinite; - animation: translateBall4 1s infinite; - bottom: 0; - left: 0; -} - -@-webkit-keyframes rotateLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 25% { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); - } - - 50% { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - } - - 75% { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); - } - - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@keyframes rotateLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 25% { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); - } - - 50% { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - } - - 75% { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); - } - - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@-webkit-keyframes translateBall1 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(4.5px, 4.5px, 0); - transform: translate3d(4.5px, 4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes translateBall1 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(4.5px, 4.5px, 0); - transform: translate3d(4.5px, 4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@-webkit-keyframes translateBall2 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(-4.5px, 4.5px, 0); - transform: translate3d(-4.5px, 4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes translateBall2 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(-4.5px, 4.5px, 0); - transform: translate3d(-4.5px, 4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@-webkit-keyframes translateBall3 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(-4.5px, -4.5px, 0); - transform: translate3d(-4.5px, -4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes translateBall3 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(-4.5px, -4.5px, 0); - transform: translate3d(-4.5px, -4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@-webkit-keyframes translateBall4 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(4.5px, -4.5px, 0); - transform: translate3d(4.5px, -4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes translateBall4 { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - - 50% { - -webkit-transform: translate3d(4.5px, -4.5px, 0); - transform: translate3d(4.5px, -4.5px, 0); - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -/** - * NOTIFICATION - * - * Markup: - * ------- - * - *
Success notification
- *
Success info
- *
Success error
- *
Success warning
- * - */ -.notification { - border-radius: 3px; - color: #fff; - margin-bottom: 36px; - padding: 16px; -} - -.notification p:last-child { - margin-bottom: 0; -} - -.notification--primary { - background-color: #03a9f4; -} - -.notification--dark { - background-color: #18232f; -} - -.notification--secondary { - background-color: #e91e63; -} - -.notification--white { - background-color: #fff; -} - -.notification--success { - background-color: #4caf50; -} - -.notification--info { - background-color: #5bc0de; -} - -.notification--warning { - background-color: #f0ad4e; -} - -.notification--error { - background-color: #e74c3c; -} - -.notification--gray { - background-color: #969da6; -} - -.notification--gray-light { - background-color: #eceff1; -} - -/** - * PAGINATOR - * - * Markup: - * ------- - * - *
    - *
  • - * < Prev - *
  • - *
  • - * 1 - *
  • - *
  • - * 2 - *
  • - *
  • - * 3 - *
  • - *
  • - * Next > - *
  • - *
- */ -.paginator-item { - display: inline-block; - margin-right: 4px; -} - -.paginator-itemLink { - background-color: #eceff1; - border-radius: 3px; - display: block; - padding: 8px 16px; -} - -.paginator-itemLink.is-active { - background-color: #03a9f4; - color: #fff; - cursor: default; -} - -/** - * TABLE - * - * Markup: - * ------- - * - * - * - * - * - * - * - * - * Blue - * One - * My life fades - * - *
First columnSecond columnThird column
- * - */ -.table { - background-color: #eceff1; - border: 1px solid var(--white); - border-collapse: collapse; - color: #272727; - max-width: 100%; - width: 100%; -} - -.table th, -.table td { - border-bottom: 1px solid var(--white); - padding: 8px; - position: relative; -} - -.table thead { - border-bottom: 1px solid var(--white); -} - -.table th { - background-color: #fff; - color: #969da6; - font-size: 12px; - font-weight: normal; - padding: 8px; - white-space: nowrap; -} - -/** - * TABLE RESPONSIVE - * - * Markup: - * ------- - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
First columnSecond columnThird column
BlueOneMy life fades
GreenTwo - * when the world was powered by the black fuel... and the desert - * sprouted great cities of pipe and steel. - *
YellowThree - * A whirlwind of looting, a firestorm of fear. - *
- * - */ -.table--responsive th { - display: none; -} - -.table--responsive td { - display: block; -} - -@media (max-width: 767px) { - .table--responsive td { - border: 0; - } -} - -.table--responsive td::before { - color: #969da6; - content: attr(data-th) ": "; - display: block; - font-weight: normal; -} - -@media (min-width: 576px) { - .table--responsive td::before { - display: none; - } -} - -.table--responsive td:first-child { - border-top: 1px solid var(--white); -} - -.table--responsive th, -.table--responsive td { - text-align: left; -} - -@media (min-width: 576px) { - - .table--responsive th, - .table--responsive td { - border-top: 1px solid var(--white); - display: table-cell; - } -} - -/** - * TABS - * - * Markup: - * ------- - * - *
- * [...] - * [...] - *
- * - */ -.tabs { - border-bottom: 1px solid var(--white); - text-align: center; -} - -.tabs-item { - border-bottom: 3px solid transparent; - color: #969da6; - display: inline-block; - margin: 0 16px 0 0; - min-width: 70px; - padding: 16px; - position: relative; -} - -.tabs-item:hover { - color: #03a9f4; - text-decoration: none; -} - -.tabs-item.is-selected { - border-bottom: 3px solid #03a9f4; - color: #03a9f4; -} - -/** - * TAG - * - * Markup: - * ------- - * - *
    - *
  • Fantasy
  • - *
  • Fiction
  • - *
  • Contemporary
  • - *
- * - * - * - */ -.tag { - background-color: #eceff1; - border-radius: 3px 0 0 3px; - color: #272727; - display: inline-block; - line-height: 16px; - margin: 0 16px 16px 0; - padding: 8px; - position: relative; -} - -.tag::before { - border-bottom: 16px solid transparent; - border-left: 8px solid #eceff1; - border-top: 16px solid transparent; - content: ""; - height: 0; - position: absolute; - right: -8px; - top: 0; - width: 0; -} - -.tag::after { - background: #fff; - border-radius: 100%; - content: ""; - height: 5px; - margin-top: -2.5px; - position: absolute; - right: -2.5px; - top: 50%; - width: 5px; -} .container { width: 100%; @@ -1858,17 +985,6 @@ input:-webkit-autofill { margin-left: -12px; } -.no-gutters { - margin-left: 0; - margin-right: 0; -} - -.no-gutters>.col, -.no-gutters>[class*="col-"] { - padding-left: 0; - padding-right: 0; -} - .col-1, .col-2, .col-3, @@ -2018,102 +1134,6 @@ input:-webkit-autofill { max-width: 100%; } -.order-first { - order: -1; -} - -.order-1 { - order: 1; -} - -.order-2 { - order: 2; -} - -.order-3 { - order: 3; -} - -.order-4 { - order: 4; -} - -.order-5 { - order: 5; -} - -.order-6 { - order: 6; -} - -.order-7 { - order: 7; -} - -.order-8 { - order: 8; -} - -.order-9 { - order: 9; -} - -.order-10 { - order: 10; -} - -.order-11 { - order: 11; -} - -.order-12 { - order: 12; -} - -.offset-1 { - margin-left: 8.33333%; -} - -.offset-2 { - margin-left: 16.66667%; -} - -.offset-3 { - margin-left: 25%; -} - -.offset-4 { - margin-left: 33.33333%; -} - -.offset-5 { - margin-left: 41.66667%; -} - -.offset-6 { - margin-left: 50%; -} - -.offset-7 { - margin-left: 58.33333%; -} - -.offset-8 { - margin-left: 66.66667%; -} - -.offset-9 { - margin-left: 75%; -} - -.offset-10 { - margin-left: 83.33333%; -} - -.offset-11 { - margin-left: 91.66667%; -} - @media (min-width: 576px) { .col-sm { flex-basis: 0; @@ -2186,106 +1206,6 @@ input:-webkit-autofill { flex: 0 0 100%; max-width: 100%; } - - .order-sm-first { - order: -1; - } - - .order-sm-1 { - order: 1; - } - - .order-sm-2 { - order: 2; - } - - .order-sm-3 { - order: 3; - } - - .order-sm-4 { - order: 4; - } - - .order-sm-5 { - order: 5; - } - - .order-sm-6 { - order: 6; - } - - .order-sm-7 { - order: 7; - } - - .order-sm-8 { - order: 8; - } - - .order-sm-9 { - order: 9; - } - - .order-sm-10 { - order: 10; - } - - .order-sm-11 { - order: 11; - } - - .order-sm-12 { - order: 12; - } - - .offset-sm-0 { - margin-left: 0; - } - - .offset-sm-1 { - margin-left: 8.33333%; - } - - .offset-sm-2 { - margin-left: 16.66667%; - } - - .offset-sm-3 { - margin-left: 25%; - } - - .offset-sm-4 { - margin-left: 33.33333%; - } - - .offset-sm-5 { - margin-left: 41.66667%; - } - - .offset-sm-6 { - margin-left: 50%; - } - - .offset-sm-7 { - margin-left: 58.33333%; - } - - .offset-sm-8 { - margin-left: 66.66667%; - } - - .offset-sm-9 { - margin-left: 75%; - } - - .offset-sm-10 { - margin-left: 83.33333%; - } - - .offset-sm-11 { - margin-left: 91.66667%; - } } @media (min-width: 768px) { @@ -2360,106 +1280,6 @@ input:-webkit-autofill { flex: 0 0 100%; max-width: 100%; } - - .order-md-first { - order: -1; - } - - .order-md-1 { - order: 1; - } - - .order-md-2 { - order: 2; - } - - .order-md-3 { - order: 3; - } - - .order-md-4 { - order: 4; - } - - .order-md-5 { - order: 5; - } - - .order-md-6 { - order: 6; - } - - .order-md-7 { - order: 7; - } - - .order-md-8 { - order: 8; - } - - .order-md-9 { - order: 9; - } - - .order-md-10 { - order: 10; - } - - .order-md-11 { - order: 11; - } - - .order-md-12 { - order: 12; - } - - .offset-md-0 { - margin-left: 0; - } - - .offset-md-1 { - margin-left: 8.33333%; - } - - .offset-md-2 { - margin-left: 16.66667%; - } - - .offset-md-3 { - margin-left: 25%; - } - - .offset-md-4 { - margin-left: 33.33333%; - } - - .offset-md-5 { - margin-left: 41.66667%; - } - - .offset-md-6 { - margin-left: 50%; - } - - .offset-md-7 { - margin-left: 58.33333%; - } - - .offset-md-8 { - margin-left: 66.66667%; - } - - .offset-md-9 { - margin-left: 75%; - } - - .offset-md-10 { - margin-left: 83.33333%; - } - - .offset-md-11 { - margin-left: 91.66667%; - } } @media (min-width: 992px) { @@ -2535,105 +1355,6 @@ input:-webkit-autofill { max-width: 100%; } - .order-lg-first { - order: -1; - } - - .order-lg-1 { - order: 1; - } - - .order-lg-2 { - order: 2; - } - - .order-lg-3 { - order: 3; - } - - .order-lg-4 { - order: 4; - } - - .order-lg-5 { - order: 5; - } - - .order-lg-6 { - order: 6; - } - - .order-lg-7 { - order: 7; - } - - .order-lg-8 { - order: 8; - } - - .order-lg-9 { - order: 9; - } - - .order-lg-10 { - order: 10; - } - - .order-lg-11 { - order: 11; - } - - .order-lg-12 { - order: 12; - } - - .offset-lg-0 { - margin-left: 0; - } - - .offset-lg-1 { - margin-left: 8.33333%; - } - - .offset-lg-2 { - margin-left: 16.66667%; - } - - .offset-lg-3 { - margin-left: 25%; - } - - .offset-lg-4 { - margin-left: 33.33333%; - } - - .offset-lg-5 { - margin-left: 41.66667%; - } - - .offset-lg-6 { - margin-left: 50%; - } - - .offset-lg-7 { - margin-left: 58.33333%; - } - - .offset-lg-8 { - margin-left: 66.66667%; - } - - .offset-lg-9 { - margin-left: 75%; - } - - .offset-lg-10 { - margin-left: 83.33333%; - } - - .offset-lg-11 { - margin-left: 91.66667%; - } } @media (min-width: 1200px) { @@ -2709,288 +1430,14 @@ input:-webkit-autofill { max-width: 100%; } - .order-xl-first { - order: -1; - } - - .order-xl-1 { - order: 1; - } - - .order-xl-2 { - order: 2; - } - - .order-xl-3 { - order: 3; - } - - .order-xl-4 { - order: 4; - } - - .order-xl-5 { - order: 5; - } - - .order-xl-6 { - order: 6; - } - - .order-xl-7 { - order: 7; - } - - .order-xl-8 { - order: 8; - } - - .order-xl-9 { - order: 9; - } - - .order-xl-10 { - order: 10; - } - - .order-xl-11 { - order: 11; - } - - .order-xl-12 { - order: 12; - } - - .offset-xl-0 { - margin-left: 0; - } - - .offset-xl-1 { - margin-left: 8.33333%; - } - - .offset-xl-2 { - margin-left: 16.66667%; - } - - .offset-xl-3 { - margin-left: 25%; - } - - .offset-xl-4 { - margin-left: 33.33333%; - } - - .offset-xl-5 { - margin-left: 41.66667%; - } - - .offset-xl-6 { - margin-left: 50%; - } - - .offset-xl-7 { - margin-left: 58.33333%; - } - - .offset-xl-8 { - margin-left: 66.66667%; - } - - .offset-xl-9 { - margin-left: 75%; - } - - .offset-xl-10 { - margin-left: 83.33333%; - } - - .offset-xl-11 { - margin-left: 91.66667%; - } -} - -/** - * Demo website styles - */ -body { - padding-top: 60px; -} - -@media (min-width: 576px) { - body { - padding-top: 80px; - } -} - -.anchor { - display: block; - position: relative; - top: -65px; - visibility: hidden; -} - -.main-logo { - width: 150px; - fill: #03a9f4; -} - -@media (max-width: 767px) { - .main-logo { - width: 100px; - } -} - -@media screen and (max-width: 550px) { - .example-image { - width: 50px; - } -} - -.examples { - width: 100%; -} - -.example1, -.example2 { - background-color: #eceff1; - display: inline-block; - max-width: 300px; - padding: 16px; - text-align: center; -} - -@media screen and (max-width: 550px) { - - .example1, - .example2 { - max-width: 100%; - } - - .example1 img, - .example2 img { - width: 100% !important; - } -} - -.language-js { - font-size: 14px; -} - -:not(pre)>code[class*="language-"], -pre[class*="language-"] { - background-color: #eceff1 !important; -} - -pre { - margin-bottom: 2em !important; - overflow-x: auto; -} - -.example-code { - max-width: 700px; -} - -.example-code pre[class*="language-"] { - font-size: 14px; - margin: 0 !important; -} - -.token.tag { - background-color: transparent; - border-radius: 0; - color: #905; - line-height: auto; - margin: 0; - padding: 0; -} - -.token.tag:before, -.token.tag:after { - display: none; -} - -.token.operator { - background: none !important; -} - -.header { - background-color: #fff; - z-index: 2000; -} - -@media (min-width: 576px) { - .header { - padding: 16px 0; - } -} - -.header.is-visible { - top: 0; -} - -.header-inner { - align-items: center; - display: flex; - justify-content: space-between; -} - -.header-logo { - align-items: center; - display: flex; - flex-shrink: 0; - position: relative; -} - -.header-logoImage { - margin-right: 8px; -} - -@media (min-width: 576px) { - .header-logoImage { - margin-right: 8px; - } -} - -.header-nav { - align-items: center; - display: flex; - margin: 0; - margin-right: -12px; - overflow-x: auto; - padding: 20px 16px 20px 8px; - white-space: nowrap; -} - -@media (min-width: 576px) { - .header-nav { - margin-right: 0; - padding: 0; - } -} - -.header-navItem { - margin: 0; - margin-right: 16px; -} - -.header-navItem:last-child { - margin-right: 0; -} - -@media (max-width: 767px) { - .hide-small { - display: none; - } } [v-cloak] { display: none; } -/** - * Reset - */ + + html, body, body, @@ -3082,9 +1529,7 @@ section { box-sizing: border-box; } -/** - * MAIN RULES - */ + *, *::after, *::before { @@ -3121,6 +1566,9 @@ li { margin-bottom: 0.5em; } +/* CUSTOM ELEMENTS */ + + .leaflet-popup-close-button { visibility: hidden; } @@ -3137,36 +1585,16 @@ li { } .list-group-item { - border: 1px solid rgba(0, 0, 0, 0.125); + border: 1px solid var(--darkdark); display: inline-block; position: relative; + cursor: pointer; + text-align: center; + padding: 0.5rem 0.8rem; } -.list-group-item div { - display: block; - padding: 0.5rem 1.5rem; -} - - - - -.custom-pin { - position: relative; - width: 32px; - height: 32px; - background-color: #ff5733; - border-radius: 50%; -} - -.custom-pin::after { - content: ""; - position: absolute; - bottom: -10px; - left: 50%; - transform: translateX(-50%); - border-left: 10px solid transparent; - border-right: 10px solid transparent; - background-color: 15px solid #ff5733; +.list-group-item:hover { + filter: brightness(85%); } .leaflet-control-attribution { @@ -3179,7 +1607,7 @@ li { .col-0 { flex: 0 0 0%; - max-width: 100%; + max-width: 0%; overflow: hidden; } @@ -3188,31 +1616,16 @@ li { transition: flex 0.5s ease-in-out, max-width 0.5s ease-in-out; } +.map-container { + min-width: 52px; + height: 100%; +} + .drawer-container { + height: 100%; right: 0; top: 0; -} - -.map-menu { - position: absolute; - top: 0; - right: 0; - display: flex; - z-index: 500; - flex-direction: column; - gap: 10px; - margin: 5px; -} - -.map-menu-item { - background-color: var(--darkdark); - padding: 5px; - border-radius: 50%; - cursor: pointer; -} - -.map-menu-item:hover { - filter: brightness(150%); + overflow: scroll; } .travel-path-icon { @@ -3220,6 +1633,52 @@ li { margin-top: -32px; } + +@-webkit-keyframes spinning { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 25% { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + } + + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + + 75% { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes spinning { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + .spinner { position: absolute; right: 0; @@ -3257,6 +1716,141 @@ li { animation-iteration-count: infinite } +.ml-auto { + margin-left: auto; +} + +.mr-auto { + margin-right: auto; +} + .input .mx-input { height: 40px; +} + +.h-100 { + height: 100%; +} + +.map-menu { + position: absolute; + display: flex; + z-index: 1100; + right: 0; + flex-direction: column; + gap: 10px; + margin: 5px; +} + +.map-menu-top { + top: 0; +} + +.map-menu-bottom { + bottom: 0; +} + +.map-menu-center { + top: 50%; +} + +.map-menu-item { + background-color: var(--darkdark); + padding: 5px; + border-radius: 50%; + cursor: pointer; +} + +.map-menu-item:hover { + filter: brightness(150%); +} + +.map-menu-sub { + display: flex; + flex-direction: row-reverse; + gap: 5px; +} + +.map-menu-item, +.map-menu-sub-item { + background-color: var(--darkdark); + padding: 5px; + border-radius: 50%; + cursor: pointer; + float: right; + width: 42px; + height: 42px; + align-content: center; + text-align: center; +} + +.vue2leaflet-map { + border-radius: var(--border-radius); +} + +.leaflet-popup-content { + margin: 10px 20px !important; + /* display: flex; + align-items: center; + justify-content: center; + width: auto !important; + max-width: 100%; */ +} + + +.leaflet-popup>.leaflet-popup-content-wrapper { + border-radius: var(--border-radius); + width: 350px; +} + +.leaflet-popup-button-group { + position: absolute; + top: 0; + right: 0; + display: flex; + flex-direction: row; + gap: 5px; + margin: 2px 6px; +} + +.leaflet-popup-button-group>a { + cursor: pointer; +} + +.leaflet-popup-button-group>a:hover { + cursor: pointer; + filter: brightness(150%); +} + +.leaflet-popup-button-group>a>i { + font-size: 1em; +} + +.query-result { + display: flex; + align-items: center; + border-radius: var(--border-radius); + cursor: pointer; +} + +.query-result:hover { + filter: brightness(85%); +} + +.scroll-content>div:first-child { + border-top-left-radius: var(--border-radius); + border-bottom-left-radius: var(--border-radius); +} + +.scroll-content>div:nth-last-child(3) { + border-top-right-radius: var(--border-radius); + border-bottom-right-radius: var(--border-radius); +} + +.scroll-content>div:last-child { + border-radius: var(--border-radius); +} + +.mx-datepicker { + width: 100% !important; } \ No newline at end of file diff --git a/src/client/api.ts b/src/client/api.ts index 8ac2945..a1dee6b 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -124,7 +124,7 @@ export const icon_type = (item: string | NominatimResult): string => { "place_of_worship", "attraction", "information", - "university", "theatre", "opera" + "university", "science_park", "theatre", "opera" ], mountain: ["peak", "viewpoint"], parking: ["parking"], diff --git a/src/client/old.js b/src/client/old.js index e845b5c..fb488a4 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -12,8 +12,6 @@ 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); -// Vue.component("multiselect", window.VueMultiselect.default); -Vue.use(window.VueTextareaAutosize); var first_boot = true @@ -24,7 +22,7 @@ const app = new Vue({ 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, + type: "", res: [], load: false, sub: false, note: false, drawer: false, }, leg_nav: { scrollInterval: null, @@ -43,6 +41,7 @@ const app = new Vue({ 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]] @@ -64,7 +63,7 @@ const app = new Vue({ ` }, generate_icon: function (item, fcolor = "", styling = "", classes = "") { - return ``; + return ``; }, @@ -169,7 +168,10 @@ const app = new Vue({ 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) { @@ -197,10 +199,19 @@ const app = new Vue({ }, 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') - - query_in.focus() + setTimeout(() => query_in.focus(), 500); this.search_active({ target: query_in }) }, @@ -219,9 +230,10 @@ const app = new Vue({ }, nav_mousemove(e) { const c = document.querySelector('.scroll-content') + const left = e.pageX - c.getBoundingClientRect().left; const newDir = - e.pageX < c.offsetWidth * 0.1 ? 'left' : - (e.pageX > c.offsetWidth * 0.9 ? 'right' : 'none') + 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); @@ -232,6 +244,13 @@ const app = new Vue({ 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) diff --git a/src/client/types/format.ts b/src/client/types/format.ts index 335f189..a0f1ff9 100644 --- a/src/client/types/format.ts +++ b/src/client/types/format.ts @@ -38,14 +38,8 @@ declare global { } } -const journey_template: journey = { - fmt_ver: 1, - title: "New Journey", - main: [], -} - const leg_template: leg = { - title: "New Leg", + title: "", day_title: [], map: { zoom: 2, center: { lng: 0, lat: 0 } }, travel: [], @@ -54,6 +48,12 @@ const leg_template: leg = { notes: "", date_range: null } +const journey_template: journey = { + fmt_ver: 1, + title: "New Journey", + main: [leg_template], +} + export { map, geoloc, leg, journey } export { journey_template, leg_template } \ No newline at end of file diff --git a/src/client/types/wrapper.ts b/src/client/types/wrapper.ts index db9923c..ade7429 100644 --- a/src/client/types/wrapper.ts +++ b/src/client/types/wrapper.ts @@ -29,6 +29,7 @@ class journey_wrapper { rm_leg(idx: number): void { this.data.main.splice(idx, 1); if (this.sel_leg == idx) this.leg_prev(); + if (this.sel_leg > this.data.main.length - 1) this.leg_next(); } tot_len(): number | "?" { if (this.leg_count() == 0) return 0; diff --git a/src/server/api_nominatim.ts b/src/server/api_nominatim.ts index 58a48f6..874b77c 100644 --- a/src/server/api_nominatim.ts +++ b/src/server/api_nominatim.ts @@ -15,6 +15,7 @@ export function nominatim_get_data(id: string, bb: string[][] | null = null): Pr const url = new URL("https://nominatim.openstreetmap.org/search"); url.searchParams.append('format', 'jsonv2') url.searchParams.append('q', id) + url.searchParams.append('limit', '20') if (bb) { url.searchParams.append('viewbox', `${bb[0][0]},${bb[0][1]},${bb[1][0]},${bb[1][1]}`) url.searchParams.append('bounded', `1`) diff --git a/template/home.pug b/template/home.pug index 9de3b59..2a3d520 100644 --- a/template/home.pug +++ b/template/home.pug @@ -2,76 +2,31 @@ doctype html include module/head.pug main#app - .container - section.mb-big + .bg-white.section.text-dark + .container.mb-big .text-center - img.main-logo.mb-medium( - src="/public/img/helcel.png", - alt="Helcel logo" - ) div h1.text-huge.text-withSubtitle Open Tourism Map h2.text-big.text-gray Collaborative Holiday Planner - p#js-header-waypoint.m-none - a.button.button--primary.button--mobileFull(href="#go") Get started - .bg-dark - .container - .row.text-center - .col-12.col-sm-3 - .section - img( - src="/public/img/lightweight.png", - alt="Lightweight", - width="118" - ) + .spacer + .section.bg-dark.text-white + .container-medium + .row + .col-8 + h2.text-big Your journey + p.text-gray + | Browse hotels, restaurants and attractions,.... br - h2.text-withSubtitle.text-big.text-white - | Lightweight - br - span.text-medium.text-gray - | Powered By - br - | Fastify & Sierra - .col-12.col-sm-4 - .section - img( - src="/public/img/customizable.png", - alt="Customizable", - width="118" - ) - br - h2.text-withSubtitle.text-big.text-white - | Customizable - br - span.text-medium.text-gray - | Many Templates - br - | to choose from - .col-12.col-sm-4 - .section - h2.text-withSubtitle.text-big.text-white - img( - src="/public/img/opensource.png", - alt="Open Source", - width="118" - ) - br - | - | FOSS - br - span.text-medium.text-gray :-) - #go.container-medium.section - h2.text-big Your journey - p - | Browse hotels, restaurants and attractions,.... - br - | - | Select and plan the varying elements of your journey - .aligner.aligner--contentEnd - .input - input#journey.id(v-model="journey.id", placeholder="ID", type="text") - button.button.button--primary.button--mobileFull( - v-on:click="start_journey" - ) Start the journey + | + | Select and plan the varying elements of your journey + .col-4 + .row.align + .input + input#journey.id(v-model="journey.id", placeholder="ID", type="text") + p + .row.align + button.button.button--primary.button--mobileFull( + v-on:click="start_journey" + ) Start the journey include module/foot.pug diff --git a/template/journey.pug b/template/journey.pug index 0ca849f..3b3e81b 100644 --- a/template/journey.pug +++ b/template/journey.pug @@ -3,6 +3,5 @@ doctype html include module/head.pug main#app(v-cloak) - include module/nav.pug - include module/journey.pug + include module/journey/main.pug include module/foot.pug diff --git a/template/module/foot.pug b/template/module/foot.pug index 8580614..6ea8792 100644 --- a/template/module/foot.pug +++ b/template/module/foot.pug @@ -2,21 +2,12 @@ script(src="https://unpkg.com/leaflet") script(src="https://unpkg.com/vue@2") script(src="https://unpkg.com/vue2-datepicker") -script(src="https://unpkg.com/vue-textarea-autosize") script(src="https://unpkg.com/vue2-leaflet") script(src="https://unpkg.com/sortablejs") script(src="https://unpkg.com/vuedraggable") script(src="/public/main.js", type="text/javascript", charset="utf-8") -footer.bg-dark - .container - .section.text-center.text-small - p.text-white - img(src="/public/img/helcel.png", alt="helcel logo", width="100") - br - br - | +footer.bg-dark.section + .container.text-center.text-small.text-white | Built with   ❤   by Helcel br span.text-small.text-gray v0.0.1 - p.text-gray - a(href="https://git.helcel.net") Helcel Git diff --git a/template/module/journey.pug b/template/module/journey.pug deleted file mode 100644 index ed370b3..0000000 --- a/template/module/journey.pug +++ /dev/null @@ -1,3 +0,0 @@ -.journey - include journey/leg.pug -include journey/impexp.pug \ No newline at end of file diff --git a/template/module/journey/leg.pug b/template/module/journey/leg.pug deleted file mode 100644 index 58eb20f..0000000 --- a/template/module/journey/leg.pug +++ /dev/null @@ -1,11 +0,0 @@ -include leg/nav.pug -.bg-dark.text-white(v-if="journey && journey.leg_get()") - .container.section - include leg/top.pug - .row(style="aspect-ratio:1.25;") - .map-container(:class="{ 'col-9': query.type, 'col-12': !query.type }" ) - include map.pug - .drawer-container(:class="{ 'col-3': query.type, 'col-0': !query.type }") - include leg/drawer.pug - - include leg/old_cfg.pug \ No newline at end of file diff --git a/template/module/journey/leg/drawer-notes.pug b/template/module/journey/leg/drawer-notes.pug new file mode 100644 index 0000000..0f4a1c7 --- /dev/null +++ b/template/module/journey/leg/drawer-notes.pug @@ -0,0 +1,8 @@ +.col-12.input.text-dark() + textarea.text-small#query_note( + v-model="journey.leg_get().notes" + @input="refreshTextAreaHeight" + @focus="refreshTextAreaHeight" + rows="1" + placeholder="...", + ) \ No newline at end of file diff --git a/template/module/journey/leg/drawer.pug b/template/module/journey/leg/drawer.pug index 9deaa70..cc30f3e 100644 --- a/template/module/journey/leg/drawer.pug +++ b/template/module/journey/leg/drawer.pug @@ -1,16 +1,18 @@ -.input.text-dark(style="width: 100%") + +.col-12.input.text-dark input#query_input( type="search" @input="search_active" + @focus="search_active" placeholder="Search ... " style="width:85%;" + :disabled="query.note" ) .spinner(v-if="query.load") -div(style="width:100%" - v-if="['hotel', 'restaurant', 'place','other', 'travel'].indexOf(query.type)>=0") + +div(v-if="['hotel', 'restaurant', 'place','other', 'travel'].indexOf(query.type)>=0") template(v-for="(item, idx) in query.res" ) - .col-12.bg-white.text-dark( - style="display:flex;align-items:center; border-radius:3px;" + .query-result.col-12.bg-white.text-dark( :key="'q'+idx" @mouseover="drawer_hover_item(item)" @mouseleave="drawer_hover_item()" @@ -20,20 +22,17 @@ div(style="width:100%" | {{ item.name }} .bg-dark.divider( :key="'qdiv'+idx" style="height:1px" ) - .col-12.bg-white.text-dark( - v-if="query.load==false && query.res.length==0" - style="display:flex;align-items:center; border-radius:3px;" ) + .query-result.col-12.bg-white.text-dark( + v-if="query.load==false && query.res.length==0" ) div( v-html="generate_icon('star', 'var(--dark)')") .col-10() | Add custom .col-12.text-white.text-center( ) {{query.load? `Loading ...` : `Found ${query.res.length} results`}} -div(style="width:100%" - v-else-if="['flight'].indexOf(query.type)>=0") +div(v-else-if="['flight'].indexOf(query.type)>=0") template(v-for="(item, idx) in query.res" ) - .col-12.bg-white.text-dark( - style="display:flex;align-items:center; border-radius:3px;" + .query-result.col-12.bg-white.text-dark( :key="'q'+idx" @mouseover="drawer_hover_item(item)" @mouseleave="drawer_hover_item()" @@ -41,10 +40,9 @@ div(style="width:100%" div( v-html="generate_icon('plane', 'var(--dark)')") .col-10() | {{ item.from }} => {{item.to}} - .bg-dark.divider( + bg-dark.divider( :key="'qdiv'+idx" style="height:1px" ) -div(style="width:100%" v-else) +div(v-else) template() - .col-12.bg-white.text-dark( - style="display:flex;align-items:center; border-radius:3px;") - | Unsuppored Query type {{query.type}} \ No newline at end of file + .query-result.col-12.bg-white.text-dark() + | Unsuppored Query type {{query.type}} diff --git a/template/module/journey/leg/nav.pug b/template/module/journey/leg/nav.pug index 94802f3..736c95e 100644 --- a/template/module/journey/leg/nav.pug +++ b/template/module/journey/leg/nav.pug @@ -1,23 +1,34 @@ -.scroll-handler( +.scroll-handler.row( @mouseleave="nav_mouseleave" @mousemove="nav_mousemove") - draggable.scroll-content.list-group.bg-dark( - tag="div", - :list="journey.data.main", - handle=".handle" - ) - .list-group-item.handle( - v-for="(element, idx) in journey.data.main", - :key="idx", - @click="journey.leg_sel(idx)", - :class="journey.sel_leg == idx ? 'bg-primary' : 'bg-white'" - ) - .text {{ element.title }} - i.fa.fa-times.close.fright( - style="top: 2px; right: 2px; position: absolute", - @click="journey.rm_leg(idx)" - ) - .list-group-item.bg-white(@click="journey.add_leg()") - .text Add Leg - i.fa.fa-plus.add(style="top: 12px; right: 5px; position: absolute") + .col-3.col-sm-2.col-md-1 + .list-group.text-dark.h-100 + .fleft.list-group-item.bg-white.text-small.rounded.h-100(v-on:click.prevent="journey.leg_prev()") + i.fas.fa-angle-left + .col-6.col-sm-8.col-md-10 + draggable.scroll-content.list-group.bg-dark( + tag="div", + :list="journey.data.main", + handle=".handle" + ) + .list-group-item.handle.text-dark( + v-for="(element, idx) in journey.data.main", + :key="idx", + @click="journey.leg_sel(idx)", + :class="journey.sel_leg == idx ? 'bg-primary' : 'bg-white'" + ) + .text {{ element.title || "Leg "+idx}} + i.fa.fa-times.close.fright( + style="top: 2px; right: 2px; position: absolute", + @click="journey.rm_leg(idx)" + ) + .list-group-item.bg-dark + .list-group-item.bg-white.text-dark(@click="journey.add_leg()") + div + i.fa.fa-plus.add() + + .col-3.col-sm-2.col-md-1 + .list-group.text-dark.h-100 + a.fright.list-group-item.bg-white.text-small.rounded.h-100(v-on:click.prevent="journey.leg_next()") + i.fas.fa-angle-right \ No newline at end of file diff --git a/template/module/journey/leg/old_cfg.pug b/template/module/journey/leg/old_cfg.pug deleted file mode 100644 index 06b75f4..0000000 --- a/template/module/journey/leg/old_cfg.pug +++ /dev/null @@ -1,12 +0,0 @@ -div - div - .row.text-center - div - label Notes - .input.text-dark(style="width: 100%") - textarea-autosize.text-small( - v-model="journey.leg_get().notes", - placeholder="Notes", - :min-height="30", - :max-height="350" - ) diff --git a/template/module/journey/leg/top.pug b/template/module/journey/leg/top.pug index a42a692..bd63bec 100644 --- a/template/module/journey/leg/top.pug +++ b/template/module/journey/leg/top.pug @@ -1,15 +1,17 @@ -.row.text-center - .col-sm-2 - .input - input(v-model="journey.leg_get().title") - .col-sm-2 +.row.text-center.align + .col-5.col-sm-4.col-md-2 .input input( - placeholder="Day title", + placeholder="Leg" + v-model="journey.leg_get().title") + + .col-5.col-sm-4.col-md-2.mr-auto + .input + input( + placeholder="Day" v-model="journey.leg_get().day_title[journey.sel_day]" ) - - .col-sm-4 + .col-8.col-sm-6.col-md-4 .input //- label Date Range ({{ journey.leg_len() }}) date-picker( @@ -20,10 +22,15 @@ placeholder="Date Range", v-on:change="journey.date_update(journey.sel_leg)" ) - .col-sm-2 - .right.col-sm-2 + .col-4.col-sm-4.col-md-3.ml-auto .input input( disabled="", :value="journey.date_sel() + ' (' + journey.sel_day + ')'" - ) \ No newline at end of file + ) + //- .col-6.list-group-item.align.center.bg-white(style="padding: 0.5rem 0;") + //- i.fas.fa-angle-double-right(v-on:click.prevent="journey.day_next()") + .col-sm-1.text-small + + //- a(href="#prev", v-on:click.prevent="journey.day_prev()") + i.fas.fa-angle-left \ No newline at end of file diff --git a/template/module/journey/main.pug b/template/module/journey/main.pug new file mode 100644 index 0000000..fb8d244 --- /dev/null +++ b/template/module/journey/main.pug @@ -0,0 +1,31 @@ +.row.fleft(style="position:absolute;right:0;") + .col-1 + a(:href="'/short/' + journey.id") + i.fas.fa-file-contract + .col-1 + a(:href="'/view/' + journey.id") + i.fas.fa-camera + .col-1 + a(href="#", v-on:click.prevent="first_step") + i.fas.fa-tools + + +.bg-dark.text-white(v-if="journey && journey.leg_get()") + .container + .row.align(style="padding-top:45px;") + .col-6.col-sm-4.col-md-3.input.text-big + input.text-center(v-model="journey.data.name" placeholder="My Journey" type="text") + //- input.small(type="text", :placeholder="journey.date_tot() + ' (' + journey.tot_len() + ')'" ) + + include leg/nav.pug + include leg/top.pug + .row(style="aspect-ratio:1.25;") + .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) }" ) + 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) }") + .drawer-container(:class="{ 'col-12 ': query.type, 'col-0': !query.type }") + include leg/drawer.pug + .drawer-container(:class="{ 'col-12': query.note, 'col-0': !query.note }") + include leg/drawer-notes.pug + +//- include impexp.pug \ No newline at end of file diff --git a/template/module/journey/map.pug b/template/module/journey/map.pug index db88834..a2e17ad 100644 --- a/template/module/journey/map.pug +++ b/template/module/journey/map.pug @@ -3,12 +3,13 @@ l-map( :center.sync="journey.leg_get().map.center", style="height:100%" no-blocking-animations=true + ref="map" ) l-tile-layer( url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", attribution="© OpenStreetMap contributors" ) - l-control-scale(position="bottomright", :imperial="false", :metric="true") + l-control-scale(position="bottomleft", :imperial="false", :metric="true") include map/override.pug include map/hotel.pug diff --git a/template/module/journey/map/mixin-marker.pug b/template/module/journey/map/mixin-marker.pug index cc4ca6b..9dc67e4 100644 --- a/template/module/journey/map/mixin-marker.pug +++ b/template/module/journey/map/mixin-marker.pug @@ -15,27 +15,23 @@ mixin map_marker(place, color_sel_c, color_sel_o, color_else) v-else v-html="generate_marker(place, \""+color_else+"\")" ) - l-popup() + l-popup( + :options="{maxWidth:400, minWidth:300}") h1.row.text-medium.text-center {{ place.sname }} span.row.text-small.text-gray {{ place.display_name }} span(v-if="edit_active") - .row.input(style="margin-bottom:0") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", + .row.input() + textarea.col-12.col-sm-12.text-small( + placeholder="", v-model="place.notes", - :min-height="30", - :max-height="350" ) - a.leaflet-popup-close-button.text-gray( - style="right: 4px; visibility: visible", - href="#rm", - v-on:click.prevent="place_delete(\""+place+"\",index)" - v-html="generate_icon('trash', 'NA')" - ) - a.leaflet-popup-close-button.text-gray( - style="right: 20px; visibility: visible", - href="#toggle_day", + .leaflet-popup-button-group(v-if="edit_active") + a.text-gray( 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')" ) + a.text-gray( + v-on:click.prevent="place_delete(\""+place+"\",index)" + v-html="generate_icon('trash', 'NA')" + ) span.row.text-small.text-dark(v-else) {{ place.notes }} diff --git a/template/module/journey/map/right_menu.pug b/template/module/journey/map/right_menu.pug index b61174e..bd5990a 100644 --- a/template/module/journey/map/right_menu.pug +++ b/template/module/journey/map/right_menu.pug @@ -1,5 +1,5 @@ -.map-menu - div( v-if="query.type" @click="drawer_click_item()" ) +.map-menu.map-menu-top + div(v-if="query.type" @click="drawer_click_item()" ) .map-menu-item(v-html="generate_icon('close')") div(v-if="!query.type" @click="search_enable('hotel')") .map-menu-item( v-html="generate_icon('bed')") @@ -14,24 +14,8 @@ .map-menu-item(v-if="query.sub" @click="search_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-sub { -//- display: flex; -//- flex-direction: row-reverse; -//- gap: 5px; -//- } -//- .map-menu-item, -//- .map-menu-sub-item { -//- background-color: var(--darkdark); -//- padding: 5px; -//- border-radius: 50%; -//- cursor: pointer; -//- float: right; -//- height: fit-content; -//- } -//- .vue2leaflet-map { -//- border-radius: 3px; -//- } -//- .leaflet-popup-content { -//- margin: 10px 20px; -//- } \ No newline at end of file +.map-menu.map-menu-center + div(v-if="query.note" @click="drawer_click_item()" ) + .map-menu-item(v-html="generate_icon('close')") + div(v-if="!query.note" @click="search_enable('notes')") + .map-menu-item( v-html="generate_icon('pencil')") \ No newline at end of file diff --git a/template/module/journey/map/travel.pug b/template/module/journey/map/travel.pug index dee910c..d7e0799 100644 --- a/template/module/journey/map/travel.pug +++ b/template/module/journey/map/travel.pug @@ -1,22 +1,22 @@ mixin flight_popup() - l-popup() - h1.row.text-medium.text-center {{ travel.id.toUpperCase() }} + l-popup( + :options="{maxWidth:400, minWidth:300}" + ) + h1.row.text-medium.text-center.text-uppercase {{ travel.id }} span.row.text-small.text-gray {{ travel.from }} - {{travel.to}} span(v-if="edit_active") .row.input(style="margin-bottom:0") - textarea-autosize.col-12.col-sm-12.text-small( - placeholder="Notes", + textarea.col-12.col-sm-12.text-small( + placeholder="", v-model="travel.notes", - :min-height="30", - :max-height="350" ) - a.leaflet-popup-close-button.text-gray( - style="right: 4px; visibility: visible", - href="#rm", - v-on:click.prevent="place_delete('flight',idx)" - v-html="generate_icon('trash', 'NA')" - ) span.row.text-small.text-dark(v-else) {{ travel.notes }} + span(v-if="edit_active") + .leaflet-popup-button-group(v-if="edit_active") + a.text-gray( + v-on:click.prevent="place_delete('flight',idx)" + v-html="generate_icon('trash', 'NA')" + ) div(v-for= "(travel, idx) in journey.leg_get().travel") l-polyline(:lat-lngs="travel.path" :color="travel.color || 'gray'") diff --git a/template/module/nav.pug b/template/module/nav.pug deleted file mode 100644 index 96eb3f7..0000000 --- a/template/module/nav.pug +++ /dev/null @@ -1,38 +0,0 @@ -header.header - .header-inner.container - a.header-logo.text-dark(href="/") - img.header-logoImage( - src="/public/img/helcel.png", - alt="Helcel logo", - width="40" - ) - span.hide-small OTM - .input.input-invis.row - input.col-6.small(v-model="journey.data.name", type="text") - input.col-6.small( - disabled, - type="text", - :placeholder="journey.date_tot() + ' (' + journey.tot_len() + ')'" - ) - .row.header-nav.text-big(style="margin-bottom: 0") - .col-sm-2 - a(:href="'/short/' + journey.id") - i.fas.fa-file-contract - .col-sm-2 - a(:href="'/view/' + journey.id") - i.fas.fa-camera - .col-sm-2 - a(href="#main", v-on:click.prevent="first_step") - i.fas.fa-tools - .col-sm-1.text-small - a(href="#prevprev", v-on:click.prevent="journey.leg_prev()") - i.fas.fa-angle-double-left - .col-sm-1 - a(href="#prev", v-on:click.prevent="journey.day_prev()") - i.fas.fa-angle-left - .col-sm-1 - a(href="#next", v-on:click.prevent="journey.day_next()") - i.fas.fa-angle-right - .col-sm-1.text-small - a(href="#nextnext", v-on:click.prevent="journey.leg_next()") - i.fas.fa-angle-double-right diff --git a/template/module/view/nav.pug b/template/module/view/nav.pug index ab88fb2..3ab7e57 100644 --- a/template/module/view/nav.pug +++ b/template/module/view/nav.pug @@ -1,12 +1,5 @@ header.header .header-inner.container - a.header-logo.text-dark(href="/") - img.header-logoImage( - src="/public/img/helcel.png", - alt="Helcel logo", - width="40" - ) - span.hide-small HOTM .input.input-invis input.small(:value="journey.data.name", type="text", disabled="") .row.header-nav.text-big(style="margin-bottom: 0") diff --git a/template/module/view/short_leg.pug b/template/module/view/short_leg.pug index bc005b0..c767330 100644 --- a/template/module/view/short_leg.pug +++ b/template/module/view/short_leg.pug @@ -16,28 +16,22 @@ input(disabled="", :value="item.map((v) => v.id).join(', ')") .row.text-center .input.col-sm-8(v-if="item.places && item.places.restaurants") - textarea-autosize.text-small( + .text-small( placeholder="No Restaurants", :value="item.places.restaurants.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ')", - :min-height="30", - :max-height="350", disabled="" ) .row.text-center .input.col-sm-8(v-if="item.places && item.places.activities") - textarea-autosize.text-small( + .text-small( placeholder="No Activities", :value="item.places.activities.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ')", - :min-height="30", - :max-height="350", disabled="" ) .row.text-center .input.col-sm-8(v-if="item.notes") - textarea-autosize.text-small( + .text-small( placeholder="No Notes", :value="item.notes", - :min-height="30", - :max-height="350", disabled="" ) diff --git a/template/view.pug b/template/view.pug index 96c486d..ff1fff4 100644 --- a/template/view.pug +++ b/template/view.pug @@ -1,6 +1,6 @@ doctype html include module/head.pug main#app(v-cloak) - div(v-if="journey.data.main[journey.sel_leg] != undefined") + div(v-if="journey.leg_get()") include module/view/view_day.pug include module/foot.pug -- 2.47.2 From 7efb63764c9dfad23f444a18e36ee926625f6a91 Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 2 Mar 2025 00:27:49 +0100 Subject: [PATCH 91/95] wip --- public/css/index.css | 4 +++ src/client/old.js | 5 ++- template/module/journey/map.pug | 4 +-- template/module/view/nav.pug | 21 ++++++------- template/module/view/short_leg.pug | 50 ++++++++++++++++-------------- template/module/view/view_day.pug | 20 ++++++------ template/short.pug | 8 ++++- 7 files changed, 61 insertions(+), 51 deletions(-) diff --git a/public/css/index.css b/public/css/index.css index 1202b96..e1aec1c 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -1754,6 +1754,10 @@ li { top: 50%; } +.padding-1 { + padding: 5px; +} + .map-menu-item { background-color: var(--darkdark); padding: 5px; diff --git a/src/client/old.js b/src/client/old.js index fb488a4..419b1dd 100644 --- a/src/client/old.js +++ b/src/client/old.js @@ -13,8 +13,6 @@ Vue.component("l-tooltip", window.Vue2Leaflet.LTooltip); Vue.component("l-polyline", window.Vue2Leaflet.LPolyline); Vue.component("l-control-scale", window.Vue2Leaflet.LControlScale); -var first_boot = true - const app = new Vue({ el: "#app", data: { @@ -282,7 +280,8 @@ const app = new Vue({ watch: { journey: { handler: function (ndata, odata) { - this.save_data(); + if (this.edit_active) + this.save_data(); }, deep: true, }, diff --git a/template/module/journey/map.pug b/template/module/journey/map.pug index a2e17ad..5087f8a 100644 --- a/template/module/journey/map.pug +++ b/template/module/journey/map.pug @@ -17,5 +17,5 @@ l-map( include map/restaurants.pug include map/travel.pug - - include map/right_menu.pug \ No newline at end of file + template(v-if="edit_active") + include map/right_menu.pug \ No newline at end of file diff --git a/template/module/view/nav.pug b/template/module/view/nav.pug index 3ab7e57..fa9eb3b 100644 --- a/template/module/view/nav.pug +++ b/template/module/view/nav.pug @@ -1,11 +1,10 @@ -header.header - .header-inner.container - .input.input-invis - input.small(:value="journey.data.name", type="text", disabled="") - .row.header-nav.text-big(style="margin-bottom: 0") - .col-sm-3 - a(:href="'/short/' + journey.id") - i.fas.fa-file-contract - .col-sm-3 - a(:href="'/view/' + journey.id") - i.fas.fa-camera +.row.fleft(style="position:absolute;right:0;") + .col-1 + a(:href="'/short/' + journey.id") + i.fas.fa-file-contract + .col-1 + a(:href="'/view/' + journey.id") + i.fas.fa-camera + //- .col-1 + //- a(:href="'/' + journey.id" v-on:click.prevent="first_step") + //- i.fas.fa-tools diff --git a/template/module/view/short_leg.pug b/template/module/view/short_leg.pug index c767330..756cabb 100644 --- a/template/module/view/short_leg.pug +++ b/template/module/view/short_leg.pug @@ -1,37 +1,39 @@ -.container.section - .row.text-center - .input.col-sm-2 - input(disabled="", :value="item.title") - .input.col-sm-4 +.col-11.container.section + .row.text-center.align.padding-1 + .input.col-5.col-sm-2 + input(disabled="", placeholder="Unnamed" :value="item.title") + .col-sm-1 + .input.col-6.col-sm-4 input( disabled="", placeholder="No Dates", - :value="item.date_range ? format_date(item.date_range[0]) + ' - ' + format_date(item.date_range[1]) : ''" + :value="item.date_range ? item.date_range[0].toLocal() + ' - ' + item.date_range[1].toLocal() : ''" ) - .input.col-sm-2 - input(disabled="", placeholder="No Hotel", :value="item.hotel.sname") - .row.text-center - .input.col-sm-3(v-if="item.transit") - div(v-for="(item, idx) in item.transit") - input(disabled="", :value="item.map((v) => v.id).join(', ')") - .row.text-center - .input.col-sm-8(v-if="item.places && item.places.restaurants") + .col-1.col-sm-2 + .input.col-5.col-sm-3.text-dark + .text(disabled="" placeholder="No Hotel" :value="item.hotel?item.hotel.sname:''") {{item.hotel?item.hotel.sname:'No Hotel'}} + //- .row.text-center + .input.col-sm-3(v-if="item.travel") + div(v-for="(item, idx) in item.travel") + input(disabled="", placeholder="-" :value="item.map((v) => v.id).join(', ')") + .row.align.padding-1 + .input.col-sm-10.text-dark .text-small( placeholder="No Restaurants", - :value="item.places.restaurants.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ')", + :value="item.places.restaurants.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ') || 'No Restaurants'", disabled="" - ) - .row.text-center - .input.col-sm-8(v-if="item.places && item.places.activities") + ) {{item.places.restaurants.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ') || 'No Restaurants'}} + .row.align.padding-1 + .input.col-sm-10.text-dark .text-small( placeholder="No Activities", - :value="item.places.activities.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ')", + :value="item.places.activities.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ') || 'No Activites'", disabled="" - ) - .row.text-center - .input.col-sm-8(v-if="item.notes") + ) {{item.places.activities.map((v) => v.sname + (v.notes ? '(' + v.notes + ')' : '')).join(', ') || 'No Activites'}} + .row.align.padding-1 + .input.col-sm-10.text-dark .text-small( placeholder="No Notes", - :value="item.notes", + :value="item.notes || 'No Notes'", disabled="" - ) + ) {{item.notes || 'No Notes'}} diff --git a/template/module/view/view_day.pug b/template/module/view/view_day.pug index 90daa75..a90fcd6 100644 --- a/template/module/view/view_day.pug +++ b/template/module/view/view_day.pug @@ -1,19 +1,19 @@ div(v-for="(e, idx) in journey.data.main", :key="idx") .bg-dark.text-white(v-if="journey.sel_leg == idx") .container.section - .aligner.text-center.text-white.text-huge(style="margin-bottom: 5px") - .aligner--itemTop.fleft - a(href="#prev", v-on:click.prevent="journey.day_prev()") + .row + .col-3.fleft.text-center.text-white.text-huge + a(v-on:click.prevent="journey.day_prev()") i.fas.fa-angle-left - span.container + .col-6.container.text-center.align span.small {{ journey.data.main[idx].title }} {{ journey.sel_day }} .text-big.text-gray {{ journey.data.main[idx].day_title[journey.sel_day] }} - .aligner--itemEnd.fright - a(href="#next", v-on:click.prevent="journey.day_next()") + .col-3.fright.text-center.text-white.text-huge + a(v-on:click.prevent="journey.day_next()") i.fas.fa-angle-right .row - .col-12.col-sm-12 - include map.pug + .col-12.col-sm-12(style="aspect-ratio:1.25;") + include ../journey/map.pug .row - .col-12.col-sm-12 - .container + .col-10 + span.small.text-gray {{journey.data.main[idx].note || '...'}} diff --git a/template/short.pug b/template/short.pug index 90390db..61662f6 100644 --- a/template/short.pug +++ b/template/short.pug @@ -2,9 +2,15 @@ doctype html include module/head.pug main#app(v-cloak) include module/view/nav.pug + + .bg-dark.text-white(v-if="journey && journey.leg_get()") + .container + .row.align(style="padding-top:45px;") + .col-7.col-sm-5.col-md-4.input.text-big + input.text-center(v-model="journey.data.name" placeholder="My Journey" type="text" disabled) div( v-for="(item, idx) in journey.data.main", - :class="idx % 2 === 0 ? 'bg-dark text-white' : ''" + :class="idx % 2 === 0 ? 'bg-white text-dark' : 'bg-dark text-white'" ) include module/view/short_leg.pug include module/foot.pug -- 2.47.2 From 14e18a3e50c6f68e432aeb651ebe345677dff37e Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 2 Mar 2025 00:53:25 +0100 Subject: [PATCH 92/95] wip --- .gitignore | 1 + package.json | 3 +- public/css/index.css | 1860 ----------------- src/server/main.ts | 8 +- src/style/custom.css | 207 ++ src/style/define.css | 19 + src/style/index.css | 13 + src/style/module/general.css | 202 ++ src/style/module/input.css | 362 ++++ src/style/module/layout.css | 354 ++++ src/style/module/load_n_spin.css | 166 ++ src/style/module/typography.css | 148 ++ {template => src/template}/home.pug | 0 {template => src/template}/journey.pug | 0 {template => src/template}/module/foot.pug | 0 {template => src/template}/module/head.pug | 2 +- .../template}/module/journey/impexp.pug | 0 .../module/journey/leg/drawer-notes.pug | 0 .../template}/module/journey/leg/drawer.pug | 0 .../template}/module/journey/leg/nav.pug | 0 .../template}/module/journey/leg/top.pug | 0 .../template}/module/journey/main.pug | 0 .../template}/module/journey/map.pug | 0 .../module/journey/map/activities.pug | 0 .../template}/module/journey/map/hotel.pug | 0 .../module/journey/map/mixin-marker.pug | 0 .../template}/module/journey/map/override.pug | 0 .../module/journey/map/restaurants.pug | 0 .../module/journey/map/right_menu.pug | 0 .../template}/module/journey/map/travel.pug | 0 .../template}/module/view/nav.pug | 0 .../template}/module/view/short_leg.pug | 0 .../template}/module/view/view_day.pug | 0 {template => src/template}/short.pug | 0 {template => src/template}/view.pug | 0 yarn.lock | 514 +++-- 36 files changed, 1858 insertions(+), 2001 deletions(-) delete mode 100644 public/css/index.css create mode 100644 src/style/custom.css create mode 100644 src/style/define.css create mode 100644 src/style/index.css create mode 100644 src/style/module/general.css create mode 100644 src/style/module/input.css create mode 100644 src/style/module/layout.css create mode 100644 src/style/module/load_n_spin.css create mode 100644 src/style/module/typography.css rename {template => src/template}/home.pug (100%) rename {template => src/template}/journey.pug (100%) rename {template => src/template}/module/foot.pug (100%) rename {template => src/template}/module/head.pug (91%) rename {template => src/template}/module/journey/impexp.pug (100%) rename {template => src/template}/module/journey/leg/drawer-notes.pug (100%) rename {template => src/template}/module/journey/leg/drawer.pug (100%) rename {template => src/template}/module/journey/leg/nav.pug (100%) rename {template => src/template}/module/journey/leg/top.pug (100%) rename {template => src/template}/module/journey/main.pug (100%) rename {template => src/template}/module/journey/map.pug (100%) rename {template => src/template}/module/journey/map/activities.pug (100%) rename {template => src/template}/module/journey/map/hotel.pug (100%) rename {template => src/template}/module/journey/map/mixin-marker.pug (100%) rename {template => src/template}/module/journey/map/override.pug (100%) rename {template => src/template}/module/journey/map/restaurants.pug (100%) rename {template => src/template}/module/journey/map/right_menu.pug (100%) rename {template => src/template}/module/journey/map/travel.pug (100%) rename {template => src/template}/module/view/nav.pug (100%) rename {template => src/template}/module/view/short_leg.pug (100%) rename {template => src/template}/module/view/view_day.pug (100%) rename {template => src/template}/short.pug (100%) rename {template => src/template}/view.pug (100%) diff --git a/.gitignore b/.gitignore index fd98ac3..f44e799 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ db/ .yarn/ public/*.js public/*.map +public/*.css .yarnrc.yml .pnp* build/ \ No newline at end of file diff --git a/package.json b/package.json index a94c2a2..0036cfd 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Open Travel Mapper", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "yarn build-server && yarn build-client", + "build": "yarn build-server && yarn build-client && yarn build-style", + "build-style": "esbuild src/style/index.css --outfile=public/index.css --bundle --minify ", "build-client": "esbuild src/client/main.ts --outfile=public/main.js --tree-shaking=true --bundle --minify --sourcemap --tsconfig=tsconfig-client.json", "build-server": "esbuild src/server/**/*.ts --outdir=build --platform=node --format=cjs", "start": "node build/main.js", diff --git a/public/css/index.css b/public/css/index.css deleted file mode 100644 index e1aec1c..0000000 --- a/public/css/index.css +++ /dev/null @@ -1,1860 +0,0 @@ -:root { - --black: #030B12; - --darkdark: #0C1D2E; - --dark: #203A53; - --lightdark: #425F7C; - --light: #93A9BE; - --lightlight: #B6C5D5; - --white: #F0F3F7; - --orange: ##F5B97D; - --yellow: #F5F57D; - --green: #B9F57D; - --turquoise: #7DF5B9; - --blue: #7DB9F5; - --purple: #B97DF5; - --pink: #F57DB9; - --red: #F57D7D; - - --border-radius: 3px; -} - -/** - * BACKGROUND - */ -.bg-primary { - background-color: var(--blue); -} - -.bg-dark { - background-color: var(--darkdark); -} - -.bg-secondary { - background-color: var(--pink); -} - -.bg-white { - background-color: var(--white); -} - -.bg-success { - background-color: var(--green); -} - -.bg-info { - background-color: var(--yellow); -} - -.bg-warning { - background-color: var(--orange); -} - -.bg-error { - background-color: var(--red); -} - -.bg-gray { - background-color: var(--lightdark); -} - -.bg-gray-light { - background-color: var(--lightlight); -} - - -/** - * ALIGNERS - */ - -.align { - align-items: center; - justify-content: center; -} - - -/** - * FLOATS - */ -.fleft { - float: left; -} - -.fright { - float: right; -} - -.clearfix ::after { - clear: both; - content: ""; - display: table; -} - -/** - * OTHERS - */ -.no-wrap { - white-space: nowrap; -} - -.overflow-hidden { - overflow: hidden; -} - -.rounded { - border-radius: var(--border-radius); -} - -/** - * LAYOUT - */ -.section { - padding-bottom: 36px; - padding-top: 36px; -} - -@media (min-width: 768px) { - .section { - padding-bottom: 72px; - padding-top: 72px; - } -} - -.section+.section { - padding-top: 0; -} - -.container { - margin: 0 auto; - max-width: 1380px; - padding-left: 12px; - padding-right: 12px; - width: 100%; -} - -@media (min-width: 768px) { - .container { - padding-left: 24px; - padding-right: 24px; - } -} - -.container-medium { - margin: 0 auto; - max-width: 944px; - padding-left: 12px; - padding-right: 12px; -} - -@media (min-width: 768px) { - .container-medium { - padding-left: 24px; - padding-right: 24px; - } -} - -.container-small { - margin: 0 auto; - max-width: 400px; - padding-left: 12px; - padding-right: 12px; -} - -@media (min-width: 768px) { - .container-small { - padding-left: 24px; - padding-right: 24px; - } -} - -/** - * TYPOGRAPHY - */ -body { - color: #272727; - font-family: "Lato", sans-serif; - font-size: 16px; - font-weight: 400; - line-height: 1.5em; -} - -a { - color: var(--blue); - text-decoration: none; -} - -a:hover { - color: color-mix(in srgb, var(--color-primary), #FFF 15%); -} - -a:focus { - color: var(--blue); -} - -.text-huge, -.text-big, -.text-medium { - margin-bottom: 1em; -} - -.text-huge { - font-size: 36px; - line-height: 1.3em; -} - -.text-big { - font-size: 24px; - line-height: 1.3em; -} - -.text-medium { - font-size: 16px; - line-height: 1.5em; -} - -.text-small { - font-size: 12px; - line-height: 1.3em; -} - -.text-body { - font-size: 16px; - line-height: 1.5em; -} - -.text-primary { - color: #03a9f4; -} - -.text-dark { - color: #18232f; -} - -.text-secondary { - color: #e91e63; -} - -.text-white { - color: #fff; -} - -.text-success { - color: #4caf50; -} - -.text-info { - color: #5bc0de; -} - -.text-warning { - color: #f0ad4e; -} - -.text-error { - color: #e74c3c; -} - -.text-gray { - color: #969da6; -} - -.text-gray-light { - color: #eceff1; -} - -.text-light { - font-weight: 300; -} - -.text-normal { - font-weight: 400; -} - -.text-lineThrough { - text-decoration: line-through; -} - -.text-italic { - font-style: italic; -} - -.text-underline { - text-decoration: underline; -} - -.text-uppercase { - text-transform: uppercase; -} - -.text-withSubtitle { - margin-bottom: 0 !important; -} - -.text-withSubtitle+.text-huge, -.text-withSubtitle+.text-big, -.text-withSubtitle+.text-medium, -.text-withSubtitle+.text-small { - margin-top: 0.5em; -} - -h1, -h2, -h3, -h4 { - font-weight: 300; -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.text-left { - text-align: left; -} - -/** - * BUTTON - * - * Markup: - * ------- - * - * - * - * - * - */ -button { - background-color: transparent; - cursor: pointer; -} - -.button { - background-color: #03a9f4; - border: 0; - border-radius: 200px; - color: #fff; - display: inline-block; - font-family: "Lato", sans-serif; - font-size: 16px; - font-weight: 600; - line-height: 1.5em; - padding: 8px 16px; - text-align: center; - text-decoration: none; - text-transform: uppercase; - transition: opacity 0.2s ease-in-out; - white-space: nowrap; -} - -.button:focus, -.button:hover, -.button:active { - color: #fff; -} - -.button:hover { - background-color: rgba(3, 169, 244, 0.8); - color: #fff; - cursor: pointer; - text-decoration: none; -} - -.button:active { - opacity: 1; -} - -.button:first-child { - margin-left: 0; -} - -.button:last-child { - margin-right: 0; -} - -.button--big { - font-size: 24px; - padding: 16px 36px; -} - -.button--small { - font-size: 12px; - padding: 4px 16px; -} - -@media (max-width: 991px) { - .button--mobileFull { - margin-left: 0; - margin-right: 0; - width: 100%; - } -} - -.button--secondary { - background-color: #e91e63; - color: #fff; -} - -.button--secondary:hover { - background-color: rgba(233, 30, 99, 0.8); - color: #fff; -} - -.button--white { - background-color: #fff; - color: #03a9f4; -} - -.button--white:hover { - background-color: rgba(255, 255, 255, 0.8); - color: rgba(3, 169, 244, 0.8); -} - -.button--green { - background-color: #4caf50; - color: #fff; -} - -.button--green:hover { - background-color: rgba(76, 175, 80, 0.8); - color: #fff; -} - -.button--red { - background-color: #e74c3c; - color: #fff; -} - -.button--red:hover { - background-color: rgba(231, 76, 60, 0.8); - color: #fff; -} - -.button--transparent { - background-color: transparent; - color: #03a9f4; -} - -.button--transparent:active, -.button--transparent:hover, -.button--transparent:focus { - background-color: transparent; - color: rgba(3, 169, 244, 0.8); - opacity: 0.8; -} - -.button--outlined { - background-color: transparent; - border: 1px solid var(--white); - color: #03a9f4; -} - -.button--outlined:active, -.button--outlined:hover, -.button--outlined:focus { - background-color: transparent; - color: rgba(3, 169, 244, 0.8); - opacity: 0.8; -} - -/** - * FORMS - * - * Markup: - * --------- - *
- * - *
- * - *
- * - *
- * - *
- * - *
- * - *
- * - * - *
- * - *
- * - * - *
- */ -input, -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - resize: none; -} - -label { - display: block; - font-weight: normal; -} - -input:-webkit-autofill { - box-shadow: 0 0 0 1000px #eceff1 inset; -} - -.textarea, -.input, -.select { - border: 1px solid var(--white); - border-radius: var(--border-radius); - box-shadow: none; - display: inline-block; - font-weight: normal; - overflow: hidden; -} - -.textarea :focus, -.input :focus, -.select :focus { - outline: none; -} - -.textarea.has-error, -.input.has-error, -.select.has-error { - background: #eceff1; - border: 1px solid #e74c3c; - margin-bottom: 0; -} - -.select { - background-color: #eceff1; - display: inline-block; - margin-right: 16px; - position: relative; -} - -.select:last-child { - margin-right: 0; -} - -.select-fullWidth { - display: block; - margin-left: 0; - margin-right: 0; - width: 100%; -} - -.select select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-color: transparent; - border: 0; - border-radius: 0; - color: #272727; - display: block; - font-size: 16px; - line-height: 1.5em; - margin: 0; - padding: 8px 16px; - padding-right: 30px; - transition: background-color 0.2s ease-in-out; - width: 100%; -} - -.select select:active, -.select select:focus { - background-color: #fbfbfc; - border: 0; - outline: none; -} - -.select select::-ms-expand { - display: none; -} - -.select::after, -.select::before { - background: #03a9f4; - content: ""; - display: block; - height: 2px; - margin-top: 2px; - position: absolute; - right: 5px; - top: 50%; - -webkit-transform-origin: 1px; - transform-origin: 1px; - width: 10px; -} - -.select::after { - -webkit-transform: rotate(-135deg); - transform: rotate(-135deg); -} - -.select::before { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); -} - -.textarea { - background-color: #eceff1; - padding: 0; -} - -.textarea-fullWidth { - display: block; - margin-left: 0; - margin-right: 0; - width: 100%; -} - -.textarea textarea { - background: transparent; - border: 0; - color: #272727; - display: block; - font-family: "Lato", sans-serif; - font-size: 16px; - line-height: 1.5em; - margin: 0; - min-height: 120px; - padding: 8px 16px; - transition: background-color 0.2s ease-in-out; - width: 100%; -} - -.textarea textarea::-webkit-input-placeholder { - color: #969da6; -} - -.textarea textarea::-ms-input-placeholder { - color: #969da6; -} - -.textarea textarea::placeholder { - color: #969da6; -} - -.textarea textarea:focus, -.textarea textarea:active { - background-color: #fbfbfc; - border: 0; - outline: none; -} - -.checkbox { - margin-bottom: 8px; - position: relative; -} - -.checkbox input[type="checkbox"] { - display: none; -} - -.checkbox input[type="checkbox"]:checked+label::after { - -webkit-animation: checkboxAndRadioAnimation 0.25s; - animation: checkboxAndRadioAnimation 0.25s; - content: ""; - -webkit-transform: scale(1) rotate(45deg); - transform: scale(1) rotate(45deg); -} - -.checkbox input[type="checkbox"]+label { - display: block; - overflow: hidden; - padding-left: 30px; - text-overflow: ellipsis; - white-space: nowrap; -} - -.checkbox input[type="checkbox"]+label::before { - background-color: #eceff1; - border: 1px solid var(--white); - border-radius: var(--border-radius); - content: ""; - display: inline-block; - height: 20px; - left: 0; - margin-top: -10px; - position: absolute; - top: 50%; - width: 20px; -} - -.checkbox input[type="checkbox"]+label::after { - border-bottom: 3px solid #03a9f4; - border-right: 3px solid #03a9f4; - display: block; - height: 12px; - left: 11px; - margin-left: -4px; - margin-top: -7px; - position: absolute; - top: 50%; - width: 7px; - z-index: 1; -} - -.radio { - margin-bottom: 8px; - position: relative; -} - -.radio input[type="radio"] { - display: none; -} - -.radio input[type="radio"]:checked+label::after { - -webkit-animation: checkboxAndRadioAnimation 0.25s; - animation: checkboxAndRadioAnimation 0.25s; - content: ""; - -webkit-transform: scale(1) rotate(45deg); - transform: scale(1) rotate(45deg); -} - -.radio input[type="radio"]+label { - display: block; - overflow: hidden; - padding-left: 30px; - text-overflow: ellipsis; - white-space: nowrap; -} - -.radio input[type="radio"]+label::before { - background-color: #eceff1; - border: 1px solid var(--white); - border-radius: 20px; - content: ""; - display: inline-block; - height: 20px; - left: 0; - margin-top: -10px; - position: absolute; - top: 50%; - width: 20px; -} - -.radio input[type="radio"]+label::after { - background-color: #03a9f4; - border-radius: 20px; - display: block; - height: 10px; - left: 11px; - margin-left: -6px; - margin-top: -6px; - position: absolute; - top: 13px; - width: 10px; - z-index: 1; -} - -@-webkit-keyframes checkboxAndRadioAnimation { - 0% { - -webkit-transform: scale(0) rotate(45deg); - transform: scale(0) rotate(45deg); - } - - 50% { - -webkit-transform: scale(1.5) rotate(45deg); - transform: scale(1.5) rotate(45deg); - } - - 100% { - -webkit-transform: scale(1) rotate(45deg); - transform: scale(1) rotate(45deg); - } -} - -@keyframes checkboxAndRadioAnimation { - 0% { - -webkit-transform: scale(0) rotate(45deg); - transform: scale(0) rotate(45deg); - } - - 50% { - -webkit-transform: scale(1.5) rotate(45deg); - transform: scale(1.5) rotate(45deg); - } - - 100% { - -webkit-transform: scale(1) rotate(45deg); - transform: scale(1) rotate(45deg); - } -} - -.input-invis { - background-color: transparent !important; - margin: auto !important; - border: 0 !important; -} - -.input { - background-color: var(--white); - padding: 0; - position: relative; -} - -.input :focus, -.input :active { - background-color: var(--white); - border-radius: var(--border-radius); -} - -.input input, -.input textarea { - background: transparent; - border: 0; - box-shadow: none; - color: #272727; - font-size: 16px; - line-height: 1.5em; - margin: 0; - outline: none; - padding: 8px 16px; - width: 100%; -} - -.input input::-webkit-input-placeholder { - color: #969da6; -} - -.input input::-ms-input-placeholder { - color: #969da6; -} - -.input input::placeholder { - color: #969da6; -} - -.input input.small { - line-height: 1em; - padding: 0; -} - -.input-withIcon input { - padding-right: 32px; -} - -.input-icon { - fill: #969da6; - height: 16px; - margin-top: -8px; - position: absolute; - right: 16px; - top: 50%; - width: 16px; -} - -/** - * LOADING BAR - * - * Markup: - * --------- - *
- * - */ -.loadingBar { - height: 6px; - left: 0; - overflow: hidden; - position: fixed; - right: 0; - top: 0; - width: 100%; - z-index: 1000; -} - -.loadingBar::before { - -webkit-animation: loading 2s linear infinite; - animation: loading 2s linear infinite; - background-color: #03a9f4; - content: ""; - display: block; - height: 6px; - left: -300px; - position: absolute; - width: 300px; -} - -@-webkit-keyframes loading { - from { - left: -300px; - width: 30%; - } - - 50% { - width: 30%; - } - - 70% { - width: 70%; - } - - 80% { - left: 50%; - } - - 95% { - left: 120%; - } - - to { - left: 100%; - } -} - -@keyframes loading { - from { - left: -300px; - width: 30%; - } - - 50% { - width: 30%; - } - - 70% { - width: 70%; - } - - 80% { - left: 50%; - } - - 95% { - left: 120%; - } - - to { - left: 100%; - } -} - - -.container { - width: 100%; - padding-right: 12px; - padding-left: 12px; - margin-right: auto; - margin-left: auto; -} - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} - -.container-fluid { - width: 100%; - padding-right: 12px; - padding-left: 12px; - margin-right: auto; - margin-left: auto; -} - -.row { - display: flex; - flex-wrap: wrap; - margin-right: -12px; - margin-left: -12px; -} - -.col-1, -.col-2, -.col-3, -.col-4, -.col-5, -.col-6, -.col-7, -.col-8, -.col-9, -.col-10, -.col-11, -.col-12, -.col, -.col-auto, -.col-sm-1, -.col-sm-2, -.col-sm-3, -.col-sm-4, -.col-sm-5, -.col-sm-6, -.col-sm-7, -.col-sm-8, -.col-sm-9, -.col-sm-10, -.col-sm-11, -.col-sm-12, -.col-sm, -.col-sm-auto, -.col-md-1, -.col-md-2, -.col-md-3, -.col-md-4, -.col-md-5, -.col-md-6, -.col-md-7, -.col-md-8, -.col-md-9, -.col-md-10, -.col-md-11, -.col-md-12, -.col-md, -.col-md-auto, -.col-lg-1, -.col-lg-2, -.col-lg-3, -.col-lg-4, -.col-lg-5, -.col-lg-6, -.col-lg-7, -.col-lg-8, -.col-lg-9, -.col-lg-10, -.col-lg-11, -.col-lg-12, -.col-lg, -.col-lg-auto, -.col-xl-1, -.col-xl-2, -.col-xl-3, -.col-xl-4, -.col-xl-5, -.col-xl-6, -.col-xl-7, -.col-xl-8, -.col-xl-9, -.col-xl-10, -.col-xl-11, -.col-xl-12, -.col-xl, -.col-xl-auto { - position: relative; - width: 100%; - min-height: 1px; - padding-right: 12px; - padding-left: 12px; -} - -.col { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; -} - -.col-auto { - flex: 0 0 auto; - width: auto; - max-width: none; -} - -.col-1 { - flex: 0 0 8.33333%; - max-width: 8.33333%; -} - -.col-2 { - flex: 0 0 16.66667%; - max-width: 16.66667%; -} - -.col-3 { - flex: 0 0 25%; - max-width: 25%; -} - -.col-4 { - flex: 0 0 33.33333%; - max-width: 33.33333%; -} - -.col-5 { - flex: 0 0 41.66667%; - max-width: 41.66667%; -} - -.col-6 { - flex: 0 0 50%; - max-width: 50%; -} - -.col-7 { - flex: 0 0 58.33333%; - max-width: 58.33333%; -} - -.col-8 { - flex: 0 0 66.66667%; - max-width: 66.66667%; -} - -.col-9 { - flex: 0 0 75%; - max-width: 75%; -} - -.col-10 { - flex: 0 0 83.33333%; - max-width: 83.33333%; -} - -.col-11 { - flex: 0 0 91.66667%; - max-width: 91.66667%; -} - -.col-12 { - flex: 0 0 100%; - max-width: 100%; -} - -@media (min-width: 576px) { - .col-sm { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - } - - .col-sm-auto { - flex: 0 0 auto; - width: auto; - max-width: none; - } - - .col-sm-1 { - flex: 0 0 8.33333%; - max-width: 8.33333%; - } - - .col-sm-2 { - flex: 0 0 16.66667%; - max-width: 16.66667%; - } - - .col-sm-3 { - flex: 0 0 25%; - max-width: 25%; - } - - .col-sm-4 { - flex: 0 0 33.33333%; - max-width: 33.33333%; - } - - .col-sm-5 { - flex: 0 0 41.66667%; - max-width: 41.66667%; - } - - .col-sm-6 { - flex: 0 0 50%; - max-width: 50%; - } - - .col-sm-7 { - flex: 0 0 58.33333%; - max-width: 58.33333%; - } - - .col-sm-8 { - flex: 0 0 66.66667%; - max-width: 66.66667%; - } - - .col-sm-9 { - flex: 0 0 75%; - max-width: 75%; - } - - .col-sm-10 { - flex: 0 0 83.33333%; - max-width: 83.33333%; - } - - .col-sm-11 { - flex: 0 0 91.66667%; - max-width: 91.66667%; - } - - .col-sm-12 { - flex: 0 0 100%; - max-width: 100%; - } -} - -@media (min-width: 768px) { - .col-md { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - } - - .col-md-auto { - flex: 0 0 auto; - width: auto; - max-width: none; - } - - .col-md-1 { - flex: 0 0 8.33333%; - max-width: 8.33333%; - } - - .col-md-2 { - flex: 0 0 16.66667%; - max-width: 16.66667%; - } - - .col-md-3 { - flex: 0 0 25%; - max-width: 25%; - } - - .col-md-4 { - flex: 0 0 33.33333%; - max-width: 33.33333%; - } - - .col-md-5 { - flex: 0 0 41.66667%; - max-width: 41.66667%; - } - - .col-md-6 { - flex: 0 0 50%; - max-width: 50%; - } - - .col-md-7 { - flex: 0 0 58.33333%; - max-width: 58.33333%; - } - - .col-md-8 { - flex: 0 0 66.66667%; - max-width: 66.66667%; - } - - .col-md-9 { - flex: 0 0 75%; - max-width: 75%; - } - - .col-md-10 { - flex: 0 0 83.33333%; - max-width: 83.33333%; - } - - .col-md-11 { - flex: 0 0 91.66667%; - max-width: 91.66667%; - } - - .col-md-12 { - flex: 0 0 100%; - max-width: 100%; - } -} - -@media (min-width: 992px) { - .col-lg { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - } - - .col-lg-auto { - flex: 0 0 auto; - width: auto; - max-width: none; - } - - .col-lg-1 { - flex: 0 0 8.33333%; - max-width: 8.33333%; - } - - .col-lg-2 { - flex: 0 0 16.66667%; - max-width: 16.66667%; - } - - .col-lg-3 { - flex: 0 0 25%; - max-width: 25%; - } - - .col-lg-4 { - flex: 0 0 33.33333%; - max-width: 33.33333%; - } - - .col-lg-5 { - flex: 0 0 41.66667%; - max-width: 41.66667%; - } - - .col-lg-6 { - flex: 0 0 50%; - max-width: 50%; - } - - .col-lg-7 { - flex: 0 0 58.33333%; - max-width: 58.33333%; - } - - .col-lg-8 { - flex: 0 0 66.66667%; - max-width: 66.66667%; - } - - .col-lg-9 { - flex: 0 0 75%; - max-width: 75%; - } - - .col-lg-10 { - flex: 0 0 83.33333%; - max-width: 83.33333%; - } - - .col-lg-11 { - flex: 0 0 91.66667%; - max-width: 91.66667%; - } - - .col-lg-12 { - flex: 0 0 100%; - max-width: 100%; - } - -} - -@media (min-width: 1200px) { - .col-xl { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - } - - .col-xl-auto { - flex: 0 0 auto; - width: auto; - max-width: none; - } - - .col-xl-1 { - flex: 0 0 8.33333%; - max-width: 8.33333%; - } - - .col-xl-2 { - flex: 0 0 16.66667%; - max-width: 16.66667%; - } - - .col-xl-3 { - flex: 0 0 25%; - max-width: 25%; - } - - .col-xl-4 { - flex: 0 0 33.33333%; - max-width: 33.33333%; - } - - .col-xl-5 { - flex: 0 0 41.66667%; - max-width: 41.66667%; - } - - .col-xl-6 { - flex: 0 0 50%; - max-width: 50%; - } - - .col-xl-7 { - flex: 0 0 58.33333%; - max-width: 58.33333%; - } - - .col-xl-8 { - flex: 0 0 66.66667%; - max-width: 66.66667%; - } - - .col-xl-9 { - flex: 0 0 75%; - max-width: 75%; - } - - .col-xl-10 { - flex: 0 0 83.33333%; - max-width: 83.33333%; - } - - .col-xl-11 { - flex: 0 0 91.66667%; - max-width: 91.66667%; - } - - .col-xl-12 { - flex: 0 0 100%; - max-width: 100%; - } - -} - -[v-cloak] { - display: none; -} - - - -html, -body, -body, -div, -span, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -abbr, -address, -cite, -code, -del, -dfn, -em, -ins, -kbd, -q, -samp, -small, -strong, -sub, -sup, -var, -b, -i, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -figure, -footer, -header, -hgroup, -menu, -nav, -section, -time, -mark, -audio, -video { - background: transparent; - border: 0; - font-size: 100%; - margin: 0; - outline: 0; - padding: 0; - vertical-align: baseline; -} - -article, -aside, -figure, -footer, -header, -main, -nav, -section { - display: block; -} - -*, -*:before, -*:after { - box-sizing: border-box; -} - - -*, -*::after, -*::before { - box-sizing: border-box; - outline: none; -} - -body { - background-color: #fff; - min-height: 100%; - overflow-x: hidden; - position: relative; -} - -p { - font-weight: normal; - margin-bottom: 1.5em; -} - -img { - max-width: 100%; -} - -strong { - font-weight: 600; -} - -ul { - margin-bottom: 1em; -} - -li { - list-style: none; - margin-bottom: 0.5em; -} - -/* CUSTOM ELEMENTS */ - - -.leaflet-popup-close-button { - visibility: hidden; -} - -.p-abs { - position: absolute; -} - -.list-group { - overflow: auto; - white-space: nowrap; - scrollbar-width: none; - padding: 1rem 0rem; -} - -.list-group-item { - border: 1px solid var(--darkdark); - display: inline-block; - position: relative; - cursor: pointer; - text-align: center; - padding: 0.5rem 0.8rem; -} - -.list-group-item:hover { - filter: brightness(85%); -} - -.leaflet-control-attribution { - display: none; -} - -.display-none { - display: none; -} - -.col-0 { - flex: 0 0 0%; - max-width: 0%; - overflow: hidden; -} - -.map-container, -.drawer-container { - transition: flex 0.5s ease-in-out, max-width 0.5s ease-in-out; -} - -.map-container { - min-width: 52px; - height: 100%; -} - -.drawer-container { - height: 100%; - right: 0; - top: 0; - overflow: scroll; -} - -.travel-path-icon { - margin-left: -12px; - margin-top: -32px; -} - - -@-webkit-keyframes spinning { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 25% { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); - } - - 50% { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - } - - 75% { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); - } - - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@keyframes spinning { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 50% { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - } - - - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -.spinner { - position: absolute; - right: 0; - top: 0; - width: 40px; - height: 40px; - display: block -} - -.spinner:after, -.spinner:before { - position: absolute; - content: ""; - top: 50%; - left: 50%; - margin: -12px 0 0 -12px; - width: 24px; - height: 24px; - border-radius: 100%; - border: 3px solid transparent; - border-top-color: var(--blue); -} - -.spinner:before { - -webkit-animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); - animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite -} - -.spinner:after { - -webkit-animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); - animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite -} - -.ml-auto { - margin-left: auto; -} - -.mr-auto { - margin-right: auto; -} - -.input .mx-input { - height: 40px; -} - -.h-100 { - height: 100%; -} - -.map-menu { - position: absolute; - display: flex; - z-index: 1100; - right: 0; - flex-direction: column; - gap: 10px; - margin: 5px; -} - -.map-menu-top { - top: 0; -} - -.map-menu-bottom { - bottom: 0; -} - -.map-menu-center { - top: 50%; -} - -.padding-1 { - padding: 5px; -} - -.map-menu-item { - background-color: var(--darkdark); - padding: 5px; - border-radius: 50%; - cursor: pointer; -} - -.map-menu-item:hover { - filter: brightness(150%); -} - -.map-menu-sub { - display: flex; - flex-direction: row-reverse; - gap: 5px; -} - -.map-menu-item, -.map-menu-sub-item { - background-color: var(--darkdark); - padding: 5px; - border-radius: 50%; - cursor: pointer; - float: right; - width: 42px; - height: 42px; - align-content: center; - text-align: center; -} - -.vue2leaflet-map { - border-radius: var(--border-radius); -} - -.leaflet-popup-content { - margin: 10px 20px !important; - /* display: flex; - align-items: center; - justify-content: center; - width: auto !important; - max-width: 100%; */ -} - - -.leaflet-popup>.leaflet-popup-content-wrapper { - border-radius: var(--border-radius); - width: 350px; -} - -.leaflet-popup-button-group { - position: absolute; - top: 0; - right: 0; - display: flex; - flex-direction: row; - gap: 5px; - margin: 2px 6px; -} - -.leaflet-popup-button-group>a { - cursor: pointer; -} - -.leaflet-popup-button-group>a:hover { - cursor: pointer; - filter: brightness(150%); -} - -.leaflet-popup-button-group>a>i { - font-size: 1em; -} - -.query-result { - display: flex; - align-items: center; - border-radius: var(--border-radius); - cursor: pointer; -} - -.query-result:hover { - filter: brightness(85%); -} - -.scroll-content>div:first-child { - border-top-left-radius: var(--border-radius); - border-bottom-left-radius: var(--border-radius); -} - -.scroll-content>div:nth-last-child(3) { - border-top-right-radius: var(--border-radius); - border-bottom-right-radius: var(--border-radius); -} - -.scroll-content>div:last-child { - border-radius: var(--border-radius); -} - -.mx-datepicker { - width: 100% !important; -} \ No newline at end of file diff --git a/src/server/main.ts b/src/server/main.ts index 91ba4d3..599b401 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -25,10 +25,10 @@ server.register(fastify_view, { server.register(api, { prefix: "/api" }); -server.get("/", (req, reply) => reply.view("/template/home.pug")); -server.get("/:id", (req, reply) => reply.view("/template/journey.pug")); -server.get("/view/:id", (req, reply) => reply.view("/template/view.pug")); -server.get("/short/:id", (req, reply) => reply.view("/template/short.pug")); +server.get("/", (req, reply) => reply.view("/src/template/home.pug")); +server.get("/:id", (req, reply) => reply.view("/src/template/journey.pug")); +server.get("/view/:id", (req, reply) => reply.view("/src/template/view.pug")); +server.get("/short/:id", (req, reply) => reply.view("/src/template/short.pug")); server.listen({ port: 8080, host: "0.0.0.0" }, (err, address) => { if (err) throw err; diff --git a/src/style/custom.css b/src/style/custom.css new file mode 100644 index 0000000..e9b5b85 --- /dev/null +++ b/src/style/custom.css @@ -0,0 +1,207 @@ +.leaflet-popup-close-button { + visibility: hidden; +} + +.p-abs { + position: absolute; +} + +.list-group { + overflow: auto; + white-space: nowrap; + scrollbar-width: none; + padding: 1rem 0rem; +} + +.list-group-item { + border: 1px solid var(--darkdark); + display: inline-block; + position: relative; + cursor: pointer; + text-align: center; + padding: 0.5rem 0.8rem; +} + +.list-group-item:hover { + filter: brightness(85%); +} + +.leaflet-control-attribution { + display: none; +} + +.display-none { + display: none; +} + +.col-0 { + flex: 0 0 0%; + max-width: 0%; + overflow: hidden; +} + +.map-container, +.drawer-container { + transition: flex 0.5s ease-in-out, max-width 0.5s ease-in-out; +} + +.map-container { + min-width: 52px; + height: 100%; +} + +.drawer-container { + height: 100%; + right: 0; + top: 0; + overflow: scroll; +} + +.travel-path-icon { + margin-left: -12px; + margin-top: -32px; +} + + +.ml-auto { + margin-left: auto; +} + +.mr-auto { + margin-right: auto; +} + +.input .mx-input { + height: 40px; +} + +.h-100 { + height: 100%; +} + +.map-menu { + position: absolute; + display: flex; + z-index: 1100; + right: 0; + flex-direction: column; + gap: 10px; + margin: 5px; +} + +.map-menu-top { + top: 0; +} + +.map-menu-bottom { + bottom: 0; +} + +.map-menu-center { + top: 50%; +} + +.padding-1 { + padding: 5px; +} + +.map-menu-item { + background-color: var(--darkdark); + padding: 5px; + border-radius: 50%; + cursor: pointer; +} + +.map-menu-item:hover { + filter: brightness(150%); +} + +.map-menu-sub { + display: flex; + flex-direction: row-reverse; + gap: 5px; +} + +.map-menu-item, +.map-menu-sub-item { + background-color: var(--darkdark); + padding: 5px; + border-radius: 50%; + cursor: pointer; + float: right; + width: 42px; + height: 42px; + align-content: center; + text-align: center; +} + +.vue2leaflet-map { + border-radius: var(--border-radius); +} + +.leaflet-popup-content { + margin: 10px 20px !important; + /* display: flex; + align-items: center; + justify-content: center; + width: auto !important; + max-width: 100%; */ +} + + +.leaflet-popup>.leaflet-popup-content-wrapper { + border-radius: var(--border-radius); + width: 350px; +} + +.leaflet-popup-button-group { + position: absolute; + top: 0; + right: 0; + display: flex; + flex-direction: row; + gap: 5px; + margin: 2px 6px; +} + +.leaflet-popup-button-group>a { + cursor: pointer; +} + +.leaflet-popup-button-group>a:hover { + cursor: pointer; + filter: brightness(150%); +} + +.leaflet-popup-button-group>a>i { + font-size: 1em; +} + +.query-result { + display: flex; + align-items: center; + border-radius: var(--border-radius); + cursor: pointer; +} + +.query-result:hover { + filter: brightness(85%); +} + +.scroll-content>div:first-child { + border-top-left-radius: var(--border-radius); + border-bottom-left-radius: var(--border-radius); +} + +.scroll-content>div:nth-last-child(3) { + border-top-right-radius: var(--border-radius); + border-bottom-right-radius: var(--border-radius); +} + +.scroll-content>div:last-child { + border-radius: var(--border-radius); +} + +.mx-datepicker { + width: 100% !important; +} \ No newline at end of file diff --git a/src/style/define.css b/src/style/define.css new file mode 100644 index 0000000..e7bbaed --- /dev/null +++ b/src/style/define.css @@ -0,0 +1,19 @@ +:root { + --black: #030B12; + --darkdark: #0C1D2E; + --dark: #203A53; + --lightdark: #425F7C; + --light: #93A9BE; + --lightlight: #B6C5D5; + --white: #F0F3F7; + --orange: ##F5B97D; + --yellow: #F5F57D; + --green: #B9F57D; + --turquoise: #7DF5B9; + --blue: #7DB9F5; + --purple: #B97DF5; + --pink: #F57DB9; + --red: #F57D7D; + + --border-radius: 3px; +} \ No newline at end of file diff --git a/src/style/index.css b/src/style/index.css new file mode 100644 index 0000000..018e967 --- /dev/null +++ b/src/style/index.css @@ -0,0 +1,13 @@ +@import './define.css'; + +@import './module/input.css'; +@import './module/load_n_spin.css'; +@import './module/typography.css'; +@import './module/layout.css'; +@import './module/general.css'; + +@import './custom.css'; + +[v-cloak] { + display: none; +} \ No newline at end of file diff --git a/src/style/module/general.css b/src/style/module/general.css new file mode 100644 index 0000000..88a2419 --- /dev/null +++ b/src/style/module/general.css @@ -0,0 +1,202 @@ +html, +body, +body, +div, +span, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +abbr, +address, +cite, +code, +del, +dfn, +em, +ins, +kbd, +q, +samp, +small, +strong, +sub, +sup, +var, +b, +i, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +time, +mark, +audio, +video { + background: transparent; + border: 0; + font-size: 100%; + margin: 0; + outline: 0; + padding: 0; + vertical-align: baseline; +} + +article, +aside, +figure, +footer, +header, +main, +nav, +section { + display: block; +} + +*, +*:before, +*:after { + box-sizing: border-box; +} + + +*, +*::after, +*::before { + box-sizing: border-box; + outline: none; +} + +body { + background-color: #fff; + min-height: 100%; + overflow-x: hidden; + position: relative; +} + +p { + font-weight: normal; + margin-bottom: 1.5em; +} + +img { + max-width: 100%; +} + +strong { + font-weight: 600; +} + +ul { + margin-bottom: 1em; +} + +li { + list-style: none; + margin-bottom: 0.5em; +} + +/** + * BACKGROUND + */ +.bg-primary { + background-color: var(--blue); +} + +.bg-dark { + background-color: var(--darkdark); +} + +.bg-secondary { + background-color: var(--pink); +} + +.bg-white { + background-color: var(--white); +} + +.bg-success { + background-color: var(--green); +} + +.bg-info { + background-color: var(--yellow); +} + +.bg-warning { + background-color: var(--orange); +} + +.bg-error { + background-color: var(--red); +} + +.bg-gray { + background-color: var(--lightdark); +} + +.bg-gray-light { + background-color: var(--lightlight); +} + + +.align { + align-items: center; + justify-content: center; +} + +.fleft { + float: left; +} + +.fright { + float: right; +} + +.clearfix ::after { + clear: both; + content: ""; + display: table; +} + +.no-wrap { + white-space: nowrap; +} + +.overflow-hidden { + overflow: hidden; +} + +.rounded { + border-radius: var(--border-radius); +} \ No newline at end of file diff --git a/src/style/module/input.css b/src/style/module/input.css new file mode 100644 index 0000000..5ebba66 --- /dev/null +++ b/src/style/module/input.css @@ -0,0 +1,362 @@ +input, +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + resize: none; +} + +label { + display: block; + font-weight: normal; +} + +input:-webkit-autofill { + box-shadow: 0 0 0 1000px #eceff1 inset; +} + +.textarea, +.input, +.select { + border: 1px solid var(--white); + border-radius: var(--border-radius); + box-shadow: none; + display: inline-block; + font-weight: normal; + overflow: hidden; +} + +.textarea :focus, +.input :focus, +.select :focus { + outline: none; +} + +.textarea.has-error, +.input.has-error, +.select.has-error { + background: #eceff1; + border: 1px solid #e74c3c; + margin-bottom: 0; +} + +.select { + background-color: #eceff1; + display: inline-block; + margin-right: 16px; + position: relative; +} + +.select:last-child { + margin-right: 0; +} + +.select-fullWidth { + display: block; + margin-left: 0; + margin-right: 0; + width: 100%; +} + +.select select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: transparent; + border: 0; + border-radius: 0; + color: #272727; + display: block; + font-size: 16px; + line-height: 1.5em; + margin: 0; + padding: 8px 16px; + padding-right: 30px; + transition: background-color 0.2s ease-in-out; + width: 100%; +} + +.select select:active, +.select select:focus { + background-color: #fbfbfc; + border: 0; + outline: none; +} + +.select select::-ms-expand { + display: none; +} + +.select::after, +.select::before { + background: #03a9f4; + content: ""; + display: block; + height: 2px; + margin-top: 2px; + position: absolute; + right: 5px; + top: 50%; + -webkit-transform-origin: 1px; + transform-origin: 1px; + width: 10px; +} + +.select::after { + -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); +} + +.select::before { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +.textarea { + background-color: #eceff1; + padding: 0; +} + +.textarea-fullWidth { + display: block; + margin-left: 0; + margin-right: 0; + width: 100%; +} + +.textarea textarea { + background: transparent; + border: 0; + color: #272727; + display: block; + font-family: "Lato", sans-serif; + font-size: 16px; + line-height: 1.5em; + margin: 0; + min-height: 120px; + padding: 8px 16px; + transition: background-color 0.2s ease-in-out; + width: 100%; +} + +.textarea textarea::-webkit-input-placeholder { + color: #969da6; +} + +.textarea textarea::-ms-input-placeholder { + color: #969da6; +} + +.textarea textarea::placeholder { + color: #969da6; +} + +.textarea textarea:focus, +.textarea textarea:active { + background-color: #fbfbfc; + border: 0; + outline: none; +} + +.checkbox { + margin-bottom: 8px; + position: relative; +} + +.checkbox input[type="checkbox"] { + display: none; +} + +.checkbox input[type="checkbox"]:checked+label::after { + -webkit-animation: checkboxAndRadioAnimation 0.25s; + animation: checkboxAndRadioAnimation 0.25s; + content: ""; + -webkit-transform: scale(1) rotate(45deg); + transform: scale(1) rotate(45deg); +} + +.checkbox input[type="checkbox"]+label { + display: block; + overflow: hidden; + padding-left: 30px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.checkbox input[type="checkbox"]+label::before { + background-color: #eceff1; + border: 1px solid var(--white); + border-radius: var(--border-radius); + content: ""; + display: inline-block; + height: 20px; + left: 0; + margin-top: -10px; + position: absolute; + top: 50%; + width: 20px; +} + +.checkbox input[type="checkbox"]+label::after { + border-bottom: 3px solid #03a9f4; + border-right: 3px solid #03a9f4; + display: block; + height: 12px; + left: 11px; + margin-left: -4px; + margin-top: -7px; + position: absolute; + top: 50%; + width: 7px; + z-index: 1; +} + +.radio { + margin-bottom: 8px; + position: relative; +} + +.radio input[type="radio"] { + display: none; +} + +.radio input[type="radio"]:checked+label::after { + -webkit-animation: checkboxAndRadioAnimation 0.25s; + animation: checkboxAndRadioAnimation 0.25s; + content: ""; + -webkit-transform: scale(1) rotate(45deg); + transform: scale(1) rotate(45deg); +} + +.radio input[type="radio"]+label { + display: block; + overflow: hidden; + padding-left: 30px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.radio input[type="radio"]+label::before { + background-color: #eceff1; + border: 1px solid var(--white); + border-radius: 20px; + content: ""; + display: inline-block; + height: 20px; + left: 0; + margin-top: -10px; + position: absolute; + top: 50%; + width: 20px; +} + +.radio input[type="radio"]+label::after { + background-color: #03a9f4; + border-radius: 20px; + display: block; + height: 10px; + left: 11px; + margin-left: -6px; + margin-top: -6px; + position: absolute; + top: 13px; + width: 10px; + z-index: 1; +} + +@-webkit-keyframes checkboxAndRadioAnimation { + 0% { + -webkit-transform: scale(0) rotate(45deg); + transform: scale(0) rotate(45deg); + } + + 50% { + -webkit-transform: scale(1.5) rotate(45deg); + transform: scale(1.5) rotate(45deg); + } + + 100% { + -webkit-transform: scale(1) rotate(45deg); + transform: scale(1) rotate(45deg); + } +} + +@keyframes checkboxAndRadioAnimation { + 0% { + -webkit-transform: scale(0) rotate(45deg); + transform: scale(0) rotate(45deg); + } + + 50% { + -webkit-transform: scale(1.5) rotate(45deg); + transform: scale(1.5) rotate(45deg); + } + + 100% { + -webkit-transform: scale(1) rotate(45deg); + transform: scale(1) rotate(45deg); + } +} + +.input-invis { + background-color: transparent !important; + margin: auto !important; + border: 0 !important; +} + +.input { + background-color: var(--white); + padding: 0; + position: relative; +} + +.input :focus, +.input :active { + background-color: var(--white); + border-radius: var(--border-radius); +} + +.input input, +.input textarea { + background: transparent; + border: 0; + box-shadow: none; + color: #272727; + font-size: 16px; + line-height: 1.5em; + margin: 0; + outline: none; + padding: 8px 16px; + width: 100%; +} + +.input input::-webkit-input-placeholder { + color: #969da6; +} + +.input input::-ms-input-placeholder { + color: #969da6; +} + +.input input::placeholder { + color: #969da6; +} + +.input input.small { + line-height: 1em; + padding: 0; +} + +.input-withIcon input { + padding-right: 32px; +} + +.input-icon { + fill: #969da6; + height: 16px; + margin-top: -8px; + position: absolute; + right: 16px; + top: 50%; + width: 16px; +} \ No newline at end of file diff --git a/src/style/module/layout.css b/src/style/module/layout.css new file mode 100644 index 0000000..58ec6d9 --- /dev/null +++ b/src/style/module/layout.css @@ -0,0 +1,354 @@ +/** + * LAYOUT + */ +.section { + padding-bottom: 36px; + padding-top: 36px; +} + +@media (min-width: 768px) { + .section { + padding-bottom: 72px; + padding-top: 72px; + } +} + +.section+.section { + padding-top: 0; +} + +.container { + margin: 0 auto; + max-width: 1380px; + padding-left: 12px; + padding-right: 12px; + width: 100%; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +@media (min-width: 768px) { + .container { + padding-left: 24px; + padding-right: 24px; + max-width: 720px; + } +} + +.container-medium { + margin: 0 auto; + max-width: 944px; + padding-left: 12px; + padding-right: 12px; +} + +@media (min-width: 768px) { + .container-medium { + padding-left: 24px; + padding-right: 24px; + } +} + +.container { + width: 100%; + padding-right: 12px; + padding-left: 12px; + margin-right: auto; + margin-left: auto; +} + +.container-fluid { + width: 100%; + padding-right: 12px; + padding-left: 12px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: flex; + flex-wrap: wrap; + margin-right: -12px; + margin-left: -12px; +} + +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12, +.col, +.col-auto, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12 { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 12px; + padding-left: 12px; +} + +.col { + flex-basis: 0; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; + max-width: none; +} + +.col-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; +} + +.col-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; +} + +.col-3 { + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; +} + +.col-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; +} + +.col-6 { + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; +} + +.col-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; +} + +.col-9 { + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; +} + +.col-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; +} + +.col-12 { + flex: 0 0 100%; + max-width: 100%; +} + +@media (min-width: 576px) { + .col-sm { + flex-basis: 0; + flex-grow: 1; + max-width: 100%; + } + + .col-sm-auto { + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-sm-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-sm-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-sm-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-sm-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-sm-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-sm-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-sm-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-sm-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-sm-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-sm-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-sm-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-sm-12 { + flex: 0 0 100%; + max-width: 100%; + } +} + +@media (min-width: 768px) { + .col-md { + flex-basis: 0; + flex-grow: 1; + max-width: 100%; + } + + .col-md-auto { + flex: 0 0 auto; + width: auto; + max-width: none; + } + + .col-md-1 { + flex: 0 0 8.33333%; + max-width: 8.33333%; + } + + .col-md-2 { + flex: 0 0 16.66667%; + max-width: 16.66667%; + } + + .col-md-3 { + flex: 0 0 25%; + max-width: 25%; + } + + .col-md-4 { + flex: 0 0 33.33333%; + max-width: 33.33333%; + } + + .col-md-5 { + flex: 0 0 41.66667%; + max-width: 41.66667%; + } + + .col-md-6 { + flex: 0 0 50%; + max-width: 50%; + } + + .col-md-7 { + flex: 0 0 58.33333%; + max-width: 58.33333%; + } + + .col-md-8 { + flex: 0 0 66.66667%; + max-width: 66.66667%; + } + + .col-md-9 { + flex: 0 0 75%; + max-width: 75%; + } + + .col-md-10 { + flex: 0 0 83.33333%; + max-width: 83.33333%; + } + + .col-md-11 { + flex: 0 0 91.66667%; + max-width: 91.66667%; + } + + .col-md-12 { + flex: 0 0 100%; + max-width: 100%; + } +} \ No newline at end of file diff --git a/src/style/module/load_n_spin.css b/src/style/module/load_n_spin.css new file mode 100644 index 0000000..17fe58c --- /dev/null +++ b/src/style/module/load_n_spin.css @@ -0,0 +1,166 @@ +/** + * LOADING BAR + * + * Markup: + * --------- + *
+ * + */ +.loadingBar { + height: 6px; + left: 0; + overflow: hidden; + position: fixed; + right: 0; + top: 0; + width: 100%; + z-index: 1000; +} + +.loadingBar::before { + -webkit-animation: loading 2s linear infinite; + animation: loading 2s linear infinite; + background-color: #03a9f4; + content: ""; + display: block; + height: 6px; + left: -300px; + position: absolute; + width: 300px; +} + +@-webkit-keyframes loading { + from { + left: -300px; + width: 30%; + } + + 50% { + width: 30%; + } + + 70% { + width: 70%; + } + + 80% { + left: 50%; + } + + 95% { + left: 120%; + } + + to { + left: 100%; + } +} + +@keyframes loading { + from { + left: -300px; + width: 30%; + } + + 50% { + width: 30%; + } + + 70% { + width: 70%; + } + + 80% { + left: 50%; + } + + 95% { + left: 120%; + } + + to { + left: 100%; + } +} + +.spinner { + position: absolute; + right: 0; + top: 0; + width: 40px; + height: 40px; + display: block +} + +.spinner:after, +.spinner:before { + position: absolute; + content: ""; + top: 50%; + left: 50%; + margin: -12px 0 0 -12px; + width: 24px; + height: 24px; + border-radius: 100%; + border: 3px solid transparent; + border-top-color: var(--blue); +} + +.spinner:before { + -webkit-animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); + animation: spinning 2.4s cubic-bezier(.41, .26, .2, .62); + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite +} + +.spinner:after { + -webkit-animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); + animation: spinning 2.4s cubic-bezier(.51, .09, .21, .8); + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite +} + +@-webkit-keyframes spinning { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 25% { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + } + + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + + 75% { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes spinning { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/src/style/module/typography.css b/src/style/module/typography.css new file mode 100644 index 0000000..96a1fa2 --- /dev/null +++ b/src/style/module/typography.css @@ -0,0 +1,148 @@ +/** + * TYPOGRAPHY + */ +body { + color: #272727; + font-family: "Lato", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 1.5em; +} + +a { + color: var(--blue); + text-decoration: none; +} + +a:hover { + color: color-mix(in srgb, var(--color-primary), #FFF 15%); +} + +a:focus { + color: var(--blue); +} + +.text-huge, +.text-big, +.text-medium { + margin-bottom: 1em; +} + +.text-huge { + font-size: 36px; + line-height: 1.3em; +} + +.text-big { + font-size: 24px; + line-height: 1.3em; +} + +.text-medium { + font-size: 16px; + line-height: 1.5em; +} + +.text-small { + font-size: 12px; + line-height: 1.3em; +} + +.text-body { + font-size: 16px; + line-height: 1.5em; +} + +.text-primary { + color: #03a9f4; +} + +.text-dark { + color: #18232f; +} + +.text-secondary { + color: #e91e63; +} + +.text-white { + color: #fff; +} + +.text-success { + color: #4caf50; +} + +.text-info { + color: #5bc0de; +} + +.text-warning { + color: #f0ad4e; +} + +.text-error { + color: #e74c3c; +} + +.text-gray { + color: #969da6; +} + +.text-gray-light { + color: #eceff1; +} + +.text-light { + font-weight: 300; +} + +.text-normal { + font-weight: 400; +} + +.text-lineThrough { + text-decoration: line-through; +} + +.text-italic { + font-style: italic; +} + +.text-underline { + text-decoration: underline; +} + +.text-uppercase { + text-transform: uppercase; +} + +.text-withSubtitle { + margin-bottom: 0 !important; +} + +.text-withSubtitle+.text-huge, +.text-withSubtitle+.text-big, +.text-withSubtitle+.text-medium, +.text-withSubtitle+.text-small { + margin-top: 0.5em; +} + +h1, +h2, +h3, +h4 { + font-weight: 300; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.text-left { + text-align: left; +} \ No newline at end of file diff --git a/template/home.pug b/src/template/home.pug similarity index 100% rename from template/home.pug rename to src/template/home.pug diff --git a/template/journey.pug b/src/template/journey.pug similarity index 100% rename from template/journey.pug rename to src/template/journey.pug diff --git a/template/module/foot.pug b/src/template/module/foot.pug similarity index 100% rename from template/module/foot.pug rename to src/template/module/foot.pug diff --git a/template/module/head.pug b/src/template/module/head.pug similarity index 91% rename from template/module/head.pug rename to src/template/module/head.pug index f0ae469..3274cfa 100644 --- a/template/module/head.pug +++ b/src/template/module/head.pug @@ -8,7 +8,7 @@ head href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,700,300", type="text/css" ) - link(rel="stylesheet", href="/public/css/index.css") + link(rel="stylesheet", href="/public/index.css") link(rel="stylesheet", href="https://unpkg.com/vue2-datepicker/index.css") link(rel="stylesheet", href="https://unpkg.com/leaflet/dist/leaflet.css") diff --git a/template/module/journey/impexp.pug b/src/template/module/journey/impexp.pug similarity index 100% rename from template/module/journey/impexp.pug rename to src/template/module/journey/impexp.pug diff --git a/template/module/journey/leg/drawer-notes.pug b/src/template/module/journey/leg/drawer-notes.pug similarity index 100% rename from template/module/journey/leg/drawer-notes.pug rename to src/template/module/journey/leg/drawer-notes.pug diff --git a/template/module/journey/leg/drawer.pug b/src/template/module/journey/leg/drawer.pug similarity index 100% rename from template/module/journey/leg/drawer.pug rename to src/template/module/journey/leg/drawer.pug diff --git a/template/module/journey/leg/nav.pug b/src/template/module/journey/leg/nav.pug similarity index 100% rename from template/module/journey/leg/nav.pug rename to src/template/module/journey/leg/nav.pug diff --git a/template/module/journey/leg/top.pug b/src/template/module/journey/leg/top.pug similarity index 100% rename from template/module/journey/leg/top.pug rename to src/template/module/journey/leg/top.pug diff --git a/template/module/journey/main.pug b/src/template/module/journey/main.pug similarity index 100% rename from template/module/journey/main.pug rename to src/template/module/journey/main.pug diff --git a/template/module/journey/map.pug b/src/template/module/journey/map.pug similarity index 100% rename from template/module/journey/map.pug rename to src/template/module/journey/map.pug diff --git a/template/module/journey/map/activities.pug b/src/template/module/journey/map/activities.pug similarity index 100% rename from template/module/journey/map/activities.pug rename to src/template/module/journey/map/activities.pug diff --git a/template/module/journey/map/hotel.pug b/src/template/module/journey/map/hotel.pug similarity index 100% rename from template/module/journey/map/hotel.pug rename to src/template/module/journey/map/hotel.pug diff --git a/template/module/journey/map/mixin-marker.pug b/src/template/module/journey/map/mixin-marker.pug similarity index 100% rename from template/module/journey/map/mixin-marker.pug rename to src/template/module/journey/map/mixin-marker.pug diff --git a/template/module/journey/map/override.pug b/src/template/module/journey/map/override.pug similarity index 100% rename from template/module/journey/map/override.pug rename to src/template/module/journey/map/override.pug diff --git a/template/module/journey/map/restaurants.pug b/src/template/module/journey/map/restaurants.pug similarity index 100% rename from template/module/journey/map/restaurants.pug rename to src/template/module/journey/map/restaurants.pug diff --git a/template/module/journey/map/right_menu.pug b/src/template/module/journey/map/right_menu.pug similarity index 100% rename from template/module/journey/map/right_menu.pug rename to src/template/module/journey/map/right_menu.pug diff --git a/template/module/journey/map/travel.pug b/src/template/module/journey/map/travel.pug similarity index 100% rename from template/module/journey/map/travel.pug rename to src/template/module/journey/map/travel.pug diff --git a/template/module/view/nav.pug b/src/template/module/view/nav.pug similarity index 100% rename from template/module/view/nav.pug rename to src/template/module/view/nav.pug diff --git a/template/module/view/short_leg.pug b/src/template/module/view/short_leg.pug similarity index 100% rename from template/module/view/short_leg.pug rename to src/template/module/view/short_leg.pug diff --git a/template/module/view/view_day.pug b/src/template/module/view/view_day.pug similarity index 100% rename from template/module/view/view_day.pug rename to src/template/module/view/view_day.pug diff --git a/template/short.pug b/src/template/short.pug similarity index 100% rename from template/short.pug rename to src/template/short.pug diff --git a/template/view.pug b/src/template/view.pug similarity index 100% rename from template/view.pug rename to src/template/view.pug diff --git a/yarn.lock b/yarn.lock index 8bc6ed8..098f05a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,7 +32,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": +"@babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": version: 7.26.9 resolution: "@babel/parser@npm:7.26.9" dependencies: @@ -435,6 +435,150 @@ __metadata: languageName: node linkType: hard +"@parcel/watcher-android-arm64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-android-arm64@npm:2.5.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-darwin-arm64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-darwin-arm64@npm:2.5.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-darwin-x64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-darwin-x64@npm:2.5.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher-freebsd-x64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-freebsd-x64@npm:2.5.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm-glibc@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm-musl@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm64-glibc@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm64-musl@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-linux-x64-glibc@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-x64-musl@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-win32-arm64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-win32-arm64@npm:2.5.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-win32-ia32@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-win32-ia32@npm:2.5.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@parcel/watcher-win32-x64@npm:2.5.1": + version: 2.5.1 + resolution: "@parcel/watcher-win32-x64@npm:2.5.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher@npm:^2.4.1": + version: 2.5.1 + resolution: "@parcel/watcher@npm:2.5.1" + dependencies: + "@parcel/watcher-android-arm64": "npm:2.5.1" + "@parcel/watcher-darwin-arm64": "npm:2.5.1" + "@parcel/watcher-darwin-x64": "npm:2.5.1" + "@parcel/watcher-freebsd-x64": "npm:2.5.1" + "@parcel/watcher-linux-arm-glibc": "npm:2.5.1" + "@parcel/watcher-linux-arm-musl": "npm:2.5.1" + "@parcel/watcher-linux-arm64-glibc": "npm:2.5.1" + "@parcel/watcher-linux-arm64-musl": "npm:2.5.1" + "@parcel/watcher-linux-x64-glibc": "npm:2.5.1" + "@parcel/watcher-linux-x64-musl": "npm:2.5.1" + "@parcel/watcher-win32-arm64": "npm:2.5.1" + "@parcel/watcher-win32-ia32": "npm:2.5.1" + "@parcel/watcher-win32-x64": "npm:2.5.1" + detect-libc: "npm:^1.0.3" + is-glob: "npm:^4.0.3" + micromatch: "npm:^4.0.5" + node-addon-api: "npm:^7.0.0" + node-gyp: "npm:latest" + dependenciesMeta: + "@parcel/watcher-android-arm64": + optional: true + "@parcel/watcher-darwin-arm64": + optional: true + "@parcel/watcher-darwin-x64": + optional: true + "@parcel/watcher-freebsd-x64": + optional: true + "@parcel/watcher-linux-arm-glibc": + optional: true + "@parcel/watcher-linux-arm-musl": + optional: true + "@parcel/watcher-linux-arm64-glibc": + optional: true + "@parcel/watcher-linux-arm64-musl": + optional: true + "@parcel/watcher-linux-x64-glibc": + optional: true + "@parcel/watcher-linux-x64-musl": + optional: true + "@parcel/watcher-win32-arm64": + optional: true + "@parcel/watcher-win32-ia32": + optional: true + "@parcel/watcher-win32-x64": + optional: true + checksum: 10c0/8f35073d0c0b34a63d4c8d2213482f0ebc6a25de7b2cdd415d19cb929964a793cb285b68d1d50bfb732b070b3c82a2fdb4eb9c250eab709a1cd9d63345455a82 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -442,17 +586,6 @@ __metadata: languageName: node linkType: hard -"@prettier/plugin-pug@npm:^3.0.0": - version: 3.2.1 - resolution: "@prettier/plugin-pug@npm:3.2.1" - dependencies: - pug-lexer: "npm:^5.0.1" - peerDependencies: - prettier: ^3.0.0 - checksum: 10c0/f361496e1669e308e1e74b3de2f524ba92364904142b23cf496bc26531f8cab3ccea965d0cb32b6272656c0415f0dbfe422aa6dc844f56f89cbdbdc815899390 - languageName: node - linkType: hard - "@types/node@npm:^22.13.5": version: 22.13.5 resolution: "@types/node@npm:22.13.5" @@ -462,21 +595,6 @@ __metadata: languageName: node linkType: hard -"@vue/compiler-sfc@npm:2.7.16": - version: 2.7.16 - resolution: "@vue/compiler-sfc@npm:2.7.16" - dependencies: - "@babel/parser": "npm:^7.23.5" - postcss: "npm:^8.4.14" - prettier: "npm:^1.18.2 || ^2.0.0" - source-map: "npm:^0.6.1" - dependenciesMeta: - prettier: - optional: true - checksum: 10c0/eaeeef054c939e6cd7591199e2b998ae33d0afd65dc1b5675b54361f0c657c08ae82945791a1a8ca76762e1c1f8e69a00595daf280b854cbc3370ed5c5a34bcd - languageName: node - linkType: hard - "abbrev@npm:^3.0.0": version: 3.0.0 resolution: "abbrev@npm:3.0.0" @@ -674,7 +792,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:~3.0.2": +"braces@npm:^3.0.3, braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -749,7 +867,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.5.2": +"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.5.2": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -768,6 +886,15 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^4.0.0": + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" + dependencies: + readdirp: "npm:^4.0.1" + checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad + languageName: node + linkType: hard + "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -833,13 +960,6 @@ __metadata: languageName: node linkType: hard -"core-js@npm:^2.6.5": - version: 2.6.12 - resolution: "core-js@npm:2.6.12" - checksum: 10c0/00128efe427789120a06b819adc94cc72b96955acb331cb71d09287baf9bd37bebd191d91f1ee4939c893a050307ead4faea08876f09115112612b6a05684b63 - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.0": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -851,6 +971,16 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:1.1.3": + version: 1.1.3 + resolution: "css-tree@npm:1.1.3" + dependencies: + mdn-data: "npm:2.0.14" + source-map: "npm:^0.6.1" + checksum: 10c0/499a507bfa39b8b2128f49736882c0dd636b0cd3370f2c69f4558ec86d269113286b7df469afc955de6a68b0dba00bc533e40022a73698081d600072d5d83c1c + languageName: node + linkType: hard + "cssstyle@npm:^4.2.1": version: 4.2.1 resolution: "cssstyle@npm:4.2.1" @@ -861,13 +991,6 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.1.0": - version: 3.1.3 - resolution: "csstype@npm:3.1.3" - checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 - languageName: node - linkType: hard - "data-urls@npm:^5.0.0": version: 5.0.0 resolution: "data-urls@npm:5.0.0" @@ -928,6 +1051,15 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^1.0.3": + version: 1.0.3 + resolution: "detect-libc@npm:1.0.3" + bin: + detect-libc: ./bin/detect-libc.js + checksum: 10c0/4da0deae9f69e13bc37a0902d78bf7169480004b1fed3c19722d56cff578d16f0e11633b7fbf5fb6249181236c72e90024cbd68f0b9558ae06e281f47326d50d + languageName: node + linkType: hard + "doctypes@npm:^1.1.0": version: 1.1.0 resolution: "doctypes@npm:1.1.0" @@ -1044,6 +1176,20 @@ __metadata: languageName: node linkType: hard +"esbuild-plugin-sass@npm:^1.0.1": + version: 1.0.1 + resolution: "esbuild-plugin-sass@npm:1.0.1" + dependencies: + css-tree: "npm:1.1.3" + fs-extra: "npm:10.0.0" + sass: "npm:1.47.0" + tmp: "npm:0.2.1" + peerDependencies: + esbuild: ">=0.11.14" + checksum: 10c0/4a8b0aec2de41a44bfeb5518e5754be6b8a39a8873f4e543bfb40595636db639b5a5f9e2561594c8de7c81e5dddb88b83e73336827cada875203a185b4a1d053 + languageName: node + linkType: hard + "esbuild@npm:^0.25.0": version: 0.25.0 resolution: "esbuild@npm:0.25.0" @@ -1276,6 +1422,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:10.0.0": + version: 10.0.0 + resolution: "fs-extra@npm:10.0.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/85802f3d9e49d197744a8372f0d78d5a1faa3df73f4c5375d6366a4b9f745197d3da1f095841443d50f29a9f81cdc01363eb6d17bef2ba70c268559368211040 + languageName: node + linkType: hard + "fs-minipass@npm:^3.0.0": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" @@ -1285,6 +1442,13 @@ __metadata: languageName: node linkType: hard +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + "fsevents@npm:~2.3.2": version: 2.3.3 resolution: "fsevents@npm:2.3.3" @@ -1380,6 +1544,20 @@ __metadata: languageName: node linkType: hard +"glob@npm:^7.1.3": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + "gopd@npm:^1.2.0": version: 1.2.0 resolution: "gopd@npm:1.2.0" @@ -1387,7 +1565,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -1498,6 +1676,20 @@ __metadata: languageName: node linkType: hard +"immutable@npm:^4.0.0": + version: 4.3.7 + resolution: "immutable@npm:4.3.7" + checksum: 10c0/9b099197081b22f6433003e34929da8ecddbbdc1474cdc8aa3b7669dee4adda349c06143de22def36016d1b6de5322b043eccd7a11db1dad2ca85dad4fff5435 + languageName: node + linkType: hard + +"immutable@npm:^5.0.2": + version: 5.0.3 + resolution: "immutable@npm:5.0.3" + checksum: 10c0/3269827789e1026cd25c2ea97f0b2c19be852ffd49eda1b674b20178f73d84fa8d945ad6f5ac5bc4545c2b4170af9f6e1f77129bc1cae7974a4bf9b04a9cdfb9 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -1505,7 +1697,17 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -1578,7 +1780,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -1720,6 +1922,19 @@ __metadata: languageName: node linkType: hard +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: "npm:^4.1.6" + universalify: "npm:^2.0.0" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 + languageName: node + linkType: hard + "jstransformer@npm:1.0.0": version: 1.0.0 resolution: "jstransformer@npm:1.0.0" @@ -1730,13 +1945,6 @@ __metadata: languageName: node linkType: hard -"leaflet@npm:^1.9.4": - version: 1.9.4 - resolution: "leaflet@npm:1.9.4" - checksum: 10c0/f639441dbb7eb9ae3fcd29ffd7d3508f6c6106892441634b0232fafb9ffb1588b05a8244ec7085de2c98b5ed703894df246898477836cfd0ce5b96d4717b5ca1 - languageName: node - linkType: hard - "level-codec@npm:^10.0.0": version: 10.0.0 resolution: "level-codec@npm:10.0.0" @@ -1856,6 +2064,23 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.14": + version: 2.0.14 + resolution: "mdn-data@npm:2.0.14" + checksum: 10c0/67241f8708c1e665a061d2b042d2d243366e93e5bf1f917693007f6d55111588b952dcbfd3ea9c2d0969fb754aad81b30fdcfdcc24546495fc3b24336b28d4bd + languageName: node + linkType: hard + +"micromatch@npm:^4.0.5": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: "npm:^3.0.3" + picomatch: "npm:^2.3.1" + checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -1890,7 +2115,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.1.2": +"minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -2001,15 +2226,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.8": - version: 3.3.8 - resolution: "nanoid@npm:3.3.8" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/4b1bb29f6cfebf3be3bc4ad1f1296fb0a10a3043a79f34fbffe75d1621b4318319211cd420549459018ea3592f0d2f159247a6f874911d6d26eaaadda2478120 - languageName: node - linkType: hard - "napi-macros@npm:~2.0.0": version: 2.0.0 resolution: "napi-macros@npm:2.0.0" @@ -2024,6 +2240,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^7.0.0": + version: 7.1.1 + resolution: "node-addon-api@npm:7.1.1" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/fb32a206276d608037fa1bcd7e9921e177fe992fc610d098aa3128baca3c0050fc1e014fa007e9b3874cf865ddb4f5bd9f43ccb7cbbbe4efaff6a83e920b17e9 + languageName: node + linkType: hard + "node-gyp-build@npm:^4.3.0": version: 4.8.4 resolution: "node-gyp-build@npm:4.8.4" @@ -2114,6 +2339,15 @@ __metadata: languageName: node linkType: hard +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + "p-map@npm:^7.0.2": version: 7.0.3 resolution: "p-map@npm:7.0.3" @@ -2137,6 +2371,13 @@ __metadata: languageName: node linkType: hard +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 + languageName: node + linkType: hard + "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -2171,14 +2412,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.1.1": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be @@ -2222,26 +2456,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.14": - version: 8.5.3 - resolution: "postcss@npm:8.5.3" - dependencies: - nanoid: "npm:^3.3.8" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3 - languageName: node - linkType: hard - -"prettier@npm:^1.18.2 || ^2.0.0": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" - bin: - prettier: bin-prettier.js - checksum: 10c0/463ea8f9a0946cd5b828d8cf27bd8b567345cf02f56562d5ecde198b91f47a76b7ac9eae0facd247ace70e927143af6135e8cf411986b8cb8478784a4d6d724a - languageName: node - linkType: hard - "prettier@npm:^3.5.2": version: 3.5.2 resolution: "prettier@npm:3.5.2" @@ -2450,6 +2664,13 @@ __metadata: languageName: node linkType: hard +"readdirp@npm:^4.0.1": + version: 4.1.2 + resolution: "readdirp@npm:4.1.2" + checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 + languageName: node + linkType: hard + "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -2527,6 +2748,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:^3.0.0": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: "npm:^7.1.3" + bin: + rimraf: bin.js + checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8 + languageName: node + linkType: hard + "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -2575,6 +2807,36 @@ __metadata: languageName: node linkType: hard +"sass@npm:1.47.0": + version: 1.47.0 + resolution: "sass@npm:1.47.0" + dependencies: + chokidar: "npm:>=3.0.0 <4.0.0" + immutable: "npm:^4.0.0" + source-map-js: "npm:>=0.6.2 <2.0.0" + bin: + sass: sass.js + checksum: 10c0/863afee6aac8529a009d184e5cf8cd79dbd4d4759a49170b2ece5a519911311b630f9630e66db287c4e883d5635c4e8a2a12e0d4579bf484df72680a64dccf56 + languageName: node + linkType: hard + +"sass@npm:^1.85.1": + version: 1.85.1 + resolution: "sass@npm:1.85.1" + dependencies: + "@parcel/watcher": "npm:^2.4.1" + chokidar: "npm:^4.0.0" + immutable: "npm:^5.0.2" + source-map-js: "npm:>=0.6.2 <2.0.0" + dependenciesMeta: + "@parcel/watcher": + optional: true + bin: + sass: sass.js + checksum: 10c0/f843aa1df1dca2f0e9cb2fb247e4939fd514ae4c182cdd1900a0622c0d71b40dfb1c4225f78b78e165a318287ca137ec597695db3e496408bd16a921a2bc2b3f + languageName: node + linkType: hard + "saxes@npm:^6.0.0": version: 6.0.0 resolution: "saxes@npm:6.0.0" @@ -2683,7 +2945,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.1": +"source-map-js@npm:>=0.6.2 <2.0.0": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf @@ -2840,6 +3102,15 @@ __metadata: languageName: node linkType: hard +"tmp@npm:0.2.1": + version: 0.2.1 + resolution: "tmp@npm:0.2.1" + dependencies: + rimraf: "npm:^3.0.0" + checksum: 10c0/67607aa012059c9ce697bee820ee51bc0f39b29a8766def4f92d3f764d67c7cf9205d537d24e0cb1ce9685c40d4c628ead010910118ea18348666b5c46ed9123 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -2936,6 +3207,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -2957,60 +3235,19 @@ __metadata: "@fastify/leveldb": "npm:^6.0.0" "@fastify/static": "npm:^8.0.0" "@fastify/view": "npm:^10.0.0" - "@prettier/plugin-pug": "npm:^3.0.0" "@types/node": "npm:^22.13.5" esbuild: "npm:^0.25.0" + esbuild-plugin-sass: "npm:^1.0.1" fastify: "npm:^5.2.1" jsdom: "npm:^26.0.0" - leaflet: "npm:^1.9.4" nodemon: "npm:^3.0.1" prettier: "npm:^3.5.2" pug: "npm:^3.0.2" + sass: "npm:^1.85.1" undici: "npm:^7.3.0" - vue: "npm:2" - vue-multiselect: "npm:2" - vue-textarea-autosize: "npm:^1.1.1" - vue2-leaflet: "npm:^2.7.1" languageName: unknown linkType: soft -"vue-multiselect@npm:2": - version: 2.1.9 - resolution: "vue-multiselect@npm:2.1.9" - checksum: 10c0/baecfbb97b4b225bd2e2054f2eed640917b47f448a76a43f084d344764c813a58e825ea2131f6803c125e6e8d4e0b4edb5712da49dd1b8a082f29ac845cc7c2b - languageName: node - linkType: hard - -"vue-textarea-autosize@npm:^1.1.1": - version: 1.1.1 - resolution: "vue-textarea-autosize@npm:1.1.1" - dependencies: - core-js: "npm:^2.6.5" - checksum: 10c0/22614d412b7e592b68c9b127cfc4257985058571d185ef1885acd3666b77381c87a2006b5084d5687b5e3729ad5b8c53ff962eaf43bbefa1dc5ae0e58cada9db - languageName: node - linkType: hard - -"vue2-leaflet@npm:^2.7.1": - version: 2.7.1 - resolution: "vue2-leaflet@npm:2.7.1" - peerDependencies: - "@types/leaflet": ^1.5.7 - leaflet: ^1.3.4 - vue: ^2.5.17 - checksum: 10c0/34ae5cc4b78deaf3ee7f73a210b2e45f9d80b92860d5ac5d831d74fd8a94d06983845f01e6203b4e61bad7f6385715f0ea3cd23b2e39fb6c8ce912fe4d096af6 - languageName: node - linkType: hard - -"vue@npm:2": - version: 2.7.16 - resolution: "vue@npm:2.7.16" - dependencies: - "@vue/compiler-sfc": "npm:2.7.16" - csstype: "npm:^3.1.0" - checksum: 10c0/15bf536c131a863d03c42386a4bbc82316262129421ef70e88d1758bcf951446ef51edeff42e3b27d026015330fe73d90155fca270eb5eadd30b0290735f2c3e - languageName: node - linkType: hard - "w3c-xmlserializer@npm:^5.0.0": version: 5.0.0 resolution: "w3c-xmlserializer@npm:5.0.0" @@ -3109,6 +3346,13 @@ __metadata: languageName: node linkType: hard +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + "ws@npm:^8.18.0": version: 8.18.1 resolution: "ws@npm:8.18.1" -- 2.47.2 From 4b2db42a2d00cf4a27f1c631ad269f539144b888 Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 2 Mar 2025 00:57:41 +0100 Subject: [PATCH 93/95] dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index c5c8264..c7caa24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ WORKDIR /usr/src/app # where available (npm@5+) COPY package*.json ./ RUN yarn +RUN yarn build # If you are building your code for production # RUN npm ci --only=production # Bundle app source -- 2.47.2 From 07699b9843d5e7fd785295f9cd70138be5aba68a Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 2 Mar 2025 01:03:10 +0100 Subject: [PATCH 94/95] fix yarnlock --- package.json | 2 +- yarn.lock | 398 +-------------------------------------------------- 2 files changed, 8 insertions(+), 392 deletions(-) diff --git a/package.json b/package.json index 0036cfd..1362059 100644 --- a/package.json +++ b/package.json @@ -30,4 +30,4 @@ "pug": "^3.0.2", "undici": "^7.3.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 098f05a..f45bb6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -435,150 +435,6 @@ __metadata: languageName: node linkType: hard -"@parcel/watcher-android-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-android-arm64@npm:2.5.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-darwin-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-darwin-arm64@npm:2.5.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-darwin-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-darwin-x64@npm:2.5.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher-freebsd-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-freebsd-x64@npm:2.5.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.1" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.1" - conditions: os=linux & cpu=arm & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm64-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm64-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-linux-x64-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-x64-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-win32-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-arm64@npm:2.5.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-win32-ia32@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-ia32@npm:2.5.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@parcel/watcher-win32-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-x64@npm:2.5.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher@npm:^2.4.1": - version: 2.5.1 - resolution: "@parcel/watcher@npm:2.5.1" - dependencies: - "@parcel/watcher-android-arm64": "npm:2.5.1" - "@parcel/watcher-darwin-arm64": "npm:2.5.1" - "@parcel/watcher-darwin-x64": "npm:2.5.1" - "@parcel/watcher-freebsd-x64": "npm:2.5.1" - "@parcel/watcher-linux-arm-glibc": "npm:2.5.1" - "@parcel/watcher-linux-arm-musl": "npm:2.5.1" - "@parcel/watcher-linux-arm64-glibc": "npm:2.5.1" - "@parcel/watcher-linux-arm64-musl": "npm:2.5.1" - "@parcel/watcher-linux-x64-glibc": "npm:2.5.1" - "@parcel/watcher-linux-x64-musl": "npm:2.5.1" - "@parcel/watcher-win32-arm64": "npm:2.5.1" - "@parcel/watcher-win32-ia32": "npm:2.5.1" - "@parcel/watcher-win32-x64": "npm:2.5.1" - detect-libc: "npm:^1.0.3" - is-glob: "npm:^4.0.3" - micromatch: "npm:^4.0.5" - node-addon-api: "npm:^7.0.0" - node-gyp: "npm:latest" - dependenciesMeta: - "@parcel/watcher-android-arm64": - optional: true - "@parcel/watcher-darwin-arm64": - optional: true - "@parcel/watcher-darwin-x64": - optional: true - "@parcel/watcher-freebsd-x64": - optional: true - "@parcel/watcher-linux-arm-glibc": - optional: true - "@parcel/watcher-linux-arm-musl": - optional: true - "@parcel/watcher-linux-arm64-glibc": - optional: true - "@parcel/watcher-linux-arm64-musl": - optional: true - "@parcel/watcher-linux-x64-glibc": - optional: true - "@parcel/watcher-linux-x64-musl": - optional: true - "@parcel/watcher-win32-arm64": - optional: true - "@parcel/watcher-win32-ia32": - optional: true - "@parcel/watcher-win32-x64": - optional: true - checksum: 10c0/8f35073d0c0b34a63d4c8d2213482f0ebc6a25de7b2cdd415d19cb929964a793cb285b68d1d50bfb732b070b3c82a2fdb4eb9c250eab709a1cd9d63345455a82 - languageName: node - linkType: hard - "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -792,7 +648,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.3, braces@npm:~3.0.2": +"braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -867,7 +723,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.5.2": +"chokidar@npm:^3.5.2": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -886,15 +742,6 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^4.0.0": - version: 4.0.3 - resolution: "chokidar@npm:4.0.3" - dependencies: - readdirp: "npm:^4.0.1" - checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad - languageName: node - linkType: hard - "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -971,16 +818,6 @@ __metadata: languageName: node linkType: hard -"css-tree@npm:1.1.3": - version: 1.1.3 - resolution: "css-tree@npm:1.1.3" - dependencies: - mdn-data: "npm:2.0.14" - source-map: "npm:^0.6.1" - checksum: 10c0/499a507bfa39b8b2128f49736882c0dd636b0cd3370f2c69f4558ec86d269113286b7df469afc955de6a68b0dba00bc533e40022a73698081d600072d5d83c1c - languageName: node - linkType: hard - "cssstyle@npm:^4.2.1": version: 4.2.1 resolution: "cssstyle@npm:4.2.1" @@ -1051,15 +888,6 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^1.0.3": - version: 1.0.3 - resolution: "detect-libc@npm:1.0.3" - bin: - detect-libc: ./bin/detect-libc.js - checksum: 10c0/4da0deae9f69e13bc37a0902d78bf7169480004b1fed3c19722d56cff578d16f0e11633b7fbf5fb6249181236c72e90024cbd68f0b9558ae06e281f47326d50d - languageName: node - linkType: hard - "doctypes@npm:^1.1.0": version: 1.1.0 resolution: "doctypes@npm:1.1.0" @@ -1176,20 +1004,6 @@ __metadata: languageName: node linkType: hard -"esbuild-plugin-sass@npm:^1.0.1": - version: 1.0.1 - resolution: "esbuild-plugin-sass@npm:1.0.1" - dependencies: - css-tree: "npm:1.1.3" - fs-extra: "npm:10.0.0" - sass: "npm:1.47.0" - tmp: "npm:0.2.1" - peerDependencies: - esbuild: ">=0.11.14" - checksum: 10c0/4a8b0aec2de41a44bfeb5518e5754be6b8a39a8873f4e543bfb40595636db639b5a5f9e2561594c8de7c81e5dddb88b83e73336827cada875203a185b4a1d053 - languageName: node - linkType: hard - "esbuild@npm:^0.25.0": version: 0.25.0 resolution: "esbuild@npm:0.25.0" @@ -1422,17 +1236,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:10.0.0": - version: 10.0.0 - resolution: "fs-extra@npm:10.0.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/85802f3d9e49d197744a8372f0d78d5a1faa3df73f4c5375d6366a4b9f745197d3da1f095841443d50f29a9f81cdc01363eb6d17bef2ba70c268559368211040 - languageName: node - linkType: hard - "fs-minipass@npm:^3.0.0": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" @@ -1442,13 +1245,6 @@ __metadata: languageName: node linkType: hard -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - "fsevents@npm:~2.3.2": version: 2.3.3 resolution: "fsevents@npm:2.3.3" @@ -1544,20 +1340,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - "gopd@npm:^1.2.0": version: 1.2.0 resolution: "gopd@npm:1.2.0" @@ -1565,7 +1347,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -1676,20 +1458,6 @@ __metadata: languageName: node linkType: hard -"immutable@npm:^4.0.0": - version: 4.3.7 - resolution: "immutable@npm:4.3.7" - checksum: 10c0/9b099197081b22f6433003e34929da8ecddbbdc1474cdc8aa3b7669dee4adda349c06143de22def36016d1b6de5322b043eccd7a11db1dad2ca85dad4fff5435 - languageName: node - linkType: hard - -"immutable@npm:^5.0.2": - version: 5.0.3 - resolution: "immutable@npm:5.0.3" - checksum: 10c0/3269827789e1026cd25c2ea97f0b2c19be852ffd49eda1b674b20178f73d84fa8d945ad6f5ac5bc4545c2b4170af9f6e1f77129bc1cae7974a4bf9b04a9cdfb9 - languageName: node - linkType: hard - "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -1697,17 +1465,7 @@ __metadata: languageName: node linkType: hard -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": +"inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -1780,7 +1538,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -1922,19 +1680,6 @@ __metadata: languageName: node linkType: hard -"jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" - dependencies: - graceful-fs: "npm:^4.1.6" - universalify: "npm:^2.0.0" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 - languageName: node - linkType: hard - "jstransformer@npm:1.0.0": version: 1.0.0 resolution: "jstransformer@npm:1.0.0" @@ -2064,23 +1809,6 @@ __metadata: languageName: node linkType: hard -"mdn-data@npm:2.0.14": - version: 2.0.14 - resolution: "mdn-data@npm:2.0.14" - checksum: 10c0/67241f8708c1e665a061d2b042d2d243366e93e5bf1f917693007f6d55111588b952dcbfd3ea9c2d0969fb754aad81b30fdcfdcc24546495fc3b24336b28d4bd - languageName: node - linkType: hard - -"micromatch@npm:^4.0.5": - version: 4.0.8 - resolution: "micromatch@npm:4.0.8" - dependencies: - braces: "npm:^3.0.3" - picomatch: "npm:^2.3.1" - checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 - languageName: node - linkType: hard - "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -2115,7 +1843,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -2240,15 +1968,6 @@ __metadata: languageName: node linkType: hard -"node-addon-api@npm:^7.0.0": - version: 7.1.1 - resolution: "node-addon-api@npm:7.1.1" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/fb32a206276d608037fa1bcd7e9921e177fe992fc610d098aa3128baca3c0050fc1e014fa007e9b3874cf865ddb4f5bd9f43ccb7cbbbe4efaff6a83e920b17e9 - languageName: node - linkType: hard - "node-gyp-build@npm:^4.3.0": version: 4.8.4 resolution: "node-gyp-build@npm:4.8.4" @@ -2339,15 +2058,6 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - "p-map@npm:^7.0.2": version: 7.0.3 resolution: "p-map@npm:7.0.3" @@ -2371,13 +2081,6 @@ __metadata: languageName: node linkType: hard -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -2412,7 +2115,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be @@ -2664,13 +2367,6 @@ __metadata: languageName: node linkType: hard -"readdirp@npm:^4.0.1": - version: 4.1.2 - resolution: "readdirp@npm:4.1.2" - checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 - languageName: node - linkType: hard - "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -2748,17 +2444,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.0": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: bin.js - checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8 - languageName: node - linkType: hard - "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -2807,36 +2492,6 @@ __metadata: languageName: node linkType: hard -"sass@npm:1.47.0": - version: 1.47.0 - resolution: "sass@npm:1.47.0" - dependencies: - chokidar: "npm:>=3.0.0 <4.0.0" - immutable: "npm:^4.0.0" - source-map-js: "npm:>=0.6.2 <2.0.0" - bin: - sass: sass.js - checksum: 10c0/863afee6aac8529a009d184e5cf8cd79dbd4d4759a49170b2ece5a519911311b630f9630e66db287c4e883d5635c4e8a2a12e0d4579bf484df72680a64dccf56 - languageName: node - linkType: hard - -"sass@npm:^1.85.1": - version: 1.85.1 - resolution: "sass@npm:1.85.1" - dependencies: - "@parcel/watcher": "npm:^2.4.1" - chokidar: "npm:^4.0.0" - immutable: "npm:^5.0.2" - source-map-js: "npm:>=0.6.2 <2.0.0" - dependenciesMeta: - "@parcel/watcher": - optional: true - bin: - sass: sass.js - checksum: 10c0/f843aa1df1dca2f0e9cb2fb247e4939fd514ae4c182cdd1900a0622c0d71b40dfb1c4225f78b78e165a318287ca137ec597695db3e496408bd16a921a2bc2b3f - languageName: node - linkType: hard - "saxes@npm:^6.0.0": version: 6.0.0 resolution: "saxes@npm:6.0.0" @@ -2945,20 +2600,6 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0": - version: 1.2.1 - resolution: "source-map-js@npm:1.2.1" - checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf - languageName: node - linkType: hard - -"source-map@npm:^0.6.1": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 - languageName: node - linkType: hard - "split2@npm:^4.0.0": version: 4.2.0 resolution: "split2@npm:4.2.0" @@ -3102,15 +2743,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: "npm:^3.0.0" - checksum: 10c0/67607aa012059c9ce697bee820ee51bc0f39b29a8766def4f92d3f764d67c7cf9205d537d24e0cb1ce9685c40d4c628ead010910118ea18348666b5c46ed9123 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -3207,13 +2839,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^2.0.0": - version: 2.0.1 - resolution: "universalify@npm:2.0.1" - checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -3237,13 +2862,11 @@ __metadata: "@fastify/view": "npm:^10.0.0" "@types/node": "npm:^22.13.5" esbuild: "npm:^0.25.0" - esbuild-plugin-sass: "npm:^1.0.1" fastify: "npm:^5.2.1" jsdom: "npm:^26.0.0" nodemon: "npm:^3.0.1" prettier: "npm:^3.5.2" pug: "npm:^3.0.2" - sass: "npm:^1.85.1" undici: "npm:^7.3.0" languageName: unknown linkType: soft @@ -3346,13 +2969,6 @@ __metadata: languageName: node linkType: hard -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - "ws@npm:^8.18.0": version: 8.18.1 resolution: "ws@npm:8.18.1" -- 2.47.2 From 8f34f7b1804bfa2dd7033d689d0c4500e5962913 Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 2 Mar 2025 01:05:24 +0100 Subject: [PATCH 95/95] update yarn lock --- yarn.lock | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/yarn.lock b/yarn.lock index f45bb6e..1ef3ec5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -443,11 +443,11 @@ __metadata: linkType: hard "@types/node@npm:^22.13.5": - version: 22.13.5 - resolution: "@types/node@npm:22.13.5" + version: 22.13.8 + resolution: "@types/node@npm:22.13.8" dependencies: undici-types: "npm:~6.20.0" - checksum: 10c0/a2e7ed7bb0690e439004779baedeb05159c5cc41ef6d81c7a6ebea5303fde4033669e1c0e41ff7453b45fd2fea8dbd55fddfcd052950c7fcae3167c970bca725 + checksum: 10c0/bfc92b734a9dce6ac5daee0a52feccdf5dcb3804d895e4bc5384e2f4644612b8801725cd03c8c3c0888fb5eeb16b875877ac44b77641e0196dc1a837b1c2a366 languageName: node linkType: hard @@ -807,7 +807,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0": +"cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -1186,11 +1186,11 @@ __metadata: linkType: hard "fastq@npm:^1.17.1": - version: 1.19.0 - resolution: "fastq@npm:1.19.0" + version: 1.19.1 + resolution: "fastq@npm:1.19.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10c0/d6a001638f1574a696660fcbba5300d017760432372c801632c325ca7c16819604841c92fd3ccadcdacec0966ca336363a5ff57bc5f0be335d8ea7ac6087b98f + checksum: 10c0/ebc6e50ac7048daaeb8e64522a1ea7a26e92b3cee5cd1c7f2316cdca81ba543aa40a136b53891446ea5c3a67ec215fbaca87ad405f102dd97012f62916905630 languageName: node linkType: hard @@ -1215,12 +1215,12 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" dependencies: - cross-spawn: "npm:^7.0.0" + cross-spawn: "npm:^7.0.6" signal-exit: "npm:^4.0.1" - checksum: 10c0/028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 languageName: node linkType: hard @@ -1871,8 +1871,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^4.0.0": - version: 4.0.0 - resolution: "minipass-fetch@npm:4.0.0" + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -1881,7 +1881,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 10c0/7fa30ce7c373fb6f94c086b374fff1589fd7e78451855d2d06c2e2d9df936d131e73e952163063016592ed3081444bd8d1ea608533313b0149156ce23311da4b + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c languageName: node linkType: hard @@ -2431,9 +2431,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10c0/c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10c0/4eff0d4a5f9383566c7d7ec437b671cc51b25963bd61bf127c3f3d3f68e44a026d99b8d2f1ad344afff8d278a8fe70a8ea092650a716d22287e8bef7126bb2fa languageName: node linkType: hard @@ -2725,21 +2725,21 @@ __metadata: languageName: node linkType: hard -"tldts-core@npm:^6.1.78": - version: 6.1.78 - resolution: "tldts-core@npm:6.1.78" - checksum: 10c0/aea5e664da879cd862ccf5df9286531ddf4c34a9ca832480188bf6cd165cd45654f5b0a0f0f5315e16203ebfb87d52f8630b9419e729b3cfe5eff073c398693e +"tldts-core@npm:^6.1.82": + version: 6.1.82 + resolution: "tldts-core@npm:6.1.82" + checksum: 10c0/bdbefb17837d7d85b79a44824feafad3d12fbbfbe4f0a89d9618765b18e880d4c7ebe9e87258a2a0e85deec23adbcaaa5f4240129d8017f896b0cda0c32ae6e4 languageName: node linkType: hard "tldts@npm:^6.1.32": - version: 6.1.78 - resolution: "tldts@npm:6.1.78" + version: 6.1.82 + resolution: "tldts@npm:6.1.82" dependencies: - tldts-core: "npm:^6.1.78" + tldts-core: "npm:^6.1.82" bin: tldts: bin/cli.js - checksum: 10c0/966f3f5a63405db6abb49b479784baa677510993f21ffbd67571f3d819451d70a603f1246b13f1c309a7573c4d9fbe0241aca6ff6e8399cbe7d2dd70b7ee4052 + checksum: 10c0/e01dd47de5a1e5ca7ffe33d9e18cfd608e93ef45cf1f80f3fced1cea192d07a840664ded894b590551ebcaaf8a583a68a4b23bc0645b5885508b57010a9316af languageName: node linkType: hard @@ -2783,11 +2783,11 @@ __metadata: linkType: hard "tough-cookie@npm:^5.0.0": - version: 5.1.1 - resolution: "tough-cookie@npm:5.1.1" + version: 5.1.2 + resolution: "tough-cookie@npm:5.1.2" dependencies: tldts: "npm:^6.1.32" - checksum: 10c0/84fe18b7c28ce273c916d95028c00ffff58c285d58e90fbd44eb9380dd1bc21892c675cd1bbd4bfbc95108fe833c406b285844757d41636248bfe264655a6ef8 + checksum: 10c0/5f95023a47de0f30a902bba951664b359725597d8adeabc66a0b93a931c3af801e1e697dae4b8c21a012056c0ea88bd2bf4dfe66b2adcf8e2f42cd9796fe0626 languageName: node linkType: hard @@ -2815,9 +2815,9 @@ __metadata: linkType: hard "undici@npm:^7.3.0": - version: 7.3.0 - resolution: "undici@npm:7.3.0" - checksum: 10c0/62c5e335725cadb02e19950932c7823fc330cbfd80106e6836daa6db1379aa727510b77de0a4e6f912087b288ded93f7daf4b8c154ad36fd5c9c4b96b26888b8 + version: 7.4.0 + resolution: "undici@npm:7.4.0" + checksum: 10c0/0d8d8d627c87e72cf58148d257a79d019ce058b6761363ee5752103aa0ab57d132448fce4ef15171671ee138ef156a695ec1daeb72cd09ae408afa74dee070b5 languageName: node linkType: hard -- 2.47.2