From 985405c76e5399113015d6d1e796e14e7fac5213 Mon Sep 17 00:00:00 2001 From: volterra79 Date: Mon, 16 Oct 2023 16:00:45 +0200 Subject: [PATCH 01/19] :sparkles: Add TODO comment where show Ux interface to choose fields to download --- src/app/core/layers/layer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/core/layers/layer.js b/src/app/core/layers/layer.js index 71068fa71..81b3f3670 100644 --- a/src/app/core/layers/layer.js +++ b/src/app/core/layers/layer.js @@ -511,6 +511,9 @@ proto.getFilterToken = function () { */ proto.getDownloadFilefromDownloadDataType = function(type, {data={}, options}) { data.filtertoken = this.getFilterToken(); + /** + * @TODO add UX fields choose + */ switch (type) { case 'shapefile': return this.getShp({data, options}); case 'xls': return this.getXls({data, options}); From a70e360de70b1717c17548bd65f302e546ecc6bc Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 08:54:18 +0200 Subject: [PATCH 02/19] :sparkles: Create GUI chooseLayerFields method to show and choose layer fields --- src/app/core/layers/layer.js | 21 +++++++++ src/components/DownloadFieldsLayer.vue | 65 ++++++++++++++++++++++++++ src/index.prod.js | 18 +++++++ 3 files changed, 104 insertions(+) create mode 100644 src/components/DownloadFieldsLayer.vue diff --git a/src/app/core/layers/layer.js b/src/app/core/layers/layer.js index 81b3f3670..8e36a06ed 100644 --- a/src/app/core/layers/layer.js +++ b/src/app/core/layers/layer.js @@ -3,6 +3,7 @@ import { DOWNLOAD_FORMATS } from 'app/constant'; import DataRouterService from 'services/data'; import ProjectsRegistry from 'store/projects'; import ApplicationService from 'services/application'; +import GUI from 'services/gui'; const { t } = require('core/i18n/i18n.service'); const { inherit, base, XHR } = require('core/utils/utils'); @@ -501,6 +502,20 @@ proto.getFilterToken = function () { return ApplicationService.getFilterToken(); }; +/** + * @since v3.9.0 + */ +proto.chooseFieldsToDownload = function() { + return new Promise((resolve, reject) => { + + GUI.chooseLayerFields(this.getTableFields().map(({name, label}) => ({ + name, + label, + selected: true + }))) + }) +} + /** * * DOWNLOAD METHODS @@ -525,6 +540,7 @@ proto.getDownloadFilefromDownloadDataType = function(type, {data={}, options}) { }; proto.getGeoTIFF = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('geotiff'), @@ -534,6 +550,7 @@ proto.getGeoTIFF = function({data={}}={}) { }; proto.getXls = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('xls'), @@ -543,6 +560,7 @@ proto.getXls = function({data={}}={}) { }; proto.getShp = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('shp'), @@ -552,6 +570,7 @@ proto.getShp = function({data={}}={}) { }; proto.getGpx = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('gpx'), @@ -561,6 +580,7 @@ proto.getGpx = function({data={}}={}) { }; proto.getGpkg = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('gpkg'), @@ -570,6 +590,7 @@ proto.getGpkg = function({data={}}={}) { }; proto.getCsv = function({data={}}={}) { + this.chooseFieldsToDownload(); data.filtertoken = this.getFilterToken(); return XHR.fileDownload({ url: this.getUrl('csv'), diff --git a/src/components/DownloadFieldsLayer.vue b/src/components/DownloadFieldsLayer.vue new file mode 100644 index 000000000..9ccb39cd8 --- /dev/null +++ b/src/components/DownloadFieldsLayer.vue @@ -0,0 +1,65 @@ + + + + diff --git a/src/index.prod.js b/src/index.prod.js index 3ddb55524..a8d50cf04 100644 --- a/src/index.prod.js +++ b/src/index.prod.js @@ -44,6 +44,7 @@ import NavbaritemsLeftComponent from 'components/NavbaritemsLeft.vue'; import NavbaritemsRightComponent from 'components/NavbaritemsRight.vue'; import SidebarComponent from 'components/Sidebar.vue'; import ViewportComponent from 'components/Viewport.vue'; +import DownloadFieldsLayer from "components/DownloadFieldsLayer.vue"; //directives import vDisabled from 'directives/v-disabled'; @@ -1069,6 +1070,23 @@ const ApplicationTemplate = function({ApplicationService}) { }); }; + /** + * @since v3.9.0 + */ + GUI.chooseLayerFields = function(fields=[]) { + if (fields.length > 0) { + + const DownloadFieldsLayerClass = Vue.extend(DownloadFieldsLayer); + const DownloadFieldsLayerInstance = new DownloadFieldsLayerClass({ + propsData: { + fields + } + }); + return GUI.showModalDialog({ + message: DownloadFieldsLayerInstance.$mount().$el + }) + } + } }; base(this); From 809a73301561eb85b79869034f77c5816872a56f Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 11:32:22 +0200 Subject: [PATCH 03/19] :recycle: Make getCsv, getXls,etc .. method private. Need to call layer getDownloadFilefromDownloadDataType method to download format --- src/app/core/layers/layer.js | 104 +++++++++++------- .../gui/queryresults/queryresultsservice.js | 5 +- src/components/CatalogLayerContextMenu.vue | 19 ++-- src/index.prod.js | 48 ++++++-- 4 files changed, 116 insertions(+), 60 deletions(-) diff --git a/src/app/core/layers/layer.js b/src/app/core/layers/layer.js index 8e36a06ed..28a05bb12 100644 --- a/src/app/core/layers/layer.js +++ b/src/app/core/layers/layer.js @@ -506,14 +506,10 @@ proto.getFilterToken = function () { * @since v3.9.0 */ proto.chooseFieldsToDownload = function() { - return new Promise((resolve, reject) => { - - GUI.chooseLayerFields(this.getTableFields().map(({name, label}) => ({ - name, - label, - selected: true - }))) - }) + return GUI.chooseLayerFields( + this.getTableFields() + .map(({name, label}) => ({name, label, selected: true})) + ) } /** @@ -521,27 +517,37 @@ proto.chooseFieldsToDownload = function() { * DOWNLOAD METHODS */ -/** + +/** + * Method to handle download layer in different format * @returns promise */ -proto.getDownloadFilefromDownloadDataType = function(type, {data={}, options}) { - data.filtertoken = this.getFilterToken(); - /** - * @TODO add UX fields choose - */ - switch (type) { - case 'shapefile': return this.getShp({data, options}); - case 'xls': return this.getXls({data, options}); - case 'csv': return this.getCsv({data, options}); - case 'gpx': return this.getGpx({data, options}); - case 'gpkg': return this.getGpkg({data, options}); - case 'geotiff': return this.getGeoTIFF({ data, options }); +proto.getDownloadFilefromDownloadDataType = async function(type, {data={}, options}={}) { + try { + const fields = await this.chooseFieldsToDownload(); + data.ftod = fields.map(field => field.name).join(); + data.filtertoken = this.getFilterToken(); + switch (type) { + case 'shapefile': return this._getShp({data, options}); + case 'xls': return this._getXls({data, options}); + case 'csv': return this._getCsv({data, options}); + case 'gpx': return this._getGpx({data, options}); + case 'gpkg': return this._getGpkg({data, options}); + case 'geotiff': return this._getGeoTIFF({ data, options }); + } + } catch(err) { + console.log(err) } + }; -proto.getGeoTIFF = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getGeoTIFF = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('geotiff'), data, @@ -549,9 +555,13 @@ proto.getGeoTIFF = function({data={}}={}) { }) }; -proto.getXls = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getXls = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('xls'), data, @@ -559,9 +569,13 @@ proto.getXls = function({data={}}={}) { }) }; -proto.getShp = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getShp = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('shp'), data, @@ -569,9 +583,13 @@ proto.getShp = function({data={}}={}) { }) }; -proto.getGpx = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getGpx = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('gpx'), data, @@ -579,9 +597,13 @@ proto.getGpx = function({data={}}={}) { }) }; -proto.getGpkg = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getGpkg = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('gpkg'), data, @@ -589,9 +611,13 @@ proto.getGpkg = function({data={}}={}) { }) }; -proto.getCsv = function({data={}}={}) { - this.chooseFieldsToDownload(); - data.filtertoken = this.getFilterToken(); +/** + * + * @param data + * @returns {Promise} + * @private + */ +proto._getCsv = async function({data={}}={}) { return XHR.fileDownload({ url: this.getUrl('csv'), data, diff --git a/src/app/gui/queryresults/queryresultsservice.js b/src/app/gui/queryresults/queryresultsservice.js index 6a1822c1b..e159a1829 100644 --- a/src/app/gui/queryresults/queryresultsservice.js +++ b/src/app/gui/queryresults/queryresultsservice.js @@ -1634,7 +1634,7 @@ class QueryResultsService extends G3WObject { downloadGpx({ id: layerId } = {}, feature) { CatalogLayersStoresRegistry .getLayerById(layerId) - .getGpx({ fid: feature ? feature.attributes[G3W_FID] : null }) + .getDownloadFilefromDownloadDataType('gpx', {data:{ fid: feature ? feature.attributes[G3W_FID] : null }}) .catch((err) => { GUI.notify.error(t("info.server_error")); }) .finally(() => { this.layerMenu.loading.shp = false; this._hideMenu(); }) } @@ -1645,7 +1645,8 @@ class QueryResultsService extends G3WObject { downloadXls({ id: layerId } = {}, feature) { CatalogLayersStoresRegistry .getLayerById(layerId) - .getXls({ fid: feature ? feature.attributes[G3W_FID] : null }) + .getDownloadFilefromDownloadDataType('xls', + { data: {fid: feature ? feature.attributes[G3W_FID] : null }}) .catch(err => { GUI.notify.error(t("info.server_error")); }) .finally(() => { this.layerMenu.loading.shp = false; this._hideMenu(); }) } diff --git a/src/components/CatalogLayerContextMenu.vue b/src/components/CatalogLayerContextMenu.vue index fb84163f6..333b895bf 100644 --- a/src/components/CatalogLayerContextMenu.vue +++ b/src/components/CatalogLayerContextMenu.vue @@ -430,8 +430,8 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.geotiff = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getGeoTIFF({ - data: map_extent ? { + layer.getDownloadFilefromDownloadDataType('geotiff',{ + data: map_extent ? { map_extent: GUI.getService('map').getMapExtent().toString() } : undefined }) @@ -447,7 +447,7 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.shp = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getShp() + layer.getDownloadFilefromDownloadDataType('shapefile') .catch(err => GUI.notify.error(t("info.server_error"))) .finally(() => { this.layerMenu.loading.shp = false; @@ -460,8 +460,11 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.csv = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getCsv() - .catch(err => GUI.notify.error(t("info.server_error"))) + + layer.getDownloadFilefromDownloadDataType('csv') + .catch(err => { + GUI.notify.error(t("info.server_error")) + }) .finally(() => { this.layerMenu.loading.csv = false; ApplicationService.setDownload(false, caller_download_id); @@ -473,7 +476,7 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.xls = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getXls() + layer.getDownloadFilefromDownloadDataType('xls') .catch(err => GUI.notify.error(t("info.server_error"))) .finally(() => { this.layerMenu.loading.xls = false; @@ -486,7 +489,7 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.gpx = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getGpx() + layer.getDownloadFilefromDownloadDataType('gpx') .catch(err => GUI.notify.error(t("info.server_error"))) .finally(() => { this.layerMenu.loading.gpx = false; @@ -499,7 +502,7 @@ const caller_download_id = ApplicationService.setDownload(true); this.layerMenu.loading.gpkg = true; const layer = CatalogLayersStoresRegistry.getLayerById(layerId); - layer.getGpkg() + layer.getDownloadFilefromDownloadDataType('gpkg') .catch(err => GUI.notify.error(t("info.server_error"))) .finally(() => { this.layerMenu.loading.gpkg = false; diff --git a/src/index.prod.js b/src/index.prod.js index a8d50cf04..55dfb3d70 100644 --- a/src/index.prod.js +++ b/src/index.prod.js @@ -1071,22 +1071,48 @@ const ApplicationTemplate = function({ApplicationService}) { }; /** + * Method to show and choose al layer fields * @since v3.9.0 */ GUI.chooseLayerFields = function(fields=[]) { - if (fields.length > 0) { + return new Promise((resolve, reject) => { + if (fields.length > 0) { - const DownloadFieldsLayerClass = Vue.extend(DownloadFieldsLayer); - const DownloadFieldsLayerInstance = new DownloadFieldsLayerClass({ - propsData: { - fields - } - }); - return GUI.showModalDialog({ - message: DownloadFieldsLayerInstance.$mount().$el - }) - } + const DownloadFieldsLayerClass = Vue.extend(DownloadFieldsLayer); + const DownloadFieldsLayerInstance = new DownloadFieldsLayerClass({ + propsData: { + fields + } + }); + const message = DownloadFieldsLayerInstance.$mount().$el; + + const dialog = GUI.showModalDialog({ + message, + closeButton: false, + buttons: { + ok: { + label: 'Ok', + className: 'btn-success', + callback() { + resolve(fields.filter(field => field.selected)); + } + } + } + }); + + /** + * @TODO + */ + dialog.on("shown.bs.modal", evt => evt.target.click()); + + DownloadFieldsLayerInstance.$on('selected-fields', bool => dialog.find('button.btn-success').prop('disabled', !bool)); + + } else { + resolve(fields); + } + }) } + }; base(this); From 3a7dbcbb06e7b99d0ba827c14be67d15ddead3d1 Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 11:33:23 +0200 Subject: [PATCH 04/19] :recycle: Clean component adding selected-fields event emit --- src/components/DownloadFieldsLayer.vue | 54 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/DownloadFieldsLayer.vue b/src/components/DownloadFieldsLayer.vue index 9ccb39cd8..641a60177 100644 --- a/src/components/DownloadFieldsLayer.vue +++ b/src/components/DownloadFieldsLayer.vue @@ -1,29 +1,35 @@ diff --git a/src/index.prod.js b/src/index.prod.js index 55dfb3d70..c7ad7ca15 100644 --- a/src/index.prod.js +++ b/src/index.prod.js @@ -44,7 +44,7 @@ import NavbaritemsLeftComponent from 'components/NavbaritemsLeft.vue'; import NavbaritemsRightComponent from 'components/NavbaritemsRight.vue'; import SidebarComponent from 'components/Sidebar.vue'; import ViewportComponent from 'components/Viewport.vue'; -import DownloadFieldsLayer from "components/DownloadFieldsLayer.vue"; +import ChooseLayerFields from "./components/ChooseLayerFields.vue"; //directives import vDisabled from 'directives/v-disabled'; @@ -1078,16 +1078,15 @@ const ApplicationTemplate = function({ApplicationService}) { return new Promise((resolve, reject) => { if (fields.length > 0) { - const DownloadFieldsLayerClass = Vue.extend(DownloadFieldsLayer); - const DownloadFieldsLayerInstance = new DownloadFieldsLayerClass({ + const ChooseLayerFieldsClass = Vue.extend(ChooseLayerFields); + const ChooseLayerFieldsInstance = new ChooseLayerFieldsClass({ propsData: { fields } }); - const message = DownloadFieldsLayerInstance.$mount().$el; const dialog = GUI.showModalDialog({ - message, + message: ChooseLayerFieldsInstance.$mount().$el, closeButton: false, buttons: { ok: { From c102d9a8344b93348c328f32358d973da1439176 Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 14:24:10 +0200 Subject: [PATCH 07/19] :bug: Renamed component instance --- src/index.prod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.prod.js b/src/index.prod.js index c7ad7ca15..1b80c0639 100644 --- a/src/index.prod.js +++ b/src/index.prod.js @@ -1104,7 +1104,7 @@ const ApplicationTemplate = function({ApplicationService}) { */ dialog.on("shown.bs.modal", evt => evt.target.click()); - DownloadFieldsLayerInstance.$on('selected-fields', bool => dialog.find('button.btn-success').prop('disabled', !bool)); + ChooseLayerFieldsInstance.$on('selected-fields', bool => dialog.find('button.btn-success').prop('disabled', !bool)); } else { resolve(fields); From f7aa93739931c06958cfb85f529826270301082b Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 14:26:24 +0200 Subject: [PATCH 08/19] Comments --- src/index.prod.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.prod.js b/src/index.prod.js index 1b80c0639..cb0aee8cf 100644 --- a/src/index.prod.js +++ b/src/index.prod.js @@ -1100,7 +1100,9 @@ const ApplicationTemplate = function({ApplicationService}) { }); /** - * @TODO + * @TODO find a better way to focus + * Once is show, need to bee clicked otherwise we need do + * click twice time ok button if no start selection is changed */ dialog.on("shown.bs.modal", evt => evt.target.click()); From 1ffed1a5b7403a585113b57ef67b0d8c6c2d770c Mon Sep 17 00:00:00 2001 From: volterra79 Date: Tue, 17 Oct 2023 14:35:19 +0200 Subject: [PATCH 09/19] Comments --- src/components/ChooseLayerFields.vue | 29 +++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/components/ChooseLayerFields.vue b/src/components/ChooseLayerFields.vue index ca281c5be..b99b8a668 100644 --- a/src/components/ChooseLayerFields.vue +++ b/src/components/ChooseLayerFields.vue @@ -1,10 +1,10 @@