Skip to content
Snippets Groups Projects
Feature_detail.vue 20.9 KiB
Newer Older
      <div class="row">
        <div class="fourteen wide column">
          <h1 class="ui header">
            <div class="content">
              {{ feature.title || feature.feature_id }}
              <div class="ui icon right floated compact buttons">
                <router-link
                  v-if="permissions.can_create_feature"
                  :to="{
                    name: 'ajouter-signalement',
                    params: {
                      slug_type_signal: $route.params.slug_type_signal,
                    },
                  }"
                  class="ui button button-hover-orange"
                  data-tooltip="Ajouter un signalement"
                  data-position="bottom left"
                >
                  <i class="plus fitted icon"></i>
                </router-link>
                <router-link
                  v-if="permissions.can_update_feature"
                  :to="{
                    name: 'editer-signalement',
                    params: {
                      slug_signal: $route.params.slug_signal,
                      slug_type_signal: $route.params.slug_type_signal,
                    },
                  }"
                  class="ui button button-hover-orange"
                >
                  <i class="inverted grey pencil alternate icon"></i>
                </router-link>
                <a
                  v-if="permissions.can_delete_feature"
                  @click="isCanceling = true"
                  id="feature-delete"
                  class="ui button button-hover-red"
                >
                  <i class="inverted grey trash alternate icon"></i>
                </a>
              </div>
              <div class="ui hidden divider"></div>
              <div class="sub header">
                {{ feature.description }}
              </div>
      <div class="row">
        <div class="seven wide column">
          <table class="ui very basic table">
            <tbody>
              <div
                v-frag
                v-for="(field, index) in feature.feature_data"
                :key="'field' + index"
              >
                <tr v-if="field">
                  <td>
                    <b>{{ field.label }}</b>
                  </td>
                  <td>
                    <b>
                      <i
                        v-if="
                          field.field_type === 'boolean' && field.value === true
                        "
                        class="olive check icon"
                      ></i>
                      <i
                        v-else-if="
                          field.field_type === 'boolean' &&
                          field.value === false
                        "
                        class="red times icon"
                      ></i>
                      <span v-else>
                        {{ field.value }}
                      </span>
                    </b>
                  </td>
                </tr>
              </div>
              <tr>
                <td>Auteur</td>
                <td>{{ feature.display_creator }}</td>
              </tr>
              <tr>
                <td>Statut</td>
                  <i
                    v-if="feature.status === 'archived'"
                    class="grey archive icon"
                  ></i>
                  <i
                    v-else-if="feature.status === 'pending'"
                    class="teal hourglass outline icon"
                  ></i>
                  <i
                    v-else-if="feature.status === 'published'"
                    class="olive check icon"
                  ></i>
                  <i
                    v-else-if="feature.status === 'draft'"
                    class="orange pencil alternate icon"
                  ></i>
                  {{ feature.get_status_display }}
                </td>
              </tr>
              <tr>
                <td>Date de création</td>
                <td v-if="feature.created_on">
                  {{ feature.created_on }}
                </td>
              </tr>
              <tr>
                <td>Date de dernière modification</td>
                <td v-if="feature.updated_on">
                  {{ feature.updated_on }}
              </tr>
              <tr>
                <td>Date d'archivage automatique</td>
                <td v-if="feature.archived_on">
                  {{ feature.archived_on }}
                </td>
              </tr>
              <tr>
                <td>Date de suppression automatique</td>
                <td v-if="feature.deletion_on">
                  {{ feature.deletion_on }}
                </td>
              </tr>
            </tbody>
          </table>

          <h3>Liaison entre signalements</h3>
          <table class="ui very basic table">
            <tbody>
              <tr
                v-for="(link, index) in linked_features"
                :key="link.feature_to.title + index"
              >
                <td v-if="link.feature_to.feature_type_slug">
                  {{ link.relation_type_display }}
                  <a @click="pushNgo(link)">{{ link.feature_to.title }} </a>
                  ({{ link.feature_to.display_creator }} -
                  {{ link.feature_to.created_on }})
                  <!--  <router-link
                    :key="$route.fullPath"
                    :to="{
                      name: 'details-signalement',
                      params: {
                        slug_type_signal: link.feature_to.feature_type_slug,
                        slug_signal: link.feature_to.feature_id,
                      },
                    }"
                    >{{ link.feature_to.title }}</router-link
                  >
                  ({{ link.feature_to.display_creator }} -
                  {{ link.feature_to.created_on }})
        <div class="seven wide column">
          <div id="map"></div>
        </div>
      <div class="row">
        <div class="seven wide column">
          <h2 class="ui header">Pièces jointes</h2>
          <div v-for="pj in attachments" :key="pj.id" class="ui divided items">
            <div class="item">
                :href="DJANGO_BASE_URL + pj.attachment_file"
                <img
                  :src="
                    pj.extension === '.pdf'
                      ? require('@/assets/img/pdf.png')
                      : DJANGO_BASE_URL + pj.attachment_file
                  "
                />
              </a>
              <div class="middle aligned content">
                <a
                  class="header"
                  target="_blank"
                  :href="DJANGO_BASE_URL + pj.attachment_file"
                  >{{ pj.title }}</a
                >
                <div class="description">
                  {{ pj.info }}
                </div>
          <i v-if="attachments.length === 0"
            >Aucune pièce jointe associée au signalement.</i
          >
        <div class="seven wide column">
          <h2 class="ui header">Activité et commentaires</h2>
          <div id="feed-event" class="ui feed">
            <div v-frag v-for="(event, index) in events" :key="'event' + index">
              <div v-frag v-if="event.event_type === 'create'">
                <div v-if="event.object_type === 'feature'" class="event">
                  <div class="content">
                    <div class="summary">
                      <div class="date">
                        {{ event.created_on }}
                      </div>
                      Création du signalement
                      <span v-if="user">par {{ event.display_user }}</span>
                    </div>
                  </div>
                </div>
                <div v-else-if="event.object_type === 'comment'" class="event">
                  <div class="content">
                    <div class="summary">
                      <div class="date">
                        {{ event.created_on }}
                      </div>
                      Commentaire
                      <span v-if="user">par {{ event.display_user }}</span>
                    </div>
                    <div class="extra text">
                      {{ event.related_comment.comment }}
                      <div v-frag v-if="event.related_comment.attachment">
                        <br /><a
                          :href="
                            DJANGO_BASE_URL +
                            event.related_comment.attachment.url
                          "
                          tarrget="_blank"
                          ><i class="paperclip fitted icon"></i>
                          {{ event.related_comment.attachment.title }}</a
                        >
                      </div>
              <div v-else-if="event.event_type === 'update'" class="event">
                <div class="content">
                  <div class="summary">
                    <div class="date">
                      {{ event.created_on }}
                    </div>
                    <span v-if="user">par {{ event.display_user }}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div v-if="permissions.can_create_feature" class="ui segment">
            <form
              id="form-comment"
              class="ui form"
              method="POST"
              enctype="multipart/form-data"
            >
              <div class="required field">
                <label :for="comment_form.comment.id_for_label"
                  >Ajouter un commentaire</label
                >
                {{ comment_form.comment.errors }}
                <textarea
                  v-model="comment_form.comment.value"
                  :name="comment_form.comment.html_name"
                  rows="2"
                ></textarea>
              <label>Pièce jointe (facultative)</label>
              <div class="two fields">
                <div class="field">
                  <label class="ui icon button" for="attachment_file">
                    <i class="paperclip icon"></i>
                    <span class="label">{{
                      comment_form.attachment_file.value
                        ? comment_form.attachment_file.value
                        : "Sélectionner un fichier ..."
                    }}</span>
                  </label>
                  <input
                    type="file"
                    accept="application/pdf, image/jpeg, image/png"
                    style="display: none"
                    name="attachment_file"
                    id="attachment_file"
                    @change="getAttachmentFileData($event)"
                  />
                </div>
                <div class="field">
                  <input
                    v-model="comment_form.title.value"
                    type="text"
                    :name="comment_form.title.html_name"
                    :id="comment_form.title.id_for_label"
                  />
                  {{ comment_form.title.errors }}
                </div>
              <button
                @click="postComment"
                type="button"
                class="ui compact green icon button"
              >
                <i class="plus icon"></i> Poster le commentaire
              </button>
            </form>
          </div>
        v-if="isCanceling"
        class="ui dimmer modals page transition visible active"
        style="display: flex !important"
        <div
          :class="[
            'ui mini modal subscription',
            { 'active visible': isCanceling },
          ]"
        >
          <i @click="isCanceling = false" class="close icon"></i>
          <div class="ui icon header">
            <i class="trash alternate icon"></i>
            Supprimer le signalement
          </div>
          <div class="actions">
            <form
              action="{% url 'geocontrib:feature_delete' slug=feature.project.slug feature_type_slug=feature.feature_type.slug feature_id=feature.feature_id %}"
              method="POST"
              <input type="hidden" name="_method" value="delete" />
              <button
                @click="deleteFeature"
                type="button"
                class="ui red compact fluid button"
              >
                Confirmer la suppression
              </button>
            </form>
          </div>
    <div v-frag v-else>Pas de signalement correspondant trouvé</div>
