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