first commit + add fe component vue accone
This commit is contained in:
194
libs/vendor/xlsprse/components/ColumnChooser.js
vendored
Normal file
194
libs/vendor/xlsprse/components/ColumnChooser.js
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="catalog-column-chooser">
|
||||
<a href="#" class="header-tool" @click="toggleHeaders">
|
||||
{{ withHeaders ? text[lang].file.withoutHeaders : text[lang].file.withHeaders }}
|
||||
</a>
|
||||
<br><br>
|
||||
<div v-for="(column, index) in localUserColumns">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-success" :class="{ 'panel-success': column.selection, 'panel-danger': !column.selection }">
|
||||
<div class="panel-heading">
|
||||
<p v-if="column.selection">{{ column.selection.name }}</p>
|
||||
<p v-else>{{ text[lang].chooseColumn }}</p>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<multiselect
|
||||
:id="index"
|
||||
v-model="column.selection"
|
||||
deselect-label=""
|
||||
:selected-label="text[lang].selected"
|
||||
:select-label="text[lang].select"
|
||||
track-by="name"
|
||||
label="name"
|
||||
:placeholder="text[lang].selectColumn"
|
||||
:options="column.options"
|
||||
:searchable="false"
|
||||
:allow-empty="false"
|
||||
@select="onSelectChange"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
{{ text[lang].columnData }} <i>"{{ column.name }}"</i>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{{ column.name }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="data in column.displayedData">
|
||||
<td>{{ data }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right" v-if="showValidateButton">
|
||||
<button @click="validate" id="validate-columns" class="btn btn-primary">{{ text[lang].submit }}</button>
|
||||
</div>
|
||||
<simplert
|
||||
:useRadius="true"
|
||||
:useIcon="true"
|
||||
ref="simplert">
|
||||
</simplert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import Simplert from 'vue2-simplert';
|
||||
import _ from 'lodash';
|
||||
import text from '../lang';
|
||||
|
||||
export default {
|
||||
name: 'ColumnChooser',
|
||||
components: { Multiselect, Simplert },
|
||||
props: {
|
||||
userColumns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
validator: columns => columns.every(column => _.has(column, 'name') && _.has(column, 'data')),
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
validator: columns => columns.every(column => _.has(column, 'name') && _.has(column, 'value')),
|
||||
},
|
||||
showValidateButton: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
default: () => 'en',
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
userColumns(newColumns) {
|
||||
this.fillLocalUserColumns(newColumns);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSelectChange({ value: selectedValue }, id) { // eslint-disable-line
|
||||
if (this.optionalValues.indexOf(selectedValue) !== -1) return;
|
||||
|
||||
_.forEach(this.localUserColumns, (column, index) => {
|
||||
if (index !== id) {
|
||||
const hasSelectionConflict = column.selection && column.selection.value === selectedValue;
|
||||
if (hasSelectionConflict) {
|
||||
column.selection = null; // eslint-disable-line
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
validate() {
|
||||
const hasMadeAllSelections = this.localUserColumns.every(column => column.selection !== null);
|
||||
if (!hasMadeAllSelections) {
|
||||
this.showError(text[this.lang].error.selectColumn); // eslint-disable-line
|
||||
} else {
|
||||
const selectedRequiredValues = _
|
||||
.map(this.localUserColumns, 'selection.value')
|
||||
.filter(value => this.requiredValues.indexOf(value) !== -1);
|
||||
|
||||
const missingValues = _.difference(this.requiredValues, selectedRequiredValues);
|
||||
if (missingValues.length > 0) {
|
||||
this.showError(`${text[this.lang].error.missingColumns} ${missingValues.join(', ')}`); // eslint-disable-line
|
||||
return;
|
||||
}
|
||||
|
||||
this.results = this.localUserColumns.map(localColumn => ({
|
||||
column: localColumn.selection.value,
|
||||
data: localColumn.data,
|
||||
}));
|
||||
this.$emit('on-validate', this.results);
|
||||
}
|
||||
},
|
||||
fillLocalUserColumns(newColumns) {
|
||||
this.localUserColumns = newColumns.map(column => ({
|
||||
name: column.name,
|
||||
displayedData: _.take(column.data, 4),
|
||||
data: column.data,
|
||||
options: _.clone(this.columns),
|
||||
selection: null,
|
||||
}));
|
||||
},
|
||||
toggleHeaders() {
|
||||
if (this.withHeaders) {
|
||||
this.localUserColumns.forEach((column, index) => {
|
||||
const data = [column.name].concat(column.data);
|
||||
column.name = `${text[this.lang].column} ${index + 1}`; // eslint-disable-line
|
||||
column.data = data; // eslint-disable-line
|
||||
column.displayedData = _.take(column.data, 4); // eslint-disable-line
|
||||
});
|
||||
} else {
|
||||
this.localUserColumns.forEach((column) => {
|
||||
column.name = column.data.shift(); // eslint-disable-line
|
||||
column.displayedData = _.take(column.data, 4); // eslint-disable-line
|
||||
});
|
||||
}
|
||||
this.withHeaders = !this.withHeaders;
|
||||
},
|
||||
showError(message) {
|
||||
this.$refs.simplert.openSimplert({
|
||||
title: text[this.lang].error.title,
|
||||
message,
|
||||
type: 'error',
|
||||
customCloseBtnText: text[this.lang].close,
|
||||
});
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
withHeaders: true,
|
||||
localUserColumns: [],
|
||||
requiredValues: [],
|
||||
optionalValues: [],
|
||||
results: [],
|
||||
text,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.fillLocalUserColumns(this.userColumns);
|
||||
this.optionalValues = this.columns
|
||||
.filter(column => column.isOptional)
|
||||
.map(column => column.value);
|
||||
this.requiredValues = this.columns
|
||||
.filter(column => !column.isOptional)
|
||||
.map(column => column.value);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
194
libs/vendor/xlsprse/components/ColumnChooser.vue
vendored
Normal file
194
libs/vendor/xlsprse/components/ColumnChooser.vue
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="catalog-column-chooser">
|
||||
<a href="#" class="header-tool" @click="toggleHeaders">
|
||||
{{ withHeaders ? text[lang].file.withoutHeaders : text[lang].file.withHeaders }}
|
||||
</a>
|
||||
<br><br>
|
||||
<div v-for="(column, index) in localUserColumns">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-success" :class="{ 'panel-success': column.selection, 'panel-danger': !column.selection }">
|
||||
<div class="panel-heading">
|
||||
<p v-if="column.selection">{{ column.selection.name }}</p>
|
||||
<p v-else>{{ text[lang].chooseColumn }}</p>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<multiselect
|
||||
:id="index"
|
||||
v-model="column.selection"
|
||||
deselect-label=""
|
||||
:selected-label="text[lang].selected"
|
||||
:select-label="text[lang].select"
|
||||
track-by="name"
|
||||
label="name"
|
||||
:placeholder="text[lang].selectColumn"
|
||||
:options="column.options"
|
||||
:searchable="false"
|
||||
:allow-empty="false"
|
||||
@select="onSelectChange"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
{{ text[lang].columnData }} <i>"{{ column.name }}"</i>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{{ column.name }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="data in column.displayedData">
|
||||
<td>{{ data }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right" v-if="showValidateButton">
|
||||
<button @click="validate" id="validate-columns" class="btn btn-primary">{{ text[lang].submit }}</button>
|
||||
</div>
|
||||
<simplert
|
||||
:useRadius="true"
|
||||
:useIcon="true"
|
||||
ref="simplert">
|
||||
</simplert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import Simplert from 'vue2-simplert';
|
||||
import _ from 'lodash';
|
||||
import text from '../lang';
|
||||
|
||||
export default {
|
||||
name: 'ColumnChooser',
|
||||
components: { Multiselect, Simplert },
|
||||
props: {
|
||||
userColumns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
validator: columns => columns.every(column => _.has(column, 'name') && _.has(column, 'data')),
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
validator: columns => columns.every(column => _.has(column, 'name') && _.has(column, 'value')),
|
||||
},
|
||||
showValidateButton: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
default: () => 'en',
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
userColumns(newColumns) {
|
||||
this.fillLocalUserColumns(newColumns);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSelectChange({ value: selectedValue }, id) { // eslint-disable-line
|
||||
if (this.optionalValues.indexOf(selectedValue) !== -1) return;
|
||||
|
||||
_.forEach(this.localUserColumns, (column, index) => {
|
||||
if (index !== id) {
|
||||
const hasSelectionConflict = column.selection && column.selection.value === selectedValue;
|
||||
if (hasSelectionConflict) {
|
||||
column.selection = null; // eslint-disable-line
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
validate() {
|
||||
const hasMadeAllSelections = this.localUserColumns.every(column => column.selection !== null);
|
||||
if (!hasMadeAllSelections) {
|
||||
this.showError(text[this.lang].error.selectColumn); // eslint-disable-line
|
||||
} else {
|
||||
const selectedRequiredValues = _
|
||||
.map(this.localUserColumns, 'selection.value')
|
||||
.filter(value => this.requiredValues.indexOf(value) !== -1);
|
||||
|
||||
const missingValues = _.difference(this.requiredValues, selectedRequiredValues);
|
||||
if (missingValues.length > 0) {
|
||||
this.showError(`${text[this.lang].error.missingColumns} ${missingValues.join(', ')}`); // eslint-disable-line
|
||||
return;
|
||||
}
|
||||
|
||||
this.results = this.localUserColumns.map(localColumn => ({
|
||||
column: localColumn.selection.value,
|
||||
data: localColumn.data,
|
||||
}));
|
||||
this.$emit('on-validate', this.results);
|
||||
}
|
||||
},
|
||||
fillLocalUserColumns(newColumns) {
|
||||
this.localUserColumns = newColumns.map(column => ({
|
||||
name: column.name,
|
||||
displayedData: _.take(column.data, 4),
|
||||
data: column.data,
|
||||
options: _.clone(this.columns),
|
||||
selection: null,
|
||||
}));
|
||||
},
|
||||
toggleHeaders() {
|
||||
if (this.withHeaders) {
|
||||
this.localUserColumns.forEach((column, index) => {
|
||||
const data = [column.name].concat(column.data);
|
||||
column.name = `${text[this.lang].column} ${index + 1}`; // eslint-disable-line
|
||||
column.data = data; // eslint-disable-line
|
||||
column.displayedData = _.take(column.data, 4); // eslint-disable-line
|
||||
});
|
||||
} else {
|
||||
this.localUserColumns.forEach((column) => {
|
||||
column.name = column.data.shift(); // eslint-disable-line
|
||||
column.displayedData = _.take(column.data, 4); // eslint-disable-line
|
||||
});
|
||||
}
|
||||
this.withHeaders = !this.withHeaders;
|
||||
},
|
||||
showError(message) {
|
||||
this.$refs.simplert.openSimplert({
|
||||
title: text[this.lang].error.title,
|
||||
message,
|
||||
type: 'error',
|
||||
customCloseBtnText: text[this.lang].close,
|
||||
});
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
withHeaders: true,
|
||||
localUserColumns: [],
|
||||
requiredValues: [],
|
||||
optionalValues: [],
|
||||
results: [],
|
||||
text,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.fillLocalUserColumns(this.userColumns);
|
||||
this.optionalValues = this.columns
|
||||
.filter(column => column.isOptional)
|
||||
.map(column => column.value);
|
||||
this.requiredValues = this.columns
|
||||
.filter(column => !column.isOptional)
|
||||
.map(column => column.value);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
132
libs/vendor/xlsprse/components/ParseFile.vue
vendored
Normal file
132
libs/vendor/xlsprse/components/ParseFile.vue
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="parse-file">
|
||||
<div class="alert alert-danger" v-if="error">
|
||||
{{ error }}
|
||||
</div>
|
||||
<div
|
||||
v-if="!file"
|
||||
:class="['dropzone-area', dragging ? 'dropzone-over' : '']"
|
||||
drag-over="handleDragOver"
|
||||
@dragenter="dragging=true"
|
||||
@dragleave="dragging=false"
|
||||
>
|
||||
<div class="dropzone-text">
|
||||
<span class="dropzone-title">{{ text[lang].file.select }}</span>
|
||||
<span class="dropzone-info" v-if="help">{{ help }}</span>
|
||||
</div>
|
||||
<input type="file" @change="upload">
|
||||
</div>
|
||||
<div class="dropzone-preview" v-else>
|
||||
<button @click="file=null" class="btn btn-primary">{{ text[lang].file.tryAgain }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import parseFile from '../parser';
|
||||
import text from '../lang';
|
||||
|
||||
export default {
|
||||
name: 'ParseFile',
|
||||
props: {
|
||||
help: {
|
||||
type: String,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
default: () => 'en',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
upload(event) {
|
||||
const files = event.target.files || event.dataTransfer.files;
|
||||
if (files.length !== 1) {
|
||||
this.error = text[this.lang].error.fileSelection;
|
||||
return;
|
||||
}
|
||||
this.file = event.target.files[0];
|
||||
parseFile(this.file, text[this.lang]).then((results) => {
|
||||
this.error = null;
|
||||
this.$emit('fileDataReceived', results);
|
||||
}).catch((error) => {
|
||||
this.error = error;
|
||||
this.file = null;
|
||||
});
|
||||
},
|
||||
reset() {
|
||||
this.error = null;
|
||||
this.file = null;
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: null,
|
||||
dragging: false,
|
||||
file: null,
|
||||
text,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dropzone-over {
|
||||
border: 1px solid red !important;
|
||||
}
|
||||
|
||||
.dropzone-area {
|
||||
height: 200px;
|
||||
position: relative;
|
||||
border: 2px dashed #CBCBCB;
|
||||
}
|
||||
.dropzone-area:hover {
|
||||
border: 2px dashed #2E94C4;
|
||||
}
|
||||
.dropzone-area .dropzone-title {
|
||||
color: #1975A0;
|
||||
}
|
||||
|
||||
.dropzone-area input {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dropzone-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
text-align: center;
|
||||
transform: translate(0, -50%);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropzone-text span {
|
||||
display: block;
|
||||
font-family: Arial, Helvetica;
|
||||
line-height: 1.9;
|
||||
}
|
||||
|
||||
.dropzone-title {
|
||||
font-size: 13px;
|
||||
color: #787878;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
.dropzone-info {
|
||||
font-size: 12px;
|
||||
color: #A8A8A8;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
|
||||
.dropzone-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
107
libs/vendor/xlsprse/components/XlsCsvParser.vue
vendored
Normal file
107
libs/vendor/xlsprse/components/XlsCsvParser.vue
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<div class="xls-csv-parser">
|
||||
<parse-file @fileDataReceived="fileDataReceived" :help="help" ref="parseFile" :lang="lang"></parse-file>
|
||||
<br><br>
|
||||
<column-chooser
|
||||
v-if="showColumnChooser"
|
||||
ref="columnChooser"
|
||||
:userColumns="userColumns"
|
||||
:columns="columns"
|
||||
:showValidateButton="showValidateButton"
|
||||
:lang="lang"
|
||||
@on-validate="onValidate"
|
||||
></column-chooser>
|
||||
<div class="parser-hidden-columns-input" v-for="(result, i) in results">
|
||||
<input type="hidden" v-for="(data, i) in result.data" :name="`${result.column}[${i}]`" :value="data">
|
||||
</div>
|
||||
<simplert
|
||||
:useRadius="true"
|
||||
:useIcon="true"
|
||||
ref="simplert">
|
||||
</simplert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import Simplert from 'vue2-simplert';
|
||||
import ColumnChooser from './ColumnChooser';
|
||||
import ParseFile from './ParseFile';
|
||||
import text from '../lang';
|
||||
|
||||
export default {
|
||||
name: 'XlsCsvParser',
|
||||
components: { ColumnChooser, ParseFile, Simplert },
|
||||
props: {
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
validator: columns => columns.every(column => _.has(column, 'name') && _.has(column, 'value')),
|
||||
},
|
||||
validateButtonId: {
|
||||
type: String,
|
||||
default: () => null,
|
||||
},
|
||||
help: {
|
||||
type: String,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
validator: language => ['en', 'fr'].indexOf(language) !== -1,
|
||||
default: () => 'en',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fileDataReceived(fileData) {
|
||||
this.results = [];
|
||||
const requiredColumns = this.columns.filter(column => !column.isOptional);
|
||||
if (fileData.length < requiredColumns.length) {
|
||||
const message = `${text[this.lang].error.columnNumber}<br> ${this.columns.map(column => column.name).join('<br> ')}`;
|
||||
this.showError(message);
|
||||
return;
|
||||
}
|
||||
this.userColumns = fileData;
|
||||
this.showColumnChooser = true;
|
||||
},
|
||||
onValidate(results) {
|
||||
this.results = results;
|
||||
this.$emit('on-validate', results);
|
||||
},
|
||||
validate(event) {
|
||||
event.preventDefault();
|
||||
if (!this.showColumnChooser) {
|
||||
this.showError(text[this.lang].error.fileNumber);
|
||||
} else {
|
||||
this.$refs.columnChooser.validate();
|
||||
}
|
||||
},
|
||||
showError(message) {
|
||||
this.$refs.simplert.openSimplert({
|
||||
title: text[this.lang].error.title,
|
||||
message,
|
||||
type: 'error',
|
||||
customCloseBtnText: text[this.lang].close,
|
||||
onClose: () => {
|
||||
this.$refs.parseFile.reset();
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.validateButtonId) {
|
||||
this.showValidateButton = false;
|
||||
document.getElementById(this.validateButtonId).addEventListener('click', this.validate);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showColumnChooser: false,
|
||||
showHiddenInputs: false,
|
||||
showValidateButton: true,
|
||||
results: [],
|
||||
userColumns: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
6
libs/vendor/xlsprse/index.js
vendored
Normal file
6
libs/vendor/xlsprse/index.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import XlsCsvParser from './components/XlsCsvParser.vue';
|
||||
import ColumnChooser from './components/ColumnChooser.vue';
|
||||
|
||||
export default XlsCsvParser;
|
||||
export { XlsCsvParser, ColumnChooser };
|
||||
|
||||
12
libs/vendor/xlsprse/index.php
vendored
Normal file
12
libs/vendor/xlsprse/index.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<script type="module">
|
||||
import XlsCsvParser from './components/XlsCsvParser.vue';
|
||||
import ColumnChooser from './components/ColumnChooser.vue';
|
||||
|
||||
export default XlsCsvParser;
|
||||
export { XlsCsvParser, ColumnChooser };
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
111
libs/vendor/xlsprse/lang/index.js
vendored
Normal file
111
libs/vendor/xlsprse/lang/index.js
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
export default {
|
||||
en: {
|
||||
column: 'Column',
|
||||
submit: 'Submit',
|
||||
close: 'OK',
|
||||
columnData: 'Data for column',
|
||||
chooseColumn: 'Choose a column',
|
||||
selected: 'Selected',
|
||||
select: 'Select',
|
||||
selectColumn: 'Please choose a column',
|
||||
file: {
|
||||
select: 'Please select a file',
|
||||
tryAgain: 'Choose another file',
|
||||
withHeaders: 'This file includes headers',
|
||||
withoutHeaders: 'This file does not include headers',
|
||||
},
|
||||
error: {
|
||||
title: 'Error',
|
||||
columnNumber: 'You do not have enough columns. <br><b>Required columns are</b>: ',
|
||||
missingColumns: 'Missing required columns:',
|
||||
selectColumn: 'You need to select all columns',
|
||||
fileNumber: 'You need to select a file',
|
||||
fileSelection: 'No file has been selected',
|
||||
invalidFile: 'This file is invalid. Try to use a CSV or Xlsx file',
|
||||
noWorksheet: 'Must have at least one worksheet',
|
||||
emptyWorksheet: 'The worksheet is empty',
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
column: 'Colonne',
|
||||
submit: 'Valider',
|
||||
close: 'OK',
|
||||
columnData: 'Données pour la colonne',
|
||||
chooseColumn: 'Choisir une colonne',
|
||||
selected: 'Selectionné',
|
||||
select: 'Choisir',
|
||||
selectColumn: 'Veuillez choisir une colonne',
|
||||
file: {
|
||||
select: 'Veuillez selectionner un fichier',
|
||||
tryAgain: 'Choisir un autre fichier',
|
||||
withHeaders: 'Ce fichier possède des entêtes',
|
||||
withoutHeaders: 'Ce fichier ne possède pas d\'entêtes',
|
||||
},
|
||||
error: {
|
||||
title: 'Erreur',
|
||||
columnNumber: 'Vous n\'avez pas assez de colonnes. <br><b>Vous devez avoir les colonnes suivantes</b>: ',
|
||||
missingColumns: 'Les colonnes nécéssaires suivantes manquent:',
|
||||
selectColumn: 'Vous devez remplir toutes les colonnes',
|
||||
fileNumber: 'Vous devez choisir un fichier',
|
||||
fileSelection: 'Aucun fichier n\'a été selectionné',
|
||||
invalidFile: 'Ce fichier est invalide. Veuillez essayer avec un fichier CSV ou Xlsx',
|
||||
noWorksheet: 'Le fichier doit avoir au moins une feuille de calcul',
|
||||
emptyWorksheet: 'Ce fichier est vide',
|
||||
},
|
||||
},
|
||||
nl: {
|
||||
column: 'Kolom',
|
||||
submit: 'Verzenden',
|
||||
close: 'OK',
|
||||
columnData: 'Data voor kolom',
|
||||
chooseColumn: 'Kies een kolom',
|
||||
selected: 'Geselecteerd',
|
||||
select: 'Selecteer',
|
||||
selectColumn: 'Kies een kolom',
|
||||
file: {
|
||||
select: 'Selecteer een bestand',
|
||||
tryAgain: 'Kies een ander bestand',
|
||||
withHeaders: 'Dit bestand bevat headers',
|
||||
withoutHeaders: 'Dit bestand bevat geen headers',
|
||||
},
|
||||
error: {
|
||||
title: 'Fout',
|
||||
columnNumber: 'Je hebt niet genoeg kolommen. <br><b>Benodigde kolommen zijn</b>: ',
|
||||
missingColumns: 'Ontbrekende verplichte kolommen:',
|
||||
selectColumn: 'Je moet alle kolommen selecteren',
|
||||
fileNumber: 'Je moet een bestand kiezen',
|
||||
fileSelection: 'Er is geen bestand gekozen',
|
||||
invalidFile: 'Dit bestand is ongeldig. Gebruik en CSV of xlsx bestand',
|
||||
noWorksheet: 'Ten minste één werkblad nodig',
|
||||
emptyWorksheet: 'Het werkblad is leeg',
|
||||
},
|
||||
},
|
||||
ptBR: {
|
||||
column: 'Coluna',
|
||||
submit: 'Enviar',
|
||||
close: 'OK',
|
||||
columnData: 'Informação por coluna',
|
||||
chooseColumn: 'Escolha uma coluna',
|
||||
selected: 'Selecionado',
|
||||
select: 'Selecionar',
|
||||
selectColumn: 'Por favor escolha uma coluna',
|
||||
file: {
|
||||
select: 'Por favor selecione um arquivo',
|
||||
tryAgain: 'Escolha outro arquivo',
|
||||
withHeaders: 'Este arquivo inclui cabeçalho',
|
||||
withoutHeaders: 'Este arquivo não inclui cabeçalho',
|
||||
},
|
||||
error: {
|
||||
title: 'Erro',
|
||||
columnNumber:
|
||||
'Seu arquivo não possui colunas suficientes. <br><b>Colunas necessárias: </b>: ',
|
||||
missingColumns: 'Está faltando as colunas:',
|
||||
selectColumn: 'Você precisa selecionar todas as colunas',
|
||||
fileNumber: 'Você precisa selecionar um arquivo',
|
||||
fileSelection: 'Nenhum arquivo selecionado',
|
||||
invalidFile: 'Este arquivo é inválido. Use um arquivo CSV ou XLSX',
|
||||
noWorksheet: 'Deve haver ao menos uma planilha',
|
||||
emptyWorksheet: 'Esta planilha está vazia',
|
||||
},
|
||||
},
|
||||
};
|
||||
27
libs/vendor/xlsprse/parser/index.js
vendored
Normal file
27
libs/vendor/xlsprse/parser/index.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import parseXlsx from './xlsx-parser';
|
||||
|
||||
function parseFileExcelFile(file, lang, callback) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = event =>
|
||||
parseXlsx(event.target.result, lang)
|
||||
.then(result => callback(result))
|
||||
.catch(error => callback(error));
|
||||
|
||||
if (file.type === 'text/csv') {
|
||||
reader.readAsText(file);
|
||||
} else {
|
||||
reader.readAsBinaryString(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default (htmlFile, lang) =>
|
||||
new Promise((resolve, reject) => {
|
||||
parseFileExcelFile(htmlFile, lang, (result) => {
|
||||
if (result.error) {
|
||||
return reject(result.error);
|
||||
}
|
||||
return resolve(result.worksheet);
|
||||
});
|
||||
});
|
||||
30
libs/vendor/xlsprse/parser/xlsx-parser.js
vendored
Normal file
30
libs/vendor/xlsprse/parser/xlsx-parser.js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import _ from 'lodash';
|
||||
import XLSX from 'xlsx';
|
||||
|
||||
export default (file, lang) => {
|
||||
const workbook = typeof window === 'undefined' ? XLSX.readFile(file) : XLSX.read(file, { type: 'binary' });
|
||||
const sheetNames = workbook.SheetNames;
|
||||
if (sheetNames.length === 0) {
|
||||
return Promise.reject({ error: lang.error.noWorksheet });
|
||||
}
|
||||
const sheets = workbook.Sheets;
|
||||
const json = XLSX.utils.sheet_to_json(sheets[sheetNames[0]], {
|
||||
header: 1,
|
||||
defVal: '',
|
||||
blankrows: false,
|
||||
});
|
||||
|
||||
if (json.length === 0) {
|
||||
return Promise.reject({ error: lang.error.emptyWorksheet });
|
||||
}
|
||||
|
||||
const transposedMatrix = _.unzip(json);
|
||||
const normalizedOutput = transposedMatrix
|
||||
.map(columnRows => ({
|
||||
name: _.first(columnRows),
|
||||
data: _.tail(columnRows),
|
||||
}))
|
||||
.filter(column => column.data.length === 0 || !column.data.every(data => data === undefined));
|
||||
|
||||
return Promise.resolve({ worksheet: normalizedOutput });
|
||||
};
|
||||
Reference in New Issue
Block a user