Timothee P's avatar
Timothee P committed
import { mapGetters, mapState } from "vuex";
import { mapUtil } from "@/assets/js/map-util.js";
import featureAPI from "@/services/feature-api";
const axios = require("axios");

export default {
  name: "Feature_detail",

  directives: {
    frag,
  },

  data() {
    return {
      isCanceling: false,
      attachments: [],
      events: [],
      comment_form: {
        attachment_file: {
          errors: null,
          value: null,
          file: null,
        },
        title: {
          id_for_label: "title",
          html_name: "title",
          errors: null,
          value: null,
        },
        comment: {
          id_for_label: "add-comment",
          html_name: "add-comment",
          errors: null,
          value: null,
        },
        non_field_errors: [],
      },
    };
  },

  computed: {
    ...mapState(["user"]),
Timothee P's avatar
Timothee P committed
    ...mapGetters(["permissions"]),
    ...mapState("feature", ["linked_features"]),
    DJANGO_BASE_URL: function () {
      return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
    },

      const result = this.$store.state.feature.features.find(
        (el) => el.feature_id === this.$route.params.slug_signal
      console.log("result", result);
      return result;
    pushNgo(link) {
      this.$router.push({
        name: "details-signalement",
        params: {
          slug_type_signal: link.feature_to.feature_type_slug,
          slug_signal: link.feature_to.feature_id,
        },
      });
      this.getFeatureEvents();
      this.getFeatureAttachments();
      this.getLinkedFeatures();
      this.addFeatureToMap();
      //this.initMap();
      //this.$router.go();
    },

      featureAPI
        .postComment({
          featureId: this.$route.params.slug_signal,
          comment: this.comment_form.comment.value,
        })
        .then((response) => {
          if (response && this.comment_form.attachment_file.file) {
            featureAPI
              .postCommentAttachment({
                featureId: this.$route.params.slug_signal,
                file: this.comment_form.attachment_file.file,
                fileName: this.comment_form.title.file,
                comment: response.data.id,
              })
              .then(() => {
Timothee P's avatar
Timothee P committed
                this.confirmComment();
                //this.getFeatureAttachments(); //* display new attachment from comment on the page
Timothee P's avatar
Timothee P committed
            this.confirmComment();
Timothee P's avatar
Timothee P committed
    confirmComment() {
      this.$store.commit("DISPLAY_MESSAGE", "Ajout du commentaire confirmé");
      this.getFeatureEvents(); //* display new comment on the page
      this.comment_form.attachment_file.file = null;
      this.comment_form.attachment_file.value = null;
      this.comment_form.title.file = null;
      this.comment_form.title.value = null;
      this.comment_form.comment.value = null;
    },

    getAttachmentFileData(evt) {
      const files = evt.target.files || evt.dataTransfer.files;
      const period = files[0].name.lastIndexOf(".");
      const fileName = files[0].name.substring(0, period);
      const fileExtension = files[0].name.substring(period + 1);
      const shortName = fileName.slice(0, 10) + "[...]." + fileExtension;
      this.comment_form.attachment_file.file = files[0];
      this.comment_form.attachment_file.value = shortName;
      this.comment_form.title.value = shortName;
    },
leandro's avatar
leandro committed
    goBackToProject(message) {
      this.$router.push({
        name: "project_detail",
        params: {
          slug: this.$store.state.project_slug,
          message,
        },
      });
    },
      this.$store
        .dispatch("feature/DELETE_FEATURE", this.feature.feature_id)
        .then((response) => {
          if (response.status === 204) {
            this.$store.dispatch("feature/GET_PROJECT_FEATURES");
            this.goBackToProject();
          }
        });
    initMap() {
      var mapDefaultViewCenter =
        this.$store.state.configuration.DEFAULT_MAP_VIEW.center;
      var mapDefaultViewZoom =
        this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom;
      this.map = mapUtil.createMap({
        mapDefaultViewCenter,
        mapDefaultViewZoom,
      });

      // Update link to feature list with map zoom and center
      mapUtil.addMapEventListener("moveend", function () {
        // update link to feature list with map zoom and center
        /*var $featureListLink = $("#feature-list-link")
        var baseUrl = $featureListLink.attr("href").split("?")[0]

        $featureListLink.attr("href", baseUrl +`?zoom=${this.map.getZoom()}&lat=${this.map.getCenter().lat}&lng=${this.map.getCenter().lng}`)*/
      });

      // Load the layers.
      // - if one basemap exists, we load the layers of the first one
      // - if not, load the default map and service options
      let layersToLoad = null;
      var baseMaps = this.$store.state.map.basemaps;
DESPRES Damien's avatar
DESPRES Damien committed
      var layers = this.$store.state.map.layers;
DESPRES Damien's avatar
DESPRES Damien committed
        const basemapIndex = 0;
        layersToLoad = baseMaps[basemapIndex].layers;
        layersToLoad.forEach((layerToLoad) => {
          layers.forEach((layer) => {
            if (layer.id === layerToLoad.id) {
              layerToLoad = Object.assign(layerToLoad, layer);
            }
          });
        });
        layersToLoad.reverse();
      }
      mapUtil.addLayers(
        layersToLoad,
        this.$store.state.configuration.DEFAULT_BASE_MAP.SERVICE,
        this.$store.state.configuration.DEFAULT_BASE_MAP.OPTIONS
      );

      mapUtil.getMap().dragging.disable();
      mapUtil.getMap().doubleClickZoom.disable();
      mapUtil.getMap().scrollWheelZoom.disable();

      this.addFeatureToMap();
    },

    addFeatureToMap() {
      const currentFeatureId = this.$route.params.slug_signal;
      const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${currentFeatureId}/?feature_type__slug=${this.$route.params.slug_type_signal}&output=geojson`;
        .then((response) => {
          const feature = response.data;
          if (feature) {
            const currentFeature = [feature];
            const featureGroup = mapUtil.addFeatures(currentFeature);
            mapUtil.getMap().fitBounds(featureGroup.getBounds());
          }
        })
        .catch((error) => {
          throw error;
        });
    getFeatureEvents() {
      featureAPI
        .getFeatureEvents(this.$route.params.slug_signal)
        .then((data) => (this.events = data));
    },

    getFeatureAttachments() {
      featureAPI
        .getFeatureAttachments(this.$route.params.slug_signal)
        .then((data) => (this.attachments = data));
    },

    getLinkedFeatures() {
      featureAPI
        .getFeatureLinks(this.$route.params.slug_signal)
        .then((data) =>
          this.$store.commit("feature/SET_LINKED_FEATURES", data)
        );
    },
    // if (!this.project) {
    //   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
    );
    this.getFeatureEvents();
    this.getFeatureAttachments();
    this.getLinkedFeatures();
    if (!this.project) {
      this.$store
        .dispatch("GET_PROJECT_INFO", this.$route.params.slug)
        .then((data) => {
          console.log(data);
          this.initMap();
        });
    } else {
      this.initMap();
    }

  beforeDestroy() {
    this.$store.commit("CLEAR_MESSAGES");
  },
};
</script>

<style>
#map {
  width: 100%;
  height: 100%;
  min-height: 250px;
  max-height: 70vh;
}
#feed-event .event {
  margin-bottom: 1em;
}
#feed-event .event .date {
  margin-right: 1em !important;
}
#feed-event .event .extra.text {
  margin-left: 107px;
  margin-top: 0;
}
</style>