view client/src/components/systemconfiguration/MapLayers.vue @ 3678:8f58851927c0

client: make layer factory only return new layer config for individual maps instead of each time it is invoked. The purpose of the factory was to support multiple maps with individual layers. But returning a new config each time it is invoked leads to bugs that rely on the layer's state. Now this factory reuses the same objects it created before, per map.
author Markus Kottlaender <markus@intevation.de>
date Mon, 17 Jun 2019 17:31:35 +0200
parents 32d7bb1afdc9
children 91b4ca03174e
line wrap: on
line source

<template>
  <div class="d-flex flex-column pb-4 border-bottom">
    <h5 class="py-2 px-3 mb-2 m-0"><translate>Map Layers</translate></h5>
    <div class="px-3 container-fluid">
      <div class="row">
        <div class="col-sm-6">
          <div class="form-group">
            <label for="ecdis-url" class="font-weight-bold">
              ECDIS WMS URL
            </label>
            <input
              type="url"
              class="form-control"
              placeholder="https://..."
              @input="lookupWMSCapabilities()"
              v-model="config.ecdis_wms_url"
            />
          </div>
          <label for="ecdis-layers">
            <translate>Layers</translate>
            <transition name="fade"
              ><font-awesome-icon
                icon="spinner"
                spin
                v-if="availableWMSLayersLoading"
                class="ml-2"
            /></transition>
          </label>
          <div class="container-fluid">
            <div class="row">
              <div
                class="custom-control custom-checkbox col-sm-4"
                v-for="layer in availableWMSLayers"
                :key="'layer-' + layer"
              >
                <input
                  type="checkbox"
                  class="custom-control-input"
                  v-model="selectedWMSLayers"
                  :id="'layer-' + layer"
                  :value="layer"
                />
                <label
                  class="custom-control-label text-break"
                  :for="'layer-' + layer"
                >
                  {{ layer }}
                </label>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="mt-4 px-3">
      <a @click.prevent="submit" class="btn btn-info btn-sm text-white">
        <translate>Send</translate>
      </a>
    </div>
  </div>
</template>

<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 by via donau
 *   – Österreichische Wasserstraßen-Gesellschaft mbH
 * Software engineering by Intevation GmbH
 *
 * Author(s):
 * Markus Kottländer <markus@intevation.de>
 */
import { mapState } from "vuex";
import WMSCapabilities from "ol/format/WMSCapabilities";
import { HTTP } from "@/lib/http";

const WMSCapabilitiesParser = new WMSCapabilities();

export default {
  data() {
    return {
      selectedWMSLayers: [],
      availableWMSLayers: [],
      availableWMSLayersLoading: false,
      lookupWMSCapabilitiesTimeout: null,
      wmsVersion: ""
    };
  },
  computed: {
    ...mapState("application", ["config"])
  },
  methods: {
    lookupWMSCapabilities() {
      if (this.lookupWMSCapabilitiesTimeout) {
        clearTimeout(this.lookupWMSCapabilitiesTimeout);
      }
      this.lookupWMSCapabilitiesTimeout = setTimeout(() => {
        let url;
        try {
          let urlParts = new URL(this.config.ecdis_wms_url);
          url =
            urlParts.protocol +
            "//" +
            urlParts.host +
            urlParts.pathname.trim("/") +
            "/";
        } catch (e) {
          url = this.config.ecdis_wms_url;
        }
        this.availableWMSLayersLoading = true;
        HTTP.get(url + "?request=GetCapabilities&service=WMS")
          .then(response => {
            let capabilities = WMSCapabilitiesParser.read(response.data);
            this.wmsVersion = capabilities.version;
            this.availableWMSLayers = [];
            this.getLayersRecursive(capabilities.Capability.Layer.Layer);
          })
          .catch(() => {
            this.availableWMSLayers = [];
          })
          .finally(() => (this.availableWMSLayersLoading = false));
      }, 500);
    },
    getLayersRecursive(layers) {
      layers.forEach(l => {
        if (l.hasOwnProperty("Layer")) {
          this.getLayersRecursive(l.Layer);
        } else {
          this.availableWMSLayers.push(l.Name);
        }
      });
    },
    submit() {
      this.$store.dispatch("application/saveConfig", {
        ecdis_wms_url: this.config.ecdis_wms_url,
        ecdis_wms_params: JSON.stringify({
          LAYERS: this.selectedWMSLayers
            .filter(l => this.availableWMSLayers.find(al => al === l))
            .join(","),
          VERSION: this.wmsVersion,
          TILED: true
        })
      });
    }
  },
  mounted() {
    let ecdisWmsParams = JSON.parse(this.config.ecdis_wms_params);
    if (ecdisWmsParams.LAYERS) {
      this.selectedWMSLayers = ecdisWmsParams.LAYERS.split(",");
    }
    this.lookupWMSCapabilities();
  }
};
</script>