Skip to content

Commit 4e4f0cf

Browse files
committed
WIP - host form updated and workflow to write to backend DB added.
Some hardcoded URLs need to be changed.
1 parent 428d098 commit 4e4f0cf

10 files changed

Lines changed: 239 additions & 266 deletions

File tree

public/data/hosts.psv

Lines changed: 0 additions & 110 deletions
This file was deleted.

src/models/Host.js

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import TimeZone from '@/models/TimeZone';
77
import User from '@/models/User';
88
import Status from '@/models/Status';
99

10+
import {to_geojson} from '@/utils/geojson.js';
11+
1012
export default class Host extends Model {
1113
static entity = 'host';
1214
static fields() {
@@ -39,13 +41,59 @@ export default class Host extends Model {
3941
comments: this.string('')
4042
};
4143
};
42-
static saving (model) {};
43-
static saved (model) { };
44-
static creating(model) {};
45-
static created(model) {};
44+
static saving (model) {
45+
console.log("saving host")
46+
console.log(model.id)
47+
};
48+
static saved (model) {
49+
// check whether we need to save to the database
50+
if( model._version === 1 && model._status_id === "tag:beta.opencdms.org,2023:/vocab/status/draft"){ // todo
51+
var to_save = to_geojson([model]);
52+
to_save.map( (obj) => {
53+
var payload = JSON.stringify(obj);
54+
var url_ = "http://localhost:5000/collections/stations/items"
55+
// PUT for update
56+
fetch(url_, {method:'OPTIONS'}).then( (response) => {console.log(response)});
57+
fetch(url_, {
58+
method: 'POST',
59+
body: payload,
60+
headers: {
61+
'encode': 'json',
62+
"Origin": "http://localhost:81",
63+
'Content-Type': 'application/geo+json'
64+
}
65+
})
66+
});
67+
};
68+
};
69+
static creating(model) {
70+
console.log("creating host")
71+
console.log(model.id)
72+
};
73+
static created(model) {
74+
};
4675
static deleting(model) {};
4776
static deleted (model) {};
4877
static updating (model) {};
49-
static updated (model) {};
78+
static updated (model) {
79+
// now we want to save to the backend
80+
var to_save = to_geojson([model]);
81+
console.log( to_save );
82+
to_save.map( (obj) => {
83+
var payload = JSON.stringify(obj);
84+
var url_ = "http://localhost:5000/collections/stations/items/" + obj.id
85+
// PUT for update
86+
fetch(url_, {method:'OPTIONS'}).then( (response) => {console.log(response)});
87+
fetch(url_, {
88+
method: 'PUT',
89+
body: payload,
90+
headers: {
91+
'encode': 'json',
92+
"Origin": "http://localhost:81",
93+
'Content-Type': 'application/geo+json'
94+
}
95+
})
96+
});
97+
};
5098
};
5199

src/router/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import User from '@/models/User';
3434
import Host from '@/models/Host';
3535
import Feature from '@/models/Feature';
3636

37+
import * as Wkt from 'wicket';
38+
39+
import {flatten_geojson} from '@/utils/geojson.js';
3740

