From 79ebec9116539c5eeab86ef6dcb4512a9f402861 Mon Sep 17 00:00:00 2001 From: sedum Date: Fri, 17 Feb 2023 00:23:35 +0100 Subject: [PATCH 01/13] reinit whereinputadvanced in /add , and init only/also online mechanism, various fixes: admin edit place; bug in nominatim display_name when place in certain nominatim_class, init refactor geocoding related code in services/geocoding/provider; init MapEdit component --- components/MapEdit.vue | 70 ++ components/WhereInput.vue | 235 +++-- components/WhereInputAdvanced.vue | 104 ++ components/admin/Places.vue | 147 +-- components/admin/Settings.vue | 20 + locales/en.json | 29 +- pages/add/_edit.vue | 15 +- pages/event/_slug.vue | 20 +- plugins/validators.js | 6 + server/api/controller/event.js | 2 + server/api/controller/settings.js | 2 + server/api/index.js | 1 + server/api/models/event.js | 3 +- server/helpers.js | 4 +- server/helpers/geolocation/index.js | 17 + server/helpers/geolocation/isoCountries.js | 987 ++++++++++++++++++ .../20221215110244-event-locations.js | 29 + server/services/geocoding/nominatim.js | 34 + server/services/geocoding/photon.js | 45 + store/index.js | 2 + yarn.lock | 41 - 21 files changed, 1558 insertions(+), 255 deletions(-) create mode 100644 components/MapEdit.vue create mode 100644 components/WhereInputAdvanced.vue create mode 100644 server/helpers/geolocation/index.js create mode 100644 server/helpers/geolocation/isoCountries.js create mode 100644 server/migrations/20221215110244-event-locations.js diff --git a/components/MapEdit.vue b/components/MapEdit.vue new file mode 100644 index 00000000..e6cf1bec --- /dev/null +++ b/components/MapEdit.vue @@ -0,0 +1,70 @@ + + + + diff --git a/components/WhereInput.vue b/components/WhereInput.vue index 1baea189..abf1625a 100644 --- a/components/WhereInput.vue +++ b/components/WhereInput.vue @@ -24,7 +24,22 @@ v-row.mb-4 v-col(cols=12 md=6) - v-text-field(v-if="!settings.allow_geolocation" + v-row.mx-0.my-0.align-center.justify-center + v-combobox.mr-4(v-model="virtualLocations" v-if="settings.allow_event_only_online && value.name === 'online'" + :prepend-icon='mdiLink' + :hint="`Online locations, for instance a url to a videconference room`" + :label="$t('event.online_event_urls')" + clearable chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint + :delimiters="[',', ';', '; ']" + :items="virtualLocations" + @change='selectLocations') + template(v-slot:selection="{ item, on, attrs, selected, parent }") + v-chip(v-bind="attrs" close :close-icon='mdiCloseCircle' @click:close='parent.selectItem(item)' + :input-value="selected" label small) {{ item }} + template(v-slot:append) + v-icon(v-text='mdiCog' :disabled='!value.name' @click="whereInputAdvancedDialog = true") + + v-text-field.mr-4(v-if="!settings.allow_geolocation && value.name !== 'online'" ref='address' :prepend-icon='mdiMap' :disabled='disableAddress' @@ -34,57 +49,66 @@ v-row.mb-4 persistent-hint @change="changeAddress" :value="value.address") - v-combobox(ref='address' v-else - :prepend-icon='mdiMapSearch' - :disabled='disableAddress' - @input.native='searchAddress' - :label="$t('common.address')" - :rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]" - :value='value.address' - item-text='address' - persistent-hint hide-no-data clearable no-filter - :loading='loading' - @change='selectAddress' - @focus='searchAddress' - :items="addressList" - :hint="$t('event.address_description_osm')") - template(v-slot:message="{message, 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)') - v-list-item-content(two-line v-if='item') - v-list-item-title(v-text='item.name') - v-list-item-subtitle(v-text='`${item.address}`') - //- v-col(cols=12 md=3 v-if='settings.allow_geolocation') - //- v-text-field(ref='latitude' :value='value.latitude' - //- :prepend-icon='mdiLatitude' - //- :disabled='disableDetails' - //- :label="$t('common.latitude')" ) - //- v-col(cols=12 md=3 v-if='settings.allow_geolocation') - //- v-text-field(ref='longitude' :value='value.longitude' - //- :prepend-icon='mdiLongitude' - //- :disabled='disableDetails' - //- :label="$t('common.longitude')") + template(v-slot:append v-if="settings.allow_event_also_online && place.name !== 'online'") + v-icon(v-text='mdiCog' :disabled='!value.name' @click="whereInputAdvancedDialog = true") + + v-combobox(ref='address' v-if="settings.allow_geolocation && value.name !== 'online' || (!settings.allow_event_only_online && value.name === 'online')" + :prepend-icon='mdiMapSearch' + :disabled='disableAddress' + @input.native='searchAddress' + :label="$t('common.address')" + :rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]" + :value='value.address' + item-text='address' + persistent-hint hide-no-data clearable no-filter + :loading='loading' + @change='selectAddress' + @focus='searchAddress' + :items="addressList" + :hint="$t('event.address_description_osm')") + template(v-slot:message="{message, 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)') + v-list-item-content(two-line v-if='item') + v-list-item-title(v-text='item.name') + v-list-item-subtitle(v-text='`${item.address}`') + template(v-slot:append v-if="settings.allow_event_also_online || settings.allow_geolocation") + v-icon(v-text='mdiCog' :disabled='!value.name || (!value.isNew && !settings.allow_event_also_online) ' @click="whereInputAdvancedDialog = true") + v-dialog(v-model='whereInputAdvancedDialog' :key="whereAdvancedId" destroy-on-close max-width='700px' :fullscreen='$vuetify.breakpoint.xsOnly' dense) + WhereInputAdvanced(ref='whereAdvanced' :place.sync='value' :event='event' @close='whereInputAdvancedDialog = false && this.$refs.address.blur()' + :virtualLocations.sync="virtualLocations" + :online_event_only_value.sync='online_event_only' + @update:onlineEvent="changeOnlineEvent" + @update:virtualLocations="selectLocations" + ) + + diff --git a/components/WhereInputAdvanced.vue b/components/WhereInputAdvanced.vue new file mode 100644 index 00000000..665e7088 --- /dev/null +++ b/components/WhereInputAdvanced.vue @@ -0,0 +1,104 @@ + + diff --git a/components/admin/Places.vue b/components/admin/Places.vue index 6c8c26b7..7edf1204 100644 --- a/components/admin/Places.vue +++ b/components/admin/Places.vue @@ -11,32 +11,57 @@ v-container v-dialog(v-model='dialog' width='600' :fullscreen='$vuetify.breakpoint.xsOnly') v-card v-card-title {{ $t('admin.edit_place') }} - v-card-text + v-card-text.mb-4 v-form(v-model='valid' ref='form' lazy-validation) v-text-field( :rules="[$validators.required('common.name')]" :label="$t('common.name')" v-model='place.name' :placeholder='$t("common.name")') - - v-combobox(ref='address' + + v-text-field( + :rules="[ v => $validators.required('common.address')(v)]" + :label="$t('common.address')" + v-model='place.address' + persistent-hint) + + v-combobox.mt-0.mb-4(ref='geocodedAddress' + v-if="(settings.allow_geolocation && place.name !== 'online')" + :disabled="!(settings.allow_geolocation && place.name !== 'online')" :prepend-icon='mdiMapSearch' @input.native='searchAddress' - :label="$t('common.address')" - :rules="[ v => $validators.required('common.address')(v)]" - :value='place.address' + :label="$t('admin.search_address')" + :value='place.latitude && place.longitude && place.geocodedAddress' persistent-hint hide-no-data clearable no-filter :loading='loading' @change='selectAddress' @focus='searchAddress' :items="addressList" - :hint="$t('event.address_description')") + :hint="$t('event.address_description_osm')") + template(v-slot:message="{message, key}") + span(v-html='message' :key="key") template(v-slot:item="{ item, attrs, on }") v-list-item(v-bind='attrs' v-on='on') v-list-item-content(two-line v-if='item') v-list-item-title(v-text='item.name') v-list-item-subtitle(v-text='`${item.address}`') + v-row.mt-4(v-if="(settings.allow_geolocation && place.name !== 'online')") + v-col.py-0(cols=12 md=6) + v-text-field(v-model="place.latitude" + :value="place.latitude" + :prepend-icon='mdiLatitude' + :disabled="(!settings.allow_geolocation || place.name === 'online')" + :label="$t('common.latitude')" + :rules="$validators.latitude") + v-col.py-0(cols=12 md=6) + v-text-field(v-model="place.longitude" + :prepend-icon='mdiLongitude' + :disabled="!settings.allow_geolocation || place.name === 'online'" + :label="$t('common.longitude')" + :rules="$validators.longitude") + + MapEdit.mt-4(:place='place' :key="mapEdit" v-if="settings.allow_geolocation && place.name !== 'online' && place.latitude && place.longitude") v-card-actions v-spacer @@ -62,15 +87,22 @@ v-container diff --git a/components/admin/Settings.vue b/components/admin/Settings.vue index 4bb3cd97..2b457976 100644 --- a/components/admin/Settings.vue +++ b/components/admin/Settings.vue @@ -56,6 +56,14 @@ v-container inset :label="$t('admin.allow_geolocation')") + v-switch.mt-1(v-model='allow_event_only_online' + inset + :label="$t('admin.allow_event_only_online')") + + v-switch.mt-1(v-model='allow_event_also_online' + inset + :label="$t('admin.allow_event_also_online')") + v-dialog(v-model='showSMTP' destroy-on-close max-width='700px' :fullscreen='$vuetify.breakpoint.xsOnly') SMTP(@close='showSMTP = false') @@ -126,6 +134,18 @@ export default { get () { return this.settings.allow_geolocation }, set (value) { this.setSetting({ key: 'allow_geolocation', value }) } }, + allow_event_only_online: { + get () { return this.settings.allow_event_only_online }, + set (value) { this.setSetting({ key: 'allow_event_only_online', value }) + if (value == true) { this.allow_event_also_online = value } + } + }, + allow_event_also_online: { + get () { return this.settings.allow_event_also_online }, + set (value) { this.setSetting({ key: 'allow_event_also_online', value }) + if (value == false) { this.setSetting({ key: 'allow_event_only_online', value }) } + } + }, filteredTimezones () { const current_timezone = moment.tz.guess() tzNames.unshift(current_timezone) diff --git a/locales/en.json b/locales/en.json index ae87414a..d9064a6b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -98,7 +98,9 @@ "about": "About", "content": "Content", "admin_actions": "Admin actions", - "recurring_event_actions": "Recurring event actions" + "recurring_event_actions": "Recurring event actions", + "latitude": "Latitude", + "longitude": "Longitude" }, "login": { "description": "By logging in you can publish new events.", @@ -178,7 +180,21 @@ "alt_text_description": "Description for people with visual impairments", "choose_focal_point": "Choose the focal point", "remove_media_confirmation": "Do you confirm the image removal?", - "download_flyer": "Download flyer" + "download_flyer": "Download flyer", + "where_advanced_options": "Place - Advanced options", + "where_advanced_options_description": "Define here additional place properties to the event", + "online_event_only": "Online event", + "event_only_online_label": "Event only online", + "online_event_only_help": "For online-only event, the default place name 'online' is applied", + "online_event_too": "Partecipate remotely", + "online_event_label": "Online locations", + "online_event_urls": "Online locations", + "online_event_fallback_urls": "Fallback links", + "additional_online_locations": "Additional online locations", + "additional_online_locations_help": "Online locations, for instance a url to a videconference room", + "address_geocoded_disclaimer": "Didn't you found the address or housenumber you are looking for? The OpenStreetMap project is open to contributions. If you have Android, we recommend StreetComplete ", + "address_overwrite": "Overwrite Address", + "address_overwrite_help": "Overwrite the geocoded address, for instance to add missing housenumber or a floor information" }, "admin": { "place_description": "If you have gotten the place or address wrong, you can change it.
All current and past events associated with this place will change address.", @@ -294,7 +310,10 @@ "tilelayer_test_button": "Test tilelayer", "tilelayer_test_success": "The tilelayer service at {service_name} is working", "tilelayer_test_error": "The tilelayer service is not reachable at {service_name}", - "geolocation": "Geolocation" + "geolocation": "Geolocation", + "allow_event_only_online": "Allow event only online", + "allow_event_also_online": "Allow event also online", + "search_address": "Search address" }, "auth": { "not_confirmed": "Not confirmed yet…", @@ -327,7 +346,9 @@ }, "validators": { "required": "{fieldName} is required", - "email": "Insert a valid email" + "email": "Insert a valid email", + "latitude": "Insert a valid latitude (-90 < latitude < 90)", + "longitude": "Insert a valid latitude (-180 < latitude < 180)" }, "about": "\n

Gancio is a shared agenda for local communities.

\n ", "oauth": { diff --git a/pages/add/_edit.vue b/pages/add/_edit.vue index b5162cf8..fcfc0553 100644 --- a/pages/add/_edit.vue +++ b/pages/add/_edit.vue @@ -30,7 +30,7 @@ v-container.container.pa-0.pa-md-3 //- Where v-col(cols=12) - WhereInput(ref='where' v-model='event.place') + WhereInput(ref='where' v-model='event.place' :event='event') //- When DateInput(ref='when' v-model='date' :event='event') @@ -125,6 +125,9 @@ export default { data.event.place.name = event.place.name data.event.place.address = event.place.address || '' + data.event.place.latitude = event.place.latitude || '' + data.event.place.longitude = event.place.longitude || '' + data.event.locations = event.locations || [] const from = dayjs.unix(event.start_datetime) const due = event.end_datetime && dayjs.unix(event.end_datetime) data.date = { @@ -154,6 +157,7 @@ export default { openImportDialog: false, event: { place: { name: '', address: '', latitude: null, longitude: null }, + locations: [], title: '', description: '', tags: [], @@ -237,6 +241,15 @@ export default { formData.append('place_address', this.event.place.address) formData.append('place_latitude', this.event.place.latitude) formData.append('place_longitude', this.event.place.longitude) + + if (this.event.locations.length) { + this.event.locations.forEach(location => formData.append('locations[]', location.url)) + } else { + // delete + this.event.locations = [] + formData.append('locations', this.event.locations ) + } + formData.append('description', this.event.description) formData.append('multidate', !!this.date.multidate) let [hour, minute] = this.date.fromHour.split(':') diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 244a2010..99ea6df0 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -36,6 +36,22 @@ v-container#event.pa-0.pa-sm-2 v-chip.p-category.ml-1.mt-1(v-for='tag in event.tags' small label color='primary' outlined :key='tag' :to='`/tag/${encodeURIComponent(tag)}`') {{tag}} + //- online events + v-divider(v-if='event.locations && event.locations.length') + v-card(v-if='event.locations && event.locations.length') + v-card-text.text-caption.pb-0(v-text="event.place.name === 'online' && $t('event.online_event_only') || $t('event.online_event_too') ") + v-list-item(target='_blank' :href='`${event.locations[0]}`') + v-list-item-icon + v-icon.my-auto(v-text='mdiMonitorAccount') + v-list-item-content.py-0 + v-text(small label v-text='`${event.locations[0]}`' outlined color='primary') + v-card.pb-2(v-if='event.locations.length > 1') + v-card-text.text-caption.pt-0.pb-0(v-text="$t('event.online_event_fallback_urls')") + v-list-item + v-list-item-content + v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" + v-bind:key="index" small label v-text="`${item}`" outlined ) + v-divider //- info & actions v-list(dense nav) @@ -172,7 +188,7 @@ const { htmlToText } = require('html-to-text') import { mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiClose, mdiMap, mdiEye, mdiEyeOff, mdiDelete, mdiRepeat, mdiLock, mdiFileDownloadOutline, - mdiCalendarExport, mdiCalendar, mdiContentCopy, mdiMapMarker, mdiChevronUp } from '@mdi/js' + mdiCalendarExport, mdiCalendar, mdiContentCopy, mdiMapMarker, mdiChevronUp, mdiMonitorAccount } from '@mdi/js' export default { name: 'Event', @@ -194,7 +210,7 @@ export default { data () { return { mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiCalendarExport, mdiCalendar, mdiFileDownloadOutline, - mdiMapMarker, mdiContentCopy, mdiClose, mdiDelete, mdiEye, mdiEyeOff, mdiRepeat, mdiLock, mdiMap, mdiChevronUp, + mdiMapMarker, mdiContentCopy, mdiClose, mdiDelete, mdiEye, mdiEyeOff, mdiRepeat, mdiLock, mdiMap, mdiChevronUp, mdiMonitorAccount, currentAttachment: 0, event: {}, diocane: '', diff --git a/plugins/validators.js b/plugins/validators.js index 8014b41c..b693ba74 100644 --- a/plugins/validators.js +++ b/plugins/validators.js @@ -12,6 +12,12 @@ export default ({ app }, inject) => { ], password: [ v => !!v || $t('validators.required', { fieldName: $t('common.password') }) + ], + latitude: [ + v => (v < 90 && v > -90) || $t('validators.latitude') + ], + longitude: [ + v => (v < 180 && v > -180) || $t('validators.longitude') ] } diff --git a/server/api/controller/event.js b/server/api/controller/event.js index 73592c04..4eabf379 100644 --- a/server/api/controller/event.js +++ b/server/api/controller/event.js @@ -401,6 +401,7 @@ const eventController = { multidate: body.multidate, start_datetime: body.start_datetime, end_datetime: body.end_datetime, + locations: body.locations, recurrent, // publish this event only if authenticated is_visible: !!req.user @@ -485,6 +486,7 @@ const eventController = { multidate: body.multidate, start_datetime: body.start_datetime || event.start_datetime, end_datetime: body.end_datetime || null, + locations: body.locations, recurrent } diff --git a/server/api/controller/settings.js b/server/api/controller/settings.js index 0645bb26..52067e5e 100644 --- a/server/api/controller/settings.js +++ b/server/api/controller/settings.js @@ -29,6 +29,8 @@ const defaultSettings = { allow_multidate_event: true, allow_recurrent_event: false, recurrent_event_visible: false, + allow_event_only_online: false, + allow_event_also_online: false, allow_geolocation: false, geocoding_provider_type: 'Nominatim', geocoding_provider: 'https://nominatim.openstreetmap.org/search', diff --git a/server/api/index.js b/server/api/index.js index 9fb8ca52..81036151 100644 --- a/server/api/index.js +++ b/server/api/index.js @@ -100,6 +100,7 @@ module.exports = () => { * @param {string} [query] - search for this string * @param {array} [tags] - List of tags * @param {array} [places] - List of places id + * @param {array} [locations] - List of locations * @param {integer} [max] - Limit events * @param {boolean} [show_recurrent] - Show also recurrent events (default: as choosen in admin settings) * @param {integer} [page] - Pagination diff --git a/server/api/models/event.js b/server/api/models/event.js index 362d9134..d94426e1 100644 --- a/server/api/models/event.js +++ b/server/api/models/event.js @@ -37,7 +37,8 @@ module.exports = (sequelize, DataTypes) => { is_visible: DataTypes.BOOLEAN, recurrent: DataTypes.JSON, likes: { type: DataTypes.JSON, defaultValue: [] }, - boost: { type: DataTypes.JSON, defaultValue: [] } + boost: { type: DataTypes.JSON, defaultValue: [] }, + locations: { type: DataTypes.JSON, defaultValue: [] } }) Event.prototype.toAP = function (username, locale, to = []) { diff --git a/server/helpers.js b/server/helpers.js index 6eab2b3c..e734d43d 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -97,7 +97,9 @@ module.exports = { tilelayer_provider: settings.tilelayer_provider, tilelayer_provider_attribution: settings.tilelayer_provider_attribution, footerLinks: settings.footerLinks, - about: settings.about + about: settings.about, + allow_event_only_online: settings.allow_event_only_online, + allow_event_also_online: settings.allow_event_also_online } // set user locale // res.locals.user_locale = settingsController.user_locale[res.locals.acceptedLocale] diff --git a/server/helpers/geolocation/index.js b/server/helpers/geolocation/index.js new file mode 100644 index 00000000..412083ec --- /dev/null +++ b/server/helpers/geolocation/index.js @@ -0,0 +1,17 @@ +const isoCountries = require('./isoCountries') +const nominatim = require('../../../server/services/geocoding/nominatim') +const photon = require('../../../server/services/geocoding/photon') + +// const geocodingProviders = [ nominatim, photon ] + +// const geolocation = { +// getGeocodingProvider(providerName) { +// geocodingProviders.forEach((item) => { +// if (item.commonName === settings.geocoding_provider_type) { +// return item +// } +// }) +// } +// } + +// module.exports = geolocation \ No newline at end of file diff --git a/server/helpers/geolocation/isoCountries.js b/server/helpers/geolocation/isoCountries.js new file mode 100644 index 00000000..0ba6e700 --- /dev/null +++ b/server/helpers/geolocation/isoCountries.js @@ -0,0 +1,987 @@ +// Iso conversions + +var isoCountries = [ + { + "code": "af", + "name": "Afghanistan" + }, + { + "code": "ax", + "name": "Aland Islands" + }, + { + "code": "al", + "name": "Albania" + }, + { + "code": "dz", + "name": "Algeria" + }, + { + "code": "as", + "name": "American Samoa" + }, + { + "code": "ad", + "name": "Andorra" + }, + { + "code": "ao", + "name": "Angola" + }, + { + "code": "ai", + "name": "Anguilla" + }, + { + "code": "aq", + "name": "Antarctica" + }, + { + "code": "ag", + "name": "Antigua And Barbuda" + }, + { + "code": "ar", + "name": "Argentina" + }, + { + "code": "am", + "name": "Armenia" + }, + { + "code": "aw", + "name": "Aruba" + }, + { + "code": "au", + "name": "Australia" + }, + { + "code": "at", + "name": "Austria" + }, + { + "code": "az", + "name": "Azerbaijan" + }, + { + "code": "bs", + "name": "Bahamas" + }, + { + "code": "bh", + "name": "Bahrain" + }, + { + "code": "bd", + "name": "Bangladesh" + }, + { + "code": "bb", + "name": "Barbados" + }, + { + "code": "by", + "name": "Belarus" + }, + { + "code": "be", + "name": "Belgium" + }, + { + "code": "bz", + "name": "Belize" + }, + { + "code": "bj", + "name": "Benin" + }, + { + "code": "bm", + "name": "Bermuda" + }, + { + "code": "bt", + "name": "Bhutan" + }, + { + "code": "bo", + "name": "Bolivia" + }, + { + "code": "ba", + "name": "Bosnia And Herzegovina" + }, + { + "code": "bw", + "name": "Botswana" + }, + { + "code": "bv", + "name": "Bouvet Island" + }, + { + "code": "br", + "name": "Brazil" + }, + { + "code": "io", + "name": "British Indian Ocean Territory" + }, + { + "code": "bn", + "name": "Brunei Darussalam" + }, + { + "code": "bg", + "name": "Bulgaria" + }, + { + "code": "bf", + "name": "Burkina Faso" + }, + { + "code": "bi", + "name": "Burundi" + }, + { + "code": "kh", + "name": "Cambodia" + }, + { + "code": "cm", + "name": "Cameroon" + }, + { + "code": "ca", + "name": "Canada" + }, + { + "code": "cv", + "name": "Cape Verde" + }, + { + "code": "ky", + "name": "Cayman Islands" + }, + { + "code": "cf", + "name": "Central African Republic" + }, + { + "code": "td", + "name": "Chad" + }, + { + "code": "cl", + "name": "Chile" + }, + { + "code": "cn", + "name": "China" + }, + { + "code": "cx", + "name": "Christmas Island" + }, + { + "code": "cc", + "name": "Cocos (Keeling) Islands" + }, + { + "code": "co", + "name": "Colombia" + }, + { + "code": "km", + "name": "Comoros" + }, + { + "code": "cg", + "name": "Congo" + }, + { + "code": "cd", + "name": "Congo, Democratic Republic" + }, + { + "code": "ck", + "name": "Cook Islands" + }, + { + "code": "cr", + "name": "Costa Rica" + }, + { + "code": "ci", + "name": "Cote D'Ivoire" + }, + { + "code": "hr", + "name": "Croatia" + }, + { + "code": "cu", + "name": "Cuba" + }, + { + "code": "cy", + "name": "Cyprus" + }, + { + "code": "cz", + "name": "Czech Republic" + }, + { + "code": "dk", + "name": "Denmark" + }, + { + "code": "dj", + "name": "Djibouti" + }, + { + "code": "dm", + "name": "Dominica" + }, + { + "code": "do", + "name": "Dominican Republic" + }, + { + "code": "ec", + "name": "Ecuador" + }, + { + "code": "eg", + "name": "Egypt" + }, + { + "code": "sv", + "name": "El Salvador" + }, + { + "code": "gq", + "name": "Equatorial Guinea" + }, + { + "code": "er", + "name": "Eritrea" + }, + { + "code": "ee", + "name": "Estonia" + }, + { + "code": "et", + "name": "Ethiopia" + }, + { + "code": "fk", + "name": "Falkland Islands (Malvinas)" + }, + { + "code": "fo", + "name": "Faroe Islands" + }, + { + "code": "fj", + "name": "Fiji" + }, + { + "code": "fi", + "name": "Finland" + }, + { + "code": "fr", + "name": "France" + }, + { + "code": "gf", + "name": "French Guiana" + }, + { + "code": "pf", + "name": "French Polynesia" + }, + { + "code": "tf", + "name": "French Southern Territories" + }, + { + "code": "ga", + "name": "Gabon" + }, + { + "code": "gm", + "name": "Gambia" + }, + { + "code": "ge", + "name": "Georgia" + }, + { + "code": "de", + "name": "Germany" + }, + { + "code": "gh", + "name": "Ghana" + }, + { + "code": "gi", + "name": "Gibraltar" + }, + { + "code": "gr", + "name": "Greece" + }, + { + "code": "gl", + "name": "Greenland" + }, + { + "code": "gd", + "name": "Grenada" + }, + { + "code": "gp", + "name": "Guadeloupe" + }, + { + "code": "gu", + "name": "Guam" + }, + { + "code": "gt", + "name": "Guatemala" + }, + { + "code": "gg", + "name": "Guernsey" + }, + { + "code": "gn", + "name": "Guinea" + }, + { + "code": "gw", + "name": "Guinea-Bissau" + }, + { + "code": "gy", + "name": "Guyana" + }, + { + "code": "ht", + "name": "Haiti" + }, + { + "code": "hm", + "name": "Heard Island & Mcdonald Islands" + }, + { + "code": "va", + "name": "Holy See (Vatican City State)" + }, + { + "code": "hn", + "name": "Honduras" + }, + { + "code": "hk", + "name": "Hong Kong" + }, + { + "code": "hu", + "name": "Hungary" + }, + { + "code": "is", + "name": "Iceland" + }, + { + "code": "in", + "name": "India" + }, + { + "code": "id", + "name": "Indonesia" + }, + { + "code": "ir", + "name": "Iran, Islamic Republic Of" + }, + { + "code": "iq", + "name": "Iraq" + }, + { + "code": "ie", + "name": "Ireland" + }, + { + "code": "im", + "name": "Isle Of Man" + }, + { + "code": "il", + "name": "Israel" + }, + { + "code": "it", + "name": "Italy" + }, + { + "code": "jm", + "name": "Jamaica" + }, + { + "code": "jp", + "name": "Japan" + }, + { + "code": "je", + "name": "Jersey" + }, + { + "code": "jo", + "name": "Jordan" + }, + { + "code": "kz", + "name": "Kazakhstan" + }, + { + "code": "ke", + "name": "Kenya" + }, + { + "code": "ki", + "name": "Kiribati" + }, + { + "code": "kr", + "name": "Korea" + }, + { + "code": "kw", + "name": "Kuwait" + }, + { + "code": "kg", + "name": "Kyrgyzstan" + }, + { + "code": "la", + "name": "Lao People's Democratic Republic" + }, + { + "code": "lv", + "name": "Latvia" + }, + { + "code": "lb", + "name": "Lebanon" + }, + { + "code": "ls", + "name": "Lesotho" + }, + { + "code": "lr", + "name": "Liberia" + }, + { + "code": "ly", + "name": "Libyan Arab Jamahiriya" + }, + { + "code": "li", + "name": "Liechtenstein" + }, + { + "code": "lt", + "name": "Lithuania" + }, + { + "code": "lu", + "name": "Luxembourg" + }, + { + "code": "mo", + "name": "Macao" + }, + { + "code": "mk", + "name": "Macedonia" + }, + { + "code": "mg", + "name": "Madagascar" + }, + { + "code": "mw", + "name": "Malawi" + }, + { + "code": "my", + "name": "Malaysia" + }, + { + "code": "mv", + "name": "Maldives" + }, + { + "code": "ml", + "name": "Mali" + }, + { + "code": "mt", + "name": "Malta" + }, + { + "code": "mh", + "name": "Marshall Islands" + }, + { + "code": "mq", + "name": "Martinique" + }, + { + "code": "mr", + "name": "Mauritania" + }, + { + "code": "mu", + "name": "Mauritius" + }, + { + "code": "yt", + "name": "Mayotte" + }, + { + "code": "mx", + "name": "Mexico" + }, + { + "code": "fm", + "name": "Micronesia, Federated States Of" + }, + { + "code": "md", + "name": "Moldova" + }, + { + "code": "mc", + "name": "Monaco" + }, + { + "code": "mn", + "name": "Mongolia" + }, + { + "code": "me", + "name": "Montenegro" + }, + { + "code": "ms", + "name": "Montserrat" + }, + { + "code": "ma", + "name": "Morocco" + }, + { + "code": "mz", + "name": "Mozambique" + }, + { + "code": "mm", + "name": "Myanmar" + }, + { + "code": "na", + "name": "Namibia" + }, + { + "code": "nr", + "name": "Nauru" + }, + { + "code": "np", + "name": "Nepal" + }, + { + "code": "nl", + "name": "Netherlands" + }, + { + "code": "an", + "name": "Netherlands Antilles" + }, + { + "code": "nc", + "name": "New Caledonia" + }, + { + "code": "nz", + "name": "New Zealand" + }, + { + "code": "ni", + "name": "Nicaragua" + }, + { + "code": "ne", + "name": "Niger" + }, + { + "code": "ng", + "name": "Nigeria" + }, + { + "code": "nu", + "name": "Niue" + }, + { + "code": "nf", + "name": "Norfolk Island" + }, + { + "code": "mp", + "name": "Northern Mariana Islands" + }, + { + "code": "no", + "name": "Norway" + }, + { + "code": "om", + "name": "Oman" + }, + { + "code": "pk", + "name": "Pakistan" + }, + { + "code": "pw", + "name": "Palau" + }, + { + "code": "ps", + "name": "Palestinian Territory, Occupied" + }, + { + "code": "pa", + "name": "Panama" + }, + { + "code": "pg", + "name": "Papua New Guinea" + }, + { + "code": "py", + "name": "Paraguay" + }, + { + "code": "pe", + "name": "Peru" + }, + { + "code": "ph", + "name": "Philippines" + }, + { + "code": "pn", + "name": "Pitcairn" + }, + { + "code": "pl", + "name": "Poland" + }, + { + "code": "pt", + "name": "Portugal" + }, + { + "code": "pr", + "name": "Puerto Rico" + }, + { + "code": "qa", + "name": "Qatar" + }, + { + "code": "re", + "name": "Reunion" + }, + { + "code": "ro", + "name": "Romania" + }, + { + "code": "ru", + "name": "Russian Federation" + }, + { + "code": "rw", + "name": "Rwanda" + }, + { + "code": "bl", + "name": "Saint Barthelemy" + }, + { + "code": "sh", + "name": "Saint Helena" + }, + { + "code": "kn", + "name": "Saint Kitts And Nevis" + }, + { + "code": "lc", + "name": "Saint Lucia" + }, + { + "code": "mf", + "name": "Saint Martin" + }, + { + "code": "pm", + "name": "Saint Pierre And Miquelon" + }, + { + "code": "vc", + "name": "Saint Vincent And Grenadines" + }, + { + "code": "ws", + "name": "Samoa" + }, + { + "code": "sm", + "name": "San Marino" + }, + { + "code": "st", + "name": "Sao Tome And Principe" + }, + { + "code": "sa", + "name": "Saudi Arabia" + }, + { + "code": "sn", + "name": "Senegal" + }, + { + "code": "rs", + "name": "Serbia" + }, + { + "code": "sc", + "name": "Seychelles" + }, + { + "code": "sl", + "name": "Sierra Leone" + }, + { + "code": "sg", + "name": "Singapore" + }, + { + "code": "sk", + "name": "Slovakia" + }, + { + "code": "si", + "name": "Slovenia" + }, + { + "code": "sb", + "name": "Solomon Islands" + }, + { + "code": "so", + "name": "Somalia" + }, + { + "code": "za", + "name": "South Africa" + }, + { + "code": "gs", + "name": "South Georgia And Sandwich Isl." + }, + { + "code": "es", + "name": "Spain" + }, + { + "code": "lk", + "name": "Sri Lanka" + }, + { + "code": "sd", + "name": "Sudan" + }, + { + "code": "sr", + "name": "Suriname" + }, + { + "code": "sj", + "name": "Svalbard And Jan Mayen" + }, + { + "code": "sz", + "name": "Swaziland" + }, + { + "code": "se", + "name": "Sweden" + }, + { + "code": "ch", + "name": "Switzerland" + }, + { + "code": "sy", + "name": "Syrian Arab Republic" + }, + { + "code": "tw", + "name": "Taiwan" + }, + { + "code": "tj", + "name": "Tajikistan" + }, + { + "code": "tz", + "name": "Tanzania" + }, + { + "code": "th", + "name": "Thailand" + }, + { + "code": "tl", + "name": "Timor-Leste" + }, + { + "code": "tg", + "name": "Togo" + }, + { + "code": "tk", + "name": "Tokelau" + }, + { + "code": "to", + "name": "Tonga" + }, + { + "code": "tt", + "name": "Trinidad And Tobago" + }, + { + "code": "tn", + "name": "Tunisia" + }, + { + "code": "tr", + "name": "Turkey" + }, + { + "code": "tm", + "name": "Turkmenistan" + }, + { + "code": "tc", + "name": "Turks And Caicos Islands" + }, + { + "code": "tv", + "name": "Tuvalu" + }, + { + "code": "ug", + "name": "Uganda" + }, + { + "code": "ua", + "name": "Ukraine" + }, + { + "code": "ae", + "name": "United Arab Emirates" + }, + { + "code": "gb", + "name": "United Kingdom" + }, + { + "code": "us", + "name": "United States" + }, + { + "code": "um", + "name": "United States Outlying Islands" + }, + { + "code": "uy", + "name": "Uruguay" + }, + { + "code": "uz", + "name": "Uzbekistan" + }, + { + "code": "vu", + "name": "Vanuatu" + }, + { + "code": "ve", + "name": "Venezuela" + }, + { + "code": "vn", + "name": "Viet Nam" + }, + { + "code": "vg", + "name": "Virgin Islands, British" + }, + { + "code": "vi", + "name": "Virgin Islands, U.S." + }, + { + "code": "wf", + "name": "Wallis And Futuna" + }, + { + "code": "eh", + "name": "Western Sahara" + }, + { + "code": "ye", + "name": "Yemen" + }, + { + "code": "zm", + "name": "Zambia" + }, + { + "code": "zw", + "name": "Zimbabwe" + } +] + + +module.exports = { isoCountries } diff --git a/server/migrations/20221215110244-event-locations.js b/server/migrations/20221215110244-event-locations.js new file mode 100644 index 00000000..469d1f25 --- /dev/null +++ b/server/migrations/20221215110244-event-locations.js @@ -0,0 +1,29 @@ +'use strict'; + +module.exports = { + async up (queryInterface, Sequelize) { + /** + * Add altering commands here. + * + * Example: + * await queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return Promise.all( + [ + await queryInterface.addColumn('events', 'locations', { type: Sequelize.JSON }), + ]) + }, + + async down (queryInterface, Sequelize) { + /** + * Add reverting commands here. + * + * Example: + * await queryInterface.dropTable('users'); + */ + return Promise.all( + [ + await queryInterface.removeColumn('events', 'locations'), + ]) + } +}; diff --git a/server/services/geocoding/nominatim.js b/server/services/geocoding/nominatim.js index 9e8b09fd..b6050bd6 100644 --- a/server/services/geocoding/nominatim.js +++ b/server/services/geocoding/nominatim.js @@ -1,5 +1,6 @@ const cache = require('memory-cache') const providerCache = new cache.Cache() +const get = require('lodash/get') const nominatim = { commonName: 'Nominatim', @@ -23,6 +24,39 @@ const nominatim = { } }, + /* + * Icons to nominatim `osm_type` and `class` conversion + */ + searchIcons_nominatim_osm_type: { + way: 'mdiRoadVariant', + house: 'mdiHome', + node: 'mdiMapMarker', + relation: 'mdiCityVariant', + }, + searchIcons_nominatim_class: { + mdiHome: ['place', 'amenity', 'shop', 'tourism', 'leisure', 'building'] + }, + + filterNameFromAddress: ['place', 'amenity', 'shop', 'tourism', 'leisure', 'building'], + + mapQueryResults (ret, addressList = []) { + if (ret && ret.length) { + addressList = ret.map(v => { + const name = get(v.namedetails, 'alt_name', get(v.namedetails, 'name')) + const address = this.filterNameFromAddress.includes(v.class) ? v.display_name.replace(name, '').replace(/^, ?/, '') : v.display_name.replace(/^, ?/, '') + return { + class: v.class, + type: v.osm_type, + lat: v.lat, + lon: v.lon, + name, + address + } + }) + } + return addressList + } + } module.exports = nominatim \ No newline at end of file diff --git a/server/services/geocoding/photon.js b/server/services/geocoding/photon.js index 4eced7db..4170c543 100644 --- a/server/services/geocoding/photon.js +++ b/server/services/geocoding/photon.js @@ -16,6 +16,51 @@ const photon = { q: details, limit: 3, } + }, + + /* + * Icons to nominatim `osm_type` and `class` conversion + */ + searchIcons_nominatim_osm_type: { + 'W': 'mdiRoadVariant', + 'N': 'mdiMapMarker', + 'R': 'mdiCityVariant', + }, + searchIcons_nominatim_class: { + mdiHome: ['amenity', 'shop', 'tourism', 'leisure', 'building'], + }, + + + fullAddressMapping: ['housenumber', 'street', 'locality', 'district', 'city', 'county', 'state', 'postcode', 'country'], + + mapQueryResults(ret, addressList = []) { + if (ret) { + addressList = ret.features.map(v => { + let pre_name = v.properties.name || v.properties.street || '' + let pre_address = '' + + this.fullAddressMapping.forEach((item, i) => { + let last = i == (this.fullAddressMapping.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 + } + }) + } + return addressList } } diff --git a/store/index.js b/store/index.js index 09a7b07e..e56592f8 100644 --- a/store/index.js +++ b/store/index.js @@ -13,6 +13,8 @@ export const state = () => ({ allow_multidate_event: true, allow_recurrent_event: true, recurrent_event_visible: false, + allow_event_only_online: false, + allow_event_also_online: false, allow_geolocation: false, geocoding_provider_type: '', geocoding_provider: '', diff --git a/yarn.lock b/yarn.lock index 10f97e71..3a042a45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3456,11 +3456,6 @@ buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" @@ -4999,13 +4994,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - editorconfig@^0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" @@ -7552,16 +7540,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonwebtoken@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" - integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== - dependencies: - jws "^3.2.2" - lodash "^4.17.21" - ms "^2.1.1" - semver "^7.3.8" - jsprim@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" @@ -7591,23 +7569,6 @@ juice@^8.0.0: slick "^1.12.2" web-resource-inliner "^6.0.1" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - keygrip@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" @@ -12687,10 +12648,8 @@ watchpack@^1.7.4: resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: - chokidar "^3.4.1" graceful-fs "^4.1.2" neo-async "^2.5.0" - watchpack-chokidar2 "^2.0.1" optionalDependencies: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1" From f298fe2fedcd11f2e3397c0cb77d7e85cc100cd5 Mon Sep 17 00:00:00 2001 From: sedum Date: Sun, 19 Feb 2023 17:59:28 +0100 Subject: [PATCH 02/13] conditional display online locations in event/_slug.vue and minor --- components/WhereInput.vue | 2 +- locales/en.json | 3 ++- pages/event/_slug.vue | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/WhereInput.vue b/components/WhereInput.vue index abf1625a..b27e17a1 100644 --- a/components/WhereInput.vue +++ b/components/WhereInput.vue @@ -27,7 +27,7 @@ v-row.mb-4 v-row.mx-0.my-0.align-center.justify-center v-combobox.mr-4(v-model="virtualLocations" v-if="settings.allow_event_only_online && value.name === 'online'" :prepend-icon='mdiLink' - :hint="`Online locations, for instance a url to a videconference room`" + :hint="$t('event.online_locations_help')" :label="$t('event.online_event_urls')" clearable chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint :delimiters="[',', ';', '; ']" diff --git a/locales/en.json b/locales/en.json index d9064a6b..77a82f6b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -194,7 +194,8 @@ "additional_online_locations_help": "Online locations, for instance a url to a videconference room", "address_geocoded_disclaimer": "Didn't you found the address or housenumber you are looking for? The OpenStreetMap project is open to contributions. If you have Android, we recommend StreetComplete ", "address_overwrite": "Overwrite Address", - "address_overwrite_help": "Overwrite the geocoded address, for instance to add missing housenumber or a floor information" + "address_overwrite_help": "Overwrite the geocoded address, for instance to add missing housenumber or a floor information", + "online_locations_help": "Online locations, for instance a url to a videconference room" }, "admin": { "place_description": "If you have gotten the place or address wrong, you can change it.
All current and past events associated with this place will change address.", diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 99ea6df0..559c78c3 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -37,15 +37,15 @@ v-container#event.pa-0.pa-sm-2 outlined :key='tag' :to='`/tag/${encodeURIComponent(tag)}`') {{tag}} //- online events - v-divider(v-if='event.locations && event.locations.length') - v-card(v-if='event.locations && event.locations.length') + v-divider(v-if='onlineSectionEnabled && event.locations && event.locations.length') + v-card(v-if='onlineSectionEnabled && event.locations && event.locations.length') v-card-text.text-caption.pb-0(v-text="event.place.name === 'online' && $t('event.online_event_only') || $t('event.online_event_too') ") v-list-item(target='_blank' :href='`${event.locations[0]}`') v-list-item-icon v-icon.my-auto(v-text='mdiMonitorAccount') v-list-item-content.py-0 v-text(small label v-text='`${event.locations[0]}`' outlined color='primary') - v-card.pb-2(v-if='event.locations.length > 1') + v-card.pb-2(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') v-card-text.text-caption.pt-0.pb-0(v-text="$t('event.online_event_fallback_urls')") v-list-item v-list-item-content @@ -207,7 +207,7 @@ export default { error({ statusCode: 404, message: 'Event not found' }) } }, - data () { + data ({$store}) { return { mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiCalendarExport, mdiCalendar, mdiFileDownloadOutline, mdiMapMarker, mdiContentCopy, mdiClose, mdiDelete, mdiEye, mdiEyeOff, mdiRepeat, mdiLock, mdiMap, mdiChevronUp, mdiMonitorAccount, @@ -217,7 +217,8 @@ export default { showEmbed: false, showResources: false, selectedResource: { data: { attachment: [] } }, - mapModal: false + mapModal: false, + onlineSectionEnabled: $store.state.settings.allow_event_only_online || $store.state.settings.allow_event_also_online } }, head () { From eefc0bb2df77695dd7979a7d3fca005be6966c8e Mon Sep 17 00:00:00 2001 From: sedum Date: Sun, 19 Feb 2023 23:19:16 +0100 Subject: [PATCH 03/13] refactor of whereInput, move geolocation related code to whereInputAdvanced --- components/WhereInput.vue | 113 +++--------------------------- components/WhereInputAdvanced.vue | 105 +++++++++++++++++++++++---- pages/add/_edit.vue | 7 +- pages/event/_slug.vue | 2 +- 4 files changed, 108 insertions(+), 119 deletions(-) diff --git a/components/WhereInput.vue b/components/WhereInput.vue index b27e17a1..0722f0a6 100644 --- a/components/WhereInput.vue +++ b/components/WhereInput.vue @@ -39,43 +39,18 @@ v-row.mb-4 template(v-slot:append) v-icon(v-text='mdiCog' :disabled='!value.name' @click="whereInputAdvancedDialog = true") - v-text-field.mr-4(v-if="!settings.allow_geolocation && value.name !== 'online'" + v-text-field.mr-4(v-if="value.name !== 'online'" ref='address' + v-model='value.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") - template(v-slot:append v-if="settings.allow_event_also_online && place.name !== 'online'") - v-icon(v-text='mdiCog' :disabled='!value.name' @click="whereInputAdvancedDialog = true") - - v-combobox(ref='address' v-if="settings.allow_geolocation && value.name !== 'online' || (!settings.allow_event_only_online && value.name === 'online')" - :prepend-icon='mdiMapSearch' - :disabled='disableAddress' - @input.native='searchAddress' - :label="$t('common.address')" - :rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]" - :value='value.address' - item-text='address' - persistent-hint hide-no-data clearable no-filter - :loading='loading' - @change='selectAddress' - @focus='searchAddress' - :items="addressList" - :hint="$t('event.address_description_osm')") - template(v-slot:message="{message, 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)') - v-list-item-content(two-line v-if='item') - v-list-item-title(v-text='item.name') - v-list-item-subtitle(v-text='`${item.address}`') - template(v-slot:append v-if="settings.allow_event_also_online || settings.allow_geolocation") - v-icon(v-text='mdiCog' :disabled='!value.name || (!value.isNew && !settings.allow_event_also_online) ' @click="whereInputAdvancedDialog = true") + persistent-hint) + template(v-slot:append v-if="!hideWhereInputAdvancedDialogButton") + v-icon(v-text='mdiCog' :disabled='!(value.name && settings.allow_event_also_online) && !(value.isNew && settings.allow_geolocation)' + @click="whereInputAdvancedDialog = true") v-dialog(v-model='whereInputAdvancedDialog' :key="whereAdvancedId" destroy-on-close max-width='700px' :fullscreen='$vuetify.breakpoint.xsOnly' dense) WhereInputAdvanced(ref='whereAdvanced' :place.sync='value' :event='event' @close='whereInputAdvancedDialog = false && this.$refs.address.blur()' @@ -88,13 +63,11 @@ v-row.mb-4 diff --git a/pages/add/_edit.vue b/pages/add/_edit.vue index 1d321b89..3ab62f6f 100644 --- a/pages/add/_edit.vue +++ b/pages/add/_edit.vue @@ -239,8 +239,11 @@ export default { } formData.append('place_name', this.event.place.name.trim()) formData.append('place_address', this.event.place.address) - formData.append('place_latitude', this.event.place.latitude) - formData.append('place_longitude', this.event.place.longitude) + + if (this.settings.allow_geolocation) { + formData.append('place_latitude', this.event.place.latitude || '') + formData.append('place_longitude', this.event.place.longitude || '') + } if (this.event.locations.length) { this.event.locations.forEach(location => formData.append('locations[]', location.url)) diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 559c78c3..96f32f49 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -44,7 +44,7 @@ v-container#event.pa-0.pa-sm-2 v-list-item-icon v-icon.my-auto(v-text='mdiMonitorAccount') v-list-item-content.py-0 - v-text(small label v-text='`${event.locations[0]}`' outlined color='primary') + v-list-item-title.text-caption(v-text='`${event.locations[0]}`') v-card.pb-2(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') v-card-text.text-caption.pt-0.pb-0(v-text="$t('event.online_event_fallback_urls')") v-list-item From 7522e811fae8bab41d0a4b9d31e8353328891c96 Mon Sep 17 00:00:00 2001 From: sedum Date: Sun, 19 Feb 2023 23:31:12 +0100 Subject: [PATCH 04/13] minor on locales --- components/WhereInputAdvanced.vue | 2 +- components/admin/Places.vue | 2 +- locales/en.json | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/WhereInputAdvanced.vue b/components/WhereInputAdvanced.vue index b5766490..e50a42b5 100644 --- a/components/WhereInputAdvanced.vue +++ b/components/WhereInputAdvanced.vue @@ -28,7 +28,7 @@ v-card v-combobox(ref='geocodedAddress' v-if="settings.allow_geolocation && place.name !== 'online' || (!settings.allow_event_only_online && place.name === 'online')" :prepend-icon='mdiMapSearch' @input.native='searchAddress' - :label="$t('common.address')" + :label="$t('common.search_address')" :value='place.geocodedAddress' item-text='address' persistent-hint hide-no-data clearable no-filter diff --git a/components/admin/Places.vue b/components/admin/Places.vue index 7edf1204..b201916a 100644 --- a/components/admin/Places.vue +++ b/components/admin/Places.vue @@ -30,7 +30,7 @@ v-container :disabled="!(settings.allow_geolocation && place.name !== 'online')" :prepend-icon='mdiMapSearch' @input.native='searchAddress' - :label="$t('admin.search_address')" + :label="$t('common.search_address')" :value='place.latitude && place.longitude && place.geocodedAddress' persistent-hint hide-no-data clearable no-filter :loading='loading' diff --git a/locales/en.json b/locales/en.json index 77a82f6b..4892d357 100644 --- a/locales/en.json +++ b/locales/en.json @@ -100,7 +100,8 @@ "admin_actions": "Admin actions", "recurring_event_actions": "Recurring event actions", "latitude": "Latitude", - "longitude": "Longitude" + "longitude": "Longitude", + "search_address": "Search address" }, "login": { "description": "By logging in you can publish new events.", @@ -313,8 +314,7 @@ "tilelayer_test_error": "The tilelayer service is not reachable at {service_name}", "geolocation": "Geolocation", "allow_event_only_online": "Allow event only online", - "allow_event_also_online": "Allow event also online", - "search_address": "Search address" + "allow_event_also_online": "Allow event also online" }, "auth": { "not_confirmed": "Not confirmed yet…", From 8efeda085a86c326e5d548ec6e3ca903136a2bac Mon Sep 17 00:00:00 2001 From: sedum Date: Mon, 20 Feb 2023 07:05:21 +0100 Subject: [PATCH 05/13] continue refactor of geocoding services, improved locale, fixes on mapEdit --- components/MapEdit.vue | 4 +- components/WhereInput.vue | 22 +- components/WhereInputAdvanced.vue | 60 +- components/admin/Geolocation.vue | 2 +- components/admin/Places.vue | 51 +- locales/en.json | 11 +- pages/event/_slug.vue | 26 +- server/helpers/geolocation.js | 987 ------------------------- server/helpers/geolocation/index.js | 25 +- server/services/geocoding/nominatim.js | 14 +- server/services/geocoding/photon.js | 15 +- 11 files changed, 117 insertions(+), 1100 deletions(-) delete mode 100644 server/helpers/geolocation.js diff --git a/components/MapEdit.vue b/components/MapEdit.vue index e6cf1bec..c60b2d39 100644 --- a/components/MapEdit.vue +++ b/components/MapEdit.vue @@ -54,7 +54,9 @@ export default { }); setTimeout(() => { - this.$refs.map.mapObject.invalidateSize(); + if (this.$refs.map && this.$refs.map.mapObject ) { + this.$refs.map.mapObject.invalidateSize(); + } }, 200); } } diff --git a/components/WhereInput.vue b/components/WhereInput.vue index 0722f0a6..481889b8 100644 --- a/components/WhereInput.vue +++ b/components/WhereInput.vue @@ -28,7 +28,7 @@ v-row.mb-4 v-combobox.mr-4(v-model="virtualLocations" v-if="settings.allow_event_only_online && value.name === 'online'" :prepend-icon='mdiLink' :hint="$t('event.online_locations_help')" - :label="$t('event.online_event_urls')" + :label="$t('event.online_locations_url')" clearable chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint :delimiters="[',', ';', '; ']" :items="virtualLocations" @@ -55,7 +55,7 @@ v-row.mb-4 v-dialog(v-model='whereInputAdvancedDialog' :key="whereAdvancedId" destroy-on-close max-width='700px' :fullscreen='$vuetify.breakpoint.xsOnly' dense) WhereInputAdvanced(ref='whereAdvanced' :place.sync='value' :event='event' @close='whereInputAdvancedDialog = false && this.$refs.address.blur()' :virtualLocations.sync="virtualLocations" - :online_event_only_value.sync='online_event_only' + :event_only_online_value.sync='event_only_online' @update:onlineEvent="changeOnlineEvent" @update:virtualLocations="selectLocations" ) @@ -86,7 +86,7 @@ export default { whereInputAdvancedDialog: false, hideWhereInputAdvancedDialogButton: !$store.state.settings.allow_event_also_online && !$store.state.settings.allow_geolocation, virtualLocations: this.event.locations || [], - online_event_only: (this.value.name === 'online') ? true : false, + event_only_online: (this.value.name === 'online') ? true : false, whereAdvancedId: 1 } }, @@ -135,7 +135,7 @@ export default { }, 200), selectPlace (p) { // force online events under place: online address: online - this.online_event_only = false + this.event_only_online = false this.place.isNew = false this.whereAdvancedId++ @@ -150,7 +150,7 @@ export default { } this.place.id = p.id if (this.settings.allow_event_only_online && this.place.name === 'online') { - this.online_event_only = true + this.event_only_online = true } this.disableAddress = true } else { // this is a new place @@ -184,6 +184,10 @@ export default { }, selectLocations () { this.event.locations = [] + // Insert up to 3 online location: the main one and 2 fallback + if (this.virtualLocations && this.virtualLocations.length > 3) { + this.$nextTick(() => this.virtualLocations.pop()) + } this.virtualLocations && this.virtualLocations.forEach((item, i) => { if (!item.startsWith('http')) { this.virtualLocations[i] = `https://${item}` @@ -192,10 +196,10 @@ export default { }) }, changeOnlineEvent(v) { - this.online_event_only = v - // console.log(this.online_event_only) - if (this.online_event_only) { this.place.name = this.place.address = 'online' } - if (!this.online_event_only) { this.place.name = this.place.address = '' } + this.event_only_online = v + // console.log(this.event_only_online) + if (this.event_only_online) { this.place.name = this.place.address = 'online' } + if (!this.event_only_online) { this.place.name = this.place.address = '' } this.place.latitude = null this.place.longitude = null diff --git a/components/WhereInputAdvanced.vue b/components/WhereInputAdvanced.vue index e50a42b5..3f396629 100644 --- a/components/WhereInputAdvanced.vue +++ b/components/WhereInputAdvanced.vue @@ -4,11 +4,11 @@ v-card v-card-subtitle {{ $t('event.where_advanced_options_description') }} v-card-text(v-if='settings.allow_event_also_online') - v-switch.mt-0.mb-4(v-model='online_event_only_update' + v-switch.mt-0.mb-4(v-model='event_only_online_update' v-if='settings.allow_event_only_online' persistent-hint :label="$t('event.event_only_online_label')" - :hint="$t('event.online_event_only_help')") + :hint="$t('event.event_only_online_help')") v-combobox.mt-0.mb-0.mr-4.my-5(v-model="virtualLocations_update" v-if="place.name !== 'online' && settings.allow_event_also_online" @@ -69,19 +69,19 @@ v-card diff --git a/locales/en.json b/locales/en.json index 4892d357..7176098f 100644 --- a/locales/en.json +++ b/locales/en.json @@ -184,13 +184,12 @@ "download_flyer": "Download flyer", "where_advanced_options": "Place - Advanced options", "where_advanced_options_description": "Define here additional place properties to the event", - "online_event_only": "Online event", + "event_only_online": "Online event", "event_only_online_label": "Event only online", - "online_event_only_help": "For online-only event, the default place name 'online' is applied", - "online_event_too": "Partecipate remotely", - "online_event_label": "Online locations", - "online_event_urls": "Online locations", - "online_event_fallback_urls": "Fallback links", + "event_only_online_help": "For online-only event, the default place name 'online' is applied", + "event_also_online": "Partecipate remotely", + "online_locations_url": "Online locations", + "online_locations_fallback_urls": "Fallback links", "additional_online_locations": "Additional online locations", "additional_online_locations_help": "Online locations, for instance a url to a videconference room", "address_geocoded_disclaimer": "Didn't you found the address or housenumber you are looking for? The OpenStreetMap project is open to contributions. If you have Android, we recommend StreetComplete ", diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 96f32f49..0ee8b377 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -38,19 +38,19 @@ v-container#event.pa-0.pa-sm-2 //- online events v-divider(v-if='onlineSectionEnabled && event.locations && event.locations.length') - v-card(v-if='onlineSectionEnabled && event.locations && event.locations.length') - v-card-text.text-caption.pb-0(v-text="event.place.name === 'online' && $t('event.online_event_only') || $t('event.online_event_too') ") - v-list-item(target='_blank' :href='`${event.locations[0]}`') - v-list-item-icon - v-icon.my-auto(v-text='mdiMonitorAccount') - v-list-item-content.py-0 - v-list-item-title.text-caption(v-text='`${event.locations[0]}`') - v-card.pb-2(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') - v-card-text.text-caption.pt-0.pb-0(v-text="$t('event.online_event_fallback_urls')") - v-list-item - v-list-item-content - v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" - v-bind:key="index" small label v-text="`${item}`" outlined ) + v-card-text.text-caption.pb-0(v-if='onlineSectionEnabled && event.locations && event.locations.length' + v-text="event.place.name === 'online' && $t('event.event_only_online') || $t('event.event_also_online') ") + v-list-item(target='_blank' :href='`${event.locations[0]}`') + v-list-item-icon + v-icon.my-auto(v-text='mdiMonitorAccount') + v-list-item-content.py-0 + v-list-item-title.text-caption(v-text='`${event.locations[0]}`') + v-card-text.text-caption.pt-0.pb-0(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1' + v-text="$t('event.online_locations_fallback_urls')") + v-list-item + v-list-item-content + v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" + v-bind:key="index" small label v-text="`${item}`" outlined ) v-divider //- info & actions diff --git a/server/helpers/geolocation.js b/server/helpers/geolocation.js deleted file mode 100644 index e1edaa88..00000000 --- a/server/helpers/geolocation.js +++ /dev/null @@ -1,987 +0,0 @@ -// Iso conversions - -var isoCountries = [ - { - "code": "af", - "name": "Afghanistan" - }, - { - "code": "ax", - "name": "Aland Islands" - }, - { - "code": "al", - "name": "Albania" - }, - { - "code": "dz", - "name": "Algeria" - }, - { - "code": "as", - "name": "American Samoa" - }, - { - "code": "ad", - "name": "Andorra" - }, - { - "code": "ao", - "name": "Angola" - }, - { - "code": "ai", - "name": "Anguilla" - }, - { - "code": "aq", - "name": "Antarctica" - }, - { - "code": "ag", - "name": "Antigua And Barbuda" - }, - { - "code": "ar", - "name": "Argentina" - }, - { - "code": "am", - "name": "Armenia" - }, - { - "code": "aw", - "name": "Aruba" - }, - { - "code": "au", - "name": "Australia" - }, - { - "code": "at", - "name": "Austria" - }, - { - "code": "az", - "name": "Azerbaijan" - }, - { - "code": "bs", - "name": "Bahamas" - }, - { - "code": "bh", - "name": "Bahrain" - }, - { - "code": "bd", - "name": "Bangladesh" - }, - { - "code": "bb", - "name": "Barbados" - }, - { - "code": "by", - "name": "Belarus" - }, - { - "code": "be", - "name": "Belgium" - }, - { - "code": "bz", - "name": "Belize" - }, - { - "code": "bj", - "name": "Benin" - }, - { - "code": "bm", - "name": "Bermuda" - }, - { - "code": "bt", - "name": "Bhutan" - }, - { - "code": "bo", - "name": "Bolivia" - }, - { - "code": "ba", - "name": "Bosnia And Herzegovina" - }, - { - "code": "bw", - "name": "Botswana" - }, - { - "code": "bv", - "name": "Bouvet Island" - }, - { - "code": "br", - "name": "Brazil" - }, - { - "code": "io", - "name": "British Indian Ocean Territory" - }, - { - "code": "bn", - "name": "Brunei Darussalam" - }, - { - "code": "bg", - "name": "Bulgaria" - }, - { - "code": "bf", - "name": "Burkina Faso" - }, - { - "code": "bi", - "name": "Burundi" - }, - { - "code": "kh", - "name": "Cambodia" - }, - { - "code": "cm", - "name": "Cameroon" - }, - { - "code": "ca", - "name": "Canada" - }, - { - "code": "cv", - "name": "Cape Verde" - }, - { - "code": "ky", - "name": "Cayman Islands" - }, - { - "code": "cf", - "name": "Central African Republic" - }, - { - "code": "td", - "name": "Chad" - }, - { - "code": "cl", - "name": "Chile" - }, - { - "code": "cn", - "name": "China" - }, - { - "code": "cx", - "name": "Christmas Island" - }, - { - "code": "cc", - "name": "Cocos (Keeling) Islands" - }, - { - "code": "co", - "name": "Colombia" - }, - { - "code": "km", - "name": "Comoros" - }, - { - "code": "cg", - "name": "Congo" - }, - { - "code": "cd", - "name": "Congo, Democratic Republic" - }, - { - "code": "ck", - "name": "Cook Islands" - }, - { - "code": "cr", - "name": "Costa Rica" - }, - { - "code": "ci", - "name": "Cote D'Ivoire" - }, - { - "code": "hr", - "name": "Croatia" - }, - { - "code": "cu", - "name": "Cuba" - }, - { - "code": "cy", - "name": "Cyprus" - }, - { - "code": "cz", - "name": "Czech Republic" - }, - { - "code": "dk", - "name": "Denmark" - }, - { - "code": "dj", - "name": "Djibouti" - }, - { - "code": "dm", - "name": "Dominica" - }, - { - "code": "do", - "name": "Dominican Republic" - }, - { - "code": "ec", - "name": "Ecuador" - }, - { - "code": "eg", - "name": "Egypt" - }, - { - "code": "sv", - "name": "El Salvador" - }, - { - "code": "gq", - "name": "Equatorial Guinea" - }, - { - "code": "er", - "name": "Eritrea" - }, - { - "code": "ee", - "name": "Estonia" - }, - { - "code": "et", - "name": "Ethiopia" - }, - { - "code": "fk", - "name": "Falkland Islands (Malvinas)" - }, - { - "code": "fo", - "name": "Faroe Islands" - }, - { - "code": "fj", - "name": "Fiji" - }, - { - "code": "fi", - "name": "Finland" - }, - { - "code": "fr", - "name": "France" - }, - { - "code": "gf", - "name": "French Guiana" - }, - { - "code": "pf", - "name": "French Polynesia" - }, - { - "code": "tf", - "name": "French Southern Territories" - }, - { - "code": "ga", - "name": "Gabon" - }, - { - "code": "gm", - "name": "Gambia" - }, - { - "code": "ge", - "name": "Georgia" - }, - { - "code": "de", - "name": "Germany" - }, - { - "code": "gh", - "name": "Ghana" - }, - { - "code": "gi", - "name": "Gibraltar" - }, - { - "code": "gr", - "name": "Greece" - }, - { - "code": "gl", - "name": "Greenland" - }, - { - "code": "gd", - "name": "Grenada" - }, - { - "code": "gp", - "name": "Guadeloupe" - }, - { - "code": "gu", - "name": "Guam" - }, - { - "code": "gt", - "name": "Guatemala" - }, - { - "code": "gg", - "name": "Guernsey" - }, - { - "code": "gn", - "name": "Guinea" - }, - { - "code": "gw", - "name": "Guinea-Bissau" - }, - { - "code": "gy", - "name": "Guyana" - }, - { - "code": "ht", - "name": "Haiti" - }, - { - "code": "hm", - "name": "Heard Island & Mcdonald Islands" - }, - { - "code": "va", - "name": "Holy See (Vatican City State)" - }, - { - "code": "hn", - "name": "Honduras" - }, - { - "code": "hk", - "name": "Hong Kong" - }, - { - "code": "hu", - "name": "Hungary" - }, - { - "code": "is", - "name": "Iceland" - }, - { - "code": "in", - "name": "India" - }, - { - "code": "id", - "name": "Indonesia" - }, - { - "code": "ir", - "name": "Iran, Islamic Republic Of" - }, - { - "code": "iq", - "name": "Iraq" - }, - { - "code": "ie", - "name": "Ireland" - }, - { - "code": "im", - "name": "Isle Of Man" - }, - { - "code": "il", - "name": "Israel" - }, - { - "code": "it", - "name": "Italy" - }, - { - "code": "jm", - "name": "Jamaica" - }, - { - "code": "jp", - "name": "Japan" - }, - { - "code": "je", - "name": "Jersey" - }, - { - "code": "jo", - "name": "Jordan" - }, - { - "code": "kz", - "name": "Kazakhstan" - }, - { - "code": "ke", - "name": "Kenya" - }, - { - "code": "ki", - "name": "Kiribati" - }, - { - "code": "kr", - "name": "Korea" - }, - { - "code": "kw", - "name": "Kuwait" - }, - { - "code": "kg", - "name": "Kyrgyzstan" - }, - { - "code": "la", - "name": "Lao People's Democratic Republic" - }, - { - "code": "lv", - "name": "Latvia" - }, - { - "code": "lb", - "name": "Lebanon" - }, - { - "code": "ls", - "name": "Lesotho" - }, - { - "code": "lr", - "name": "Liberia" - }, - { - "code": "ly", - "name": "Libyan Arab Jamahiriya" - }, - { - "code": "li", - "name": "Liechtenstein" - }, - { - "code": "lt", - "name": "Lithuania" - }, - { - "code": "lu", - "name": "Luxembourg" - }, - { - "code": "mo", - "name": "Macao" - }, - { - "code": "mk", - "name": "Macedonia" - }, - { - "code": "mg", - "name": "Madagascar" - }, - { - "code": "mw", - "name": "Malawi" - }, - { - "code": "my", - "name": "Malaysia" - }, - { - "code": "mv", - "name": "Maldives" - }, - { - "code": "ml", - "name": "Mali" - }, - { - "code": "mt", - "name": "Malta" - }, - { - "code": "mh", - "name": "Marshall Islands" - }, - { - "code": "mq", - "name": "Martinique" - }, - { - "code": "mr", - "name": "Mauritania" - }, - { - "code": "mu", - "name": "Mauritius" - }, - { - "code": "yt", - "name": "Mayotte" - }, - { - "code": "mx", - "name": "Mexico" - }, - { - "code": "fm", - "name": "Micronesia, Federated States Of" - }, - { - "code": "md", - "name": "Moldova" - }, - { - "code": "mc", - "name": "Monaco" - }, - { - "code": "mn", - "name": "Mongolia" - }, - { - "code": "me", - "name": "Montenegro" - }, - { - "code": "ms", - "name": "Montserrat" - }, - { - "code": "ma", - "name": "Morocco" - }, - { - "code": "mz", - "name": "Mozambique" - }, - { - "code": "mm", - "name": "Myanmar" - }, - { - "code": "na", - "name": "Namibia" - }, - { - "code": "nr", - "name": "Nauru" - }, - { - "code": "np", - "name": "Nepal" - }, - { - "code": "nl", - "name": "Netherlands" - }, - { - "code": "an", - "name": "Netherlands Antilles" - }, - { - "code": "nc", - "name": "New Caledonia" - }, - { - "code": "nz", - "name": "New Zealand" - }, - { - "code": "ni", - "name": "Nicaragua" - }, - { - "code": "ne", - "name": "Niger" - }, - { - "code": "ng", - "name": "Nigeria" - }, - { - "code": "nu", - "name": "Niue" - }, - { - "code": "nf", - "name": "Norfolk Island" - }, - { - "code": "mp", - "name": "Northern Mariana Islands" - }, - { - "code": "no", - "name": "Norway" - }, - { - "code": "om", - "name": "Oman" - }, - { - "code": "pk", - "name": "Pakistan" - }, - { - "code": "pw", - "name": "Palau" - }, - { - "code": "ps", - "name": "Palestinian Territory, Occupied" - }, - { - "code": "pa", - "name": "Panama" - }, - { - "code": "pg", - "name": "Papua New Guinea" - }, - { - "code": "py", - "name": "Paraguay" - }, - { - "code": "pe", - "name": "Peru" - }, - { - "code": "ph", - "name": "Philippines" - }, - { - "code": "pn", - "name": "Pitcairn" - }, - { - "code": "pl", - "name": "Poland" - }, - { - "code": "pt", - "name": "Portugal" - }, - { - "code": "pr", - "name": "Puerto Rico" - }, - { - "code": "qa", - "name": "Qatar" - }, - { - "code": "re", - "name": "Reunion" - }, - { - "code": "ro", - "name": "Romania" - }, - { - "code": "ru", - "name": "Russian Federation" - }, - { - "code": "rw", - "name": "Rwanda" - }, - { - "code": "bl", - "name": "Saint Barthelemy" - }, - { - "code": "sh", - "name": "Saint Helena" - }, - { - "code": "kn", - "name": "Saint Kitts And Nevis" - }, - { - "code": "lc", - "name": "Saint Lucia" - }, - { - "code": "mf", - "name": "Saint Martin" - }, - { - "code": "pm", - "name": "Saint Pierre And Miquelon" - }, - { - "code": "vc", - "name": "Saint Vincent And Grenadines" - }, - { - "code": "ws", - "name": "Samoa" - }, - { - "code": "sm", - "name": "San Marino" - }, - { - "code": "st", - "name": "Sao Tome And Principe" - }, - { - "code": "sa", - "name": "Saudi Arabia" - }, - { - "code": "sn", - "name": "Senegal" - }, - { - "code": "rs", - "name": "Serbia" - }, - { - "code": "sc", - "name": "Seychelles" - }, - { - "code": "sl", - "name": "Sierra Leone" - }, - { - "code": "sg", - "name": "Singapore" - }, - { - "code": "sk", - "name": "Slovakia" - }, - { - "code": "si", - "name": "Slovenia" - }, - { - "code": "sb", - "name": "Solomon Islands" - }, - { - "code": "so", - "name": "Somalia" - }, - { - "code": "za", - "name": "South Africa" - }, - { - "code": "gs", - "name": "South Georgia And Sandwich Isl." - }, - { - "code": "es", - "name": "Spain" - }, - { - "code": "lk", - "name": "Sri Lanka" - }, - { - "code": "sd", - "name": "Sudan" - }, - { - "code": "sr", - "name": "Suriname" - }, - { - "code": "sj", - "name": "Svalbard And Jan Mayen" - }, - { - "code": "sz", - "name": "Swaziland" - }, - { - "code": "se", - "name": "Sweden" - }, - { - "code": "ch", - "name": "Switzerland" - }, - { - "code": "sy", - "name": "Syrian Arab Republic" - }, - { - "code": "tw", - "name": "Taiwan" - }, - { - "code": "tj", - "name": "Tajikistan" - }, - { - "code": "tz", - "name": "Tanzania" - }, - { - "code": "th", - "name": "Thailand" - }, - { - "code": "tl", - "name": "Timor-Leste" - }, - { - "code": "tg", - "name": "Togo" - }, - { - "code": "tk", - "name": "Tokelau" - }, - { - "code": "to", - "name": "Tonga" - }, - { - "code": "tt", - "name": "Trinidad And Tobago" - }, - { - "code": "tn", - "name": "Tunisia" - }, - { - "code": "tr", - "name": "Turkey" - }, - { - "code": "tm", - "name": "Turkmenistan" - }, - { - "code": "tc", - "name": "Turks And Caicos Islands" - }, - { - "code": "tv", - "name": "Tuvalu" - }, - { - "code": "ug", - "name": "Uganda" - }, - { - "code": "ua", - "name": "Ukraine" - }, - { - "code": "ae", - "name": "United Arab Emirates" - }, - { - "code": "gb", - "name": "United Kingdom" - }, - { - "code": "us", - "name": "United States" - }, - { - "code": "um", - "name": "United States Outlying Islands" - }, - { - "code": "uy", - "name": "Uruguay" - }, - { - "code": "uz", - "name": "Uzbekistan" - }, - { - "code": "vu", - "name": "Vanuatu" - }, - { - "code": "ve", - "name": "Venezuela" - }, - { - "code": "vn", - "name": "Viet Nam" - }, - { - "code": "vg", - "name": "Virgin Islands, British" - }, - { - "code": "vi", - "name": "Virgin Islands, U.S." - }, - { - "code": "wf", - "name": "Wallis And Futuna" - }, - { - "code": "eh", - "name": "Western Sahara" - }, - { - "code": "ye", - "name": "Yemen" - }, - { - "code": "zm", - "name": "Zambia" - }, - { - "code": "zw", - "name": "Zimbabwe" - } - ] - - -module.exports = { isoCountries } diff --git a/server/helpers/geolocation/index.js b/server/helpers/geolocation/index.js index 412083ec..f8beaf3d 100644 --- a/server/helpers/geolocation/index.js +++ b/server/helpers/geolocation/index.js @@ -1,17 +1,18 @@ -const isoCountries = require('./isoCountries') const nominatim = require('../../../server/services/geocoding/nominatim') const photon = require('../../../server/services/geocoding/photon') -// const geocodingProviders = [ nominatim, photon ] +const geocodingProviders = [ nominatim, photon ] -// const geolocation = { -// getGeocodingProvider(providerName) { -// geocodingProviders.forEach((item) => { -// if (item.commonName === settings.geocoding_provider_type) { -// return item -// } -// }) -// } -// } +const geolocation = { + getGeocodingProvider(providerName) { + let geocodingProvider + geocodingProviders.forEach((item) => { + if (item.commonName === providerName) { + geocodingProvider = item + } + }) + return geocodingProvider + } +} -// module.exports = geolocation \ No newline at end of file +module.exports = geolocation \ No newline at end of file diff --git a/server/services/geocoding/nominatim.js b/server/services/geocoding/nominatim.js index b6050bd6..ffac8693 100644 --- a/server/services/geocoding/nominatim.js +++ b/server/services/geocoding/nominatim.js @@ -24,7 +24,7 @@ const nominatim = { } }, - /* + /** * Icons to nominatim `osm_type` and `class` conversion */ searchIcons_nominatim_osm_type: { @@ -33,10 +33,18 @@ const nominatim = { node: 'mdiMapMarker', relation: 'mdiCityVariant', }, - searchIcons_nominatim_class: { - mdiHome: ['place', 'amenity', 'shop', 'tourism', 'leisure', 'building'] + searchIcons_nominatim_class: ['place', 'amenity', 'shop', 'tourism', 'leisure', 'building'], + + loadResultIcon (item) { + if (this.searchIcons_nominatim_class.includes(item.class)) { + return 'mdiHome' + } + return this.searchIcons_nominatim_osm_type[item.type] }, + /** + * Map results from provider + */ filterNameFromAddress: ['place', 'amenity', 'shop', 'tourism', 'leisure', 'building'], mapQueryResults (ret, addressList = []) { diff --git a/server/services/geocoding/photon.js b/server/services/geocoding/photon.js index 4170c543..dce5e9a5 100644 --- a/server/services/geocoding/photon.js +++ b/server/services/geocoding/photon.js @@ -18,7 +18,7 @@ const photon = { } }, - /* + /** * Icons to nominatim `osm_type` and `class` conversion */ searchIcons_nominatim_osm_type: { @@ -26,11 +26,18 @@ const photon = { 'N': 'mdiMapMarker', 'R': 'mdiCityVariant', }, - searchIcons_nominatim_class: { - mdiHome: ['amenity', 'shop', 'tourism', 'leisure', 'building'], + searchIcons_nominatim_class: ['amenity', 'shop', 'tourism', 'leisure', 'building'], + + loadResultIcon (item) { + if (this.searchIcons_nominatim_class.includes(item.class)) { + return 'mdiHome' + } + return this.searchIcons_nominatim_osm_type[item.type] }, - + /** + * Map results from provider + */ fullAddressMapping: ['housenumber', 'street', 'locality', 'district', 'city', 'county', 'state', 'postcode', 'country'], mapQueryResults(ret, addressList = []) { From 434d0904f4bb9cd17b0933c3f42c5937393d1cf4 Mon Sep 17 00:00:00 2001 From: sedum Date: Mon, 20 Feb 2023 07:10:08 +0100 Subject: [PATCH 06/13] minor on event/_slug --- pages/event/_slug.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 0ee8b377..902e564c 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -47,7 +47,7 @@ v-container#event.pa-0.pa-sm-2 v-list-item-title.text-caption(v-text='`${event.locations[0]}`') v-card-text.text-caption.pt-0.pb-0(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1' v-text="$t('event.online_locations_fallback_urls')") - v-list-item + v-list-item(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') v-list-item-content v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" v-bind:key="index" small label v-text="`${item}`" outlined ) From 3ca86b9a3b6136b72d5038f417cec79dab465368 Mon Sep 17 00:00:00 2001 From: sedum Date: Mon, 20 Feb 2023 07:19:45 +0100 Subject: [PATCH 07/13] re-minor on event/_slug --- pages/event/_slug.vue | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pages/event/_slug.vue b/pages/event/_slug.vue index 902e564c..3f5fc48a 100644 --- a/pages/event/_slug.vue +++ b/pages/event/_slug.vue @@ -38,19 +38,19 @@ v-container#event.pa-0.pa-sm-2 //- online events v-divider(v-if='onlineSectionEnabled && event.locations && event.locations.length') - v-card-text.text-caption.pb-0(v-if='onlineSectionEnabled && event.locations && event.locations.length' - v-text="event.place.name === 'online' && $t('event.event_only_online') || $t('event.event_also_online') ") - v-list-item(target='_blank' :href='`${event.locations[0]}`') - v-list-item-icon - v-icon.my-auto(v-text='mdiMonitorAccount') - v-list-item-content.py-0 - v-list-item-title.text-caption(v-text='`${event.locations[0]}`') - v-card-text.text-caption.pt-0.pb-0(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1' - v-text="$t('event.online_locations_fallback_urls')") - v-list-item(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') - v-list-item-content - v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" - v-bind:key="index" small label v-text="`${item}`" outlined ) + div(v-if='onlineSectionEnabled && event.locations && event.locations.length') + v-card-text.text-caption.pb-0(v-text="event.place.name === 'online' && $t('event.event_only_online') || $t('event.event_also_online') ") + v-list-item(target='_blank' :href='`${event.locations[0]}`') + v-list-item-icon + v-icon.my-auto(v-text='mdiMonitorAccount') + v-list-item-content.py-0 + v-list-item-title.text-caption(v-text='`${event.locations[0]}`') + div(v-if='onlineSectionEnabled && event.locations && event.locations.length > 1') + v-card-text.text-caption.pt-0.pb-0(v-text="$t('event.online_locations_fallback_urls')") + v-list-item + v-list-item-content + v-chip(v-for='(item, index) in event.locations' v-if="index > 0" target='_blank' :href="`${item}`" + v-bind:key="index" small label v-text="`${item}`" outlined ) v-divider //- info & actions From cff608c06f6a08d8f09141f838e96582247ab038 Mon Sep 17 00:00:00 2001 From: sedum Date: Wed, 22 Feb 2023 03:11:58 +0100 Subject: [PATCH 08/13] move event.locations to more unique event.online_locations, various fixes on insertion workflow, improved locale messages --- components/MapEdit.vue | 8 +- components/WhereInput.vue | 77 ++++++++++--------- components/WhereInputAdvanced.vue | 35 +++++---- components/admin/Places.vue | 32 ++++---- locales/en.json | 18 ++--- pages/add/_edit.vue | 12 +-- pages/event/_slug.vue | 12 +-- server/api/controller/event.js | 4 +- server/api/index.js | 3 +- server/api/models/event.js | 2 +- ....js => 20221215110244-online_locations.js} | 4 +- 11 files changed, 105 insertions(+), 102 deletions(-) rename server/migrations/{20221215110244-event-locations.js => 20221215110244-online_locations.js} (74%) diff --git a/components/MapEdit.vue b/components/MapEdit.vue index c60b2d39..d0c8bb3a 100644 --- a/components/MapEdit.vue +++ b/components/MapEdit.vue @@ -1,6 +1,6 @@