Skip to content

Commit

Permalink
Merge pull request #2351 from DenverCoder544/featuredata-export-data-…
Browse files Browse the repository at this point in the history
…size-limit

limit size of json when trying to export to excel and build csv-optio…
  • Loading branch information
ZakarFin authored Aug 14, 2023
2 parents aa625af + 090438b commit b11d530
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 10 deletions.
68 changes: 60 additions & 8 deletions bundles/framework/featuredata/plugin/FeatureDataPluginHandler.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { StateHandler, controllerMixin, Messaging } from 'oskari-ui/util';
import { showFeatureDataFlyout } from '../view/FeatureDataFlyout';
import { FilterTypes, LogicalOperators, showSelectByPropertiesPopup } from '../view/SelectByProperties';
import { COLUMN_SELECTION, FILETYPES, showExportDataPopup } from '../view/ExportData';
import { COLUMN_SELECTION, FILETYPES, SEPARATORS, showExportDataPopup } from '../view/ExportData';
import { FEATUREDATA_BUNDLE_ID } from '../view/FeatureDataContainer';
import { FilterSelector } from '../FilterSelector';

export const FEATUREDATA_DEFAULT_HIDDEN_FIELDS = ['__fid', '__centerX', '__centerY', 'geometry'];

export const SELECTION_SERVICE_CLASSNAME = 'Oskari.mapframework.service.VectorFeatureSelectionService';
const EXPORT_FEATUREDATA_ROUTE = 'ExportTableFile';
const EXPORT_FEATUREDATA_EXCEL_MAX_LENGTH = 120000;

class FeatureDataPluginUIHandler extends StateHandler {
constructor (mapModule) {
Expand Down Expand Up @@ -420,19 +421,70 @@ class FeatureDataPluginUIHandler extends StateHandler {
const layer = layers?.find(layer => layer.getId() === activeLayerId);

params.filename = layer.getName();
params.data = JSON.stringify(this.gatherExportData(exportOnlySelected, columns === COLUMN_SELECTION.opened));
params.additionalData = JSON.stringify(
this.gatherAdditionalInfo(
exportDataSource,
exportMetadataLink,
layer));
params.data = this.gatherExportData(exportOnlySelected, columns === COLUMN_SELECTION.opened);
params.additionalData = this.gatherAdditionalInfo(
exportDataSource,
exportMetadataLink,
layer
);

if (format === FILETYPES.excel) {
this.exportAsExcel(params);
return;
}

this.exportAsCsv(params);
}

exportAsExcel (params) {
params.data = JSON.stringify(params.data);
params.additionalData = JSON.stringify(params.additionalData);
let contentLength = 0;
Object.keys(params).forEach((key) => {
if (params[key]?.length) {
contentLength += params[key].length;
}
});

if (contentLength >= EXPORT_FEATUREDATA_EXCEL_MAX_LENGTH) {
Messaging.error(Oskari.getMsg(FEATUREDATA_BUNDLE_ID, 'exportDataPopup.datasetTooLargeForExcel'));
return;
}

const payload = new URLSearchParams();
Object.keys(params).forEach(key => payload.append(key, params[key]));
const extension = format === FILETYPES.csv ? '.csv' : '.xlsx';
const extension = '.xlsx';
this.sendData(payload, params.filename + extension);
}

exportAsCsv (params) {
if (params?.delimiter === SEPARATORS.tabulator) {
params.delimiter = '\t';
}
const replacer = (value) => !value ? '' : value;
const headers = params.data.splice(0, 1)[0];
const headerRow = headers.join(params.delimiter);
const dataRows = params.data
.map((values) => values.map((value) => replacer(value)).join(params.delimiter))
.join('\r\n');

const additionalDataRows = params.additionalData.map((value) => {
// TODO: case metadata - we should dig up the metadata service url from someplace
// not currently available in fe
return [value.name, value.value].join(params.delimiter);
}).join('\r\n');
const emptyRow = null;
const csv = [headerRow, dataRows, emptyRow, additionalDataRows].join('\r\n');

const link = document.createElement('a');
link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(csv));
link.setAttribute('download', params.filename + '.csv');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

sendData (payload, filename) {
try {
fetch(Oskari.urls.getRoute(EXPORT_FEATUREDATA_ROUTE), {
Expand Down
1 change: 1 addition & 0 deletions bundles/framework/featuredata/resources/locale/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Oskari.registerLocalization(
"openButtonLabel": "Export data",
"exportButtonLabel": "Export",
"exportFailed": "Exporting the data failed.",
"datasetTooLargeForExcel": "Dataset is too large for generating an excel file. Limit the number of features or choose csv as format.",
"fileFormat": {
"title": "File format",
"excel": "Excel",
Expand Down
1 change: 1 addition & 0 deletions bundles/framework/featuredata/resources/locale/fi.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Oskari.registerLocalization(
"openButtonLabel": "Aineiston vienti",
"exportButtonLabel": "Vie",
"exportFailed": "Aineiston vienti epäonnistui.",
"datasetTooLargeForExcel": "Dataset is too large for generating an excel file. Limit the number of features or choose csv as format.",
"fileFormat": {
"title": "Tiedostomuoto",
"excel": "Excel",
Expand Down
1 change: 1 addition & 0 deletions bundles/framework/featuredata/resources/locale/sv.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Oskari.registerLocalization(
"openButtonLabel": "Exportera data",
"exportButtonLabel": "Exportera",
"exportFailed": "Exporting the data failed.",
"datasetTooLargeForExcel": "Dataset is too large for generating an excel file. Limit the number of features or choose csv as format.",
"fileFormat": {
"title": "Filformat",
"excel": "Excel",
Expand Down
3 changes: 1 addition & 2 deletions bundles/framework/featuredata/view/ExportData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ const ColumnHeader = styled('h3')`
padding-bottom: 0.25em;
`;


const SEPARATORS = {
export const SEPARATORS = {
semicolon: ';',
comma: ',',
tabulator: 'tab'
Expand Down

0 comments on commit b11d530

Please sign in to comment.