Newer
Older

Timothee P
committed
<template>
<div v-frag>
<div class="fourteen wide column">
<h1
v-if="feature && $router.history.current.name === 'editer-signalement'"
>
Mise à jour du signalement "{{ feature.title || feature.feature_id }}"
<h1
v-else-if="
feature_type && $router.history.current.name === 'ajouter-signalement'
"
>
Création d'un signalement <small>[{{ feature_type.title }}]</small>

Timothee P
committed
</h1>
<form
id="form-feature-edit"
action=""
method="post"
enctype="multipart/form-data"
class="ui form"
>
<!-- Feature Fields -->
<div class="two fields">
<div class="required field">
<label :for="form.title.id_for_label">{{ form.title.label }}</label>

Timothee P
committed
<input
type="text"
required
:maxlength="form.title.field.max_length"
:name="form.title.html_name"
:id="form.title.id_for_label"
v-model="form.title.value"

Timothee P
committed
@blur="updateStore"

Timothee P
committed
/>

Timothee P
committed
</div>
<div class="required field">
<label :for="form.status.id_for_label">{{
form.status.label

Timothee P
committed
}}</label>

Timothee P
committed
:selected="selected_status"
:selection.sync="selected_status"

Timothee P
committed
</div>
</div>
<div class="field">
<label :for="form.description.id_for_label">{{
form.description.label

Timothee P
committed
}}</label>
<textarea

Timothee P
committed
rows="5"

Timothee P
committed
@blur="updateStore"

Timothee P
committed
></textarea>

Timothee P
committed
</div>
<!-- Geom Field -->
<div class="field">
<label :for="form.geom.id_for_label">{{ form.geom.label }}</label>

Timothee P
committed
<!-- Import GeoImage -->
<div v-frag v-if="feature_type && feature_type.geom_type === 'point'">
<p>
<button
id="add-geo-image"
type="button"
class="ui compact button"
>
<i class="file image icon"></i>Importer une image géoréférencée
</button>
Vous pouvez utiliser une image géoréférencée pour localiser le
signalement.
</p>

Timothee P
committed
<p>
<button
id="create-point-geoposition"
type="button"
class="ui compact button"
>
<i class="ui map marker alternate icon"></i>Positionner le
signalement à partir de votre géolocalisation
</button>
</p>
<span id="erreur-geolocalisation" style="display: none">
<div class="ui negative message">
<div class="header">
Une erreur est survenue avec la fonctionnalité de
géolocalisation
</div>
<p id="erreur-geolocalisation-message"></p>

Timothee P
committed
</div>

Timothee P
committed

Timothee P
committed
<!-- Map -->
<input
type="hidden"
:name="form.geom.html_name"
:id="form.geom.id_for_label"
v-model="form.geom.value"

Timothee P
committed
@blur="updateStore"

Timothee P
committed
/>
<div class="ui tab active map-container" data-tab="map">
<div id="map"></div>
<!-- {% if serialized_base_maps|length > 0 %} {% include

Timothee P
committed
"geocontrib/map-layers/sidebar-layers.html" with
basemaps=serialized_base_maps layers=serialized_layers
project=project.slug%} {% endif %} -->

Timothee P
committed
</div>
</div>
<!-- Extra Fields -->
<div class="ui horizontal divider">DONNÉES MÉTIER</div>
<!-- // Todo: Récupérer les "extra_form" de l'API -->
<div
v-for="(field, index) in extra_form_with_values"
:key="field.field_type + index"
class="field"
>
<div v-frag v-if="field.field_type === 'char'">
<label for="field.name">{{ field.label }}</label>

Timothee P
committed
<input

Timothee P
committed
:name="field.name"
:id="field.name"
v-model="field.value"