3841
const router = createRouter({
3942
history: createWebHashHistory(process.env.BASE_URL),
@@ -66,10 +69,9 @@ router.beforeEach( async () => {
6669
if( useRepo(Territory).all().length === 0){await loadData('http://localhost:5000/vocabularies/territory/items?f=csv', true).then( (result) => { useRepo(Territory).save(result) })};
6770
if( useRepo(TimeZone).all().length === 0){await loadData('http://localhost:5000/vocabularies/time_zone/items?f=csv', true).then( (result) => { useRepo(TimeZone).save(result) })};
6871
if( useRepo(Topography).all().length === 0){await loadData('http://localhost:5000/vocabularies/topography/items?f=csv', true).then( (result) => { useRepo(Topography).save(result) })};
69-
//if( useRepo(WmoRegion).all().length === 0){await loadData('http://localhost:5000/vocabularies/wmo_region/items?f=csv', true).then( (result) => { useRepo(WmoRegion).save(result) })};
7072
if( useRepo(WmoRegion).all().length === 0){await loadData('http://localhost:5000/vocabularies/wmo_region/items?f=csv', true).then( (result) => { useRepo(WmoRegion).save(result) })};
7173
if( useRepo(User).all().length === 0){await loadData('http://localhost:5000/vocabularies/user/items?f=csv', true).then( (result) => { useRepo(User).save(result) })};
72-
if( useRepo(Host).all().length === 0){await loadData('/data/hosts.psv').then( (result) => { useRepo(Host).save(result) })};
74+
if( useRepo(Host).all().length === 0){await loadData('http://localhost:5000/collections/stations/items?f=json', true).then( (result) => flatten_geojson(result.features) ).then( (result) => { useRepo(Host).save(result) })};
7375
if( useRepo(Feature).all().length === 0){await loadData('/data/features.psv').then( (result) => { useRepo(Feature).save(result) })};
7476
});
7577

src/utils/geojson.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as Wkt from 'wicket';
2+
// utility functions to convert to / from geojson
3+
export async function flatten_geojson(features){
4+
if( features.length ){
5+
var returnValue = features.map( (feature) => {
6+
var _wkt = new Wkt.Wkt();
7+
var result = feature.properties;
8+
_wkt.read(JSON.stringify(feature.geometry));
9+
result.location = "SRID=4326; " + _wkt.write();
10+
result.id = feature.id;
11+
return result;
12+
})
13+
return returnValue;
14+
}
15+
};
16+
17+
export function to_geojson(rows){
18+
19+
const nullify_empty_strings = (key, value) => {
20+
return value === '' ? null: value;
21+
}
22+
23+
if( rows.length ){
24+
console.log(rows)
25+
var returnValue = rows.map( (row) => {
26+
console.log(row);
27+
const coords = row.location.match(/POINT\(([-\d\.]+)\s+([-\d\.]+)\)/);
28+
const latlng = [parseFloat(coords[1]), parseFloat(coords[2])];
29+
var geojson = {
30+
id: row.id,
31+
type: 'Feature',
32+
properties: JSON.parse(JSON.stringify(row, nullify_empty_strings)),
33+
geometry: {
34+
type: 'Point',
35+
coordinates: latlng
36+
}
37+
};
38+
// remove id and location
39+
delete geojson.properties.id;
40+
delete geojson.properties.location;
41+
return geojson;
42+
})
43+
console.log(rows)
44+
return returnValue;
45+
}
46+
};

src/utils/load-data.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,23 @@ import axios from 'axios';
33

44
export async function loadData(datafile, isUrl = false) {
55
let data;
6-
const fileType = datafile.split('.').pop();
76
if (isUrl) {
8-
if (fileType === 'csv', d3.autoType) {
9-
data = await d3.csv(datafile);
7+
const fileType = datafile.split('?f=').pop();
8+
if (fileType === 'csv') {
9+
data = await d3.csv(datafile, d3.autoType);
1010
} else if (fileType === 'psv') {
11+
console.log("Loading PSV")
1112
data = await d3.dsv('|', datafile, d3.autoType);
12-
} else if (fileType === 'geojson') {
13+
} else if (fileType === 'geojson' || fileType === 'json') {
14+
console.log("Loading geojson")
1315
const response = await axios.get(datafile);
1416
data = response.data;
1517
} else {
18+
console.log("Error")
1619
throw new Error(`Unsupported file type: ${fileType}`);
1720
}
1821
} else {
22+
const fileType = datafile.split('.').pop();
1923
if (fileType === 'csv') {
2024
data = await d3.csv(datafile, d3.autoType);
2125
} else if (fileType === 'psv') {

src/web-components/forms/host.vue

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,30 @@
1010
<v-card-item><geometry-picker v-model="host.location" style="height: 100%"/></v-card-item>
1111
<v-card-item><v-text-field label="elevation" v-model="host.elevation" type="number" hint="Elevation of station above mean sea level in meters" persistent-hint></v-text-field></v-card-item>
1212
<v-card-item><v-text-field label="wigos_station_identifier" v-model="host.wigos_station_identifier" hint="WIGOS station identifier" persistent-hint></v-text-field></v-card-item>
13-
<v-card-item><v-select :items="facilityTypeOptions" item-title="name" item-value="id" label="facility_type" v-model="host.facility_type" :hint="facilityTypeOptionsHint" return-object persistent-hint></v-select></v-card-item>
13+
<v-card-item><v-autocomplete :items="facilityTypeOptions" item-title="name" item-value="id" label="facility_type" v-model="host.facility_type" :hint="facilityTypeOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
1414
<v-card-item>
1515
<v-container>
1616
<v-row>
17-
<v-col :cols="3"><VueDatePicker label="date_established" v-model="host.date_established" hint="Date host was first established" persistent-hint></VueDatePicker></v-col>
18-
<v-col :cols="3"><VueDatePicker label="date_closed" v-model="host.date_closed" hint="Date host was first established" persistent-hint></VueDatePicker></v-col>
17+
<v-col :cols="4"><VueDatePicker label="date_established" v-model="host.date_established" hint="Date host was first established" persistent-hint></VueDatePicker></v-col>
18+
<v-col :cols="4"><VueDatePicker label="date_closed" v-model="host.date_closed" hint="Date host was first established" persistent-hint></VueDatePicker></v-col>
1919
</v-row>
2020
</v-container>
2121
</v-card-item>
22-
<v-card-item><v-select :items="wmoRegionOptions" item-title="name" item-value="id" label="wmo_region" v-model="host.wmo_region" :hint="wmoRegionOptionsHint" return-object persistent-hint></v-select></v-card-item>
23-
<v-card-item><v-select :items="territoryOptions" item-title="name" item-value="id" label="territory" v-model="host.territory" :hint="territoryOptionsHint" return-object persistent-hint></v-select></v-card-item>
24-
<v-card-item><v-select :items="timeZoneOptions" item-title="name" item-value="id" label="time_zone" v-model="host.time_zone" :hint="timeZoneOptionsHint" return-object persistent-hint></v-select></v-card-item>
22+
<v-card-item><v-autocomplete :items="wmoRegionOptions" item-title="name" item-value="id" label="wmo_region" v-model="host.wmo_region" :hint="wmoRegionOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
23+
<v-card-item><v-autocomplete :items="territoryOptions" item-title="name" item-value="id" label="territory" v-model="host.territory" :hint="territoryOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
24+
<v-card-item><v-autocomplete :items="timeZoneOptions" item-title="name" item-value="id" label="time_zone" v-model="host.time_zone" :hint="timeZoneOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
2525
<v-card-item>
2626
<v-container>
2727
<v-row>
28-
<v-col :cols="3"><VueDatePicker label="valid_from" v-model="host.valid_from" hint="Date from which the details for this record are valid" persistent-hint></VueDatePicker></v-col>
29-
<v-col :cols="3"><VueDatePicker label="valid_to" v-model="host.valid_to" hint="Date after which the details for this record are no longer valid" persistent-hint></VueDatePicker></v-col>
28+
<v-col :cols="4"><VueDatePicker label="valid_from" v-model="host.valid_from" hint="Date from which the details for this record are valid" persistent-hint></VueDatePicker></v-col>
29+
<v-col :cols="4"><VueDatePicker label="valid_to" v-model="host.valid_to" hint="Date after which the details for this record are no longer valid" persistent-hint></VueDatePicker></v-col>
3030
</v-row>
3131
</v-container>
3232
</v-card-item>
3333
<v-card-item><v-text-field label="_version" v-model="host._version" type="number" hint="Version number of this record (autoupdated)" persistent-hint readonly></v-text-field></v-card-item>
3434
<v-card-item><v-text-field label="_change_date" v-model="host._change_date" hint="Date this record was changed (autoupdated)" persistent-hint readonly></v-text-field></v-card-item>
35-
<v-card-item><v-select :items="userOptions" item-title="name" item-value="id" label="user" v-model="host._user" :hint="userOptionsHint" return-object persistent-hint></v-select></v-card-item>
36-
<v-card-item><v-select :items="statusOptions" item-title="name" item-value="id" label="status" v-model="host._status" :hint="statusOptionsHint" return-object persistent-hint></v-select></v-card-item>
35+
<v-card-item><v-autocomplete :items="userOptions" item-title="name" item-value="id" label="user" v-model="host._user" :hint="userOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
36+
<v-card-item><v-autocomplete :items="statusOptions" item-title="name" item-value="id" label="status" v-model="host._status" :hint="statusOptionsHint" return-object persistent-hint></v-autocomplete></v-card-item>
3737
<v-card-item><v-text-field label="comments" v-model="host.comments" hint="Free text comments on this record, for example description of changes made etc" persistent-hint></v-text-field></v-card-item>
3838
</v-form>
3939
<v-btn @click="createHost">{{ route.params.id ? 'Save' : 'Create' }}</v-btn>
@@ -45,7 +45,7 @@
4545
<script>
4646
import * as d3 from 'd3';
4747
import { defineComponent, ref, computed, watch } from 'vue';
48-
import { VCard, VCardTitle, VCardText, VCardItem, VForm, VTextField, VSelect, VBtn } from 'vuetify/lib/components';
48+
import { VCard, VCardTitle, VCardText, VCardItem, VForm, VTextField, VSelect, VBtn, VAutocomplete } from 'vuetify/lib/components';
4949
import { VContainer, VRow, VCol } from 'vuetify/lib/components';
5050
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured} from 'vue';
5151
import {useStore} from 'pinia';
@@ -89,7 +89,7 @@ export default defineComponent({
8989
VCardText,
9090
VCardItem,
9191
VTextField,
92-
VSelect,
92+
VSelect, VAutocomplete,
9393
VForm,
9494
VBtn,
9595
VueDatePicker,
@@ -240,8 +240,8 @@ export default defineComponent({
240240
host.value._version = host.value._version + 1;
241241
}else{
242242
host.value._version = 1;
243-
host.value._user_id = "tag:beta.opencdms.org,2023:/data/user/default";
244-
host.value._status_id = "tag:beta.opencdms.org,2023:/vocab/status/draft";
243+
host.value._user = useRepo(User).where('id','tag:beta.opencdms.org,2023:/data/user/default').first();
244+
host.value._status = useRepo(Status).where('id','tag:beta.opencdms.org,2023:/vocab/status/draft').first();
245245
}
246246
});
247247
Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<template>
2-
<v-card style="height: 600px;">
3-
<v-card-title>{{title}}</v-card-title>
4-
<base-map @mapLoaded="onMapLoaded" style="height: 100%;" zoom="4"/>
2+
<v-card style="height: 500pt;">
3+
<v-card-text style="height: 100%;">
4+
<base-map @mapLoaded="onMapLoaded" style="height: 100%;" zoom="4"/>
5+
</v-card-text>
56
</v-card>
67
</template>
78

@@ -14,7 +15,7 @@ import * as gjv from 'geojson-validation';
1415
import L from 'leaflet';
1516
1617
// vue imports
17-
import { defineComponent, ref, computed } from 'vue';
18+
import { defineComponent, ref, computed, watch } from 'vue';
1819
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured} from 'vue';
1920
2021
// vuetify imports
@@ -32,36 +33,37 @@ export default defineComponent({
3233
}
3334
},
3435
components: {
35-
VCard, VCardTitle, VCardItem,
36+
VCard, VCardTitle, VCardItem, VCardText,
3637
BaseMap
3738
},
3839
setup( props, context ){
3940
const map = ref(null);
40-
const onMapLoaded = async (map) => {
41+
const markerLayer = ref(null);
42+
const onMapLoaded = async (mapInstance) => {
43+
map.value = mapInstance;
4144
if ( props.geom ){
4245
// make sure the geometry is valid
4346
if( gjv.isFeature(props.geom) ){
44-
console.log("Have geom");
4547
// now add to map
46-
L.geoJSON(geom).addTo(props.geom);
47-
}else{
48-
var example = {
49-
"type": "Feature",
50-
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
51-
"properties": {"prop0": "value0"}
52-
}
53-
console.log(example)
54-
L.geoJSON(example).addTo(map);
48+
markerLayer.value = L.geoJSON(props.geom).addTo(map.value);
49+
map.value.fitBounds(markerLayer.value.getBounds());
50+
map.value.setZoom(6);
5551
console.log("invalid geom");
5652
}
5753
}else{
5854
console.log("No geometry");
5955
}
6056
};
57+
watch( () => props.geom, (newValue) => {
58+
if( markerLayer.value ){
59+
markerLayer.value.remove();
60+
}
61+
markerLayer.value = L.geoJSON(newValue).addTo(map.value);
62+
map.value.fitBounds(markerLayer.value.getBounds());
63+
map.value.setZoom(6);
64+
})
6165
return {map, onMapLoaded};
6266
}
6367
});
6468
65-
// https://api.opencdms.org/collections/ca_clim/items?filter=phenomenon_end%20DURING%201990-02-01T00:00:00Z/1990-03-01T00:00:00Z
66-
6769
</script>

src/web-components/pickers/geometry.vue

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
// update the wkt
101101
var _wkt = new Wkt.Wkt();
102102
_wkt.read(JSON.stringify(geom.value));
103-
console.log("setting WKT")
104103
geom.value.properties.wkt = "SRID=4326; " + _wkt.write();
105104
updateMap(map);
106105
}, { deep: true });
@@ -118,17 +117,11 @@
118117
)
119118
120119
const updateMap = (map) => {
121-
console.log("updating map")
122120
if( map.value ){
123121
if( geom.value.geometry.coordinates[0] != null & geom.value.geometry.coordinates[1] != null ){
124-
console.log(9)
125122
geojsonLayer.value.clearLayers();
126-
console.log(8)
127123
geojsonLayer.value.addData( geom.value);
128-
console.log(7)
129124
map.value.setView( [ geom.value.geometry.coordinates[1], geom.value.geometry.coordinates[0]])
130-
console.log(6)
131-
console.log(geom.value.properties.wkt, " emitted")
132125
emit("update:modelValue", geom.value.properties.wkt);
133126
}
134127
}

0 commit comments

Comments
 (0)