Skip to content
Snippets Groups Projects
Commit 82bdb496 authored by Timothee P's avatar Timothee P :sunflower:
Browse files

Add import of feature_type from geoJSON

parent 6312ecc0
No related branches found
No related tags found
No related merge requests found
......@@ -103,4 +103,10 @@ export default {
window.removeEventListener("mousedown", this.clickOutsideDropdown);
},
};
</script>
\ No newline at end of file
</script>
<style scoped>
.ui.selection.dropdown .menu > .item {
white-space: nowrap;
}
</style>
\ No newline at end of file
......@@ -66,7 +66,7 @@
}}</label>
<Dropdown
:disabled="!form.label.value || !form.name.value"
:options="form.field_type.field.choices"
:options="fieldTypeChoices"
:selected="selected"
:selection.sync="selected"
/>
......@@ -81,9 +81,8 @@
:maxlength="form.options.field.max_length"
:name="form.options.html_name"
:id="form.options.id_for_label"
v-model="form.options.value"
v-model="arrayOption"
class="options-field"
@input="updateOptions"
/>
<small>{{ form.help_text }}</small>
{{ form.options.errors }}
......@@ -108,22 +107,17 @@ export default {
props: ["customForm"],
computed: {
selected: {
// getter
get() {
return this.form.field_type.value;
},
// setter
set(newValue) {
this.form.field_type.value = newValue;
this.updateStore();
},
},
},
data() {
return {
fieldTypeChoices: [
{ name: "Booléen", value: "boolean" },
{ name: "Chaîne de caractères", value: "char" },
{ name: "Date", value: "date" },
{ name: "Liste de valeurs", value: "list" },
{ name: "Nombre entier", value: "integer" },
{ name: "Nombre décimal", value: "decimal" },
{ name: "Texte multiligne", value: "text" },
],
form: {
label: {
errors: null,
......@@ -169,17 +163,8 @@ export default {
help_text: "",
field: {
max_length: 50,
choices: [
"Booléen",
"Chaîne de caractères",
"Date",
"Liste de valeurs",
"Nombre entier",
"Nombre décimal",
"Texte multiligne",
],
},
value: null,
value: null, //* field to send to the backend
},
options: {
errors: null,
......@@ -190,11 +175,43 @@ export default {
field: {
max_length: 256,
},
value: null,
value: [],
},
},
};
},
computed: {
selected: {
// getter
get() {
const currentFieldType = this.fieldTypeChoices.find(
(el) => el.value === this.form.field_type.value
);
if (currentFieldType) {
return currentFieldType.name;
}
return null;
},
// setter
set(newValue) {
this.form.field_type.value = newValue.value;
this.form = { ...this.form }; // ! quick & dirty fix for getter not updating because of Vue caveat https://vuejs.org/v2/guide/reactivity.html#For-Objects
// Vue.set(this.form.field_type, "value", newValue.value); // ? vue.set didn't work, maybe should flatten form ?
this.updateStore();
},
},
arrayOption: { // * because backend expects an array
get() {
return [this.form.options.value]
},
set(newValue) {
this.form.options.value = [newValue];
this.updateOptions()
}
}
},
methods: {
removeCustomForm() {
this.$store.commit(
......@@ -217,14 +234,16 @@ export default {
this.$store.commit("feature_type/UPDATE_COLOR_STYLE");
},
},
// beforeDestroy(){
// this.$store.commit("feature_type/EMPTY_CUSTOM_FORM");
// },
beforeDestroy(){
this.$store.commit("feature_type/EMPTY_CUSTOM_FORMS");
},
mounted() {
for (let el in this.customForm) {
if (el && this.form[el]) this.form[el].value = this.customForm[el].value;
if (el && this.form[el] && this.customForm[el]) {
this.form[el].value = this.customForm[el].value;
}
}
this.updateStore();
},
};
</script>
......@@ -4,7 +4,7 @@ import axios from "axios"
// export const RESET = 'RESET';
/* const initialState = () => ({
/* const initialState = () => ({ // ? closure ?
form: null,
colorsStyleList: [],
customForms: [],
......@@ -59,6 +59,9 @@ const feature_type = {
},
SET_IMPORT_FEATURE_TYPES_DATA(state, payload) {
state.importFeatureTypeData = payload;
},
EMPTY_CUSTOM_FORMS(state) {
state.customForms = [];
}
},
getters: {
......@@ -81,11 +84,11 @@ const feature_type = {
//'project': state.form.project.value,
'customfield_set': state.customForms.map(el => {
return {
'position': el.position.value,
'label': el.label.value,
'name': el.name.value,
'field_type': el.field_type.value,
'options': el.options.value,
'position': el.position,
'label': el.label,
'name': el.name,
'field_type': el.field_type,
'options': el.options,
}
}),
//'is_editable': true,
......@@ -96,26 +99,21 @@ const feature_type = {
.post(`${process.env.VUE_APP_DJANGO_API_BASE}feature-types/`, data)
.then((response) => {
console.log(response)
// const routerHistory = this.$router.options.routerHistory
//store.commit("SET_USER", response.data.user);
// this.$router.push(routerHistory[routerHistory.length - 1] || "/")
//store.dispatch("GET_USER_LEVEL_PROJECTS");
})
.catch((error) => {
console.error(error);
// store.commit("SET_USER", false)
});
},
POST_FEATURES_FROM_GEOJSON({ rootGetters, dispatch }, payload) {
const { feature_type_slug, filenameToImport } = payload
POST_FEATURES_FROM_GEOJSON({ dispatch }, payload) {
const { slug, feature_type_slug, filenameToImport } = payload
if (filenameToImport.size > 0) {
var formData = new FormData();
formData.append("json_file", filenameToImport);
let url =
process.env.VUE_APP_URL_BASE +
"projet/" + rootGetters.project.slug +
"projet/" + slug +
"/type-signalement/" + feature_type_slug +
"/importer-geojson/";
axios
......@@ -146,7 +144,6 @@ const feature_type = {
.get(url)
.then((response) => {
commit("SET_IMPORT_FEATURE_TYPES_DATA", response.data);
//commit("SET_IMPORT_TASK_DATA", response.data);
})
.catch((err) => {
console.log(err);
......
......@@ -209,11 +209,7 @@ export default {
watch: {
structure(newVal, oldVal) {
if (newVal !== oldVal) {
//this.getImports();
this.$store.dispatch(
"feature_type/GET_IMPORTS",
this.structure.slug
);
this.$store.dispatch("feature_type/GET_IMPORTS", this.structure.slug);
}
},
},
......@@ -227,7 +223,6 @@ export default {
fileToImport: {},
showImport: false,
showExport: true,
//dataImport: [],
};
},
......@@ -240,54 +235,11 @@ export default {
importGeoJson() {
this.$store.dispatch("feature_type/POST_FEATURES_FROM_GEOJSON", {
//slug: this.$route.params.slug,
slug: this.$route.params.slug,
feature_type_slug: this.$route.params.feature_type_slug,
filenameToImport: this.filenameToImport,
});
/* if (this.filenameToImport.size > 0) {
var formData = new FormData();
formData.append("json_file", this.filenameToImport);
let url =
process.env.VUE_APP_URL_BASE +
"projet/" +
this.$route.params.slug +
"/type-signalement/" +
this.$route.params.feature_type_slug +
"/importer-geojson/";
axios
.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
if (response.status == 200) {
this.getImports();
// TODO : RELOAD DERNIER SIGNALEMENTS
}
})
.catch((err) => {
// TODO : HANDLER ERROR
console.log(err);
});
} */
},
/* getImports() {
let url =
process.env.VUE_APP_DJANGO_API_BASE +
"import-tasks?feature_type_id=" +
this.structure.feature_type;
axios
.get(url)
.then((response) => {
this.dataImport = response.data;
})
.catch((err) => {
console.log(err);
});
}, */
exportFeatures() {
console.log("TEST", this.$store);
this.$store.dispatch(
......
......@@ -32,7 +32,7 @@
v-model="form.title.value"
@blur="updateStore"
/>
<ul class="errorlist">
<ul id="errorlist" class="errorlist">
<li v-for="error in form.title.errors" :key="error">
{{ error }}
</li>
......@@ -43,9 +43,9 @@
form.geom_type.label
}}</label>
<Dropdown
:options="form.geom_type.field.choices"
:selected="selected_geom_type"
:selection.sync="selected_geom_type"
:options="geomTypeChoices"
:selected="selectedGeomType"
:selection.sync="selectedGeomType"
/>
<!-- {{ form.geom_type.errors }} -->
</div>
......@@ -156,6 +156,11 @@ export default {
return {
action: "create",
dataKey: 0,
geomTypeChoices: [
{ value: "linestring", name: "Ligne" },
{ value: "point", name: "Point" },
{ value: "polygon", name: "Polygone" },
],
form: {
colors_style: {
value: null,
......@@ -185,7 +190,7 @@ export default {
id_for_label: "geom_type",
label: "Type de géométrie",
field: {
choices: ["Ligne", "Point", "Polygone"],
//choices: ["Ligne", "Point", "Polygone"],
max_length: 128, // ! Vérifier la valeur dans django
},
html_name: "geom_type",
......@@ -203,16 +208,6 @@ export default {
"deletion_on",
"feature_type",
],
typeDict: {
boolean: "Booléen",
string: "Chaîne de caractères",
date: "Date",
list: "Liste de valeurs",
integer: "Nombre entier",
decimal: "Nombre décimal",
text: "Texte multiligne",
},
};
},
props: ["geojson"],
......@@ -221,12 +216,19 @@ export default {
...mapGetters(["project"]),
...mapState("feature_type", ["customForms", "colorsStyleList"]),
...mapGetters("feature_type", ["feature_type"]),
selected_geom_type: {
selectedGeomType: {
get() {
return this.form.geom_type.value;
const currentGeomType = this.geomTypeChoices.find(
(el) => el.value === this.form.geom_type.value
);
if (currentGeomType) {
return currentGeomType ? currentGeomType.name : null;
}
return null;
},
set(newValue) {
this.form.geom_type.value = newValue;
this.form.geom_type.value = newValue.value;
this.form = { ...this.form }; // ! quick & dirty fix for getter not updating because of Vue caveat https://vuejs.org/v2/guide/reactivity.html#For-Objects
this.updateStore();
},
},
......@@ -275,7 +277,7 @@ export default {
dataKey: this.dataKey,
};
if (customForm) {
newCustomForm = { newCustomForm, ...customForm };
newCustomForm = { ...newCustomForm, ...customForm };
}
this.$store.commit("feature_type/ADD_CUSTOM_FORM", newCustomForm); // * create an object with the counter in store
},
......@@ -302,6 +304,9 @@ export default {
!this.form.title.errors.includes("Veuillez compléter ce champ.") // TODO : Gérer les autres champs
) {
this.form.title.errors.push("Veuillez compléter ce champ.");
document
.getElementById("errorlist")
.scrollIntoView({ block: "end", inline: "nearest" });
}
},
postFeatureTypeNfeatures() {
......@@ -327,67 +332,59 @@ export default {
},
translateLabel(value) {
if (value == "LineString") {
return "Ligne";
return "linestring";
} else if (value == "Polygon") {
return "Polygone";
return "polygon";
}
return "point";
//("linestring", "Ligne"),
//("point", "Point"),
//("polygon", "Polygone"),
},
transformProperties(prop) {
const type = typeof prop;
const date = new Date(prop);
if (type === "boolean") {
return "Booléen";
return "boolean";
} else if (type === "number") {
return "Nombre entier";
return "integer";
} else if (type === "string") {
//* check if string is not convertible to a decimal
if (isNaN(parseFloat(prop))) {
if (new Date(prop) !== "Invalid Date") {
return "Date";
} /* else if (prop.includes(",")) {
return "Liste de valeurs";
} */
else {
return "Chaîne de caractères";
}
} else {
return "Nombre décimal";
//* check if string is convertible to a number, then it should be a decimal
if (date instanceof Date && !isNaN(date.valueOf())) {
return "date";
} else if (!isNaN(parseFloat(prop))) {
return "decimal";
}
}
return null;
},
getFieldType(val) {
if (val in this.typeDict) return this.typeDict[val];
return "char"; //* string by default, most accepted type in database
},
importGeoJson() {
this.updateStore()
// TODO : VALIDATION IF A JSONDICT HAS NOT FEATURES
if (this.geojson.features) {
if (this.geojson.features && this.geojson.features.length) {
//* in order to get feature_type properties, the first feature is enough
const { properties, geometry } = this.geojson.features[0];
this.form.title.value = properties.feature_type;
this.form.geom_type.value = this.translateLabel(geometry.type);
this.updateStore(); //* register title & geom_type in store
//* loop properties to create a customForm for each of them
for (const [key, val] of Object.entries(properties)) {
//* check that the property is not a keyword from the backend or map style (to add)
//* check that the property is not a keyword from the backend or map style
// todo: add map style keywords)
if (!this.reservedKeywords.includes(key)) {
const customForm = {
label: { value: key || "" },
name: { value: key || "" },
// todo : increment position
position: { value: 0 }, // * not available in export
position: { value: this.dataKey }, // * use dataKey incremented at addCustomForm
field_type: { value: this.transformProperties(val) }, // * guessed from the type
options: { value: null }, // * not available in export
options: { value: [] }, // * not available in export
};
console.log("customForm", customForm, this.transformProperties(val), val);
console.log(
"val",
val,
"transformProperties",
this.transformProperties(val)
);
this.addCustomForm(customForm);
}
}
......
......@@ -193,7 +193,8 @@
<label class="ui" for="json_file">
<i class="ui plus icon"></i>
<span class="label"
>Créer un nouveau type de signalement à partir d'un GeoJSON</span
>Créer un nouveau type de signalement à partir d'un
GeoJSON</span
>
</label>
<input
......@@ -486,8 +487,8 @@ export default {
...mapState(["last_comments", "user"]),
BASE_URL: () => process.env.VUE_APP_BASE_URL,
last_features: function () {
// TODO : Filter les dernières
return this.$store.state.feature.features;
// * limit to last five element of array (looks sorted chronologically, but not sure...)
return this.$store.state.feature.features.slice(-5);
},
},
created() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment