mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-03-01 12:44:28 +00:00
166 lines
4.1 KiB
Vue
166 lines
4.1 KiB
Vue
<template>
|
|
<div>
|
|
<label class="ds-input-label">
|
|
{{ `${$t('settings.data.labelCity')}` + locationNameLabelAddOnOldName }}
|
|
</label>
|
|
<ds-select
|
|
id="city"
|
|
v-model="currentValue"
|
|
:options="cities"
|
|
icon="map-marker"
|
|
:icon-right="null"
|
|
:placeholder="$t('settings.data.labelCity') + ' …'"
|
|
:loading="loadingGeo"
|
|
@input.native="handleCityInput"
|
|
/>
|
|
<os-button
|
|
v-if="locationName !== '' && canBeCleared"
|
|
data-test="clear-location-button"
|
|
variant="primary"
|
|
appearance="ghost"
|
|
size="sm"
|
|
:aria-label="$t('actions.clear')"
|
|
style="right: -94%; top: -48px"
|
|
@click="clearLocationName"
|
|
>
|
|
<template #icon><os-icon :icon="icons.close" /></template>
|
|
</os-button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
|
import { iconRegistry } from '~/utils/iconRegistry'
|
|
import { queryLocations } from '~/graphql/location'
|
|
|
|
let timeout
|
|
|
|
export default {
|
|
name: 'LocationSelect',
|
|
components: { OsButton, OsIcon },
|
|
props: {
|
|
value: {
|
|
type: [String, Object],
|
|
required: true,
|
|
},
|
|
canBeCleared: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: true,
|
|
},
|
|
showPreviousLocation: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: true,
|
|
},
|
|
},
|
|
async created() {
|
|
this.icons = iconRegistry
|
|
await this.resolveLocalizedLocation()
|
|
},
|
|
data() {
|
|
return {
|
|
currentValue: this.value,
|
|
loadingGeo: false,
|
|
cities: [],
|
|
}
|
|
},
|
|
computed: {
|
|
locationName() {
|
|
return typeof this.value === 'object' ? this.value.value : this.value
|
|
},
|
|
locationNameLabelAddOnOldName() {
|
|
return this.locationName !== '' && this.showPreviousLocation ? ' — ' + this.locationName : ''
|
|
},
|
|
currentLocale() {
|
|
return this.$store && this.$store.state.i18n && this.$store.state.i18n.locale
|
|
},
|
|
},
|
|
watch: {
|
|
currentValue() {
|
|
if (this.currentValue !== this.value) {
|
|
this.$emit('input', this.currentValue)
|
|
}
|
|
},
|
|
value(newVal, oldVal) {
|
|
if (newVal !== this.currentValue) {
|
|
this.currentValue = newVal
|
|
}
|
|
// resolve when value is set after initial mount (e.g. settings page)
|
|
const newName = typeof newVal === 'object' ? newVal.value : newVal
|
|
const oldName = typeof oldVal === 'object' ? oldVal.value : oldVal
|
|
if (newName && newName !== oldName) {
|
|
this.resolveLocalizedLocation()
|
|
}
|
|
},
|
|
currentLocale() {
|
|
this.resolveLocalizedLocation()
|
|
},
|
|
},
|
|
methods: {
|
|
handleCityInput(event) {
|
|
clearTimeout(timeout)
|
|
timeout = setTimeout(
|
|
() => this.requestGeoData(event.target ? event.target.value.trim() : ''),
|
|
500,
|
|
)
|
|
},
|
|
processLocationsResult(places) {
|
|
if (!places.length) {
|
|
return []
|
|
}
|
|
const result = []
|
|
places.forEach((place) => {
|
|
result.push({
|
|
label: place.place_name,
|
|
value: place.place_name,
|
|
id: place.id,
|
|
})
|
|
})
|
|
|
|
return result
|
|
},
|
|
async requestGeoData(value) {
|
|
if (value === '') {
|
|
this.cities = []
|
|
return
|
|
}
|
|
|
|
try {
|
|
this.loadingGeo = true
|
|
|
|
const place = encodeURIComponent(value)
|
|
const lang = this.$i18n.locale()
|
|
|
|
const {
|
|
data: { queryLocations: result },
|
|
} = await this.$apollo.query({
|
|
query: queryLocations(),
|
|
variables: { place, lang },
|
|
fetchPolicy: 'network-only',
|
|
})
|
|
|
|
this.cities = this.processLocationsResult(result)
|
|
this.loadingGeo = false
|
|
|
|
return this.cities.find((city) => city.value === value)
|
|
} catch (error) {
|
|
this.$toast.error(error.message)
|
|
} finally {
|
|
this.loadingGeo = false
|
|
}
|
|
},
|
|
async resolveLocalizedLocation() {
|
|
if (!this.locationName) return
|
|
const result = await this.requestGeoData(this.locationName)
|
|
this.$nextTick(() => {
|
|
this.currentValue = result || (this.cities.length ? this.cities[0] : this.locationName)
|
|
})
|
|
},
|
|
clearLocationName() {
|
|
this.currentValue = ''
|
|
},
|
|
},
|
|
}
|
|
</script>
|