Timothee P
committed
/>
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
</div>
<div v-frag v-else-if="field.field_type === 'list'">
<label for="field.name">{{ field.label }}</label>
<Dropdown
:options="field.choices"
:selected="selected_extra_form_list"
:selection.sync="selected_extra_form_list"
/>
</div>
<div v-frag v-else-if="field.field_type === 'integer'">
<label for="field.name">{{ field.label }}</label>
<div class="ui input">
<!-- //* si click sur fléche dans champ input, pas de focus, donc pas de blur, donc utilisation de @change -->
<input
type="number"
:name="field.name"
:id="field.name"
v-model.number="field.value"
@change="updateStore_extra_form"
/>
</div>
</div>
<div v-frag v-else-if="field.field_type === 'boolean'">
<div class="ui checkbox">
<input
type="checkbox"
:checked="field.value"
:name="field.name"
:id="field.name"
@change="updateStore_extra_form"
/>
<label for="field.name">{{ field.label }}</label>

Timothee P
committed
</div>
</div>
<div v-frag v-else-if="field.field_type === 'date'">
<label for="field.name">{{ field.label }}</label>

Timothee P
committed
<input

Timothee P
committed
:name="field.name"
:id="field.name"
v-model="field.value"

Timothee P
committed
/>
</div>
<div v-frag v-else-if="field.field_type === 'decimal'">

Timothee P
committed
<label for="field.name">{{ field.label }}</label>
<div class="ui input">
<input
type="number"
step=".01"
:name="field.name"
:id="field.name"
v-model.number="field.value"
@change="updateStore_extra_form"
/>
</div>

Timothee P
committed
</div>
<div v-frag v-else-if="field.field_type === 'text'">
<label :for="field.name">{{ field.label }}</label>
<textarea

Timothee P
committed
:name="field.name"

Timothee P
committed
v-model="field.value"
@blur="updateStore_extra_form"
></textarea>

Timothee P
committed
</div>
{{ field.errors }}
</div>
<!-- Pièces jointes -->
<div class="ui horizontal divider">PIÈCES JOINTES</div>

Timothee P
committed
<!-- {{ attachment_formset.non_form_errors }} -->

Timothee P
committed
<div id="formsets-attachment">

Timothee P
committed
<!-- {{ attachment_formset.management_form }} -->

Timothee P
committed
v-for="form in attachmentFormset"
:key="form.dataKey"
:attachmentForm="form"
/>

Timothee P
committed

Timothee P
committed
<button

Timothee P
committed
id="add-attachment"
type="button"
class="ui compact basic button button-hover-green"
>
<i class="ui plus icon"></i>Ajouter une pièce jointe
</button>
<!-- Signalements liés -->
<div class="ui horizontal divider">SIGNALEMENTS LIÉS</div>
<!-- {{ linked_formset.non_form_errors }} -->

Timothee P
committed
<div id="formsets-link">
<!-- {{ linked_formset.management_form }} -->
<FeatureLinkedForm
v-for="form in linkedFormset"
:key="form.dataKey"
:linkedForm="form"
:features="features"
/>

Timothee P
committed
<button

Timothee P
committed
id="add-link"
type="button"
class="ui compact basic button button-hover-green"
>
<i class="ui plus icon"></i>Ajouter une liaison
</button>
<div class="ui divider"></div>
<button @click="postForm" type="button" class="ui teal icon button">

Timothee P
committed
<i class="white save icon"></i> Enregistrer les changements
</button>
</form>
</div>
</div>
</template>
<script>
import frag from "vue-frag";

Timothee P
committed
import { mapGetters, mapState } from "vuex";
import FeatureAttachmentForm from "@/components/feature/FeatureAttachmentForm";
import FeatureLinkedForm from "@/components/feature/FeatureLinkedForm";
import Dropdown from "@/components/Dropdown.vue";
import SidebarLayers from "@/components/map-layers/SidebarLayers";

