Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choose layer fields to download before saving file #506

Draft
wants to merge 28 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
985405c
:sparkles: Add TODO comment where show Ux interface to choose fields …
volterra79 Oct 16, 2023
a70e360
:sparkles: Create GUI chooseLayerFields method to show and choose lay…
volterra79 Oct 17, 2023
809a733
:recycle: Make getCsv, getXls,etc .. method private. Need to call lay…
volterra79 Oct 17, 2023
3a7dbcb
:recycle: Clean component adding selected-fields event emit
volterra79 Oct 17, 2023
fb1ed71
:globe_with_meridians: Add translations
volterra79 Oct 17, 2023
18e115d
Renamed component from DownloadFiledsLayer to ChooseLayerFields.vue. …
volterra79 Oct 17, 2023
c102d9a
:bug: Renamed component instance
volterra79 Oct 17, 2023
f7aa937
Comments
volterra79 Oct 17, 2023
1ffed1a
Comments
volterra79 Oct 17, 2023
6293db7
Comments
volterra79 Oct 17, 2023
04f3926
If no fields reject
volterra79 Oct 17, 2023
8a3ff0b
move code related to `ChooseLayerFields.vue` into `CatalogLayerConte…
Raruto Oct 18, 2023
3cbff58
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Oct 23, 2023
38b183e
Merge branch 'g3w-admin/PR#619' of https://github.com/g3w-suite/g3w-c…
volterra79 Oct 23, 2023
e2e112a
Fix merge
volterra79 Oct 23, 2023
fb66d8a
Clean Code
volterra79 Oct 23, 2023
ccaa5bd
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Dec 1, 2023
d871f8e
Clean code
volterra79 Dec 1, 2023
e4b01bd
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Dec 19, 2023
eaa2b1a
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Jan 8, 2024
66eef13
Remove _.isNull lodash dependency
volterra79 Jan 8, 2024
c2664f8
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Jan 17, 2024
43965c9
Merge branch 'dev' into g3w-admin/PR#619
volterra79 Jan 31, 2024
8b2567d
Fix merge. Add removed GUI import
volterra79 Jan 31, 2024
8ba61e9
Clean code
volterra79 Jan 31, 2024
57d0b22
Create common _downloadFile method
volterra79 Jan 31, 2024
ba455ee
Merge branch 'dev' into g3w-admin/PR#619
Raruto Feb 15, 2024
98568bc
Merge branch 'dev' into g3w-admin/PR#619
Raruto Apr 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/app/core/layers/layer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GEOMETRY_FIELDS as geometryFields } from 'app/constant';
import ApplicationState from 'store/application-state';
import GUI from 'services/gui';
import DataRouterService from 'services/data';
import ProjectsRegistry from 'store/projects';
import DownloadMixin from 'core/layers/mixins/download';
Expand Down Expand Up @@ -360,6 +361,55 @@ proto.isWmsUseLayerIds = function() {
return this.config.wms_use_layer_ids;
};

/**
* @TODO error handling
*
* [FILE DOWNLOAD] Export layer in different formats
*
* @param { 'shp' | 'shapefile' | 'xls' | 'csv' | 'gpx' | 'gpkg' | 'geotiff' } type
* @param { Object } opts
* @param opts.data
* @param opts.options
*
* @returns { Promise }
*
* @listens GUI~before_download_layer since 3.9.0
* @fires GUI~choose_layer_fields_to_download since 3.9.0
*/
proto.downloadAsFile = function(type, {
data = {},
options,
} = {}) {
return new Promise((resolve, reject) => {
GUI.once(
'before_download_layer',
async (fields) => {
data.ftod = fields.map(field => field.name).join();
data.filtertoken = this.getFilterToken(); //from SelectionMixin
// alias
if ('shapefile' === type) {
type = 'shp';
}
// allowed download types
if (['shp', 'xls', 'csv', 'gpx', 'gpkg', 'geotiff'].includes(type)) {
resolve(
XHR.fileDownload({
url: this.getUrl(type),
data,
httpMethod: "POST",
})
);
}
}
);
GUI.emit(
'choose_layer_fields_to_download',
this.getTableFields().map(({ name, label }) => ({ name, label, selected: true }))
);
})
.catch(console.warn);
};

/**
* @returns {*|null} source type of layer
*/
Expand Down Expand Up @@ -1372,4 +1422,9 @@ Layer.EDITOPS = {
*/
Layer.SELECTION_STATE = SELECTION_STATE;

/**
* @deprecated since 3.9.0. Will be deleted in 4.x. Use Layer.downloadAsFile(type, options) instead
*/
Layer.prototype.getDownloadFilefromDownloadDataType = deprecate(Layer.prototype.downloadAsFile, '[G3W-CLIENT] Layer::getDownloadFilefromDownloadDataType(type, options) is deprecated');

module.exports = Layer;
7 changes: 4 additions & 3 deletions src/app/gui/queryresults/queryresultsservice.js
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@ class QueryResultsService extends G3WObject {
({layer, type, data}= {}) => {
return CatalogLayersStoresRegistry
.getLayerById(layer.id)
.getDownloadFilefromDownloadDataType(type, { data }) ||
.downloadAsFile(type, { data }) ||
Promise.resolve();
},
{
Expand Down Expand Up @@ -1649,7 +1649,7 @@ class QueryResultsService extends G3WObject {
downloadGpx({ id: layerId } = {}, feature) {
CatalogLayersStoresRegistry
.getLayerById(layerId)
.getGpx({ fid: feature ? feature.attributes[G3W_FID] : null })
.downloadAsFile('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(); })
}
Expand All @@ -1660,7 +1660,8 @@ class QueryResultsService extends G3WObject {
downloadXls({ id: layerId } = {}, feature) {
CatalogLayersStoresRegistry
.getLayerById(layerId)
.getXls({ fid: feature ? feature.attributes[G3W_FID] : null })
.downloadAsFile('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(); })
}
Expand Down
200 changes: 128 additions & 72 deletions src/components/CatalogLayerContextMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -552,24 +552,64 @@
<script>
import { Chrome as ChromeComponent } from 'vue-color';

import LayerOpacityPicker from "components/LayerOpacityPicker.vue";

import { CatalogEventBus as VM } from 'app/eventbus';
import CatalogLayersStoresRegistry from 'store/catalog-layers';
import ApplicationService from 'services/application';
import GUI from 'services/gui';

const { t } = require('core/i18n/i18n.service');
const shpwrite = require('shp-write');
const TableComponent = require('gui/table/vue/table');
const { downloadFile } = require('utils');

import LayerOpacityPicker from 'components/LayerOpacityPicker.vue';
import ChooseLayerFields from 'components/ChooseLayerFields.vue';
import { CatalogEventBus as VM } from 'app/eventbus';
import CatalogLayersStoresRegistry from 'store/catalog-layers';
import ApplicationService from 'services/application';
import GUI from 'services/gui';

const { t } = require('core/i18n/i18n.service');
const shpwrite = require('shp-write');
const TableComponent = require('gui/table/vue/table');
const { downloadFile } = require('utils');

const OFFSETMENU = {
top: 50,
left: 15
};

/**
* Show ChooseLayerFields modal
*
* @listens ChooseLayerFields~selected-fields since 3.9.0
* @fires GUI~before_download_layer since 3.9.0
*/
function _choose_layer_fields_to_download(fields = []) {

/** @TODO error handling */
// skip when ..
// if (!fields.length) {
// GUI.emit('invalid_layer_fields_to_download');
// }

const modal = new (Vue.extend(ChooseLayerFields))({ propsData: { fields }});

const dialog = GUI.showModalDialog({
message: modal.$mount().$el,
closeButton: false,
buttons: {
ok: {
label: 'Ok',
className: 'btn-success',
callback() {
GUI.emit('before_download_layer', fields.filter(field => field.selected))
}
}
}
});

/**
* @TODO find a better way to set focus.
* Once shown, need to be clicked otherwise,
* the user need click twice "ok button"
* when initial selection is not changed
*/
dialog.on("shown.bs.modal", evt => evt.target.click());

modal.$on('selected-fields', bool => dialog.find('button.btn-success').prop('disabled', !bool));
}

export default {
name: 'Cataloglayermenu',

Expand Down Expand Up @@ -777,86 +817,99 @@
}, 600);
},

downloadGeoTIFF(layerId, map_extent=false) {
/**
* @since v3.10.0
* @param type
* @param layerId
* @param options
* @private
*/
_downloadFile({type, layerId, options={}}) {
const caller_download_id = ApplicationService.setDownload(true);
this.layerMenu.loading.geotiff = true;
this.layerMenu.loading[type] = true;
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer.getGeoTIFF({
data: map_extent ? {
map_extent: GUI.getService('map').getMapExtent().toString()
} : undefined
})
.catch(err => GUI.notify.error(t("info.server_error")))
layer.downloadAsFile(type, options)
.catch(err => {
console.warn(err);
GUI.notify.error(t("info.server_error"))
})
.finally(() => {
this.layerMenu.loading.geotiff = false;
this.layerMenu.loading[type] = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
},

/**
* @FIXME add description
* @param layerId
* @param map_extent
*/
downloadGeoTIFF(layerId, map_extent=false) {
this._downloadFile({
type: 'geotiff',
layerId,
options: {
data: map_extent ? {
map_extent: GUI.getService('map').getMapExtent().toString()
} : undefined
}
})
},

/**
* @FIXME add description
* @param layerId
*/
downloadShp(layerId) {
const caller_download_id = ApplicationService.setDownload(true);
this.layerMenu.loading.shp = true;
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer.getShp()
.catch(err => GUI.notify.error(t("info.server_error")))
.finally(() => {
this.layerMenu.loading.shp = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
this._downloadFile({
type: 'shp',
layerId,
})
},

/**
* @FIXME add description
* @param layerId
*/
downloadCsv(layerId) {
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")))
.finally(() => {
this.layerMenu.loading.csv = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
this._downloadFile({
type: 'csv',
layerId,
})
},

/**
* @FIXME add description
* @param layerId
*/
downloadXls(layerId) {
const caller_download_id = ApplicationService.setDownload(true);
this.layerMenu.loading.xls = true;
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer.getXls()
.catch(err => GUI.notify.error(t("info.server_error")))
.finally(() => {
this.layerMenu.loading.xls = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
this._downloadFile({
type: 'xls',
layerId,
})
},

/**
* @FIXME add description
* @param layerId
*/
downloadGpx(layerId) {
const caller_download_id = ApplicationService.setDownload(true);
this.layerMenu.loading.gpx = true;
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer.getGpx()
.catch(err => GUI.notify.error(t("info.server_error")))
.finally(() => {
this.layerMenu.loading.gpx = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
this._downloadFile({
type: 'gpx',
layerId,
})
},

/**
* @FIXME add description
* @param layerId
*/
downloadGpkg(layerId) {
const caller_download_id = ApplicationService.setDownload(true);
this.layerMenu.loading.gpkg = true;
const layer = CatalogLayersStoresRegistry.getLayerById(layerId);
layer.getGpkg()
.catch(err => GUI.notify.error(t("info.server_error")))
.finally(() => {
this.layerMenu.loading.gpkg = false;
ApplicationService.setDownload(false, caller_download_id);
this._hideMenu();
})
this._downloadFile({
type: 'gpkg',
layerId,
})
},

changeLayerMapPosition({position, layer}) {
Expand Down Expand Up @@ -1081,7 +1134,9 @@
menu.maxHeight = height >= maxH ? maxH : null;
menu.overflowY = height >= maxH ? 'scroll' : null;
menu.top = (height >= maxH ? contextmenu : menuentry).offset().top;
menu.left = this.isMobile() ? 0 : menuentry.offset().left + menuentry.width() + ((menuentry.outerWidth() - menuentry.width()) /2) + OFFSETMENU.left;
menu.left = this.isMobile()
? 0
: menuentry.offset().left + menuentry.width() + ((menuentry.outerWidth() - menuentry.width()) /2) + OFFSETMENU.left;
await this.$nextTick();
}
menu.show = bool;
Expand Down Expand Up @@ -1215,6 +1270,7 @@
created() {
VM.$on('show-layer-context-menu', this.onShowLayerContextMenu );
VM.$on('hide-layer-context-menu', this._hideMenu)
GUI.on('choose_layer_fields_to_download', _choose_layer_fields_to_download);
},

};
Expand Down
Loading