Skip to content
Snippets Groups Projects
FeatureAttachmentForm.vue 7.56 KiB
Newer Older
<template>
  <div>
    <div class="ui teal segment">
      <h4>
        Pièce jointe
        <button
          class="ui small compact right floated icon button remove-formset"
          type="button"
          @click="removeAttachmentFormset(form.dataKey)"
Florent Lavelle's avatar
Florent Lavelle committed
          <i
            class="ui times icon"
            aria-hidden="true"
          />
      <!-- {{ form.errors }} -->
      <div class="visible-fields">
        <div class="two fields">
          <div class="required field">
            <label :for="form.title.id_for_label">{{ form.title.label }}</label>
            <input
              :id="form.title.id_for_label"
              v-model="form.title.value"
              type="text"
              required
              :maxlength="form.title.field.max_length"
              :name="form.title.html_name"
            >
            <ul
              :id="form.title.id_for_error"
              class="errorlist"
            >
              <li
                v-for="error in form.title.errors"
                :key="error"
              >
          </div>
          <div class="required field">
            <label>Fichier (PDF, PNG, JPEG)</label>
            <label
              class="ui icon button"
              :for="'attachment_file' + attachmentForm.dataKey"
            >
Florent Lavelle's avatar
Florent Lavelle committed
              <i
                class="file icon"
                aria-hidden="true"
              />
              <span
                v-if="form.attachment_file.value"
                class="label"
              >{{
              <span
                v-else
                class="label"
              >Sélectionner un fichier ... </span>
              :id="'attachment_file' + attachmentForm.dataKey"
              accept="application/pdf, image/jpeg, image/png"
              style="display: none"
              :name="form.attachment_file.html_name"
              @change="onFileChange"
            >
            <ul
              :id="form.attachment_file.id_for_error"
              class="errorlist"
            >
              <li
                v-for="error in form.attachment_file.errors"
                :key="error"
              >
          </div>
        </div>
        <div class="field">
          <label for="form.info.id_for_label">{{ form.info.label }}</label>
          <textarea
            v-model="form.info.value"
          <!-- {{ form.info.errors }} -->
  name: 'FeatureAttachmentFormset',
Timothee P's avatar
Timothee P committed
  props:  {
    attachmentForm: {
      type: Object,
      default: null,
    }
  },
Timothee P's avatar
Timothee P committed
      fileToImport: null,
          value: '',
          errors: null,
          label: 'ID',
          errors: [],
          id_for_error: `errorlist-title-${this.attachmentForm.dataKey}`,
          id_for_label: 'titre',
          field: {
            max_length: 30, // todo : vérifier dans django
          },
          html_name: 'titre',
          label: 'Titre',
          value: '',
          errors: [],
          id_for_error: `errorlist-file-${this.attachmentForm.dataKey}`,
          html_name: 'titre',
          label: 'Titre',
          value: '',
          label: 'Info',

  watch: {
    attachmentForm(newValue) {
      this.initForm(newValue);
    },
    //* utilisation de watcher, car @change aurait un délai
    'form.title.value': function (newValue, oldValue) {
      if (oldValue !== '') {
          this.updateStore();
        }
      }
    },
    'form.info.value': function (newValue, oldValue) {
      if (oldValue !== '') {
          this.updateStore();
        }
      }
    },
  mounted() {
    this.initForm(this.attachmentForm);
  },

Florent Lavelle's avatar
Florent Lavelle committed
      for (const el in attachmentForm) {
          if (el === 'attachment_file' && attachmentForm[el]) {
            this.form[el].value = attachmentForm[el].split('/').pop(); //* keep only the file name, not the path
          } else {
            this.form[el].value = attachmentForm[el];
          }
    removeAttachmentFormset() {
        'feature/REMOVE_ATTACHMENT_FORM',
Florent Lavelle's avatar
Florent Lavelle committed
      if (this.form.id.value) {
        this.$store.commit('feature/ADD_ATTACHMENT_TO_DELETE', this.form.id.value);
Florent Lavelle's avatar
Florent Lavelle committed
      }
      const data = {
        id: this.form.id.value,
        dataKey: this.attachmentForm.dataKey,
        title: this.form.title.value,
        attachment_file: this.form.attachment_file.value,
        info: this.form.info.value,
Timothee P's avatar
Timothee P committed
        fileToImport: this.fileToImport,
      this.$store.commit('feature/UPDATE_ATTACHMENT_FORM', data);
    validateImgFile(files, handleFile) {
Florent Lavelle's avatar
Florent Lavelle committed
      const url = window.URL || window.webkitURL;
      const image = new Image();
      image.onload = function () {
        handleFile(true);
        URL.revokeObjectURL(image.src);
      };
      image.onerror = function () {
        handleFile(false);
        URL.revokeObjectURL(image.src);
      };
      image.src = url.createObjectURL(files);
    },

Timothee P's avatar
Timothee P committed
    onFileChange(e) {
      // * read image file
Timothee P's avatar
Timothee P committed
      const files = e.target.files || e.dataTransfer.files;

      const _this = this; //* 'this' is different in onload function
      function handleFile(isValid) {
        if (isValid) {
          _this.fileToImport = files[0]; //* store the file to post later
          _this.form.attachment_file.value = files[0].name; //* add name to the form for display, in order to match format return from API
          _this.updateStore();
          _this.form.attachment_file.errors = [];
        } else {
          _this.form.attachment_file.errors.push(
            "Transférez une image valide. Le fichier que vous avez transféré n'est pas une image, ou il est corrompu."
          );
        }
      }

      if (files.length) {
        //* exception for pdf
        if (files[0].type === 'application/pdf') {
          handleFile(true);
        } else {
          this.form.attachment_file.errors = [];
          //* check if file is an image and pass callback to handle file
          this.validateImgFile(files[0], handleFile);
        }
      }
Timothee P's avatar
Timothee P committed
    },
      if (this.form.title.value === '') {
        this.form.title.errors = ['Veuillez compléter ce champ.'];
        document
          .getElementById(this.form.title.id_for_error)
          .scrollIntoView({ block: 'start', inline: 'nearest' });
        isValid = false;
      } else if (this.form.attachment_file.value === null) {
        this.form.attachment_file.errors = ['Veuillez compléter ce champ.'];
        this.form.title.errors = [];
        document
          .getElementById(this.form.attachment_file.id_for_error)
          .scrollIntoView({ block: 'start', inline: 'nearest' });
        isValid = false;
      } else {
        this.form.title.errors = [];
        this.form.attachment_file.errors = [];
      }
      return isValid;
    },
Florent Lavelle's avatar
Florent Lavelle committed
</script>