Skip to content

Commit

Permalink
Merge pull request #417 from Progress1/main
Browse files Browse the repository at this point in the history
Fix import csv (Word lists), Add possibility skip unwanted columns
  • Loading branch information
Progress1 authored Nov 11, 2024
2 parents ea36677 + 833bcb6 commit 6b27bc6
Showing 1 changed file with 114 additions and 98 deletions.
212 changes: 114 additions & 98 deletions src/gui/src/components/common/ImportCSV.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
<!-- https://github.com/jgile/vue-csv-import/blob/vue2/src/components/VueCsvImport.vue
there is also Vue v3 version for future project conversion -->
<template>
<div class="vue-csv-uploader" data-id="csv-importer">
<div class="form">
<div class="vue-csv-uploader-part-one">
<div class="form-check form-group csv-import-checkbox" v-if="headers === null">
<slot name="hasHeaders" :headers="hasHeaders" :toggle="toggleHasHeaders">
<input :class="checkboxClass" type="checkbox" :id="makeId('hasHeaders')" :value="hasHeaders" @change="toggleHasHeaders">
<input :class="checkboxClass" type="checkbox"
:id="makeId('hasHeaders')"
:value="hasHeaders"
@change="toggleHasHeaders" />
<label class="form-check-label" :for="makeId('hasHeaders')">
File Has Headers
</label>
</slot>
</div>
<div class="form-group csv-import-file">
<input ref="csv" type="file" @change.prevent="validFileMimeType" :class="inputClass" name="csv">
<input ref="csv"
type="file"
@change.prevent="validFileMimeType"
:class="inputClass"
name="csv" />
<slot name="error" v-if="showErrorMessage">
<div class="invalid-feedback d-block">
File type is invalid
Expand All @@ -28,38 +37,34 @@
</div>
<div class="vue-csv-uploader-part-two">
<div class="vue-csv-mapping" v-if="sample">
<v-simple-table :class="tableClass">
<table :class="tableClass">
<slot name="thead">
<thead>
<tr>
<th>Field</th>
<th>CSV Column</th>
</tr>
<tr>
<th>Field</th>
<th>CSV Column</th>
</tr>
</thead>
</slot>
<tbody>
<tr v-for="(field, key) in fieldsToMap" :key="key">
<td>{{ field.label }}</td>
<td>
<select :class="tableSelectClass" :name="`csv_uploader_map_${key}`" v-model="map[field.key]">
<option :value="null" v-if="canIgnore">Ignore</option>
<option v-for="(column, key) in firstRow" :key="key" :value="key">{{ column }}</option>
</select>

<!--<v-select
:class="tableSelectClass"
:name="`csv_uploader_map_${key}`"
v-model="map[field.key]"
:items="firstRow"
:value="key"
/>-->
</td>
</tr>
<tr v-for="(field, key) in fieldsToMap" :key="key">
<td>{{ field.label }}</td>
<td>
<select :class="tableSelectClass"
:name="`csv_uploader_map_${key}`"
v-model="map[field.key]">
<option :value="null" v-if="canIgnore">{{ ignoreOptionText }}</option>
<option v-for="(column, key) in firstRow" :key="key" :value="key">
{{ column }}
</option>
</select>
</td>
</tr>
</tbody>
</v-simple-table>
</table>
<div class="form-group" v-if="url">
<slot name="submit" :submit="submit">
<input type="submit" :class="buttonClass" @click.prevent="submit" :value="submitBtnText">
<input type="submit" :class="buttonClass" @click.prevent="submit" :value="submitBtnText" />
</slot>
</div>
</div>
Expand All @@ -69,72 +74,76 @@
</template>

<script>
import { drop, every, forEach, get, isArray, map, set } from 'lodash';
import axios from 'axios';
import Papa from 'papaparse';
import { drop, every, forEach, get, isArray, map, set } from "lodash";
import axios from "axios";
import Papa from "papaparse";
import mimeTypes from "mime-types";

