Add position filters to Vue.

Given some text and an item containing a Point geometry,
the `position` filter replaces occurences of @POS@ or
@POSITION@ with the item's geometry (it has to be lat/lon).

Occurrences of @DMS@ are replaced with the position in
sexagesimal degrees.

This can be used anywhere a Vue filter can. However, we
have used it in the event comments edit dialogue. The positions
are replaced before saving the comment to the database.
This commit is contained in:
D. Berge
2021-05-14 03:17:36 +02:00
parent 814e071698
commit f1953807db
3 changed files with 79 additions and 2 deletions

View File

@@ -26,4 +26,70 @@ function withParentProps(item, parent, childrenKey, prop, currentValue) {
return [];
}
export { withParentProps }
function dms (lat, lon) {
const λh = lat < 0 ? "S" : "N";
const φh = lon < 0 ? "W" : "E";
const λn = Math.abs(lat);
const φn = Math.abs(lon);
const λi = Math.trunc(λn);
const φi = Math.trunc(φn);
const λf = λn - λi;
const φf = φn - φi;
const λs = ((λf*3600)%60).toFixed(1);
const φs = ((φf*3600)%60).toFixed(1);
const λm = Math.trunc(λf*60);
const φm = Math.trunc(φf*60);
const λ =
String(λi).padStart(2, "0") + "°" +
String(λm).padStart(2, "0") + "'" +
String(λs).padStart(4, "0") + '" ' +
λh;
const φ =
String(φi).padStart(3, "0") + "°" +
String(φm).padStart(2, "0") + "'" +
String(φs).padStart(4, "0") + '" ' +
φh;
return λ+" "+φ;
}
function geometryAsString (item, opts = {}) {
const key = "key" in opts ? opts.key : "geometry";
const formatDMS = opts.dms;
let str = "";
if (key in item) {
const geometry = item[key];
if ("coordinates" in geometry) {
if (geometry.type == "Point") {
if (formatDMS) {
str = dms(geometry.coordinates[1], geometry.coordinates[0]);
} else {
str = `${geometry.coordinates[1].toFixed(6)}, ${geometry.coordinates[0].toFixed(6)}`;
}
}
if (str) {
if (opts.url) {
if (typeof opts.url === 'string') {
str = `[${str}](${opts.url.replace("$x", geometry.coordinates[0]).replace("$y", geometry.coordinates[1])})`;
} else {
str = `[${str}](geo:${geometry.coordinates[0]},${geometry.coordinates[1]})`;
}
}
}
}
}
return str;
}
export { withParentProps, geometryAsString }

View File

@@ -6,6 +6,7 @@ import vuetify from './plugins/vuetify'
import vueDebounce from 'vue-debounce'
import { mapMutations } from 'vuex';
import { markdown, markdownInline } from './lib/markdown';
import { geometryAsString } from './lib/utils';
Vue.config.productionTip = false
@@ -13,7 +14,12 @@ Vue.use(vueDebounce);
Vue.filter('markdown', markdown);
Vue.filter('markdownInline', markdownInline);
Vue.filter('position', (str, item, opts) =>
str
.replace(/@POS(ITION)?@/g, geometryAsString(item, opts))
.replace(/@DMS@/g, geometryAsString(item, {...opts, dms:true}))
);
// Vue.filter('position', (str, item, opts) => str.replace(/@POS(ITION)?@/, "☺"));
new Vue({
data () {

View File

@@ -573,6 +573,11 @@ export default {
const promises = [];
for (const editedItem of this.editedRow.items) {
// Process special text in remarks
if (editedItem.remarks) {
editedItem.remarks = this.$options.filters.position(editedItem.remarks, editedItem);
}
// Discard non user writable labels
editedItem.labels = editedItem.labels.filter(l => this.labels[l].model.user);