Newer
Older
Sébastien DA ROCHA
committed
<template>
<div class="fourteen wide column">
<form id="form-project-edit" class="ui form">
<h1>
<span v-if="action === 'edit'"
>Édition du projet "{{ form.title }}"</span
>
<span v-else-if="action === 'create'">Création d'un projet</span>
</h1>
<div class="ui horizontal divider">INFORMATIONS</div>
<div class="two fields">
<div class="required field">
<label for="title">Titre</label>
<input
type="text"
required
maxlength="128"
name="title"
id="title"
v-model="form.title"
/>
<ul id="errorlist-title" class="errorlist">
<li v-for="error in errors.title" :key="error">
{{ error }}
</li>
</ul>
Sébastien DA ROCHA
committed
</div>
<div class="field">
<label>Illustration du projet</label>
<img
class="ui small image"
id="form-input-file-logo"
:src="
thumbnailFileSrc
? thumbnailFileSrc
: DJANGO_BASE_URL + form.thumbnail
"
/>
<label class="ui icon button" for="thumbnail">
<i class="file icon"></i>
<span class="label">{{
form.thumbnail_name ? form.thumbnail_name : fileToImport.name
}}</span>
</label>
<input
@change="onFileChange"
class="file-selection"
type="file"
accept="image/jpeg, image/png"
style="display: none"
name="thumbnail"
id="thumbnail"
/>
<ul v-if="errorThumbnail.length" id="errorlist-thumbnail" class="errorlist">
<li>
{{ errorThumbnail[0] }}
</li>
</ul>
Sébastien DA ROCHA
committed
</div>
</div>
<div class="field">
<label for="description">Description</label>
<textarea
v-model="form.description"
name="description"
rows="5"
></textarea>
<!-- {{ form.description.errors }} -->
</div>
<div class="ui horizontal divider">PARAMÈTRES</div>
<div class="four fields">
<div class="field">
<label for="archive_feature">Délai avant archivage</label>
<div class="ui right labeled input">
<input
type="number"
min="0"
Sébastien DA ROCHA
committed
style="padding: 1px 2px"
name="archive_feature"
id="archive_feature"
v-model="form.archive_feature"
/>
<div class="ui label">jour(s)</div>
</div>
<ul v-if="errors_archive_feature.length" id="errorlist-achivage" class="errorlist">
<li>
{{ errors_archive_feature[0] }}
</li>
</ul>
Sébastien DA ROCHA
committed
</div>
<div class="field">
<label for="delete_feature">Délai avant suppression</label>
<div class="ui right labeled input">
<input
type="number"
min="0"
Sébastien DA ROCHA
committed
style="padding: 1px 2px"
name="delete_feature"
id="delete_feature"
v-model="form.delete_feature"
/>
<div class="ui label">jour(s)</div>
</div>
</div>
<div class="required field">
<label for="access_level_pub_feature"
>Visibilité des signalements publiés</label
>
<Dropdown
:options="levelPermissions"
:selected="form.access_level_pub_feature.name"
:selection.sync="form.access_level_pub_feature"
/>
<ul id="errorlist-access_level_pub_feature" class="errorlist">
<li v-for="error in errors.access_level_pub_feature" :key="error">
{{ error }}
</li>
</ul>
Sébastien DA ROCHA
committed
</div>
<div class="required field">
<label for="access_level_arch_feature">
Visibilité des signalements archivés
</label>
<Dropdown
:options="levelPermissions"
:selected="form.access_level_arch_feature.name"
:selection.sync="form.access_level_arch_feature"
/>
<ul id="errorlist-access_level_arch_feature" class="errorlist">
<li v-for="error in errors.access_level_arch_feature" :key="error">
{{ error }}
</li>
</ul>
Sébastien DA ROCHA
committed
140
141
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
175
176
177
178
179
180
181
182
183
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input
type="checkbox"
v-model="form.moderation"
name="moderation"
id="moderation"
/>
<label for="moderation">Modération</label>
</div>
<!-- {{ form.moderation.errors }} -->
</div>
<div class="field">
<div class="ui checkbox">
<input
type="checkbox"
v-model="form.is_project_type"
name="is_project_type"
id="is_project_type"
/>
<label for="is_project_type">Est un projet type</label>
</div>
<!-- {{ form.is_project_type.errors }} -->
</div>
<div class="ui divider"></div>
<button @click="postForm" type="button" class="ui teal icon button">
<i class="white save icon"></i> Enregistrer les changements
</button>
</form>
</div>
</template>
<script>
const axios = require("axios");
import Dropdown from "@/components/Dropdown.vue";
import { mapGetters } from "vuex";
axios.defaults.headers.common["X-CSRFToken"] = ((name) => {
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return value != null ? unescape(value[1]) : null;
})("csrftoken");
Sébastien DA ROCHA
committed
export default {
name: "Project_edit",
components: {
Dropdown,
},
data() {
return {
action: "create",
levelPermissions: [
{ name: "Utilisateur anonyme", value: "anonymous" },
{ name: "Utilisateur connecté", value: "logged_user" },
{ name: "Contributeur", value: "contributor" },
],
fileToImport: {
name: "Sélectionner une image ...",
size: 0,
},
errors: {
title: [],
access_level_pub_feature: [],
access_level_arch_feature: [],
},
Sébastien DA ROCHA
committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
form: {
title: "",
slug: "",
created_on: "",
updated_on: "",
description: "",
moderation: false,
thumbnail: "", // todo : utiliser l'image par défaut
thumbnail_name: "", // todo: delete after getting image in jpg or png instead of data64 (require post to django)
creator: null,
access_level_pub_feature: { name: "", value: "" },
access_level_arch_feature: { name: "", value: "" },
archive_feature: 0,
delete_feature: 0,
nb_features: 0,
nb_published_features: 0,
nb_comments: 0,
nb_published_features_comments: 0,
nb_contributors: 0,
is_project_type: false,
},
thumbnailFileSrc: "",
};
},
computed: {
...mapGetters(["project"]),
Sébastien DA ROCHA
committed
return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
},
},
methods: {
definePageType() {
if (this.$router.history.current.name === "project_create") {
this.action = "create";
} else if (this.$router.history.current.name === "project_edit") {
this.action = "edit";
} else if (this.$router.history.current.name === "project_create_from") {
this.action = "create_from";
}
},
truncate(n, len) {
let ext = n.substring(n.lastIndexOf(".") + 1, n.length).toLowerCase();
let filename = n.replace("." + ext, "");
Sébastien DA ROCHA
committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
if (filename.length <= len) {
return n;
}
filename = filename.substr(0, len) + (n.length > len ? "[...]" : "");
return filename + "." + ext;
},
onFileChange(e) {
// * read image file
const files = e.target.files || e.dataTransfer.files;
if (!files.length) return; //* abort if no file
this.fileToImport = files[0]; //* stock the file to post later
let reader = new FileReader(); //* read the file to display in the page
let _this = this; //* 'this' is different in onload function
reader.onload = function (e) {
_this.thumbnailFileSrc = e.target.result;
};
reader.readAsDataURL(this.fileToImport);
},
goBackNrefresh(slug) {
let _this = this;
// * go back to project list
this.$router.push(
{
name: "project_detail",
params: { slug },
},
function () {
_this.$store.dispatch("GET_ALL_PROJECTS"); //* & refresh project list
}
);
},
postProjectThumbnail(projectSlug) {
//* send img to the backend when feature_type is created
let formData = new FormData();
formData.append("file", this.fileToImport);
const url =
this.$store.state.configuration.VUE_APP_DJANGO_API_BASE +
"projects/" +
projectSlug +
"/thumbnail/";
return axios
.put(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
if (response && response.status === 200) {
//dispatch("GET_IMPORTS", feature_type_slug); // ? Besoin de vérifier le statut de l'import ?
this.goBackNrefresh(projectSlug);
}
})
.catch((error) => {
let err_msg = "Transférez une image valide. Le fichier que vous avez transféré n'est pas une image, ou il est corrompu."
if (error.response.data[0])
err_msg = error.response.data[0]
this.errorThumbnail.push(err_msg);
Sébastien DA ROCHA
committed
},
if (this.form.archive_feature > this.form.delete_feature){
this.errors_archive_feature.push("Le délais de suppression doit être supérieur au délais d'archivage.");
return false;
}
for (const key in this.errors) {
if ((key === "title" && this.form[key]) || this.form[key].value) {
this.errors[key] = [];
} else if (!this.errors[key].length) {
this.errors[key].push(
key === "title"
? "Veuillez compléter ce champ."
: "Sélectionnez un choix valide. Ce choix ne fait pas partie de ceux disponibles."
);
document
.getElementById(`errorlist-${key}`)
.scrollIntoView({ block: "end", inline: "nearest" });
return false;
}
}
return true;
},
Sébastien DA ROCHA
committed
async postForm() {
Sébastien DA ROCHA
committed
const projectData = {
title: this.form.title,
description: this.form.description,
access_level_arch_feature: this.form.access_level_arch_feature.value,
access_level_pub_feature: this.form.access_level_pub_feature.value,
archive_feature: this.form.archive_feature,
delete_feature: this.form.delete_feature,
is_project_type: this.form.is_project_type,
moderation: this.form.moderation,
};
if (this.action === "create" || this.action === "duplicate") {
await axios
.post(
`${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/`,
projectData
)
Sébastien DA ROCHA
committed
.then((response) => {
if (response && response.status === 201 && response.data) {
//* send thumbnail after feature_type was created
Sébastien DA ROCHA
committed
this.postProjectThumbnail(response.data.slug);
this.goBackNrefresh(response.data.slug);
}
Sébastien DA ROCHA
committed
}
})
.catch((error) => {
let err_msg = "Veuillez modifier le titre de votre projet, un projet avec ce titre existe déjà."
if (error.response.data.title[0])
err_msg = error.response.data.title[0]
this.errors.title.push(err_msg);
Sébastien DA ROCHA
committed
throw error;
});
} else if (this.action === "edit") {
await axios
.put(
`${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.project.slug}/`,
projectData
)
.then((response) => {
if (response && response.status === 200) {
//* send thumbnail after feature_type was updated
if (this.fileToImport.size > 0) {
Sébastien DA ROCHA
committed
this.postProjectThumbnail(this.project.slug);
} else {
this.goBackNrefresh(this.project.slug);
}
Sébastien DA ROCHA
committed
}
})
.catch((error) => {
throw error;
});
}
},
},
created() {
this.definePageType();

Timothee P
committed
console.log(this.action);
Sébastien DA ROCHA
committed
if (this.action === "create") {
this.thumbnailFileSrc = require("@/assets/img/default.png");

Timothee P
committed
} else if (this.action === "edit" || this.action === "create_from") {
Sébastien DA ROCHA
committed
if (!this.project) {
this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug);
}

Timothee P
committed
this.form = { ...this.project }; //* create a new object to avoid modifying original one
if (this.action === "create_from") {
this.form.title =
this.project.title +
` (Copie-${new Date()
.toLocaleString()
.slice(0, -3)
.replace(",", "")})`;
this.form.is_project_type = false;
}
Sébastien DA ROCHA
committed
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
//* transform string values to objects for dropdowns display (could be in a computed)
this.form.access_level_pub_feature = {
name: this.project.access_level_pub_feature,
value: this.levelPermissions.find(
(el) => (el.name = this.project.access_level_pub_feature)
).value,
};
this.form.access_level_arch_feature = {
name: this.project.access_level_arch_feature,
value: this.levelPermissions.find(
(el) => (el.name = this.project.access_level_arch_feature)
).value,
};
}
},
};
</script>
<style media="screen">
#form-input-file-logo {
margin-left: auto;
margin-right: auto;
}
.close.icon:hover {
cursor: pointer;
}
</style>