Timothee P
committed
export default {
name: "Feature_edit",
directives: {
frag,
},
components: {
FeatureAttachmentForm,
FeatureLinkedForm,

Timothee P
committed
SidebarLayers,
},
computed: {
...mapState(["project"]),
...mapState("feature", [
"attachmentFormset",
"linkedFormset",
"features",
"extra_form",
]),

Timothee P
committed
...mapGetters("feature_type", ["feature_type"]),
feature: function () {
return this.$store.state.feature.features.find(
(el) => el.feature_id === this.$route.params.slug_signal

Timothee P
committed
selected_status: {
get() {

Timothee P
committed
},
set(newValue) {

Timothee P
committed
this.updateStore();
},
},
extra_form_with_values: function () {
return this.extra_form.map((el) => {
return { ...el, value: el.value ? el.value : null };
});
},
selected_extra_form_list: {
get() {

Timothee P
committed
return this.extra_form_with_values.find(
(el) => el.field_type === "list"
).value;

Timothee P
committed
const index = this.extra_form_with_values.findIndex(
(el) => el.field_type === "list"
);
this.extra_form_with_values[index].value = newValue;
this.updateStore_extra_form();
},
},

Timothee P
committed
},
data() {
return {
attachmentDataKey: 0,
linkedDataKey: 0,

Timothee P
committed
title: {
errors: null,
id_for_label: "name",

Timothee P
committed
field: {
max_length: 30,
},
html_name: "name",
label: "Nom",
value: "",

Timothee P
committed
},
status: {
errors: null,
id_for_label: "status",

Timothee P
committed
field: {
choices: ["Brouillon", "Publié", "Archivé"],

Timothee P
committed
},
html_name: "status",
label: "Statut",
value: "Brouillon",

Timothee P
committed
},
description: {
errors: null,
id_for_label: "description",
html_name: "description",
label: "Description",
value: "",

Timothee P
committed
},
geom: {

Timothee P
committed
},
},
};
},
methods: {

Timothee P
committed
this.$store.commit("feature/ADD_ATTACHMENT_FORM", this.attachmentDataKey); // * create an object with the counter in store
this.attachmentDataKey += 1; // * increment counter for key in v-for
this.$store.commit("feature/ADD_LINKED_FORM", this.linkedDataKey); // * create an object with the counter in store
this.linkedDataKey += 1; // * increment counter for key in v-for

Timothee P
committed
updateStore() {
this.$store.commit("feature/UPDATE_FORM", {
title: this.form.title.value,
status: this.form.status.value,
description: this.form.description,

Timothee P
committed
// ? geom ?
});
updateStore_extra_form() {
this.$store.commit(
"feature/UPDATE_EXTRA_FORM",
this.extra_form_with_values
);
},
postForm() {
if (this.form.title.value) {
this.form.title.errors = null;
this.$store.dispatch("feature/POST_FEATURE");
} else {
this.form.title.errors = "Veuillez compléter ce champ.";
}
},

Timothee P
committed
},
created() {
if (!this.project) {

Timothee P
committed
this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
this.$store.commit(
"feature_type/SET_CURRENT_FEATURE_TYPE_SLUG",
this.$route.params.slug_type_signal
);
mounted() {
if (this.$router.history.current.name === "editer-signalement") {
for (let el in this.feature) {
if (el && this.form[el]) this.form[el].value = this.feature[el];
}
}

Timothee P
committed
this.$store.dispatch("map/INITIATE_MAP");
},

Timothee P
committed
};
// TODO : add script from django and convert:
</script>
<style>
#map {
height: 70vh;
width: 100%;

Timothee P
committed
border: 1px solid grey;

Timothee P
committed
@media only screen and (max-width: 767px) {
#map {
height: 80vh;
}
}
/* // ! missing style in semantic.min.css, je ne comprends pas comment... */
.ui.right.floated.button {
float: right;
margin-right: 0;
margin-left: 0.25em;
}

Timothee P
committed
/* // ! margin écrasé par class last-child first-child, pas normal ... */
.ui.segment {
margin: 1rem 0 !important;
}