Mercurial > gemma
view client/src/components/systemconfiguration/PDFTemplates.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 | f96def15847e |
children | 851c0ccba59b |
line wrap: on
line source
<template> <div class="d-flex flex-column pb-4 border-bottom"> <h5 class="py-2 px-3 m-0"><translate>PDF-Templates</translate></h5> <input @change="uploadTemplate" id="uploadTemplate" ref="uploadTemplate" type="file" style="visibility: hidden; position: absolute;" /> <UITableHeader :columns="[ { id: 'name', title: `${nameLabel}`, class: 'col-3' }, { id: 'time', title: `${dateLabel}`, class: 'col-3' }, { id: 'type', title: `${typeLabel}`, class: 'col-2' }, { id: 'country', title: `${countryLabel}`, class: 'col-2' } ]" /> <UITableBody :data="templates | sortTable(sortColumn, sortDirection)"> <template v-slot:row="{ item: template }"> <div class="py-1 col-3">{{ template.name }}</div> <div class="py-1 col-3">{{ template.time }}</div> <div class="py-1 col-2">{{ template.type }}</div> <div class="py-1 col-2" v-if="template.country"> {{ template.country }} </div> <div class="py-1 col-2" v-else><i>global</i></div> <div class="col py-1 text-right"> <button class="btn btn-xs btn-info mr-1" ref="downloadTemplate" @click="downloadTemplate(template)" > <font-awesome-icon icon="download" fixed-width /> </button> <button class="btn btn-xs btn-dark" @click="deleteTemplate(template)"> <font-awesome-icon icon="trash" fixed-width /> </button> </div> </template> </UITableBody> <div class="px-3 mt-2"> <button class="btn btn-info btn-sm mr-2" @click=" type = 'map'; $refs.uploadTemplate.click(); " > <font-awesome-icon icon="spinner" class="fa-spin fa-fw" v-if="uploading" /> <font-awesome-icon icon="upload" class="fa-fw" v-else /> <translate>Upload new map template</translate> </button> <button class="btn btn-info btn-sm" @click=" type = 'diagram'; $refs.uploadTemplate.click(); " > <font-awesome-icon icon="spinner" class="fa-spin fa-fw" v-if="uploading" /> <font-awesome-icon icon="upload" class="fa-fw" v-else /> <translate>Upload new diagram template</translate> </button> </div> </div> </template> <style lang="scss" scoped> .table th, td { font-size: $smaller; border-top: 0px !important; text-align: left; padding: $small-offset !important; } </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): * Markus Kottländer <markus@intevation.de> * Fadi Abbud <fadi.abbud@intevation.de> */ import { HTTP } from "@/lib/http"; import { displayError, displayInfo } from "@/lib/errors"; import { sortTable } from "@/lib/mixins"; export default { name: "pdftemplates", mixins: [sortTable], data() { return { templates: [], uploading: false, type: null }; }, computed: { nameLabel() { return this.$gettext("Name"); }, dateLabel() { return this.$gettext("Date"); }, countryLabel() { return this.$gettext("Country"); }, typeLabel() { return this.$gettext("Type"); } }, methods: { downloadTemplate(template) { if (template) { var templateData = ""; var element = document.createElement("a"); element.style.display = "none"; element.setAttribute("download", template.name + ".json"); document.body.appendChild(element); HTTP.get(`/templates/${template.type}/${template.name}`, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(response => { templateData = response.data.template_data; element.setAttribute( "href", "data:text/json;charset=utf-8," + encodeURIComponent( JSON.stringify( { name: templateData.name, properties: templateData.properties, elements: templateData.elements }, null, 2 ) ) ); element.click(); }) .catch(e => { const { status, data } = e.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }) .finally(() => { document.body.removeChild(element); }); } }, uploadTemplate() { const reader = new FileReader(); reader.onload = event => { let template; try { template = JSON.parse(event.target.result); } catch (e) { displayError({ title: this.$gettext("Format Error"), message: this.$gettext( "Uploaded file does not contain valid json data." ) }); // allow the user to upload the same file // if user wants to upload the same file after edit it. this.$refs.uploadTemplate.value = null; } if (template.name) { // check if an element in the uploaded file does not match the predefind template-elements let checkElement = false; template.elements.forEach(e => { if ( [ "text", "box", "textbox", "image", "bottleneck", "legend", "scalebar", "scale", "northarrow", "diagramlegend", "diagramtitle", "diagram" ].indexOf(e.type) === -1 ) { checkElement = true; displayError({ title: this.$gettext("Invalid element"), message: e.type + this.$gettext(" does not match any template's element") }); // allow the user to upload the same file this.$refs.uploadTemplate.value = null; } }); if (!checkElement) { this.uploading = true; HTTP.post( "/templates/" + this.type + "/" + template.name, { template_name: template.name, template_data: template }, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } } ) .then(() => { this.loadTemplates(); displayInfo({ message: template.name + " " + this.$gettext("uploaded successfully") }); }) .catch(e => { const { status, data } = e.response; if (status === 400) { displayError({ title: this.$gettext("Error"), message: `${data.message || data}` }); } else { displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); } }) .finally(() => { this.uploading = false; this.$refs.uploadTemplate.value = null; }); } } else { displayError({ title: this.$gettext("Format Error"), message: this.$gettext( "The provided template has no name property." ) }); // allow the user to upload the same file this.$refs.uploadTemplate.value = null; } }; reader.onerror = error => console.log(error); reader.readAsText(this.$refs.uploadTemplate.files[0]); }, loadTemplates() { HTTP.get("/templates", { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(response => { this.templates = response.data; }) .catch(e => { const { status, data } = e.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, deleteTemplate(template) { this.$store.commit("application/popup", { icon: "trash", title: this.$gettext("Delete Template"), content: this.$gettext( "Do you really want to delete the following template:" ) + `<br> <b>${template.name}</b>`, confirm: { label: this.$gettext("Delete"), icon: "trash", callback: () => { HTTP.delete(`/templates/${template.type}/${template.name}`, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }).then(() => { let removeIndex = this.templates.findIndex( t => t.name === template.name ); if (removeIndex !== -1) { this.templates.splice(removeIndex, 1); displayInfo({ message: template.name + " " + this.$gettext("deleted successfully") }); } }); } }, cancel: { label: this.$gettext("Cancel"), icon: "times" } }); } }, mounted() { this.loadTemplates(); } }; </script>