diff --git a/CHANGELOG b/CHANGELOG index 135228d1..61c3a8a3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,27 +1,45 @@ All notable changes to this project will be documented in this file. -### UNRELEASED +### 1.6.2 - 12 jan '23 + - add swipe gesture to move to next/prev event + - fix refresh collections, fix #219 + - add russian translation (thanks @drunkod) + - refactor search / filter / selection fix #225, 227, #224 + - models initialization refactored, better dev experience, fix backend HMR + +### 1.6.1 - 15 dec '22 + - allow edit tags in admin panel, fix #170 + - fix header / fallback image upload, fix #222 + - fix WPGancio MU + - fix recurrent events label + - update translations (de, es, eu, gl) + +### 1.6.0 - 11 dec '22 - new plugin system - fix #177 - new "publish on telegram" plugin: (thanks @fadelkon) - - i18n refactoring - people can now choose the language displayed - fix #171 - - fix place "[Object]" issue - #194 - - live search - admin could choose a custom fallback image - fix #195 - it is now possible NOT to enter the end time of an event - fix #188 - - Wordpress plugin now supports MU installation - - add nominatim / openstreetmap feature (thanks @sedum) + - live search - improve event import - - new chinese translation - - new portuguese translation - add Apple touch icon - fix #200 - - improve navbar layout - - improve event layout + - add nominatim / openstreetmap search feature (thanks @sedum) - new hide calendar option - new hide thumbs from homepage option + - linkable admin tab + - friendly instances label is now customizable (thanks @sedum) + - i18n refactoring + - Wordpress plugin now supports MU installation + - new chinese translation + - new portuguese translation + - improved navbar layout + - improved event layout - complete oauth2 refactoring + - fix ics unique uuid + - fix place "[Object]" issue - #194 - fix random restart while downloading random media - fix mobile dialog layout + - urlencode place and tag urls ### 1.5.6 - 22 set '22 diff --git a/assets/helper.js b/assets/helper.js index 44692a33..78b2b3d2 100644 --- a/assets/helper.js +++ b/assets/helper.js @@ -8,7 +8,7 @@ export function attributesFromEvents(_events) { const key = dayjs.unix(e.start_datetime).tz().format('MMDD') // Math.floor(e.start_datetime/(3600*24)) // dayjs.unix(e.start_datetime).tz().format('YYYYMMDD') const c = (e.end_datetime || e.start_datetime) < now ? 'vc-past' : '' - if (e.multidate) { + if (e.multidate === true) { attributes.push({ dates: { start: new Date(e.start_datetime * 1000), end: new Date(e.end_datetime * 1000) }, highlight: { diff --git a/components/Appbar.vue b/components/Appbar.vue index abbe6427..c0167544 100644 --- a/components/Appbar.vue +++ b/components/Appbar.vue @@ -1,22 +1,20 @@ \ No newline at end of file + diff --git a/components/Calendar.vue b/components/Calendar.vue index 1bdca9f8..cee0d865 100644 --- a/components/Calendar.vue +++ b/components/Calendar.vue @@ -15,13 +15,14 @@ aria-label='Calendar' is-expanded is-inline) - template(v-slot="{ inputValue, inputEvents }") + //- template(v-slot="{ inputValue, inputEvents }") v-btn#calendarButton(v-on='inputEvents' text tile :color='selectedDate ? "primary" : "" ') {{inputValue || $t('common.calendar')}} v-icon(v-if='selectedDate' v-text='mdiClose' right small icon @click.prevent.stop='selectedDate = null') v-icon(v-else v-text='mdiChevronDown' right small icon) - template(v-slot:placeholder) - v-btn#calendarButton(text tile) {{$t('common.calendar')}} - v-icon(v-text='mdiChevronDown' right small icon) + .calh.d-flex.justify-center.align-center(slot='placeholder') + v-progress-circular(indeterminate) + //- v-btn#calendarButton(text tile) {{$t('common.calendar')}} + //- v-icon(v-text='mdiChevronDown' right small icon) @@ -65,6 +66,16 @@ export default { \ No newline at end of file + diff --git a/components/WhereInput.vue b/components/WhereInput.vue index 520b83b8..1baea189 100644 --- a/components/WhereInput.vue +++ b/components/WhereInput.vue @@ -22,16 +22,19 @@ v-row.mb-4 v-list-item-title(v-text='item.name') v-list-item-subtitle(v-text='item.address') - //- v-text-field( - //- ref='address' - //- :prepend-icon='mdiMap' - //- :disabled='disableAddress' - //- :rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]" - //- :label="$t('common.address')" - //- @change="changeAddress" - //- :value="value.address") + v-col(cols=12 md=6) - v-combobox(ref='address' + v-text-field(v-if="!settings.allow_geolocation" + ref='address' + :prepend-icon='mdiMap' + :disabled='disableAddress' + :rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]" + :label="$t('common.address')" + :hint="$t('event.address_description')" + persistent-hint + @change="changeAddress" + :value="value.address") + v-combobox(ref='address' v-else :prepend-icon='mdiMapSearch' :disabled='disableAddress' @input.native='searchAddress' @@ -44,9 +47,9 @@ v-row.mb-4 @change='selectAddress' @focus='searchAddress' :items="addressList" - :hint="$t('event.address_description' + (settings.allow_geolocation && '_osm'))") + :hint="$t('event.address_description_osm')") template(v-slot:message="{message, key}") - span(v-html='message' :key="key") + span(v-html='message' :key="key") template(v-slot:item="{ item, attrs, on }") v-list-item(v-bind='attrs' v-on='on') v-icon.pr-4(v-text='loadCoordinatesResultIcon(item)') @@ -76,7 +79,7 @@ export default { props: { value: { type: Object, default: () => ({}) } }, - data () { + data ( {$store} ) { return { mdiMap, mdiMapMarker, mdiPlus, mdiMapSearch, mdiLatitude, mdiLongitude, mdiRoadVariant, mdiHome, mdiCityVariant, place: { }, @@ -91,7 +94,14 @@ export default { node: mdiMapMarker, relation: mdiCityVariant, }, - nominatim_class: ['amenity', 'shop', 'tourism', 'leisure', 'building'] + nominatim_class: ['amenity', 'shop', 'tourism', 'leisure', 'building'], + photon_osm_key: ['amenity', 'shop', 'tourism', 'leisure', 'building'], + photon_osm_type: { + 'W': mdiRoadVariant, + 'N': mdiMapMarker, + 'R': mdiCityVariant, + }, + geocoding_provider_type: $store.state.settings.geocoding_provider_type || 'Nominatim' } }, computed: { @@ -115,21 +125,33 @@ export default { return matches } }, + mounted () { + this.$nextTick( () => { + this.search() + }) + }, methods: { search: debounce(async function(ev) { - const search = ev.target.value.trim().toLowerCase() + const search = ev ? ev.target.value.trim().toLowerCase() : '' this.places = await this.$axios.$get(`place?search=${search}`) if (!search && this.places.length) { return this.places } const matches = this.places.find(p => search === p.name.toLocaleLowerCase()) if (!matches && search) { this.places.unshift({ create: true, name: ev.target.value.trim() }) } - }, 100), + }, 200), loadCoordinatesResultIcon(item) { - if ( this.nominatim_class.includes(item.class)) { - return this.mdiHome + if (this.geocoding_provider_type == "Nominatim") { + if ( this.nominatim_class.includes(item.class)) { + return this.mdiHome + } + return this.nominatim_osm_type[item.type] + } else if (this.geocoding_provider_type == "Photon") { + if ( this.photon_osm_key.includes(item.class)) { + return this.mdiHome + } + return this.photon_osm_type[item.type] } - return this.nominatim_osm_type[item.type] }, selectPlace (p) { if (!p) { return } @@ -168,11 +190,11 @@ export default { } this.$emit('input', { ...this.place }) }, - // changeAddress (v) { - // this.place.address = v - // this.$emit('input', { ...this.place }) - // this.disableDetails = false - // }, + changeAddress (v) { + this.place.address = v + this.$emit('input', { ...this.place }) + this.disableDetails = false + }, selectAddress (v) { if (!v) { return } if (typeof v === 'object') { @@ -220,22 +242,55 @@ export default { if (searchCoordinates.length) { this.loading = true - const ret = await this.$axios.$get(`placeNominatim/${searchCoordinates}`) - if (ret && ret.length) { - this.addressList = ret.map(v => { - const name = get(v.namedetails, 'alt_name', get(v.namedetails, 'name')) - const address = v.display_name ? v.display_name.replace(name, '').replace(/^, ?/, '') : '' - return { - class: v.class, - type: v.osm_type, - lat: v.lat, - lon: v.lon, - name, - address - } - }) - } else { - this.addressList = [] + const ret = await this.$axios.$get(`placeOSM/${this.geocoding_provider_type}/${searchCoordinates}`) + if (this.geocoding_provider_type == "Nominatim") { + if (ret && ret.length) { + this.addressList = ret.map(v => { + const name = get(v.namedetails, 'alt_name', get(v.namedetails, 'name')) + const address = v.display_name ? v.display_name.replace(name, '').replace(/^, ?/, '') : '' + return { + class: v.class, + type: v.osm_type, + lat: v.lat, + lon: v.lon, + name, + address + } + }) + } else { + this.addressList = [] + } + } else if (this.geocoding_provider_type == "Photon") { + let photon_properties = ['housenumber', 'street', 'locality', 'district', 'city', 'county', 'state', 'postcode', 'country'] + + if (ret) { + this.addressList = ret.features.map(v => { + let pre_name = v.properties.name || v.properties.street || '' + let pre_address = '' + + photon_properties.forEach((item, i) => { + let last = i == (photon_properties.length - 1) + if (v.properties[item] && !last) { + pre_address += v.properties[item]+', ' + } else if (v.properties[item]) { + pre_address += v.properties[item] + } + }); + + let name = pre_name + let address = pre_address + return { + class: v.properties.osm_key, + type: v.properties.osm_type, + lat: v.geometry.coordinates[1], + lon: v.geometry.coordinates[0], + name, + address + } + }) + } else { + this.addressList = [] + } } this.loading = false } diff --git a/components/admin/Collections.vue b/components/admin/Collections.vue index 260a796d..2f9da6a5 100644 --- a/components/admin/Collections.vue +++ b/components/admin/Collections.vue @@ -33,7 +33,7 @@ v-container :prepend-icon="mdiTagMultiple" chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint :disabled="!collection.id" - placeholder='Tutte' + placeholder='All' @input.native='searchTags' @focus='searchTags' :delimiters="[',', ';']" @@ -69,7 +69,7 @@ v-container //- v-list-item-subtitle(v-text='item.address') v-col(cols=2) - v-btn(color='primary' text @click='addFilter' :disabled='!collection.id || !filterPlaces.length && !filterTags.length') add + v-btn(color='primary' :loading='loading' text @click='addFilter' :disabled='loading || !collection.id || !filterPlaces.length && !filterTags.length') add v-data-table( :headers='filterHeaders' @@ -110,6 +110,9 @@ v-container + + diff --git a/components/admin/Places.vue b/components/admin/Places.vue index 78a773f5..6c8c26b7 100644 --- a/components/admin/Places.vue +++ b/components/admin/Places.vue @@ -68,7 +68,7 @@ import debounce from 'lodash/debounce' import get from 'lodash/get' export default { - data() { + data( {$store} ) { return { mdiPencil, mdiChevronRight, mdiChevronLeft, mdiMagnify, mdiEye, mdiMapSearch, mdiChevronDown, loading: false, @@ -84,11 +84,12 @@ export default { { value: 'address', text: this.$t('common.address') }, { value: 'map', text: 'Map' }, { value: 'actions', text: this.$t('common.actions'), align: 'right' } - ] + ], + geocoding_provider_type: $store.state.settings.geocoding_provider_type || 'Nominatim' } }, async fetch() { - this.places = await this.$axios.$get('/place/all') + this.places = await this.$axios.$get('/places') }, computed: { ...mapState(['settings']), @@ -124,7 +125,7 @@ export default { this.place.latitude = this.place.longitude = null } this.$emit('input', { ...this.place }) - }, + }, searchAddress: debounce(async function(ev) { const pre_searchCoordinates = ev.target.value.trim().toLowerCase() // allow pasting coordinates lat/lon and lat,lon @@ -159,24 +160,59 @@ export default { if (searchCoordinates.length) { this.loading = true - const ret = await this.$axios.$get(`placeNominatim/${searchCoordinates}`) - if (ret && ret.length) { - this.addressList = ret.map(v => { - const name = get(v.namedetails, 'alt_name', get(v.namedetails, 'name')) - const address = v.display_name ? v.display_name.replace(name, '').replace(/^, ?/, '') : '' - return { - lat: v.lat, - lon: v.lon, - name, - address - } - }) - } else { - this.addressList = [] + const ret = await this.$axios.$get(`placeOSM/${this.geocoding_provider_type}/${searchCoordinates}`) + if (this.geocoding_provider_type == "Nominatim") { + if (ret && ret.length) { + this.addressList = ret.map(v => { + const name = get(v.namedetails, 'alt_name', get(v.namedetails, 'name')) + const address = v.display_name ? v.display_name.replace(name, '').replace(/^, ?/, '') : '' + return { + class: v.class, + type: v.osm_type, + lat: v.lat, + lon: v.lon, + name, + address + } + }) + } else { + this.addressList = [] + } + } else if (this.geocoding_provider_type == "Photon") { + let photon_properties = ['housenumber', 'street', 'district', 'city', 'county', 'state', 'postcode', 'country'] + + if (ret) { + this.addressList = ret.features.map(v => { + let pre_name = v.properties.name || v.properties.street || '' + let pre_address = '' + + photon_properties.forEach((item, i) => { + let last = i == (photon_properties.length - 1) + if (v.properties[item] && !last) { + pre_address += v.properties[item]+', ' + } else if (v.properties[item]) { + pre_address += v.properties[item] + } + }); + + let name = pre_name + let address = pre_address + return { + class: v.properties.osm_key, + type: v.properties.osm_type, + lat: v.geometry.coordinates[1], + lon: v.geometry.coordinates[0], + name, + address + } + }) + } else { + this.addressList = [] + } } this.loading = false } - }, 300) + }, 300) } } diff --git a/components/admin/SMTP.vue b/components/admin/SMTP.vue index 0bda92fd..67b2d7a6 100644 --- a/components/admin/SMTP.vue +++ b/components/admin/SMTP.vue @@ -7,7 +7,9 @@ v-card v-text-field(v-model='admin_email' @blur="save('admin_email', admin_email )" - :label="$t('admin.sender_email')" + :label="$t('admin.admin_email')" + :hint="$t('admin.admin_email_help')" + persistent-hint :rules="$validators.email") v-switch(v-model='smtp.sendmail' diff --git a/components/admin/Settings.vue b/components/admin/Settings.vue index 938609b4..4bb3cd97 100644 --- a/components/admin/Settings.vue +++ b/components/admin/Settings.vue @@ -39,6 +39,10 @@ v-container inset :label="$t('admin.allow_anon_event')") + v-switch.mt-1(v-model='allow_multidate_event' + inset + :label="$t('admin.allow_multidate_event')") + v-switch.mt-1(v-model='allow_recurrent_event' inset :label="$t('admin.allow_recurrent_event')") @@ -57,32 +61,35 @@ v-container v-card-actions v-btn(text @click='showSMTP=true') - {{$t('admin.show_smtp_setup')}} - v-btn(text @click='$emit("complete")' color='primary' v-if='setup') {{$t('common.next')}} - v-icon(v-text='mdiArrowRight') + {{$t('admin.show_smtp_setup')}} + + v-btn(text @click='$emit("complete")' color='primary' v-if='setup') {{$t('common.next')}} + v-icon(v-text='mdiArrowRight') diff --git a/components/admin/Theme.vue b/components/admin/Theme.vue index 6b65ffd4..1bc47c09 100644 --- a/components/admin/Theme.vue +++ b/components/admin/Theme.vue @@ -16,6 +16,7 @@ v-container :label="$t('admin.hide_calendar')") v-card-title {{$t('admin.default_images')}} + v-card-subtitle(v-html="$t('admin.default_images_help')") v-card-text v-row v-col(cols='4') @@ -109,12 +110,13 @@ import { mdiDeleteForever, mdiRestore, mdiPlus, mdiChevronUp } from '@mdi/js' export default { name: 'Theme', data () { + const t = new Date().getMilliseconds() return { mdiDeleteForever, mdiRestore, mdiPlus, mdiChevronUp, valid: false, - logoKey: 0, - fallbackImageKey: 0, - headerImageKey: 0, + logoKey: t, + fallbackImageKey: t, + headerImageKey: t, link: { href: '', label: '' }, linkModal: false // menu: [false, false, false, false] diff --git a/docs/assets/js/gancio-events.es.js b/docs/assets/js/gancio-events.es.js index a0a2adee..7376dcbb 100644 --- a/docs/assets/js/gancio-events.es.js +++ b/docs/assets/js/gancio-events.es.js @@ -117,9 +117,9 @@ const Ce = /* @__PURE__ */ new Set(); function Ae(t, e) { t && t.i && (Ce.delete(t), t.i(e)); } -function Me(t, e, i, n) { - const { fragment: l, on_mount: o, on_destroy: r, after_update: f } = t.$$; - l && l.m(e, i), n || Q(() => { +function Me(t, e, i, l) { + const { fragment: n, on_mount: o, on_destroy: r, after_update: f } = t.$$; + n && n.m(e, i), l || Q(() => { const c = o.map(W).filter(_e); r ? r.push(...c) : O(c), t.$$.on_mount = []; }), f.forEach(Q); @@ -131,7 +131,7 @@ function Ne(t, e) { function Te(t, e) { t.$$.dirty[0] === -1 && (H.push(t), Se(), t.$$.dirty.fill(0)), t.$$.dirty[e / 31 | 0] |= 1 << e % 31; } -function ye(t, e, i, n, l, o, r, f = [-1]) { +function ye(t, e, i, l, n, o, r, f = [-1]) { const c = I; R(t); const s = t.$$ = { @@ -139,7 +139,7 @@ function ye(t, e, i, n, l, o, r, f = [-1]) { ctx: null, props: o, update: L, - not_equal: l, + not_equal: n, bound: ee(), on_mount: [], on_destroy: [], @@ -156,8 +156,8 @@ function ye(t, e, i, n, l, o, r, f = [-1]) { let k = !1; if (s.ctx = i ? i(t, e.props || {}, (m, _, ...C) => { const w = C.length ? C[0] : _; - return s.ctx && l(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _; - }) : [], s.update(), k = !0, O(s.before_update), s.fragment = n ? n(s.ctx) : !1, e.target) { + return s.ctx && n(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _; + }) : [], s.update(), k = !0, O(s.before_update), s.fragment = l ? l(s.ctx) : !1, e.target) { if (e.hydrate) { const m = $e(e.target); s.fragment && s.fragment.l(m), m.forEach(x); @@ -190,8 +190,8 @@ typeof HTMLElement == "function" && (X = class extends HTMLElement { $on(t, e) { const i = this.$$.callbacks[t] || (this.$$.callbacks[t] = []); return i.push(e), () => { - const n = i.indexOf(e); - n !== -1 && i.splice(n, 1); + const l = i.indexOf(e); + l !== -1 && i.splice(l, 1); }; } $set(t) { @@ -211,13 +211,13 @@ function F(t, e = "long") { function V(t) { return t.multidate ? F(t.start_datetime) + " - " + F(t.end_datetime) : F(t.start_datetime) + (t.end_datetime ? "-" + F(t.end_datetime, "short") : ""); } -function ne(t, e, i) { - const n = t.slice(); - return n[12] = e[i], n; -} function le(t, e, i) { - const n = t.slice(); - return n[15] = e[i], n; + const l = t.slice(); + return l[12] = e[i], l; +} +function ne(t, e, i) { + const l = t.slice(); + return l[15] = e[i], l; } function re(t) { let e; @@ -225,11 +225,11 @@ function re(t) { c() { e = g("link"), a(e, "rel", "stylesheet"), a(e, "href", t[4]); }, - m(i, n) { - v(i, e, n); + m(i, l) { + v(i, e, l); }, - p(i, n) { - n & 16 && a(e, "href", i[4]); + p(i, l) { + l & 16 && a(e, "href", i[4]); }, d(i) { i && x(e); @@ -237,51 +237,51 @@ function re(t) { }; } function oe(t) { - let e, i, n = t[1] && t[3] === "true" && ae(t), l = t[5], o = []; - for (let r = 0; r < l.length; r += 1) - o[r] = ue(ne(t, l, r)); + let e, i, l = t[1] && t[3] === "true" && ae(t), n = t[5], o = []; + for (let r = 0; r < n.length; r += 1) + o[r] = ue(le(t, n, r)); return { c() { - e = g("div"), n && n.c(), i = z(); + e = g("div"), l && l.c(), i = z(); for (let r = 0; r < o.length; r += 1) o[r].c(); a(e, "id", "gancioEvents"), T(e, "dark", t[2] === "dark"), T(e, "light", t[2] === "light"), T(e, "sidebar", t[3] === "true"), T(e, "nosidebar", t[3] !== "true"); }, m(r, f) { - v(r, e, f), n && n.m(e, null), u(e, i); + v(r, e, f), l && l.m(e, null), u(e, i); for (let c = 0; c < o.length; c += 1) o[c].m(e, null); }, p(r, f) { - if (r[1] && r[3] === "true" ? n ? n.p(r, f) : (n = ae(r), n.c(), n.m(e, i)) : n && (n.d(1), n = null), f & 41) { - l = r[5]; + if (r[1] && r[3] === "true" ? l ? l.p(r, f) : (l = ae(r), l.c(), l.m(e, i)) : l && (l.d(1), l = null), f & 41) { + n = r[5]; let c; - for (c = 0; c < l.length; c += 1) { - const s = ne(r, l, c); + for (c = 0; c < n.length; c += 1) { + const s = le(r, n, c); o[c] ? o[c].p(s, f) : (o[c] = ue(s), o[c].c(), o[c].m(e, null)); } for (; c < o.length; c += 1) o[c].d(1); - o.length = l.length; + o.length = n.length; } f & 4 && T(e, "dark", r[2] === "dark"), f & 4 && T(e, "light", r[2] === "light"), f & 8 && T(e, "sidebar", r[3] === "true"), f & 8 && T(e, "nosidebar", r[3] !== "true"); }, d(r) { - r && x(e), n && n.d(), pe(o, r); + r && x(e), l && l.d(), pe(o, r); } }; } function ae(t) { - let e, i, n, l, o, r, f; + let e, i, l, n, o, r, f; return { c() { - e = g("a"), i = g("div"), n = g("div"), l = j(t[1]), o = z(), r = g("img"), a(n, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header"); + e = g("a"), i = g("div"), l = g("div"), n = j(t[1]), o = z(), r = g("img"), a(l, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header"); }, m(c, s) { - v(c, e, s), u(e, i), u(i, n), u(n, l), u(i, o), u(i, r); + v(c, e, s), u(e, i), u(i, l), u(l, n), u(i, o), u(i, r); }, p(c, s) { - s & 2 && N(l, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]); + s & 2 && N(n, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]); }, d(c) { c && x(e); @@ -293,50 +293,50 @@ function se(t) { function i(o, r) { return o[12].media.length ? Ge : Le; } - let n = i(t), l = n(t); + let l = i(t), n = l(t); return { c() { - e = g("div"), l.c(), a(e, "class", "img"); + e = g("div"), n.c(), a(e, "class", "img"); }, m(o, r) { - v(o, e, r), l.m(e, null); + v(o, e, r), n.m(e, null); }, p(o, r) { - n === (n = i(o)) && l ? l.p(o, r) : (l.d(1), l = n(o), l && (l.c(), l.m(e, null))); + l === (l = i(o)) && n ? n.p(o, r) : (n.d(1), n = l(o), n && (n.c(), n.m(e, null))); }, d(o) { - o && x(e), l.d(); + o && x(e), n.d(); } }; } function Le(t) { - let e, i, n; + let e, i, l; return { c() { - e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, n = t[0] + "/fallbackimage.png") || a(e, "src", n), a(e, "loading", "lazy"); + e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, l = t[0] + "/fallbackimage.png") || a(e, "src", l), a(e, "loading", "lazy"); }, - m(l, o) { - v(l, e, o); + m(n, o) { + v(n, e, o); }, - p(l, o) { - o & 32 && i !== (i = l[12].title) && a(e, "alt", i), o & 1 && !G(e.src, n = l[0] + "/fallbackimage.png") && a(e, "src", n); + p(n, o) { + o & 32 && i !== (i = n[12].title) && a(e, "alt", i), o & 1 && !G(e.src, l = n[0] + "/fallbackimage.png") && a(e, "src", l); }, - d(l) { - l && x(e); + d(n) { + n && x(e); } }; } function Ge(t) { - let e, i, n, l; + let e, i, l, n; return { c() { - e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", n = t[12].media[0].name), G(e.src, l = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", l), a(e, "loading", "lazy"); + e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", l = t[12].media[0].name), G(e.src, n = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", n), a(e, "loading", "lazy"); }, m(o, r) { v(o, e, r); }, p(o, r) { - r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && n !== (n = o[12].media[0].name) && a(e, "alt", n), r & 33 && !G(e.src, l = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", l); + r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && l !== (l = o[12].media[0].name) && a(e, "alt", l), r & 33 && !G(e.src, n = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", n); }, d(o) { o && x(e); @@ -344,50 +344,50 @@ function Ge(t) { }; } function ce(t) { - let e, i = t[12].tags, n = []; - for (let l = 0; l < i.length; l += 1) - n[l] = fe(le(t, i, l)); + let e, i = t[12].tags, l = []; + for (let n = 0; n < i.length; n += 1) + l[n] = fe(ne(t, i, n)); return { c() { e = g("div"); - for (let l = 0; l < n.length; l += 1) - n[l].c(); + for (let n = 0; n < l.length; n += 1) + l[n].c(); a(e, "class", "tags"); }, - m(l, o) { - v(l, e, o); - for (let r = 0; r < n.length; r += 1) - n[r].m(e, null); + m(n, o) { + v(n, e, o); + for (let r = 0; r < l.length; r += 1) + l[r].m(e, null); }, - p(l, o) { + p(n, o) { if (o & 32) { - i = l[12].tags; + i = n[12].tags; let r; for (r = 0; r < i.length; r += 1) { - const f = le(l, i, r); - n[r] ? n[r].p(f, o) : (n[r] = fe(f), n[r].c(), n[r].m(e, null)); + const f = ne(n, i, r); + l[r] ? l[r].p(f, o) : (l[r] = fe(f), l[r].c(), l[r].m(e, null)); } - for (; r < n.length; r += 1) - n[r].d(1); - n.length = i.length; + for (; r < l.length; r += 1) + l[r].d(1); + l.length = i.length; } }, - d(l) { - l && x(e), pe(n, l); + d(n) { + n && x(e), pe(l, n); } }; } function fe(t) { - let e, i, n = t[15] + "", l; + let e, i, l = t[15] + "", n; return { c() { - e = g("span"), i = j("#"), l = j(n), a(e, "class", "tag"); + e = g("span"), i = j("#"), n = j(l), a(e, "class", "tag"); }, m(o, r) { - v(o, e, r), u(e, i), u(e, l); + v(o, e, r), u(e, i), u(e, n); }, p(o, r) { - r & 32 && n !== (n = o[15] + "") && N(l, n); + r & 32 && l !== (l = o[15] + "") && N(n, l); }, d(o) { o && x(e); @@ -395,16 +395,16 @@ function fe(t) { }; } function ue(t) { - let e, i, n, l, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t); + let e, i, l, n, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t); return { c() { - e = g("a"), $ && $.c(), i = z(), n = g("div"), l = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(l, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(n, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank"); + e = g("a"), $ && $.c(), i = z(), l = g("div"), n = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(n, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(l, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank"); }, m(p, M) { - v(p, e, M), $ && $.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(n, Y), E && E.m(n, null), u(e, Z); + v(p, e, M), $ && $.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(l, Y), E && E.m(l, null), u(e, Z); }, p(p, M) { - p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(n, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q); + p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(l, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q); }, d(p) { p && x(e), $ && $.d(), E && E.d(); @@ -412,21 +412,21 @@ function ue(t) { }; } function He(t) { - let e, i, n = t[4] && re(t), l = t[5].length && oe(t); + let e, i, l = t[4] && re(t), n = t[5].length && oe(t); return { c() { - n && n.c(), e = z(), l && l.c(), i = ve(), this.c = L; + l && l.c(), e = z(), n && n.c(), i = ve(), this.c = L; }, m(o, r) { - n && n.m(o, r), v(o, e, r), l && l.m(o, r), v(o, i, r); + l && l.m(o, r), v(o, e, r), n && n.m(o, r), v(o, i, r); }, p(o, [r]) { - o[4] ? n ? n.p(o, r) : (n = re(o), n.c(), n.m(e.parentNode, e)) : n && (n.d(1), n = null), o[5].length ? l ? l.p(o, r) : (l = oe(o), l.c(), l.m(i.parentNode, i)) : l && (l.d(1), l = null); + o[4] ? l ? l.p(o, r) : (l = re(o), l.c(), l.m(e.parentNode, e)) : l && (l.d(1), l = null), o[5].length ? n ? n.p(o, r) : (n = oe(o), n.c(), n.m(i.parentNode, i)) : n && (n.d(1), n = null); }, i: L, o: L, d(o) { - n && n.d(o), o && x(e), l && l.d(o), o && x(i); + l && l.d(o), o && x(e), n && n.d(o), o && x(i); } }; } @@ -438,12 +438,12 @@ function de(t) { return "center center"; } function Re(t, e, i) { - let { baseurl: n = "" } = e, { title: l = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = []; + let { baseurl: l = "" } = e, { title: n = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = []; function w(d) { if (!_) return; const S = []; - o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${n}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => { + o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${l}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => { i(5, C = h); }).catch((h) => { console.error("Error loading Gancio API -> ", h); @@ -452,12 +452,12 @@ function Re(t, e, i) { return we(() => { _ = !0, w(); }), t.$$set = (d) => { - "baseurl" in d && i(0, n = d.baseurl), "title" in d && i(1, l = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style); + "baseurl" in d && i(0, l = d.baseurl), "title" in d && i(1, n = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style); }, t.$$.update = () => { t.$$.dirty & 975 && w(); }, [ - n, l, + n, c, k, m, @@ -570,13 +570,13 @@ class Ie extends X { } customElements.define("gancio-events", Ie); function he(t) { - let e, i, n, l, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t); + let e, i, l, n, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t); return { c() { - e = g("a"), h && h.c(), i = z(), n = g("div"), l = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(n, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank"); + e = g("a"), h && h.c(), i = z(), l = g("div"), n = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(l, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank"); }, m(b, A) { - v(b, e, A), h && h.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d); + v(b, e, A), h && h.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d); }, p(b, A) { b[1].media.length ? h ? h.p(b, A) : (h = ge(b), h.c(), h.m(e, i)) : h && (h.d(1), h = null), A & 2 && o !== (o = b[1].title + "") && N(r, o), A & 2 && s !== (s = V(b[1]) + "") && N(k, s), A & 2 && w !== (w = b[1].place.name + "") && N(d, w), A & 3 && S !== (S = b[0] + "/event/" + (b[1].slug || b[1].id)) && a(e, "href", S); @@ -587,16 +587,16 @@ function he(t) { }; } function ge(t) { - let e, i, n, l; + let e, i, l, n; return { c() { - e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", n = t[1].media[0].name), a(e, "style", l = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;"); + e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", l = t[1].media[0].name), a(e, "style", n = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;"); }, m(o, r) { v(o, e, r); }, p(o, r) { - r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && n !== (n = o[1].media[0].name) && a(e, "alt", n), r & 2 && l !== (l = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", l); + r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && l !== (l = o[1].media[0].name) && a(e, "alt", l), r & 2 && n !== (n = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", n); }, d(o) { o && x(e); @@ -609,16 +609,16 @@ function Oe(t) { c() { i && i.c(), e = ve(), this.c = L; }, - m(n, l) { - i && i.m(n, l), v(n, e, l); + m(l, n) { + i && i.m(l, n), v(l, e, n); }, - p(n, [l]) { - n[1] ? i ? i.p(n, l) : (i = he(n), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null); + p(l, [n]) { + l[1] ? i ? i.p(l, n) : (i = he(l), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null); }, i: L, o: L, - d(n) { - i && i.d(n), n && x(e); + d(l) { + i && i.d(l), l && x(e); } }; } @@ -630,21 +630,21 @@ function me(t) { return "center center"; } function Ue(t, e, i) { - let { baseurl: n = "https://demo.gancio.org" } = e, { id: l } = e, o = !1, r; + let { baseurl: l = "https://demo.gancio.org" } = e, { id: n } = e, o = !1, r; function f(s, k) { - o && fetch(`${k}/api/event/${s}`).then((m) => m.json()).then((m) => i(1, r = m)); + o && fetch(`${k}/api/event/detail/${s}`).then((m) => m.json()).then((m) => i(1, r = m)); } we(() => { - o = !0, f(l, n); + o = !0, f(n, l); }); function c(s) { - return `${n}/media/thumb/${s.media[0].url}`; + return `${l}/media/thumb/${s.media[0].url}`; } return t.$$set = (s) => { - "baseurl" in s && i(0, n = s.baseurl), "id" in s && i(3, l = s.id); + "baseurl" in s && i(0, l = s.baseurl), "id" in s && i(3, n = s.id); }, t.$$.update = () => { - t.$$.dirty & 9 && f(l, n); - }, [n, r, c, l]; + t.$$.dirty & 9 && f(n, l); + }, [l, r, c, n]; } class qe extends X { constructor(e) { diff --git a/docs/changelog.md b/docs/changelog.md index 1ba74939..e7d46a58 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -8,6 +8,47 @@ nav_order: 10 All notable changes to this project will be documented in this file. +### 1.6.2 - 12 jan '23 + - add swipe gesture to move to next/prev event + - fix refresh collections, fix #219 + - add russian translation (thanks @drunkod) + - refactor search / filter / selection fix #225, 227, #224 + - models initialization refactored, better dev experience, fix backend HMR + +### 1.6.1 - 15 dec '22 + - allow edit tags in admin panel, fix #170 + - fix header / fallback image upload, fix #222 + - fix WPGancio MU + - fix recurrent events label + - update translations (de, es, eu, gl) + +### 1.6.0 - 11 dec '22 + - new plugin system - fix #177 + - new "publish on telegram" plugin: (thanks @fadelkon) + - people can now choose the language displayed - fix #171 + - admin could choose a custom fallback image - fix #195 + - it is now possible NOT to enter the end time of an event - fix #188 + - live search + - improve event import + - add Apple touch icon - fix #200 + - add nominatim / openstreetmap search feature (thanks @sedum) + - new hide calendar option + - new hide thumbs from homepage option + - linkable admin tab + - friendly instances label is now customizable (thanks @sedum) + - i18n refactoring + - Wordpress plugin now supports MU installation + - new chinese translation + - new portuguese translation + - improved navbar layout + - improved event layout + - complete oauth2 refactoring + - fix ics unique uuid + - fix place "[Object]" issue - #194 + - fix random restart while downloading random media + - fix mobile dialog layout + - urlencode place and tag urls + ### 1.5.6 - 22 set '22 - update linkifyjs, sequelizem, nuxt deps - improve homepage loading time diff --git a/docs/contact.md b/docs/contact.md index ed7bb3db..8b6be488 100644 --- a/docs/contact.md +++ b/docs/contact.md @@ -11,5 +11,5 @@ nav_order: 9 - :elephant: Mastodon ⇒ [@gancio@mastodon.cisti.org](https://mastodon.cisti.org/@gancio) - :email: Email ⇒ [info@cisti.org](mailto:info@cisti.org) - IRC ⇒ #gancio @ irc.autistici.org (sometimes...) -- Issues ⇒ https://framagit.org/les/gancio/-/issues +- Issues ⇒ [https://framagit.org/les/gancio/-/issues](https://framagit.org/les/gancio/-/issues) diff --git a/docs/docker/nominatim/.env.example b/docs/docker/nominatim/.env.example new file mode 100644 index 00000000..f4a780f2 --- /dev/null +++ b/docs/docker/nominatim/.env.example @@ -0,0 +1,7 @@ + +NOMINATIM_PASSWORD=CeMA4M1kiDo0k + +# Choose PBF_PATH to import a local file +PBF_PATH=/nominatim/data/default.osm.pbf +# PBF_URL= https://download.geofabrik.de/europe/italy/nord-est-latest.osm.pbf +# REPLICATION_URL= https://download.geofabrik.de/europe/italy/nord-est-updates/ diff --git a/docs/docker/nominatim/docker-compose.yml b/docs/docker/nominatim/docker-compose.yml new file mode 100644 index 00000000..25901b80 --- /dev/null +++ b/docs/docker/nominatim/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' + +services: + nominatim: + container_name: nominatim + image: mediagis/nominatim:4.2 + restart: always + ports: + - "8080:8080" + environment: + # see https://github.com/mediagis/nominatim-docker/tree/master/4.2#configuration for more options + PBF_PATH: "${PBF_PATH}" + PBF_URL: "${PBF_URL}" + REPLICATION_URL: "${REPLICATION_URL}" + NOMINATIM_PASSWORD: ${NOMINATIM_PASSWORD} + volumes: + - ./nominatim-data:/var/lib/postgresql/14/main + - ./nominatim/data/"${PBF_PATH}":/nominatim/data/"${PBF_PATH}" + shm_size: 1gb diff --git a/docs/install/configuration.md b/docs/install/configuration.md index 6fcce96a..36de449a 100644 --- a/docs/install/configuration.md +++ b/docs/install/configuration.md @@ -16,7 +16,7 @@ The configuration file shoud be a `.json` or a `.js` file and could be specified 1. TOC {:toc} -- ### Server +### Server This probably support unix socket too ```json @@ -26,7 +26,7 @@ This probably support unix socket too } ``` -- ### Database +### Database DB configuration, look [here](https://sequelize.org/v6/class/src/sequelize.js~Sequelize.html#instance-constructor-constructor) for options. ```json "db": { @@ -34,11 +34,15 @@ DB configuration, look [here](https://sequelize.org/v6/class/src/sequelize.js~Se "storage": "/tmp/db.sqlite" } ``` -- ### Upload path -Where to save images +### Upload path +Where to save images `"upload_path": "./uploads"` -- ### User locale +### Plugins path +Where to search for [plugins](/usage/plugins) +`"plugins_path": "./plugins"` + +### User locale Probably you want to modify some text for your specific community, that's why we thought the `user_locale` configuration: you can specify your version of each string of **gancio** making a directory with your locales inside. diff --git a/docs/install/nominatim.md b/docs/install/nominatim.md new file mode 100644 index 00000000..5202861a --- /dev/null +++ b/docs/install/nominatim.md @@ -0,0 +1,139 @@ +--- +layout: default +title: Nominatim +permalink: /install/nominatim +parent: Install +nav_order: 7 +--- + +## Nominatim installation +{: .no_toc } + +1. TOC +{:toc} + +--- + +## Testing +For testing purposes you could skip the nominatim installation and use one of this geocoding providers that run a server for free: + +- [https://photon.komoot.io/](https://photon.komoot.io/) [Terms of service](https://photon.komoot.io/) +- [https://nominatim.openstreetmap.org/](https://nominatim.openstreetmap.org/) [Terms of service](https://operations.osmfoundation.org/policies/nominatim/) + +--- + +## Requirements +From [https://nominatim.org/release-docs/latest/admin/Installation/](https://nominatim.org/release-docs/latest/admin/Installation/) + +"A minimum of 2GB of RAM is required or installation will fail. For a full planet import 128GB of RAM or more are strongly recommended. Do not report out of memory problems if you have less than 64GB RAM." + +### Planet mirrors +There is a list of planet mirror at [https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors](https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors) +There you can also find `Country and area extracts`, divided by `Worldwide extract sources` and `Regional extract sources` + +### Download an extract +For Nominatim to work, you will needs to import files in [PBF Format](https://wiki.openstreetmap.org/wiki/PBF_Format) in the PostGis database. Those files have extension `*.osm.pbf`. + +Some of these mirrors provide also incremental updates via [OsmChange](https://wiki.openstreetmap.org/wiki/OsmChange), for example: +- Provides updates but with a lower detail +[https://download.geofabrik.de/europe/italy/nord-ovest-updates/nord-ovest-latest.osm.pbf](http://download.geofabrik.de/europe/italy/nord-ovest-latest.osm.pbf) +[https://download.geofabrik.de/europe/italy/nord-ovest-updates/](https://download.geofabrik.de/europe/italy/nord-ovest-updates/) +- Does not provide updates but as higher level of detail +[https://osmit-estratti-test.wmcloud.org/dati/poly/province/pbf/015_Milano_poly.osm.pbf](https://osmit-estratti-test.wmcloud.org/dati/poly/province/pbf/015_Milano_poly.osm.pbf) + +Needs to host multiple areas? Checkout [Osmium](https://osmcode.org/osmium-tool/manual.html), to merge multiple PBF files into one. + +--- + +## Install on Debian +There is a [detailed documentaion](https://nominatim.org/release-docs/latest/appendix/Install-on-Ubuntu-22/) for installing nominatim on `Ubuntu 22` that should be valid also to install on `Debian`. + +### Setup +[https://nominatim.org/release-docs/latest/appendix/Install-on-Ubuntu-22/#installing-the-required-software](https://nominatim.org/release-docs/latest/appendix/Install-on-Ubuntu-22/#installing-the-required-software) + +### Building and Configuration + +Get the source code from Github and change into the source directory +``` +cd $USERHOME +wget https://nominatim.org/release/Nominatim-4.2.0.tar.bz2 +tar xf Nominatim-4.2.0.tar.bz2 +``` + +The code must be built in a separate directory. Create this directory, then configure and build Nominatim in there: +``` +mkdir $USERHOME/build +cd $USERHOME/build +cmake $USERHOME/Nominatim-4.2.0 +make +``` + +### Setting up the webserver +[https://nominatim.org/release-docs/latest/appendix/Install-on-Ubuntu-22/#setting-up-a-webserver](https://nominatim.org/release-docs/latest/appendix/Install-on-Ubuntu-22/#setting-up-a-webserver) + +### Import the database +[https://nominatim.org/release-docs/latest/admin/Import/](https://nominatim.org/release-docs/latest/admin/Import/) + +--- + +## Install using docker + +### Setup +Make sure to have [Docker Engine](https://docs.docker.com/engine/install/), +[Docker Compose](https://docs.docker.com/compose/install/) and [git](https://git-scm.com/downloads) installed: +```bash +sudo apt install docker docker-compose git +``` + +### Clone the project +From [https://github.com/mediagis/nominatim-docker](https://github.com/mediagis/nominatim-docker) + +- Clone the project from sources +```bash +git clone git@github.com:mediagis/nominatim-docker.git +# cd nominatim-docker/ +cd nominatim-docker/4.2/contrib # released Nov 29, 2022 +docker-compose pull +``` + +- Or, use the template at `docs/docker/nominatim` +``` +cd /opt/gancio/docs/docker/nominatim +docker-compose pull +``` + +### Import the database +See [Requirements](#requirements) about downloading the `.osm.pbf` files +```bash +cd docs/docker/nominatim/ +wget https://download.geofabrik.de/europe/italy/nord-ovest-latest.osm.pbf \ + ./nominatim/data/default.osm.pbf +``` + +### Configure the environment file +``` +cd docs/docker/nominatim/ +cp .env.example .env +``` +Create a random password for nominatim a add it to .env file +```bash +NOMINATIM_PASSWORD=random_password; +NOMINATIM_PASSWORD=$(echo $NOMINATIM_PASSWORD | openssl passwd --stdin); +echo $NOMINATIM_PASSWORD; +sed -i -e 's/\(NOMINATIM_PASSWORD=\)\(.*\)/\1'$NOMINATIM_PASSWORD'/g' .env +``` + +### Start nominatim-docker + +Start your container: +```bash +docker-compose up -d +``` +Checkout the logs to see when data are imported to the database: +```bash +docker-compose logs -f +``` + +Try out the search: + +[http://0.0.0.0:8080/search?q=building](http://0.0.0.0:8080/search?q=building) diff --git a/docs/instances.md b/docs/instances.md index 74dbedf2..6ab4ad28 100644 --- a/docs/instances.md +++ b/docs/instances.md @@ -11,7 +11,11 @@ nav_order: 7 - [sapratza.in](https://sapratza.in/) (Sardinia, Italy) - [ponente.rocks](https://ponente.rocks) (Ponente Ligure, Italy) - [puntello.org](https://puntello.org) (Milan, Italy) +- [lasitua.org](https://lasitua.org) (Brescia, Italy) +- [balotta.org](https://balotta.org) (Bologna, Italy) +- [gancio.daghe.xyz](https://gancio.daghe.xyz/) (Trento, Italy) - [bcn.convoca.la](https://bcn.convoca.la/) (Barcelona) +- [mad.convoca.la](https://bcn.convoca.la/) (Madrid) - [bonn.jetzt](https://bonn.jetzt/) (Digital-Events aus Bonn, Rhein-Sieg und der Region) - [quest.livellosegreto.it](https://quest.livellosegreto.it/) - [ezkerraldea.euskaragendak.eus](https://ezkerraldea.euskaragendak.eus/) @@ -20,6 +24,7 @@ nav_order: 7 - [lubakiagenda.net](https://lubakiagenda.net/) - [eventos.coletivos.org](https://eventos.coletivos.org/) - [calendario.extinctionrebellion.es](https://calendario.extinctionrebellion.es/) +- [cloudspeakers.org](https://cloudspeakers.org/) (Utrecht?) Do you want your instance to appear here? [Write us]({% link contact.md %}). diff --git a/docs/usage/plugins.md b/docs/usage/plugins.md new file mode 100644 index 00000000..79794518 --- /dev/null +++ b/docs/usage/plugins.md @@ -0,0 +1,62 @@ +--- +layout: default +title: Plugins +permalink: /usage/plugins +nav_order: 2 +parent: Usage +has_toc: true +--- + +# Plugins +{: .no_toc } + +This page is a guide to install plugins, if you want to develop one instead look [here](/dev/plugins) + +1. TOC +{:toc} + + + +## Install + +To install a plugin you have to: + +1. **download the .zip archive (look for the url on the plugin list below)** +``` +wget https://framagit.org/les/gancio-plugin-telegram-bridge/-/archive/v0.2.0/gancio-plugin-telegram-bridge-v0.2.0.zip +``` + +2. **unpack it in the `./plugins` directory.** +``` +cd plugins +unzip https://framagit.org/les/gancio-plugin-telegram-bridge/-/archive/v0.2.0/gancio-plugin-telegram-bridge-v0.2.0.zip +``` + + +3. **install the dependencies with `yarn`** +``` +cd plugins/gancio-plugin-telegram-bridge +yarn +``` + +4. **restart gancio** +__with debian__ +``` +sudo sytemctl restart gancio +``` +__with docker__ +``` +docker-compose restart +``` + +# List of plugins + +## __Telegram__ + +This plugin republishes events to Telegram channels or groups. +The goal is to spread the info of our networks to the capitalist cyberspace, and pull otherwise isolated people to our radical and free part of the internet. + +- **Website**: [https://framagit.org/bcn.convocala/gancio-plugin-telegram-bridge](https://framagit.org/bcn.convocala/gancio-plugin-telegram-bridge) +- **Download**: [gancio-plugin-telegram-bridge-v0.2.0.zip](https://framagit.org/les/gancio-plugin-telegram-bridge/-/archive/v0.2.0/gancio-plugin-telegram-bridge-v0.2.0.zip) +- **Release**: v0.2.0 / 10 Dec '22 + diff --git a/layouts/default.vue b/layouts/default.vue index 54e41b8d..2227c6ca 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -4,7 +4,9 @@ - + + +