Skip to content
Snippets Groups Projects
Feature_detail.vue 18.5 KiB
Newer Older
<template>
  <div v-frag>
    <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">
              <!-- {% if permissions|lookup:'can_create_feature' %} -->
              <router-link
                :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>
              <!-- {% endif %} {% if permissions|lookup:'can_update_feature' %} -->
              <router-link
                :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>
              <!-- {% endif %} {% if permissions|lookup:'can_delete_feature' %} -->
              <a
                @click="isCanceling = true"
                id="feature-delete"
                class="ui button button-hover-red"
              >
                <i class="inverted grey trash alternate icon"></i>
              </a>
              <!-- {% endif %} -->
            </div>
            <div class="ui hidden divider"></div>
            <div class="sub header">
              {{ feature.description }}
              <!--  | linebreaks -->
            </div>
          </div>
        </h1>
      </div>
    </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>
              <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 }}
              </td>
            </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>
                {{ link.relation_type }}
                <router-link
                  :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.creator }} -
                {{ link.feature_to.created_on }})
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="seven wide column">
        <div id="map"></div>
      </div>
    </div>

    <div class="row">
      <div class="seven wide column">
        <h2 class="ui header">Pièces jointes</h2>

Timothee P's avatar
Timothee P committed
        <div v-for="pj in attachments" :key="pj.id" class="ui divided items">
          <div class="item">
            <a
              class="ui tiny image"
              target="_blank"
              :href="DJANGO_BASE_URL + pj.attachment_file"
                :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>
            </div>
          </div>
        </div>
        <i v-if="attachments.length === 0"
          >Aucune pièce jointe associée au signalement.</i
        >
      </div>

      <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.attachments">
                      <div
                        v-frag
                        v-for="att in event.related_comment.attachments"
                        :key="att.title"
                      >
                        <br /><a :href="att.url" tarrget="_blank"
                          ><i class="paperclip fitted icon"></i>
                          {{ att.title }}</a
                        >
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div v-else-if="event.event_type === 'update'" class="event">
              <div class="content">
                <div class="summary">
                  <div class="date">
                    {{ event.created_on }}
                  </div>
                  Signalement mis à jour
                  <span v-if="user">par {{ event.display_user }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- {% if permissions|lookup:'can_create_feature' %} -->
        <div class="ui segment">
          <form
            id="form-comment"
            class="ui form"
            method="POST"
            enctype="multipart/form-data"
          >
            <!-- <div
              v-if="comment_form.non_field_errors"
              class="alert alert-danger"
              role="alert"
            >
              <span v-for="error in comment_form.non_field_errors" :key="error">
                {{ error }}
              </span>
            </div> -->
            <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>
            </div>
            <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)"
                />
                <!-- {{ comment_form.attachment_file.errors }} -->
              </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>
            </div>
            <button
              @click="postComment"
              type="button"
              class="ui compact green icon button"
            >
              <i class="plus icon"></i> Poster le commentaire
            </button>
          </form>
        </div>
      </div>
    </div>

    <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>
    </div>
  </div>
</template>

<script>
import frag from "vue-frag";
import { 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"]),
    ...mapState("feature", ["linked_features"]),
    DJANGO_BASE_URL: function () {
      return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
    },

    feature: function () {
      return (
        this.$store.state.feature.features.find(
          (el) => el.feature_id === this.$route.params.slug_signal
        ) || []
      );
    },
  },

  methods: {
    postComment() {
      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,
            });
          }
        });
    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;
    },
    deleteFeature() {
      this.$store.dispatch(
        "feature/DELETE_FEATURE",
        this.$route.params.slug_signal
      );
    },
    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;
      var project = "";
      var layers = [];
      if (baseMaps && baseMaps.length > 0) {
        // Use active one if exists, otherwise index 0 (first basemap in the list)
        const mapOptions =
          JSON.parse(localStorage.getItem("geocontrib-map-options")) || {};
        const basemapIndex =
          mapOptions &&
          mapOptions[project] &&
          mapOptions[project]["current-basemap-index"]
            ? mapOptions[project]["current-basemap-index"]
            : 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();
      var currentFeatureId = this.$route.params.slug_signal;
      const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${currentFeatureId}/?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;
        });

    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)
        );
    },
  },

  created() {
    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.getFeatureAttachments();
    this.getLinkedFeatures();
  },

  mounted() {
    this.initMap();
  },
};
</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>