From 5437969353eccca5884577664fe47b4c440e34fa Mon Sep 17 00:00:00 2001 From: Mauro Bartolomeoli Date: Thu, 18 Jan 2018 12:46:03 +0100 Subject: [PATCH 1/2] Fixes #2526: download button in the TOC --- web/client/actions/layers.js | 13 ++++++-- web/client/components/TOC/Toolbar.jsx | 33 ++++++++++++++++--- .../components/TOC/__tests__/Toolbar-test.jsx | 15 +++++++-- .../epics/__tests__/wfsdownload-test.js | 32 ++++++++++++++++-- web/client/epics/wfsdownload.js | 13 +++++++- web/client/localConfig.json | 1 + web/client/plugins/TOC.jsx | 19 +++++++++-- web/client/selectors/__tests__/layers-test.js | 13 +++++++- web/client/selectors/layers.js | 2 ++ web/client/translations/data.de-DE | 1 + web/client/translations/data.en-US | 1 + web/client/translations/data.es-ES | 1 + web/client/translations/data.fr-FR | 1 + web/client/translations/data.it-IT | 1 + web/client/translations/data.nl-NL | 1 + 15 files changed, 130 insertions(+), 17 deletions(-) diff --git a/web/client/actions/layers.js b/web/client/actions/layers.js index 7954159605..c694982187 100644 --- a/web/client/actions/layers.js +++ b/web/client/actions/layers.js @@ -25,6 +25,7 @@ const REFRESH_LAYERS = 'REFRESH_LAYERS'; const LAYERS_REFRESHED = 'LAYERS_REFRESHED'; const LAYERS_REFRESH_ERROR = 'LAYERS_REFRESH_ERROR'; const BROWSE_DATA = 'LAYERS:BROWSE_DATA'; +const DOWNLOAD = 'LAYERS:DOWNLOAD'; const CLEAR_LAYERS = 'LAYERS:CLEAR_LAYERS'; const SELECT_NODE = 'LAYERS:SELECT_NODE'; const FILTER_LAYERS = 'LAYERS:FILTER_LAYERS'; @@ -189,6 +190,12 @@ function browseData(layer) { layer }; } +function download(layer) { + return { + type: DOWNLOAD, + layer + }; +} function clearLayers() { return { type: CLEAR_LAYERS @@ -227,8 +234,10 @@ function hideLayerMetadata() { module.exports = {changeLayerProperties, changeGroupProperties, toggleNode, sortNode, removeNode, contextNode, updateNode, layerLoading, layerLoad, layerError, addLayer, removeLayer, showSettings, hideSettings, updateSettings, refreshLayers, - layersRefreshed, layersRefreshError, refreshLayerVersion, browseData, clearLayers, selectNode, filterLayers, showLayerMetadata, hideLayerMetadata, + layersRefreshed, layersRefreshError, refreshLayerVersion, browseData, clearLayers, selectNode, filterLayers, showLayerMetadata, + hideLayerMetadata, download, CHANGE_LAYER_PROPERTIES, CHANGE_GROUP_PROPERTIES, TOGGLE_NODE, SORT_NODE, REMOVE_NODE, UPDATE_NODE, LAYER_LOADING, LAYER_LOAD, LAYER_ERROR, ADD_LAYER, REMOVE_LAYER, - SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, BROWSE_DATA, CLEAR_LAYERS, SELECT_NODE, FILTER_LAYERS, SHOW_LAYER_METADATA, HIDE_LAYER_METADATA + SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, BROWSE_DATA, DOWNLOAD, + CLEAR_LAYERS, SELECT_NODE, FILTER_LAYERS, SHOW_LAYER_METADATA, HIDE_LAYER_METADATA }; diff --git a/web/client/components/TOC/Toolbar.jsx b/web/client/components/TOC/Toolbar.jsx index 19827f7c12..0bd6d83b34 100644 --- a/web/client/components/TOC/Toolbar.jsx +++ b/web/client/components/TOC/Toolbar.jsx @@ -30,6 +30,7 @@ class Toolbar extends React.Component { style: PropTypes.object, settings: PropTypes.object, layerMetadata: PropTypes.object, + wfsdownload: PropTypes.object, metadataTemplate: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object, PropTypes.func]) }; @@ -50,6 +51,7 @@ class Toolbar extends React.Component { onHideSettings: () => {}, onReload: () => {}, onAddLayer: () => {}, + onDownload: () => {}, onGetMetadataRecord: () => {}, onHideLayerMetadata: () => {}, onShow: () => {} @@ -73,6 +75,7 @@ class Toolbar extends React.Component { GROUP: '' }, featuresGridTooltip: '', + downloadToolTooltip: '', trashTooltip: { LAYER: '', LAYERS: '' @@ -89,6 +92,7 @@ class Toolbar extends React.Component { activateRemoveLayer: true, activateZoomTool: true, activateQueryTool: true, + activateDownloadTool: true, activateSettingsTool: true, activateAddLayer: true, includeDeleteButtonInSettings: false, @@ -103,6 +107,7 @@ class Toolbar extends React.Component { }, settings: {}, layerMetadata: {}, + wfsdownload: {}, metadataTemplate: null }; @@ -191,7 +196,7 @@ class Toolbar extends React.Component { : null} - {this.props.activateTool.activateSettingsTool && (status === 'LAYER' || status === 'GROUP') && !this.props.layerMetadata.expanded ? + {this.props.activateTool.activateSettingsTool && (status === 'LAYER' || status === 'GROUP') && !this.props.layerMetadata.expanded && !this.props.wfsdownload.expanded ? : null} - {this.props.activateTool.activateQueryTool && status === 'LAYER' && this.props.selectedLayers[0].search && !this.props.settings.expanded && !this.props.layerMetadata.expanded ? + {this.props.activateTool.activateQueryTool && status === 'LAYER' && this.props.selectedLayers[0].search && !this.props.settings.expanded && !this.props.layerMetadata.expanded && !this.props.wfsdownload.expanded ? : null} - {this.props.activateTool.activateRemoveLayer && (status === 'LAYER' || status === 'GROUP' || status === 'LAYERS' || status === 'GROUPS' || status === 'LAYERS_LOAD_ERROR') && this.props.selectedLayers.length > 0 && !this.props.settings.expanded && !this.props.layerMetadata.expanded ? + {this.props.activateTool.activateRemoveLayer && (status === 'LAYER' || status === 'GROUP' || status === 'LAYERS' || status === 'GROUPS' || status === 'LAYERS_LOAD_ERROR') && this.props.selectedLayers.length > 0 && !this.props.settings.expanded && !this.props.layerMetadata.expanded && !this.props.wfsdownload.expanded ? : null} - {this.props.activateTool.activateWidgetTool && (status === 'LAYER') && this.props.selectedLayers.length === 1 && !this.props.settings.expanded && !this.props.layerMetadata.expanded ? + {this.props.activateTool.activateWidgetTool && (status === 'LAYER') && this.props.selectedLayers.length === 1 && !this.props.settings.expanded && !this.props.layerMetadata.expanded && !this.props.wfsdownload.expanded ? : null} - {this.props.activateTool.activateMetedataTool && (status === 'LAYER') && this.props.selectedLayers[0].catalogURL && !this.props.settings.expanded ? + {this.props.activateTool.activateDownloadTool && status === 'LAYER' && this.props.selectedLayers[0].search && !this.props.settings.expanded && !this.props.layerMetadata.expanded ? + {this.props.text.downloadToolTooltip}}> + + + : null} + {this.props.activateTool.activateMetedataTool && (status === 'LAYER') && this.props.selectedLayers[0].catalogURL && !this.props.settings.expanded && !this.props.wfsdownload.expanded ? { + this.props.onToolsActions.onDownload({ + url: this.props.selectedLayers[0].search.url || this.props.selectedLayers[0].url, + name: this.props.selectedLayers[0].name, + id: this.props.selectedLayers[0].id + }); + } + checkBbox = () => { const layersBbox = this.props.selectedLayers.filter(l => l.bbox).map(l => l.bbox); const uniqueCRS = layersBbox.length > 0 ? layersBbox.reduce((a, b) => a.crs === b.crs ? a : {crs: 'differentCRS'}) : {crs: 'differentCRS'}; diff --git a/web/client/components/TOC/__tests__/Toolbar-test.jsx b/web/client/components/TOC/__tests__/Toolbar-test.jsx index fbd420d7d4..b107402bcd 100644 --- a/web/client/components/TOC/__tests__/Toolbar-test.jsx +++ b/web/client/components/TOC/__tests__/Toolbar-test.jsx @@ -16,6 +16,7 @@ const TestUtils = require('react-dom/test-utils'); const onToolsActions = { onZoom: () => {}, onBrowseData: () => {}, + onDownload: () => {}, onUpdate: () => {}, onRemove: () => {}, onClear: () => {}, @@ -58,6 +59,7 @@ describe('TOC Toolbar', () => { const spyZoom = expect.spyOn(onToolsActions, 'onZoom'); const spySettings = expect.spyOn(onToolsActions, 'onSettings'); const spyBrowseData = expect.spyOn(onToolsActions, 'onBrowseData'); + const spyDownload = expect.spyOn(onToolsActions, 'onDownload'); const selectedLayers = [{ id: 'l001', title: 'layer001', @@ -83,7 +85,7 @@ describe('TOC Toolbar', () => { const el = ReactDOM.findDOMNode(cmp); expect(el).toExist(); const btn = el.getElementsByClassName("btn"); - expect(btn.length).toBe(4); + expect(btn.length).toBe(5); TestUtils.Simulate.click(btn[0]); expect(spyZoom).toHaveBeenCalledWith({ maxx: 10, @@ -102,6 +104,13 @@ describe('TOC Toolbar', () => { name: selectedLayers[0].name, id: selectedLayers[0].id }); + TestUtils.Simulate.click(btn[4]); + expect(spyDownload).toHaveBeenCalled(); + expect(spyDownload).toHaveBeenCalledWith({ + url: selectedLayers[0].search.url, + name: selectedLayers[0].name, + id: selectedLayers[0].id + }); TestUtils.Simulate.click(btn[3]); const removeModal = document.getElementsByClassName('modal-dialog').item(0); @@ -214,10 +223,10 @@ describe('TOC Toolbar', () => { const el = ReactDOM.findDOMNode(cmp); expect(el).toExist(); const btn = el.getElementsByClassName("btn"); - expect(btn.length).toBe(5); + expect(btn.length).toBe(6); - TestUtils.Simulate.click(btn[4]); + TestUtils.Simulate.click(btn[5]); expect(spyGetMetadataRecord).toHaveBeenCalled(); TestUtils.Simulate.click(btn[3]); diff --git a/web/client/epics/__tests__/wfsdownload-test.js b/web/client/epics/__tests__/wfsdownload-test.js index 9284d0d788..3f781e5796 100644 --- a/web/client/epics/__tests__/wfsdownload-test.js +++ b/web/client/epics/__tests__/wfsdownload-test.js @@ -9,8 +9,10 @@ var expect = require('expect'); const {toggleControl, TOGGLE_CONTROL} = require('../../actions/controls'); - -const {closeExportDownload} = require('../wfsdownload'); +const {download} = require('../../actions/layers'); +const { DOWNLOAD_OPTIONS_CHANGE } = require('../../actions/wfsdownload'); +const { QUERY_CREATE } = require('../../actions/wfsquery'); +const { closeExportDownload, openDownloadTool} = require('../wfsdownload'); const {testEpic} = require('./epicTestUtils'); describe('wfsdownload Epics', () => { it('close export panel', (done) => { @@ -26,4 +28,30 @@ describe('wfsdownload Epics', () => { const state = {controls: { queryPanel: {enabled: false}, wfsdownload: {enabled: true}}}; testEpic(closeExportDownload, 1, toggleControl("queryPanel"), epicResult, state); }); + it('downloads a layer', (done) => { + const epicResult = actions => { + expect(actions.length).toBe(3); + actions.map((action) => { + switch (action.type) { + case TOGGLE_CONTROL: + expect(action.control).toBe('wfsdownload'); + break; + case DOWNLOAD_OPTIONS_CHANGE: + expect(action.key).toBe('singlePage'); + expect(action.value).toBe(false); + break; + case QUERY_CREATE: + expect(action.searchUrl).toBe('myurl'); + expect(action.filterObj.featureTypeName).toBe('mylayer'); + break; + default: + break; + } + }); + done(); + }; + + const state = { controls: { wfsdownload: { enabled: false, downloadOptions: {}} } }; + testEpic(openDownloadTool, 3, download({name: 'mylayer', url: 'myurl'}), epicResult, state); + }); }); diff --git a/web/client/epics/wfsdownload.js b/web/client/epics/wfsdownload.js index b894b8d238..4e4969ea5d 100644 --- a/web/client/epics/wfsdownload.js +++ b/web/client/epics/wfsdownload.js @@ -1,5 +1,7 @@ -const {FORMAT_OPTIONS_FETCH, DOWNLOAD_FEATURES, onDownloadFinished, updateFormats} = require('../actions/wfsdownload'); +const { FORMAT_OPTIONS_FETCH, DOWNLOAD_FEATURES, onDownloadFinished, updateFormats, onDownloadOptionChange} = require('../actions/wfsdownload'); const {TOGGLE_CONTROL, toggleControl} = require('../actions/controls'); +const {DOWNLOAD} = require('../actions/layers'); +const {createQuery} = require('../actions/wfsquery'); const {error} = require('../actions/notifications'); const Rx = require('rxjs'); const {get, find, pick, toPairs} = require('lodash'); @@ -68,6 +70,15 @@ const str2bytes = (str) => { }; */ module.exports = { + openDownloadTool: (action$) => + action$.ofType(DOWNLOAD) + .switchMap((action) => { + return Rx.Observable.from([ + toggleControl("wfsdownload"), + onDownloadOptionChange("singlePage", false), + createQuery(action.layer.url, {featureTypeName: action.layer.name}) + ]); + }), fetchFormatsWFSDownload: (action$) => action$.ofType(FORMAT_OPTIONS_FETCH) .switchMap( action => { diff --git a/web/client/localConfig.json b/web/client/localConfig.json index 9512e8c1c4..b7843368dd 100644 --- a/web/client/localConfig.json +++ b/web/client/localConfig.json @@ -260,6 +260,7 @@ "name": "TOC", "cfg": { "activateQueryTool": true, + "activateDownloadTool": true, "activateAddLayerButton": true, "spatialOperations": [ {"id": "INTERSECTS", "name": "queryform.spatialfilter.operations.intersects"}, diff --git a/web/client/plugins/TOC.jsx b/web/client/plugins/TOC.jsx index 2972b71b83..12fc8ea5bc 100644 --- a/web/client/plugins/TOC.jsx +++ b/web/client/plugins/TOC.jsx @@ -13,10 +13,11 @@ const {Glyphicon} = require('react-bootstrap'); const {changeLayerProperties, changeGroupProperties, toggleNode, contextNode, sortNode, showSettings, hideSettings, updateSettings, updateNode, removeNode, - browseData, selectNode, filterLayers, refreshLayerVersion, hideLayerMetadata} = require('../actions/layers'); + browseData, selectNode, filterLayers, refreshLayerVersion, hideLayerMetadata, + download} = require('../actions/layers'); const {getLayerCapabilities} = require('../actions/layerCapabilities'); const {zoomToExtent} = require('../actions/map'); -const {groupsSelector, layersSelector, selectedNodesSelector, layerFilterSelector, layerSettingSelector, layerMetadataSelector} = require('../selectors/layers'); +const {groupsSelector, layersSelector, selectedNodesSelector, layerFilterSelector, layerSettingSelector, layerMetadataSelector, wfsDownloadSelector} = require('../selectors/layers'); const {mapSelector, mapNameSelector} = require('../selectors/map'); const {currentLocaleSelector} = require("../selectors/locale"); const {widgetBuilderAvailable} = require('../selectors/controls'); @@ -70,6 +71,7 @@ const tocSelector = createSelector( groupsSelector, layerSettingSelector, layerMetadataSelector, + wfsDownloadSelector, mapSelector, currentLocaleSelector, selectedNodesSelector, @@ -79,11 +81,12 @@ const tocSelector = createSelector( activeSelector, widgetBuilderAvailable, generalInfoFormatSelector - ], (enabled, groups, settings, layerMetadata, map, currentLocale, selectedNodes, filterText, layers, mapName, catalogActive, activateWidgetTool, generalInfoFormat) => ({ + ], (enabled, groups, settings, layerMetadata, wfsdownload, map, currentLocale, selectedNodes, filterText, layers, mapName, catalogActive, activateWidgetTool, generalInfoFormat) => ({ enabled, groups, settings, layerMetadata, + wfsdownload, currentZoomLvl: map && map.zoom, scales: mapUtils.getScales( map && map.projection || 'EPSG:3857', @@ -130,6 +133,7 @@ class LayerTree extends React.Component { groups: PropTypes.array, settings: PropTypes.object, layerMetadata: PropTypes.object, + wfsdownload: PropTypes.object, metadataTemplate: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object, PropTypes.func]), refreshMapEnabled: PropTypes.bool, groupStyle: PropTypes.object, @@ -139,6 +143,7 @@ class LayerTree extends React.Component { onToggleLayer: PropTypes.func, onContextMenu: PropTypes.func, onBrowseData: PropTypes.func, + onDownload: PropTypes.func, onSelectNode: PropTypes.func, selectedNodes: PropTypes.array, onZoomToExtent: PropTypes.func, @@ -162,6 +167,7 @@ class LayerTree extends React.Component { activateLegendTool: PropTypes.bool, activateZoomTool: PropTypes.bool, activateQueryTool: PropTypes.bool, + activateDownloadTool: PropTypes.bool, activateSettingsTool: PropTypes.bool, activateMetedataTool: PropTypes.bool, activateWidgetTool: PropTypes.bool, @@ -224,6 +230,7 @@ class LayerTree extends React.Component { activateMetedataTool: true, activateRemoveLayer: true, activateQueryTool: false, + activateDownloadTool: false, activateWidgetTool: false, visibilityCheckType: "glyph", settingsOptions: { @@ -328,12 +335,14 @@ class LayerTree extends React.Component { generalInfoFormat={this.props.generalInfoFormat} settings={this.props.settings} layerMetadata={this.props.layerMetadata} + wfsdownload={this.props.wfsdownload} metadataTemplate={this.props.metadataTemplate} activateTool={{ activateToolsContainer: this.props.activateToolsContainer, activateRemoveLayer: this.props.activateRemoveLayer, activateZoomTool: this.props.activateZoomTool, activateQueryTool: this.props.activateQueryTool, + activateDownloadTool: this.props.activateDownloadTool, activateSettingsTool: this.props.activateSettingsTool, activateAddLayer: this.props.activateAddLayerButton && !this.props.catalogActive, includeDeleteButtonInSettings: false, @@ -367,6 +376,7 @@ class LayerTree extends React.Component { GROUP: }, featuresGridTooltip: , + downloadToolTooltip: , trashTooltip: { LAYER: , LAYERS: @@ -382,6 +392,7 @@ class LayerTree extends React.Component { onZoom: this.props.onZoomToExtent, onNewWidget: this.props.onNewWidget, onBrowseData: this.props.onBrowseData, + onDownload: this.props.onDownload, onUpdate: this.props.updateNode, onRemove: this.props.removeNode, onClear: this.props.onSelectNode, @@ -433,6 +444,7 @@ class LayerTree extends React.Component { * @prop {boolean} cfg.activateSettingsTool: activate settings of layers and groups, default `true` * @prop {boolean} cfg.activateRemoveLayer: activate remove layer tool, default `true` * @prop {boolean} cfg.activateQueryTool: activate query tool options, default `false` + * @prop {boolean} cfg.activateDownloadTool: activate a button to download layer data through wfs, default `false` * @prop {boolean} cfg.activateSortLayer: activate drag and drob to sort layers, default `true` * @prop {boolean} cfg.activateAddLayerButton: activate a button to open the catalog, default `false` * @prop {object} cfg.layerOptions: options to pass to the layer. @@ -461,6 +473,7 @@ const TOCPlugin = connect(tocSelector, { onToggleLayer: LayersUtils.toggleByType('layers', toggleNode), onContextMenu: contextNode, onBrowseData: browseData, + onDownload: download, onSort: LayersUtils.sortUsing(LayersUtils.sortLayers, sortNode), onSettings: showSettings, onZoomToExtent: zoomToExtent, diff --git a/web/client/selectors/__tests__/layers-test.js b/web/client/selectors/__tests__/layers-test.js index 0df3fc3acc..ce28d84a4e 100644 --- a/web/client/selectors/__tests__/layers-test.js +++ b/web/client/selectors/__tests__/layers-test.js @@ -7,7 +7,8 @@ */ const expect = require('expect'); -const {layersSelector, layerSelectorWithMarkers, groupsSelector, selectedNodesSelector, layerFilterSelector, layerSettingSelector, layerMetadataSelector, backgroundControlsSelector, currentBackgroundSelector, tempBackgroundSelector} = require('../layers'); +const {layersSelector, layerSelectorWithMarkers, groupsSelector, selectedNodesSelector, layerFilterSelector, layerSettingSelector, + layerMetadataSelector, wfsDownloadSelector, backgroundControlsSelector, currentBackgroundSelector, tempBackgroundSelector} = require('../layers'); describe('Test layers selectors', () => { it('test layersSelector from config', () => { @@ -160,6 +161,16 @@ describe('Test layers selectors', () => { expect(props).toEqual({expanded: false, metadataRecord: {}, maskLoading: false}); }); + it('test wfsDownloadSelector', () => { + const props = wfsDownloadSelector({ controls: { wfsdownload: { enabled: true } } }); + expect(props).toEqual({ expanded: true }); + }); + + it('test wfsDownloadSelector no state', () => { + const props = wfsDownloadSelector({}); + expect(props).toEqual({ expanded: false }); + }); + it('test backgroundControlsSelector', () => { const props = backgroundControlsSelector({ controls: { diff --git a/web/client/selectors/layers.js b/web/client/selectors/layers.js index bd2e81567c..63b9220b79 100644 --- a/web/client/selectors/layers.js +++ b/web/client/selectors/layers.js @@ -63,6 +63,7 @@ const getSelectedLayer = state => { const layerFilterSelector = (state) => state.layers && state.layers.filter || ''; const layerSettingSelector = (state) => state.layers && state.layers.settings || {expanded: false, options: {opacity: 1}}; const layerMetadataSelector = (state) => state.layers && state.layers.layerMetadata || {expanded: false, metadataRecord: {}, maskLoading: false}; +const wfsDownloadSelector = (state) => state.controls && state.controls.wfsdownload ? { expanded: state.controls.wfsdownload.enabled } : {expanded: false}; const backgroundControlsSelector = (state) => (state.controls && state.controls.backgroundSelector) || {}; const currentBackgroundSelector = (state) => { @@ -89,6 +90,7 @@ module.exports = { layerFilterSelector, layerSettingSelector, layerMetadataSelector, + wfsDownloadSelector, backgroundControlsSelector, currentBackgroundSelector, tempBackgroundSelector diff --git a/web/client/translations/data.de-DE b/web/client/translations/data.de-DE index 19e75a271e..dd570aca5d 100644 --- a/web/client/translations/data.de-DE +++ b/web/client/translations/data.de-DE @@ -252,6 +252,7 @@ "toolTrashLayerTooltip": "Entferne die ausgewählte Ebene", "toolTrashLayersTooltip": "Entferne ausgewählte Ebenen", "toolFeaturesGridTooltip": "Öffnen Sie die Attributtabelle", + "toolDownloadTooltip": "Layerdaten exportieren", "noFilteredResults": "Keine Ergebnisse", "filterPlaceholder": "Ebenen filtern", "clearFilter": "Filter löschen", diff --git a/web/client/translations/data.en-US b/web/client/translations/data.en-US index 09548ffa1f..6beb7490d5 100644 --- a/web/client/translations/data.en-US +++ b/web/client/translations/data.en-US @@ -252,6 +252,7 @@ "toolTrashLayerTooltip": "Remove selected layer", "toolTrashLayersTooltip": "Remove selected layers", "toolFeaturesGridTooltip": "Open Attribute Table", + "toolDownloadTooltip": "Export layer data", "noFilteredResults": "No results", "filterPlaceholder": "Filter layers", "clearFilter": "Clear filter", diff --git a/web/client/translations/data.es-ES b/web/client/translations/data.es-ES index cc241ed30a..eb57a37848 100644 --- a/web/client/translations/data.es-ES +++ b/web/client/translations/data.es-ES @@ -252,6 +252,7 @@ "toolTrashLayerTooltip": "Eliminar la capa seleccionada", "toolTrashLayersTooltip": "Eliminar capas seleccionadas", "toolFeaturesGridTooltip": "Abrir la tabla de atributos", + "toolDownloadTooltip": "Exportar datos de capa", "noFilteredResults": "Capas de filtro", "filterPlaceholder": "Capas de filtro", "clearFilter": "Filtro claro", diff --git a/web/client/translations/data.fr-FR b/web/client/translations/data.fr-FR index e2257cd1f5..e6131af3ac 100644 --- a/web/client/translations/data.fr-FR +++ b/web/client/translations/data.fr-FR @@ -253,6 +253,7 @@ "toolTrashLayerTooltip": "Retirer la couche sélectionnée", "toolTrashLayersTooltip": "Retirer les couches sélectionnées", "toolFeaturesGridTooltip": "Ouvrir la table attributaires", + "toolDownloadTooltip": "Exporter les données de la couche", "noFilteredResults": "Pas de résultats", "filterPlaceholder": "Filtrer les couches", "clearFilter": "Supprimer le filtre", diff --git a/web/client/translations/data.it-IT b/web/client/translations/data.it-IT index d683ddb043..1e45696656 100644 --- a/web/client/translations/data.it-IT +++ b/web/client/translations/data.it-IT @@ -252,6 +252,7 @@ "toolTrashLayerTooltip": "Rimuovi livello selezionato", "toolTrashLayersTooltip": "Rimuovi livelli selezionati", "toolFeaturesGridTooltip": "Apri tabella degli attributi", + "toolDownloadTooltip": "Esporta i dati del livello", "noFilteredResults": "Nessun risultato", "filterPlaceholder": "Filtra layers", "clearFilter": "Pulisci filtro", diff --git a/web/client/translations/data.nl-NL b/web/client/translations/data.nl-NL index c7ed5df450..50a6d799bf 100644 --- a/web/client/translations/data.nl-NL +++ b/web/client/translations/data.nl-NL @@ -243,6 +243,7 @@ "loadingerror": "De laag is niet correct geladen", "measure": "Meten", "backgroundSwitcher": "achtergrond kaart", + "toolDownloadTooltip": "Export layer data", "layers": "Lagen", "drawerButton": "Lagen", "refreshTitle": "Lagen bijwerken", From adf7f067be0af9fa149762d01a623d5cc0a9a6d9 Mon Sep 17 00:00:00 2001 From: Mauro Bartolomeoli Date: Thu, 18 Jan 2018 12:55:03 +0100 Subject: [PATCH 2/2] Fixed ESLint --- web/client/actions/layers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/client/actions/layers.js b/web/client/actions/layers.js index c694982187..edd6574e7b 100644 --- a/web/client/actions/layers.js +++ b/web/client/actions/layers.js @@ -238,6 +238,6 @@ module.exports = {changeLayerProperties, changeGroupProperties, toggleNode, sort hideLayerMetadata, download, CHANGE_LAYER_PROPERTIES, CHANGE_GROUP_PROPERTIES, TOGGLE_NODE, SORT_NODE, REMOVE_NODE, UPDATE_NODE, LAYER_LOADING, LAYER_LOAD, LAYER_ERROR, ADD_LAYER, REMOVE_LAYER, - SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, BROWSE_DATA, DOWNLOAD, + SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, BROWSE_DATA, DOWNLOAD, CLEAR_LAYERS, SELECT_NODE, FILTER_LAYERS, SHOW_LAYER_METADATA, HIDE_LAYER_METADATA };