export default {
props: {
value: Array,
url: {
type: String
type: String,
},
mapFields: {
required: true
required: true,
},
callback: {
type: Function,
default: () => ({})
default: () => ({}),
},
catch: {
type: Function,
default: () => ({})
default: () => ({}),
},
finally: {
type: Function,
default: () => ({})
default: () => ({}),
},
parseConfig: {
type: Object,
default() {
return {};
}
},
},
headers: {
default: null
default: null,
},
loadBtnText: {
type: String,
default: "Next"
default: "Next",
},
submitBtnText: {
type: String,
default: "Submit"
default: "Submit",
},
ignoreOptionText: {
type: String,
default: "Ignore",
},
autoMatchFields: {
type: Boolean,
default: false
default: false,
},
autoMatchIgnoreCase: {
type: Boolean,
default: false
default: false,
},
tableClass: {
type: String,
default: "table"
default: "table",
},
checkboxClass: {
type: String,
default: "form-check-input"
default: "form-check-input",
},
buttonClass: {
type: String,
default: "btn btn-primary"
default: "btn btn-primary",
},
inputClass: {
type: String,
default: "form-control-file"
default: "form-control-file",
},
validation: {
type: Boolean,
Expand All @@ -144,16 +153,16 @@
type: Array,
default: () => {
return ["text/csv", "text/x-csv", "application/vnd.ms-excel", "text/plain"];
}
},
},
tableSelectClass: {
type: String,
default: 'form-control'
default: "form-control",
},
canIgnore: {
type: Boolean,
default: false,
}
default: true,
},
},

data: () => ({
Expand All @@ -166,48 +175,54 @@
csv: null,
sample: null,
isValidFileMimeType: false,
fileSelected: false
fileSelected: false,
}),

created() {
this.hasHeaders = this.headers;
if (isArray(this.mapFields)) {
this.fieldsToMap = map(this.mapFields, (item) => {
return {
key: item,
label: item
};
});
} else {
this.fieldsToMap = map(this.mapFields, (label, key) => {
return {
key: key,
label: label
};
});
}
this.$root.$on('reset-csv-dialog', () => {
this.reset();
});
this.initializeFromProps();
},

methods: {
initializeFromProps() {
this.hasHeaders = this.headers;

if (isArray(this.mapFields)) {
this.fieldsToMap = map(this.mapFields, (item) => {
return {
key: item,
label: item,
};
});
} else {
this.fieldsToMap = map(this.mapFields, (label, key) => {
return {
key: key,
label: label,
};
});
}

this.$root.$on('reset-csv-dialog', () => {
this.reset();
});
},
submit() {
const _this = this;
this.form.csv = this.buildMappedCsv();
this.$emit('input', this.form.csv);
this.$emit("input", this.form.csv);

if (this.url) {
axios.post(this.url, this.form).then(response => {
_this.callback(response);
}).catch(response => {
_this.catch(response);
}).finally(response => {
_this.finally(response);
});
axios
.post(this.url, this.form)
.then((response) => {
_this.callback(response);
})
.catch((response) => {
_this.catch(response);
})
.finally((response) => {
_this.finally(response);
});
} else {
_this.callback(this.form.csv);
}
Expand Down Expand Up @@ -277,51 +292,54 @@
this.sample = null;
//this.isValidFileMimeType = false;
this.fileSelected = false;
this.hasHeaders = false;

let fileHead = document.querySelector("input[type='checkbox']");
fileHead.checked = false;

let file = document.querySelector("input[name='csv']");
file.value = '';
}
},
},
watch: {
map: {
deep: true,
handler: function (newVal) {
if (!this.url) {
let hasAllKeys = Array.isArray(this.mapFields) ? every(this.mapFields, function (item) {
return newVal.hasOwnProperty(item);
}) : every(this.mapFields, function (item, key) {
return newVal.hasOwnProperty(key);
});
let hasAllKeys = Array.isArray(this.mapFields)
? every(this.mapFields, function (item) {
return Object.prototype.hasOwnProperty.call(newVal, item);
})
: every(this.mapFields, function (item, key) {
return Object.prototype.hasOwnProperty.call(newVal, key);
});

if (hasAllKeys) {
this.submit();
}
}
}
},
},
sample(newVal) {
if(this.autoMatchFields){
if(newVal !== null){
this.fieldsToMap.forEach(field => {
if (this.autoMatchFields) {
if (newVal !== null) {
this.fieldsToMap.forEach((field) => {
newVal[0].forEach((columnName, index) => {
if(this.autoMatchIgnoreCase === true){
if(field.label.toLowerCase().trim() === columnName.toLowerCase().trim()){
if (this.autoMatchIgnoreCase === true) {
if (field.label.toLowerCase().trim() === columnName.toLowerCase().trim()) {
this.$set(this.map, field.key, index);
}
} else{
if(field.label.trim() === columnName.trim()){
} else {
if (field.label.trim() === columnName.trim()) {
this.$set(this.map, field.key, index);
}
}
});
});
}
}
//window.console.debug(oldVal);
},
mapFields() {
this.initializeFromProps();
}
},
computed: {
Expand All @@ -333,9 +351,7 @@
},
disabledNextButton() {
return !this.isValidFileMimeType;
}
},
},
mounted() {
}
};
</script>

0 comments on commit 6b27bc6

Please sign in to comment.