kopia lustrzana https://github.com/manuelkasper/sotlas-frontend
280 wiersze
8.6 KiB
Vue
280 wiersze
8.6 KiB
Vue
<template>
|
|
<div class="modal-card" style="width: auto">
|
|
<header class="modal-card-head">
|
|
<p class="modal-card-title">{{ this.spot ? 'Edit' : 'Add' }} Spot</p>
|
|
</header>
|
|
<section class="modal-card-body">
|
|
<b-field label="Callsign" :message="isOwnCallsign ? '' : 'You are spotting someone else\'s callsign'" :type="isOwnCallsign ? '' : 'is-info'">
|
|
<b-input type="text" class="callsign" v-model="callsign" pattern="[a-zA-Z0-9/]{3,}" validation-message="Invalid callsign" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
|
|
</b-field>
|
|
|
|
<b-field label="Summit reference" :message="summitDisplay" :type="summitType" :class="summitLabelClass" expanded>
|
|
<b-field>
|
|
<b-input type="text" ref="summitCode" v-model="summitCode" placeholder="XX/YY-000" :loading="summitLoading" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
|
|
<p class="control">
|
|
<NearbySummitsList @summitSelected="onSummitSelected" />
|
|
</p>
|
|
</b-field>
|
|
</b-field>
|
|
|
|
<b-field label="Frequency" :message="maybeKhz ? 'Do you really mean ' + frequency + ' MHz, or are you missing a dot?' : ''" :type="maybeKhz ? 'is-warning' : ''">
|
|
<b-field :type="maybeKhz ? 'is-warning' : ''">
|
|
<b-input v-model="frequency" type="number" step="any" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
|
|
<p class="control">
|
|
<span class="button is-static">MHz</span>
|
|
</p>
|
|
</b-field>
|
|
</b-field>
|
|
|
|
<b-field label="Mode">
|
|
<b-field>
|
|
<b-radio-button v-for="(curModeDisp, curMode) in allModes()" :key="curMode" v-model="mode" :size="$mq.mobile ? 'is-small' : ''" :native-value="curMode">{{ curModeDisp }}</b-radio-button>
|
|
</b-field>
|
|
</b-field>
|
|
|
|
<b-field label="Comments">
|
|
<b-input v-model="comments" type="text" maxlength="60" />
|
|
</b-field>
|
|
</section>
|
|
<footer class="modal-card-foot">
|
|
<b-button @click="$parent.close()">Cancel</b-button>
|
|
<b-button type="is-info" :disabled="!isInputValid" :loading="posting" @click="postSpot">{{ (this.spot && this.spot.id) ? 'Edit' : 'Add' }} Spot</b-button>
|
|
</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import axios from 'axios'
|
|
import utils from '../mixins/utils.js'
|
|
import prefs from '../mixins/prefs.js'
|
|
import sotawatch from '../mixins/sotawatch.js'
|
|
import NearbySummitsList from './NearbySummitsList.vue'
|
|
|
|
export default {
|
|
components: {
|
|
NearbySummitsList
|
|
},
|
|
mixins: [utils, prefs, sotawatch],
|
|
props: {
|
|
defaultSummitCode: String,
|
|
spot: Object
|
|
},
|
|
prefs: {
|
|
key: 'spotPrefs',
|
|
props: ['lastCallsign', 'lastSummitCode', 'defaultComments']
|
|
},
|
|
mounted () {
|
|
if (!this.callsign) {
|
|
if (this.lastCallsign) {
|
|
this.callsign = this.lastCallsign
|
|
} else if (this.myCallsign) {
|
|
this.callsign = this.myCallsign
|
|
if (!/\/P$/.test(this.callsign)) {
|
|
this.callsign += '/P'
|
|
}
|
|
}
|
|
}
|
|
if (!this.summitCode) {
|
|
if (this.lastSummitCode) {
|
|
this.summitCode = this.lastSummitCode
|
|
}
|
|
}
|
|
if (!this.comments && this.defaultComments) {
|
|
this.comments = this.defaultComments
|
|
}
|
|
},
|
|
computed: {
|
|
summitDisplay () {
|
|
if (this.summit) {
|
|
if (this.$store.state.altitudeUnits === 'ft') {
|
|
return this.summit.name + ' (' + Math.round(this.summit.altitude * 3.28084) + ' ft)'
|
|
} else {
|
|
return this.summit.name + ' (' + this.summit.altitude + ' m)'
|
|
}
|
|
} else if (this.summitInvalid) {
|
|
return 'Summit not found'
|
|
} else {
|
|
return 'You can enter spaces instead of / and -'
|
|
}
|
|
},
|
|
summitType () {
|
|
if (this.summitInvalid) {
|
|
return 'is-danger'
|
|
} else {
|
|
return ''
|
|
}
|
|
},
|
|
isInputValid () {
|
|
return /^[a-zA-Z0-9/]{3,}$/.test(this.callsign) && this.summit !== null && this.isSummitValid(this.summit) && this.frequency && this.mode
|
|
},
|
|
summitLabelClass () {
|
|
if (!this.summit || this.isSummitValid(this.summit)) {
|
|
return { summitref: true }
|
|
} else {
|
|
return { summitref: true, invalid: true }
|
|
}
|
|
},
|
|
isOwnCallsign () {
|
|
return (!this.callsign || !this.myCallsign || (this.homeCallsign(this.callsign) === this.homeCallsign(this.myCallsign)))
|
|
},
|
|
maybeKhz () {
|
|
return (this.frequency && this.frequency > 1500)
|
|
}
|
|
},
|
|
watch: {
|
|
defaultSummitCode: {
|
|
immediate: true,
|
|
handler () {
|
|
if (!this.summitCode) {
|
|
this.summitCode = this.defaultSummitCode
|
|
}
|
|
}
|
|
},
|
|
summitCode: {
|
|
immediate: true,
|
|
handler () {
|
|
if (this.summitCode) {
|
|
// Shorthand input
|
|
let summitRegex = /^([A-Z0-9]{1,8})[/ ]([A-Z]{2})[- ]?([0-9]{3})$/i
|
|
let matches = this.summitCode.match(summitRegex)
|
|
if (matches) {
|
|
this.summitCode = (matches[1] + '/' + matches[2] + '-' + matches[3]).toUpperCase()
|
|
this.summitLoading = true
|
|
axios.get('https://api.sotl.as/summits/' + this.summitCode)
|
|
.then(response => {
|
|
this.summitLoading = false
|
|
this.summitInvalid = false
|
|
this.summit = response.data
|
|
})
|
|
.catch(() => {
|
|
this.summitLoading = false
|
|
this.summitInvalid = true
|
|
this.summit = null
|
|
})
|
|
} else {
|
|
this.summit = null
|
|
this.summitInvalid = false
|
|
}
|
|
} else {
|
|
this.summit = null
|
|
this.summitInvalid = false
|
|
}
|
|
}
|
|
},
|
|
spot: {
|
|
immediate: true,
|
|
handler () {
|
|
if (this.spot) {
|
|
this.callsign = this.spot.activatorCallsign
|
|
this.summitCode = this.spot.summit.code
|
|
this.frequency = this.spot.frequency
|
|
this.mode = this.spot.mode.toLowerCase()
|
|
this.comments = (this.spot.comments ? this.spot.comments.replace('[sotl.as]', '').trim() : '')
|
|
}
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
postSpot () {
|
|
this.lastCallsign = this.callsign.toUpperCase()
|
|
this.lastSummitCode = this.summitCode
|
|
|
|
// Advertise in comments :)
|
|
let commentsTag = '[sotl.as]'
|
|
let comments = this.comments
|
|
if ((comments.length + commentsTag.length) < 60 && !comments.endsWith(commentsTag)) {
|
|
if (comments.length > 0) {
|
|
comments += ' '
|
|
}
|
|
comments += commentsTag
|
|
}
|
|
|
|
let params = {
|
|
callsign: this.myCallsign,
|
|
activatorCallsign: this.callsign.toUpperCase(),
|
|
associationCode: this.summitCode.substring(0, this.summitCode.indexOf('/')),
|
|
summitCode: this.summitCode.substring(this.summitCode.indexOf('/') + 1),
|
|
frequency: this.frequency,
|
|
mode: this.allModes()[this.mode],
|
|
comments
|
|
}
|
|
if (this.spot && this.spot.id) {
|
|
params.id = this.spot.id
|
|
}
|
|
this.posting = true
|
|
this.postSotaWatchSpot(params)
|
|
.then(response => {
|
|
this.$store.commit('updateSpot', {
|
|
id: (this.spot && this.spot.id) ? this.spot.id : response.data.id,
|
|
timeStamp: response.data.timeStamp,
|
|
frequency: response.data.frequency,
|
|
mode: response.data.mode,
|
|
summit: this.summit,
|
|
activatorCallsign: response.data.activatorCallsign,
|
|
callsign: response.data.callsign,
|
|
comments: response.data.comments
|
|
})
|
|
|
|
this.$parent.close()
|
|
})
|
|
.finally(() => {
|
|
this.posting = false
|
|
})
|
|
},
|
|
onSummitSelected (summit) {
|
|
this.summitCode = summit.code
|
|
this.$nextTick(() => {
|
|
this.$refs.summitCode.checkHtml5Validity()
|
|
})
|
|
}
|
|
},
|
|
data () {
|
|
return {
|
|
callsign: '',
|
|
lastCallsign: null,
|
|
defaultComments: '',
|
|
summitCode: '',
|
|
lastSummitCode: null,
|
|
frequency: '',
|
|
mode: '',
|
|
comments: '',
|
|
summit: null,
|
|
summitInvalid: false,
|
|
summitLoading: false,
|
|
posting: false
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.callsign >>> input {
|
|
text-transform: uppercase;
|
|
}
|
|
.invalid >>> .help {
|
|
text-decoration: line-through;
|
|
}
|
|
>>> input::-webkit-outer-spin-button,
|
|
>>> input::-webkit-inner-spin-button {
|
|
-webkit-appearance: none;
|
|
margin: 0;
|
|
}
|
|
>>> input[type=number] {
|
|
-moz-appearance:textfield;
|
|
}
|
|
.summitref .field {
|
|
margin-bottom: 0;
|
|
}
|
|
>>> .help.is-warning {
|
|
color: #cda400;
|
|
}
|
|
|
|
/* Fix from https://github.com/buefy/buefy/issues/1932#issuecomment-551453842 */
|
|
>>> .field.has-addons {
|
|
flex-wrap: wrap;
|
|
}
|
|
>>> .field.has-addons .help {
|
|
width: 100%;
|
|
}
|
|
</style>
|