diff --git a/package-lock.json b/package-lock.json index 0910a9aac51e1d483ac0dfd470833f00f33d1a22..d597b30628b53ba076f5b3085493f3d10e2a5a1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "geocontrib-frontend", - "version": "3.0.2", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2562,6 +2562,16 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -2571,6 +2581,34 @@ "array-uniq": "^1.0.1" } }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, "dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -2642,6 +2680,13 @@ "slash": "^2.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -2679,6 +2724,28 @@ "requires": { "minipass": "^3.1.1" } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.8.3", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", + "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + } } } }, @@ -3561,8 +3628,7 @@ "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { "version": "5.2.0", @@ -5207,6 +5273,16 @@ } } }, + "csvtojson": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", + "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", + "requires": { + "bluebird": "^3.5.1", + "lodash": "^4.17.3", + "strip-bom": "^2.0.0" + } + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -8321,6 +8397,11 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -12273,6 +12354,14 @@ } } }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "requires": { + "is-utf8": "^0.2.0" + } + }, "strip-comments": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-1.0.2.tgz", @@ -13257,75 +13346,6 @@ } } }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.8.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", - "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "vue-multiselect": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.6.tgz", diff --git a/package.json b/package.json index e354da93825ab0839f017a113dacfe453884496e..26aaa046a456842652f0a609ec0335b835715e56 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@turf/helpers": "^6.5.0", "axios": "^0.21.1", "core-js": "^3.20.2", + "csvtojson": "^2.0.10", "lodash": "^4.17.21", "ol": "6.8.1", "ol-mapbox-style": "^6.8.3", diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js index 0680fcdfad82586d6325e4cc501bf9873abf4d7c..85e7a1b11496402eb57d688f13dcd2d187a90665 100644 --- a/src/assets/js/utils.js +++ b/src/assets/js/utils.js @@ -12,30 +12,4 @@ export function fileConvertSizeToMo(aSize){ aSize = Math.abs(parseInt(aSize, 10)); const def = [1024*1024, 'Mo', 1]; return (aSize/def[0]).toFixed(def[2]); -} - -export function csvToJson(csv, delimiter) { - const result = []; - - const allLines = csv.split('\n'); - const headers = allLines[0].split(delimiter).map(el => { - return el.replace('\r', ''); - }); - const [, ...lines] = allLines; - - for (const line of lines) { - if (line) { - const obj = {}; - const currentLine = line.split(delimiter).map(el => { - return el.replace('\r', ''); - }); - - for (let i = 0; i < headers.length; i++) { - obj[headers[i]] = currentLine[i]; - } - - result.push(obj); - } - } - return JSON.parse(JSON.stringify(result)); -} +} \ No newline at end of file diff --git a/src/components/FeatureType/FeatureTypeCustomForm.vue b/src/components/FeatureType/FeatureTypeCustomForm.vue index e71b17585637336eace2b1f6e7fe029e79f4afcc..51f068a1460a50452a0bd20da3def1f4302fb3ea 100644 --- a/src/components/FeatureType/FeatureTypeCustomForm.vue +++ b/src/components/FeatureType/FeatureTypeCustomForm.vue @@ -365,53 +365,46 @@ export default { return occurences.length === 1; }, - checkFilledOptions() { - if (this.form.field_type.value === 'list') { - if (this.form.options.value.length < 1) { - return false; - } else if ( - this.form.options.value.length === 1 && - this.form.options.value[0] === '' - ) { - return false; - } - } - return true; + checkListOptions() { + if (this.form.field_type.value !== 'list') return true; + return this.form.options.value.length >= 2 && !this.form.options.value.includes(''); }, checkCustomForm() { this.form.label.errors = []; this.form.name.errors = []; this.form.options.errors = []; + let isValid = true; if (!this.form.label.value) { //* vérifier que le label est renseigné this.form.label.errors = ['Veuillez compléter ce champ.']; - return false; + isValid = false; } else if (!this.form.name.value) { //* vérifier que le nom est renseigné this.form.name.errors = ['Veuillez compléter ce champ.']; - return false; + isValid = false; } else if (!this.hasRegularCharacters(this.form.name.value)) { //* vérifier qu'il n'y a pas de caractères spéciaux this.form.name.errors = [ 'Veuillez utiliser seulement les caratères autorisés.', ]; - return false; + isValid = false; } else if (!this.checkUniqueName()) { //* vérifier si les noms sont pas dupliqués this.form.name.errors = [ 'Les champs personnalisés ne peuvent pas avoir des noms similaires.', ]; - return false; - } else if (!this.checkFilledOptions()) { + isValid = false; + } else if (!this.checkListOptions()) { //* s'il s'agit d'un type liste, vérifier que le champ option est bien renseigné this.form.options.errors = ['Veuillez compléter ce champ.']; - return false; + isValid = false; } else if (this.hasDuplicateOptions()) { //* pour le cas d'options dupliqués - return false; + isValid = false; } - return true; + if (!isValid) document.getElementById(`custom_form-${this.form.position.value}`).scrollIntoView({ block: 'start', inline: 'nearest' }); + return isValid; }, }, }; diff --git a/src/components/Project/Detail/ProjectFeatureTypes.vue b/src/components/Project/Detail/ProjectFeatureTypes.vue index fa88de3e66e19b648fc845c0f5258eff69964bc2..f98acb30e2b0eb3b59d8be7f9adca67a805e03a8 100644 --- a/src/components/Project/Detail/ProjectFeatureTypes.vue +++ b/src/components/Project/Detail/ProjectFeatureTypes.vue @@ -426,10 +426,11 @@ </template> <script> +import { csv } from 'csvtojson'; import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; -import { fileConvertSizeToMo, csvToJson } from '@/assets/js/utils'; +import { fileConvertSizeToMo } from '@/assets/js/utils'; import FeatureTypeLink from '@/components/FeatureType/FeatureTypeLink'; export default { @@ -665,7 +666,11 @@ export default { .filter(Boolean); if (sampleLine.length > 1 && headersCoord.length === 2) { this.csvError = null; - this.csvImport = csvToJson(fr.result, delimiter); + csv() + .fromString(fr.result) + .then((jsonObj)=>{ + this.csvImport = jsonObj; + }); this.featureTypeImporting = false; //* stock filename to import features afterward this.SET_FILE_TO_IMPORT(this.csvFileToImport); diff --git a/src/utils/index.js b/src/utils/index.js index 432cd2970a33e4be66ba5293a3501b9e7f76b2d5..a89354b8305aaae4b1d12e04003990b7e25cda55 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -58,4 +58,29 @@ export function allowedStatus2change(user, isModerate, userStatus, isOwnFeature, } } return []; +} + +export function transformProperties(prop) { + const type = typeof prop; + const date = new Date(prop); + const regInteger = /^-*?\d+$/; + const regFloat = /^-*?\d*?\.\d+$/; + const regText = /[\r\n]/; + if (type === 'boolean' || prop.toLowerCase() === 'true' || prop.toLowerCase() === 'False') { + return 'boolean'; + } else if (regInteger.test(prop) || Number.isSafeInteger(prop)) { + return 'integer'; + } else if ( + type === 'string' && + ['/', ':', '-'].some((el) => prop.includes(el)) && // check for chars found in datestring + date instanceof Date && + !isNaN(date.valueOf()) + ) { + return 'date'; + } else if (regFloat.test(prop) || type === 'number' && !isNaN(parseFloat(prop))) { + return 'decimal'; + } else if (regText.test(prop)) { + return 'text'; + } + return 'char'; //* string by default, most accepted type in database } \ No newline at end of file diff --git a/src/views/FeatureType/FeatureTypeDetail.vue b/src/views/FeatureType/FeatureTypeDetail.vue index 2c20b6c90632cacfd92a6942e2b0539e14cb7a9c..389aeae9eae8ba16ed58aacaf566c1a99015e003 100644 --- a/src/views/FeatureType/FeatureTypeDetail.vue +++ b/src/views/FeatureType/FeatureTypeDetail.vue @@ -352,12 +352,14 @@ </template> <script> +import { csv } from 'csvtojson'; + import { mapActions, mapMutations, mapGetters, mapState } from 'vuex'; -import { formatStringDate } from '@/utils'; +import { formatStringDate, transformProperties } from '@/utils'; import ImportTask from '@/components/ImportTask'; import featureAPI from '@/services/feature-api'; -import { fileConvertSizeToMo, csvToJson } from '@/assets/js/utils'; +import { fileConvertSizeToMo } from '@/assets/js/utils'; // TODO: refactor with above utils, those files are similar export default { name: 'FeatureTypeDetail', @@ -539,26 +541,6 @@ export default { } }, - transformProperties(prop) { - const type = typeof prop; - const date = new Date(prop); - if (type === 'boolean') { - return 'boolean'; - } else if (Number.isSafeInteger(prop)) { - return 'integer'; - } else if ( - type === 'string' && - ['/', ':', '-'].some((el) => prop.includes(el)) && // check for chars found in datestring - date instanceof Date && - !isNaN(date.valueOf()) - ) { - return 'char'; - } else if (type === 'number' && !isNaN(parseFloat(prop))) { - return 'decimal'; - } - return 'char'; //* string by default, most accepted type in database - }, - checkJsonValidity(json) { this.importError = ''; const fields = this.structure.customfield_set.map((el) => { @@ -570,9 +552,10 @@ export default { }); for (const feature of json.features) { for (const { name, field_type, options } of fields) { - if (name in feature.properties) { - const fieldInFeature = feature.properties[name]; - const customType = this.transformProperties(fieldInFeature); + const properties = feature.properties || feature; + if (name in properties) { + const fieldInFeature = properties[name]; + const customType = transformProperties(fieldInFeature); //* if custom field value is not null, then check validity of field if (fieldInFeature !== null) { //* if field type is list, it's not possible to guess from value type @@ -595,22 +578,20 @@ export default { return true; }, - checkCsvValidity(csv) { + async checkCsvValidity(csvString) { this.importError = ''; - - // Find csv delimiter - const commaDelimited = csv.split('\n')[0].includes(','); - const semicolonDelimited = csv.split('\n')[0].includes(';'); + // Find csvString delimiter + const commaDelimited = csvString.split('\n')[0].includes(','); + const semicolonDelimited = csvString.split('\n')[0].includes(';'); const delimiter = commaDelimited && !semicolonDelimited ? ',' : semicolonDelimited ? ';' : false; if ((commaDelimited && semicolonDelimited) || !delimiter) { this.importError = `Le fichier ${this.csvFileToImport.name} n'est pas formaté correctement`; return false; } - // Check if file contains 'lat' and 'long' fields const headersLine = - csv + csvString .split('\n')[0] .replace(/(\r\n|\n|\r)/gm, '') .split(delimiter) @@ -622,7 +603,7 @@ export default { return false; } const sampleLine = - csv + csvString .split('\n')[1] .split(delimiter) .map(el => { @@ -630,55 +611,8 @@ export default { }) .filter(Boolean); if (sampleLine.length > 1 && headersLine.length === 2) { - const fields = this.structure.customfield_set.map((el) => { - return { - name: el.name, - field_type: el.field_type, - options: el.options, - }; - }); - const csvFeatures = csvToJson(csv, delimiter); - for (const feature of csvFeatures) { - for (let { name, field_type, options } of fields) { - if (name in feature) { - const fieldInFeature = feature[name]; - - // overide some specific cases on date type data - if ( - typeof fieldInFeature === 'string' && - ['/', ':', '-'].some((el) => fieldInFeature.includes(el)) && - (new Date(fieldInFeature)) instanceof Date && - !isNaN((new Date(fieldInFeature)).valueOf()) - ) { - field_type = 'char'; - } else if ( - field_type === 'date' && - ((new Date(fieldInFeature)) instanceof Date) - ) { - field_type = 'char'; - } - - const customType = this.transformProperties(fieldInFeature); - //* if custom field value is not null, then check validity of field - if (fieldInFeature !== null) { - //* if field type is list, it's not possible to guess from value type - if (field_type === 'list') { - //*then check if the value is an available option - if (fieldInFeature && !options.includes(fieldInFeature)) { - this.importError = `Le fichier est invalide: la valeur [ ${fieldInFeature} ] n'est pas une option valide - pour le champ personnalisé "${name}".`; - return false; - } - } else if (customType !== field_type) { - //* check if custom field value match - this.importError = `Le fichier est invalide: Un champ de type ${field_type} ne peut pas avoir la valeur [ ${fieldInFeature} ]`; - return false; - } - } - } - } - } - return true; + const features = await csv().fromString(csvString); + return this.checkJsonValidity({ features }); } else { return false; } diff --git a/src/views/FeatureType/FeatureTypeEdit.vue b/src/views/FeatureType/FeatureTypeEdit.vue index 315acba70feeaf31c5d1beb13cbc259fbb08a0a3..47bad6dceb3668063f9c76a1b9de51d7c13fdc7c 100644 --- a/src/views/FeatureType/FeatureTypeEdit.vue +++ b/src/views/FeatureType/FeatureTypeEdit.vue @@ -159,6 +159,7 @@ import { mapGetters, mapState, mapMutations, mapActions } from 'vuex'; import Dropdown from '@/components/Dropdown.vue'; import FeatureTypeCustomForm from '@/components/FeatureType/FeatureTypeCustomForm.vue'; +import { transformProperties } from'@/utils'; export default { name: 'FeatureTypeEdit', @@ -639,23 +640,21 @@ export default { return 'point'; }, - transformProperties(prop) { - const type = typeof prop; - const date = new Date(prop); - if (type === 'boolean') { - return 'boolean'; - } else if (Number.isSafeInteger(prop)) { - return 'integer'; - } else if ( - type === 'string' && - date instanceof Date && - !isNaN(date.valueOf()) - ) { - return 'date'; - } else if (type === 'number' && !isNaN(parseFloat(prop))) { - return 'decimal'; + buildCustomForm(properties) { + for (const [key, val] of Object.entries(properties)) { + //* check that the property is not a keyword from the backend or map style + // todo: add map style keywords + if (!this.reservedKeywords.includes(key)) { + const customForm = { + label: { value: key || '' }, + name: { value: key || '' }, + position: this.dataKey, // * use dataKey already incremented by addCustomForm + field_type: { value: transformProperties(val) }, // * guessed from the type + options: { value: [] }, // * not available in export + }; + this.addCustomForm(customForm); + } } - return 'char'; //* string by default, most accepted type in database }, importGeoJsonFeatureType() { @@ -665,93 +664,16 @@ export default { this.form.title.value = properties.feature_type; this.form.geom_type.value = this.translateLabel(geometry.type); this.updateStore(); //* register title & geom_type in store - - //* loop properties to create a customForm for each of them - for (const [key, val] of Object.entries(properties)) { - //* check that the property is not a keyword from the backend or map style - // todo: add map style keywords - if (!this.reservedKeywords.includes(key)) { - const customForm = { - label: { value: key || '' }, - name: { value: key || '' }, - position: this.dataKey, // * use dataKey already incremented by addCustomForm - field_type: { value: this.transformProperties(val) }, // * guessed from the type - options: { value: [] }, // * not available in export - }; - this.addCustomForm(customForm); - } - } + this.buildCustomForm(properties); } }, importCSVFeatureType() { if (this.csv.length) { this.updateStore(); //* register title & geom_type in store - // List fileds for user to select coords fields - // this.csvFields = - // Object.keys(this.csv[0]) - // .map(el => { - // return { - // field: el, - // x: false, - // y:false - // }; - // }); - for (const [key, val] of Object.entries(this.csv[0])) { - //* check that the property is not a keyword from the backend or map style - // todo: add map style keywords - if (!this.reservedKeywords.includes(key)) { - const customForm = { - label: { value: key || '' }, - name: { value: key || '' }, - position: this.dataKey, // * use dataKey already incremented by addCustomForm - field_type: { value: this.transformProperties(val) }, // * guessed from the type - options: { value: [] }, // * not available in export - }; - this.addCustomForm(customForm); - } - } + this.buildCustomForm(this.csv[0]); } }, - - // pickXcsvCoordField(e) { - // this.csvFields.forEach(el => { - // if (el.field === e.field) { - // el.x = true; - // } else { - // el.x = false; - // } - // }); - // }, - // pickYcsvCoordField(e) { - // this.csvFields.forEach(el => { - // if (el.field === e.field) { - // el.y = true; - // } else { - // el.y = false; - // } - // }); - // }, - // setCSVCoordsFields() { - // const xField = this.csvFields.find(el => el.x === true).field; - // const yField = this.csvFields.find(el => el.y === true).field; - // this.csvFields = null; - - // for (const [key, val] of Object.entries(this.csv[0])) { - // //* check that the property is not a keyword from the backend or map style - // // todo: add map style keywords - // if (!this.reservedKeywords.includes(key) && key !== xField && key !== yField) { - // const customForm = { - // label: { value: key || '' }, - // name: { value: key || '' }, - // position: this.dataKey, // * use dataKey already incremented by addCustomForm - // field_type: { value: this.transformProperties(val) }, // * guessed from the type - // options: { value: [] }, // * not available in export - // }; - // this.addCustomForm(customForm); - // } - // } - // } }, }; </script>