view client/src/components/sections/Sections.vue @ 5629:84d01a536bec 729-node-js-newer-version

Transformed scss and sass styles into css
author Luisa Beerboom <lbeerboom@intevation.de>
date Thu, 11 May 2023 13:23:52 +0200
parents 6b054b91d9b2
children
line wrap: on
line source

<template>
  <div class="d-flex flex-column">
    <UIBoxHeader icon="road" :title="title" :closeCallback="$parent.close" />
    <div class="position-relative">
      <UISpinnerOverlay v-if="loading" />
      <SectionForm v-if="showForm" :editSection="editSection" />
      <div v-else>
        <UITableHeader
          :columns="[
            { id: 'properties.name', title: `${nameLabel}`, class: 'col-4' },
            {
              id: 'properties.date_info',
              title: `${dateLabel}`,
              class: 'col-2'
            },
            {
              id: 'properties.source_organization',
              title: `${sourceorganizationLabel}`,
              class: 'col-3'
            }
          ]"
        />
        <UITableBody
          :data="filteredSections() | sortTable(sortColumn, sortDirection)"
        >
          <template v-slot:row="{ item: section }">
            <div class="py-1 px-2 col-4">
              <a @click="moveMapToSection(section)" href="#">
                {{ section.properties.name }}
              </a>
            </div>
            <div class="py-1 px-2 col-2">
              {{ section.properties.date_info | surveyDate }}
            </div>
            <div class="py-1 px-2 col-3">
              {{ section.properties.source_organization }}
            </div>
            <div class="py-1 px-2 col text-right">
              <button
                v-if="isInStaging(section.properties.name)"
                @click="gotoStaging(section.properties.name)"
                class="btn btn-xs btn-danger mr-1"
              >
                <font-awesome-icon
                  icon="exclamation-triangle"
                  fixed-width
                  v-tooltip="reviewTooltip"
                />
              </button>
              <button
                v-if="
                  userCountry === 'global' ||
                    section.properties.country === userCountry
                "
                class="btn btn-xs btn-dark"
                @click="deleteSection(section)"
              >
                <font-awesome-icon icon="trash" fixed-width />
              </button>
            </div>
          </template>
        </UITableBody>
        <div class="text-right p-2 border-top">
          <button
            @click="
              showForm = true;
              editSection = null;
            "
            class="btn btn-sm btn-info"
          >
            <translate>New section</translate>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.input-button {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  right: 0;
  height: 31px;
}
</style>

<script>
/* This is Free Software under GNU Affero General Public License v >= 3.0
 * without warranty, see README.md and license for details.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 * License-Filename: LICENSES/AGPL-3.0.txt
 *
 * Copyright (C) 2018, 2019 by via donau
 *   – Österreichische Wasserstraßen-Gesellschaft mbH
 * Software engineering by Intevation GmbH
 *
 * Author(s):
 * Thomas Junk <thomas.junk@intevation.de>
 * Tom Gottfried <tom.gottfried@intevation.de>
 */
import { mapState, mapGetters } from "vuex";
import { displayError, displayInfo } from "@/lib/errors";
import { HTTP } from "@/lib/http";
import { sortTable } from "@/lib/mixins";

export default {
  mixins: [sortTable],
  components: {
    SectionForm: () => import("./SectionForm")
  },
  data() {
    return {
      staging: [],
      loading: false,
      showForm: false,
      editSection: null
    };
  },
  computed: {
    ...mapState("user", ["user"]),
    ...mapGetters("usermanagement", ["userCountries"]),
    ...mapState("application", ["searchQuery"]),
    ...mapGetters("map", ["openLayersMap"]),
    ...mapState("imports", ["sections"]),
    title() {
      return this.$gettext("Define Sections");
    },
    nameLabel() {
      return this.$gettext("Name");
    },
    dateLabel() {
      return this.$gettext("Date");
    },
    sourceorganizationLabel() {
      return this.$gettext("Source organization");
    },
    reviewTooltip() {
      return this.$gettext("Review pending import");
    },
    userCountry() {
      return this.userCountries[this.user];
    }
  },
  methods: {
    filteredSections() {
      return this.sections.filter(s => {
        return (s.properties.name + s.properties.source_organization)
          .toLowerCase()
          .includes(this.searchQuery.toLowerCase());
      });
    },
    gotoStaging(sectionName) {
      let pendingImport = this.staging.find(s => s.name === sectionName);
      if (pendingImport)
        this.$router.push("/imports/overview/" + pendingImport.id);
    },
    isInStaging(sectionName) {
      return !!this.staging.find(s => s.name === sectionName);
    },
    loadStagingData() {
      HTTP.get("/imports?states=pending&kinds=sec", {
        headers: { "X-Gemma-Auth": localStorage.getItem("token") }
      })
        .then(response => {
          response.data.imports.forEach(i => {
            HTTP.get("/imports/" + i.id, {
              headers: { "X-Gemma-Auth": localStorage.getItem("token") }
            })
              .then(response => {
                this.staging.push({
                  id: i.id,
                  name: response.data.summary.section
                });
              })
              .catch(error => {
                let message = "Backend not reachable";
                if (error.response) {
                  const { status, data } = error.response;
                  message = `${status}: ${data.message || data}`;
                }
                displayError({
                  title: this.$gettext("Backend Error"),
                  message: message
                });
              })
              .finally(() => (this.loading = false));
          });
        })
        .catch(error => {
          let message = "Backend not reachable";
          if (error.response) {
            const { status, data } = error.response;
            message = `${status}: ${data.message || data}`;
          }
          displayError({
            title: this.$gettext("Backend Error"),
            message: message
          });
        });
    },
    deleteSection(section) {
      HTTP.post(
        "/imports/dsec",
        {
          id: section.id.split(".")[1] * 1
        },
        {
          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
        }
      ).then(() => {
        displayInfo({
          title: this.$gettext("Staging Area"),
          message: this.$gettext("Deleting ") + section.properties.objnam
        });
      });
    },
    moveMapToSection(section) {
      this.$store.commit("imports/selectedSectionId", section.id);
      this.$store.commit("fairwayavailability/type", "sections");
      this.$store.commit("application/showFairwayDepth", true);
      this.openLayersMap()
        .getLayer("SECTIONS")
        .setVisible(true);
      this.$store.dispatch("map/moveToFeauture", {
        feature: section,
        zoom: 17,
        preventZoomOut: true
      });
    }
  },
  mounted() {
    this.loading = true;
    this.$store
      .dispatch("imports/loadSections")
      .catch(error => {
        let message = "Backend not reachable";
        if (error.response) {
          const { status, data } = error.response;
          message = `${status}: ${data.message || data}`;
        }
        displayError({
          title: this.$gettext("Backend Error"),
          message: message
        });
      })
      .finally(() => (this.loading = false));
    this.loadStagingData();
  }
};
</script>