first commit + add fe component vue accone

This commit is contained in:
2026-05-07 17:10:10 +07:00
parent fd8e4d694b
commit 38a182641a
327 changed files with 263946 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
> 1%
last 2 versions

View File

@@ -0,0 +1,17 @@
version: 2
jobs:
build:
docker:
- image: circleci/node:8
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- run: npm install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: npm run test:unit

View File

@@ -0,0 +1,7 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 4
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 200

View File

@@ -0,0 +1,23 @@
module.exports = {
root: true,
env: {
node: true
},
extends: ["plugin:vue/essential", "eslint:recommended"],
rules: {
'no-console': 'off',
'no-debugger': 'off',
'vue/script-indent': ['error', 4, {
baseIndent: 1,
switchCase: 0,
ignores: []
}]
},
parserOptions: {
parser: 'babel-eslint'
},
};

View File

@@ -0,0 +1,26 @@
name: Node CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm ci
npm run build --if-present
npm run test:unit
env:
CI: true

View File

@@ -0,0 +1,24 @@
.DS_Store
node_modules
/dist
/tests/e2e/reports/
selenium-debug.log
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,43 @@
# Changelog
All notable changes to `vue-csv-import` will be documented in this file
## 1.0.0
- Initial release
## 1.5.0
- Added ability to use custom labels for fields.
## 1.5.1
- Change default file class.
- Add options for the button values
## 1.6
- Debug and added tests
## 2.1.0
- Remove csv-parse dependency and replace with papaparse - smaller and more dependable.
- Can now use with v-model. will return a parsed csv.
## 2.3.0
- Added slots for file header checkbox and table thead.
- default button text changed to "next"
- added callback for usage without url.
- Added 'headers' prop. Define whether csv has headers by default. Removes checkbox.
## 2.3.4
- restructure app
- make axios and lodash external dependencies.
- papaparse is bundled in component.
## 2.3.5
- Mime type validation when selecting file
## 2.3.6
- added names to select fields
- added other mime types to default accepted types array
- added some more meaningful tests
## 2.3.7
- added class to table select fields
- added canIgnore to allow users to ignore fields if required

View File

@@ -0,0 +1,19 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,143 @@
# Vue.js component to handle CSV uploads with field mapping.
[![Latest Version on NPM](https://img.shields.io/npm/v/vue-csv-import.svg?style=flat-square)](https://npmjs.com/package/vue-csv-import)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![CircleCI](https://circleci.com/gh/jgile/vue-csv-import.svg?style=svg)](https://circleci.com/gh/jgile/vue-csv-import)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/jgile/vue-csv-import/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/jgile/vue-csv-import/?branch=master)
## Demo
[Demo](https://jgile.github.io/vue-csv-import/)
Go to the "demo" folder for a working example.
## Installation
You can install the package via yarn:
```bash
yarn add vue-csv-import
```
or npm:
```bash
npm install vue-csv-import --save
```
## Usage
Import component:
```js
import { VueCsvImport } from 'vue-csv-import';
new Vue({
components: { VueCsvImport },
el: '#app',
});
```
Include in template:
```html
<vue-csv-import url="/url/to/post" :map-fields="['array', 'of', 'field', 'names']"></vue-csv-import>
```
or with labels:
```html
<vue-csv-import url="/url/to/post" :map-fields="{field1: 'Label 1', field2: 'Label 2'}"></vue-csv-import>
```
or with v-model:
```html
<vue-csv-import v-model="parseCsv" :map-fields="{field1: 'Label 1', field2: 'Label 2'}"></vue-csv-import>
```
With all available slots:
```html
<vue-csv-import
v-model="csv"
url="/hello"
:map-fields="['name', 'age']">
<template slot="hasHeaders" slot-scope="{headers, toggle}">
<label>
<input type="checkbox" id="hasHeaders" :value="headers" @change="toggle">
Headers?
</label>
</template>
<template slot="error">
File type is invalid
</template>
<template slot="thead">
<tr>
<th>My Fields</th>
<th>Column</th>
</tr>
</template>
<template slot="next" slot-scope="{load}">
<button @click.prevent="load">load!</button>
</template>
<template slot="submit" slot-scope="{submit}">
<button @click.prevent="submit">send!</button>
</template>
</vue-csv-import>
```
Options:
| Option | Default | Description |
| ------ | ------- | ----------- |
| mapFields | N/A | (required) These are the field names that the CSV will be mapped to |
| url | null | If present, the component will post the mapped values to this url. Otherwise, the component will only emit the value to be used as a normal input |
| callback | null | The callback to be called on successful upload. (url required) |
| catch | null | The function to be called on an error in posting (url required) |
| finally | null | The function to be called no matter what on posting (url required) |
| tableClass | "table" | The class to be added to table element |
| checkboxClass | "form-check-input" | The class to be added to the checkbox |
| buttonClass | "btn btn-default" | The class to be added to buttons |
| inputClass | "form-control-file" | The class to be added to the file input |
| tableSelectClass | "form-control" | The class to be added to the table element selects |
| submitBtnText | "Submit" | The value of the final submit button |
| loadBtnText | "Submit" | The value of the initial load file button |
| headers | null | Define whether csv has headers by default. Removes checkbox. |
| fileMimeTypes | ["text/csv"] | Array of valid mime types
| canIgnore | false | Can fields be ignored (Boolean)
Slots:
| Slot | Description |
| ------ | ----------- |
| thead | The content of "thead" in the field mapping table |
| next | The next button. Use slot-scope "next" to load csv. |
| submit | The submit button. Use slot-scope "submit" to submit form. |
| hasHeaders | The "has headers" checkbox. Use slot-scope "toggle" and "headers". |
### Testing
```bash
npm run test
```
### Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
### Security
If you discover any security related issues, please contact John Gile.
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
## Credits
- [John Gile](https://github.com/jgile)
- [All Contributors](../../contributors)

View File

@@ -0,0 +1,3 @@
module.exports = {
presets: ['@vue/cli-plugin-babel/preset']
};

View File

@@ -0,0 +1,66 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png"/>
<div class="container">
<div class="row mt-5 text-center">
<div class="col-6 offset-3">
<a href="./csv-sample.csv" target="_blank">Example CSV</a>
</div>
</div>
<section class="py-5">
<div class="row mt-5">
<div class="col-8 offset-2">
<h4>Source:</h4>
<pre><code>&lt;vue-csv-import v-model="csv" :map-fields="['name', 'age']"&gt;&lt;/vue-csv-import&gt;</code></pre>
</div>
</div>
<div class="row mt-5">
<div class="col-8 offset-2">
<h4 class="mb-4">Result:</h4>
<vue-csv-import v-model="csv" :map-fields="['name', 'age']"></vue-csv-import>
<div class="mt-2">
{{ csv }}
</div>
</div>
</div>
</section>
</div>
</div>
</template>
<script>
export default {
name: "app",
data() {
return {
csv: null,
};
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.container {
text-align: left;
}
pre code {
background-color: #eee;
border: 1px solid #999;
display: block;
padding: 20px;
}
#app .form {
text-align: left;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,10 @@
import Vue from "vue";
import App from "./App.vue";
import { VueCsvImportPlugin } from "../src";
Vue.use(VueCsvImportPlugin);
Vue.config.productionTip = false;
new Vue({
render: h => h(App)
}).$mount("#app");

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env sh
# abort on errors
set -e
# build
npm run build:demo
# navigate into the build output directory
cd dist/demo
git init
git add -A
git commit -m 'deploy'
git push -f git@github.com:jgile/vue-csv-import.git master:gh-pages
cd -

View File

@@ -0,0 +1,22 @@
module.exports = {
moduleFileExtensions: ["js", "jsx", "json", "vue"],
transform: {
"^.+\\.vue$": "vue-jest",
".+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$":
"jest-transform-stub",
"^.+\\.jsx?$": "babel-jest"
},
transformIgnorePatterns: ["/node_modules/"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1"
},
snapshotSerializers: ["jest-serializer-vue"],
testMatch: [
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
],
testURL: "http://localhost/",
watchPlugins: [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
]
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
{
"name": "vue-csv-import",
"version": "3.1.0",
"private": false,
"description": "Vue.js component to handle CSV uploads with field mapping.",
"author": "John Gile",
"scripts": {
"serve": "vue-cli-service serve ./demo/main",
"build": "vue-cli-service build --target lib --name VueCsvImport src/index.js",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint",
"build:demo": "vue-cli-service --mode development build --dest ./dist/demo ./demo/main"
},
"main": "dist/VueCsvImport.umd.js",
"browser": "dist/VueCsvImport.common.js",
"jsDelivr": "dist/VueCsvImport.umd.min.js",
"unpkg": "dist/VueCsvImport.umd.min.js",
"dependencies": {
"axios": "^0.19.0",
"core-js": "^3.6.4",
"lodash": "^4.17.15",
"mime-types": "^2.1.24",
"papaparse": "^5.0.0",
"vue": "^2.5.22"
},
"devDependencies": {
"@vue/cli": "^4.2.2",
"@vue/cli-plugin-babel": "~4.2.2",
"@vue/cli-plugin-eslint": "~4.2.2",
"@vue/cli-plugin-unit-jest": "~4.2.2",
"@vue/cli-service": "^4.2.2",
"@vue/cli-upgrade": "^3.12.1",
"@vue/test-utils": "1.0.0-beta.29",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.3",
"babel-jest": "^23.6.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"vue-template-compiler": "^2.6.10"
},
"peerDependencies": {
"vue": "^2.5.22"
},
"bugs": {
"url": "https://github.com/jgile/vue-csv-import/issues"
},
"keywords": [
"jgile",
"csv",
"map"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/jgile/vue-csv-import.git"
}
}

View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
};

View File

@@ -0,0 +1,5 @@
columnA,columnB,columnC
"Susan",41,a
"Mike",5,b
"Jake",33,c
"Jill",30,d
1 columnA columnB columnC
2 Susan 41 a
3 Mike 5 b
4 Jake 33 c
5 Jill 30 d

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<title>vue-csv-import</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-csv-import doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,293 @@
<template>
<div class="vue-csv-uploader">
<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">
<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">
<slot name="error" v-if="showErrorMessage">
<div class="invalid-feedback d-block">
File type is invalid
</div>
</slot>
</div>
<div class="form-group">
<slot name="next" :load="load">
<button type="submit" :disabled="disabledNextButton" :class="buttonClass" @click.prevent="load">
{{ loadBtnText }}
</button>
</slot>
</div>
</div>
<div class="vue-csv-uploader-part-two">
<div class="vue-csv-mapping" v-if="sample">
<table :class="tableClass">
<slot name="thead">
<thead>
<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>
</td>
</tr>
</tbody>
</table>
<div class="form-group" v-if="url">
<slot name="submit" :submit="submit">
<input type="submit" :class="buttonClass" @click.prevent="submit" :value="submitBtnText">
</slot>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
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
},
mapFields: {
required: true
},
callback: {
type: Function,
default: () => ({})
},
catch: {
type: Function,
default: () => ({})
},
finally: {
type: Function,
default: () => ({})
},
parseConfig: {
type: Object,
default() {
return {};
}
},
headers: {
default: null
},
loadBtnText: {
type: String,
default: "Next"
},
submitBtnText: {
type: String,
default: "Submit"
},
tableClass: {
type: String,
default: "table"
},
checkboxClass: {
type: String,
default: "form-check-input"
},
buttonClass: {
type: String,
default: "btn btn-primary"
},
inputClass: {
type: String,
default: "form-control-file"
},
validation: {
type: Boolean,
default: true,
},
fileMimeTypes: {
type: Array,
default: () => {
return ["text/csv", "text/x-csv", "application/vnd.ms-excel", "text/plain"];
}
},
tableSelectClass: {
type: String,
default: 'form-control'
},
canIgnore: {
type: Boolean,
default: false,
}
},
data: () => ({
form: {
csv: null,
},
fieldsToMap: [],
map: {},
hasHeaders: true,
csv: null,
sample: null,
isValidFileMimeType: 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
};
});
}
},
methods: {
submit() {
const _this = this;
this.form.csv = this.buildMappedCsv();
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);
});
} else {
_this.callback(this.form.csv);
}
},
buildMappedCsv() {
const _this = this;
let csv = this.hasHeaders ? drop(this.csv) : this.csv;
return map(csv, (row) => {
let newRow = {};
forEach(_this.map, (column, field) => {
set(newRow, field, get(row, column));
});
return newRow;
});
},
validFileMimeType() {
let file = this.$refs.csv.files[0];
const mimeType = file.type === "" ? mimeTypes.lookup(file.name) : file.type;
if (file) {
this.fileSelected = true;
this.isValidFileMimeType = this.validation ? this.validateMimeType(mimeType) : true;
} else {
this.isValidFileMimeType = !this.validation;
this.fileSelected = false;
}
},
validateMimeType(type) {
return this.fileMimeTypes.indexOf(type) > -1;
},
load() {
const _this = this;
this.readFile((output) => {
_this.sample = get(Papa.parse(output, { preview: 2, skipEmptyLines: true }), "data");
_this.csv = get(Papa.parse(output, { skipEmptyLines: true }), "data");
});
},
readFile(callback) {
let file = this.$refs.csv.files[0];
if (file) {
let reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
callback(evt.target.result);
};
reader.onerror = function () {
};
}
},
toggleHasHeaders() {
this.hasHeaders = !this.hasHeaders;
},
makeId(id) {
return `${id}${this._uid}`;
}
},
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);
});
if (hasAllKeys) {
this.submit();
}
}
}
},
sample(newVal, oldVal) {
if(newVal !== null){
this.fieldsToMap.forEach(field => {
newVal[0].forEach((columnName, index) => {
if(field.key === columnName){
this.map[field.key] = index;
}
});
});
}
}
},
computed: {
firstRow() {
return get(this, "sample.0");
},
showErrorMessage() {
return this.fileSelected && !this.isValidFileMimeType;
},
disabledNextButton() {
return !this.isValidFileMimeType;
}
},
};
</script>

View File

@@ -0,0 +1,16 @@
import Vue from 'vue';
import VueCsvImport from "./components/VueCsvImport.vue";
const VueCsvImportPlugin = {
install(Vue, options = {}) {
Vue.component(options.componentName || 'VueCsvImport', VueCsvImport);
}
};
if (typeof window !== undefined && window.Vue && window.Vue === Vue) {
VueCsvImportPlugin.install(window.Vue);
}
export { VueCsvImport, VueCsvImportPlugin };
export default VueCsvImport;

View File

@@ -0,0 +1,51 @@
name,date,home
Home Ing,2/9/2018,false
Y-find,8/4/2017,true
Zamit,5/31/2017,false
Duobam,4/13/2017,true
Solarbreeze,8/1/2017,true
Domainer,8/14/2017,true
Zoolab,1/2/2018,true
Toughjoyfax,2/9/2018,true
Flowdesk,7/15/2017,false
Lotlux,6/11/2017,false
Holdlamis,11/18/2017,true
Voyatouch,8/1/2017,false
Tres-Zap,11/7/2017,false
Toughjoyfax,5/4/2017,false
Y-find,4/12/2017,true
Redhold,9/1/2017,false
Voyatouch,7/21/2017,false
Wrapsafe,5/25/2017,false
Tres-Zap,12/19/2017,false
Konklab,9/2/2017,false
Job,11/6/2017,true
Stim,11/11/2017,true
Vagram,1/2/2018,false
Konklab,8/30/2017,true
Tresom,1/20/2018,false
Quo Lux,9/20/2017,false
Tin,9/25/2017,false
Veribet,1/21/2018,true
Holdlamis,3/16/2018,false
Redhold,3/2/2018,true
Fintone,3/24/2018,false
Viva,8/25/2017,false
Voltsillam,7/20/2017,false
Pannier,1/28/2018,true
Cookley,12/7/2017,false
Zaam-Dox,11/21/2017,false
Regrant,11/28/2017,false
Cookley,7/3/2017,false
Otcom,5/29/2017,false
Fintone,3/26/2018,false
Prodder,11/3/2017,true
Andalax,5/10/2017,true
Duobam,5/19/2017,true
Span,11/4/2017,true
Bytecard,2/13/2018,false
Otcom,1/5/2018,false
Gembucket,11/22/2017,false
Voyatouch,12/22/2017,false
Zamit,8/18/2017,true
Redhold,10/11/2017,true
1 name date home
2 Home Ing 2/9/2018 false
3 Y-find 8/4/2017 true
4 Zamit 5/31/2017 false
5 Duobam 4/13/2017 true
6 Solarbreeze 8/1/2017 true
7 Domainer 8/14/2017 true
8 Zoolab 1/2/2018 true
9 Toughjoyfax 2/9/2018 true
10 Flowdesk 7/15/2017 false
11 Lotlux 6/11/2017 false
12 Holdlamis 11/18/2017 true
13 Voyatouch 8/1/2017 false
14 Tres-Zap 11/7/2017 false
15 Toughjoyfax 5/4/2017 false
16 Y-find 4/12/2017 true
17 Redhold 9/1/2017 false
18 Voyatouch 7/21/2017 false
19 Wrapsafe 5/25/2017 false
20 Tres-Zap 12/19/2017 false
21 Konklab 9/2/2017 false
22 Job 11/6/2017 true
23 Stim 11/11/2017 true
24 Vagram 1/2/2018 false
25 Konklab 8/30/2017 true
26 Tresom 1/20/2018 false
27 Quo Lux 9/20/2017 false
28 Tin 9/25/2017 false
29 Veribet 1/21/2018 true
30 Holdlamis 3/16/2018 false
31 Redhold 3/2/2018 true
32 Fintone 3/24/2018 false
33 Viva 8/25/2017 false
34 Voltsillam 7/20/2017 false
35 Pannier 1/28/2018 true
36 Cookley 12/7/2017 false
37 Zaam-Dox 11/21/2017 false
38 Regrant 11/28/2017 false
39 Cookley 7/3/2017 false
40 Otcom 5/29/2017 false
41 Fintone 3/26/2018 false
42 Prodder 11/3/2017 true
43 Andalax 5/10/2017 true
44 Duobam 5/19/2017 true
45 Span 11/4/2017 true
46 Bytecard 2/13/2018 false
47 Otcom 1/5/2018 false
48 Gembucket 11/22/2017 false
49 Voyatouch 12/22/2017 false
50 Zamit 8/18/2017 true
51 Redhold 10/11/2017 true

View File

@@ -0,0 +1,5 @@
module.exports = {
env: {
jest: true
}
}

View File

@@ -0,0 +1,199 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`VueCsvImport has expected html 1`] = `
<div
class="vue-csv-uploader"
>
<div
class="form"
>
<div
class="vue-csv-uploader-part-one"
>
<div
class="form-check form-group csv-import-checkbox"
>
<input
class="form-check-input"
id="hasHeaders9"
type="checkbox"
value=""
/>
<label
class="form-check-label"
for="hasHeaders9"
>
File Has Headers
</label>
</div>
<div
class="form-group csv-import-file"
>
<input
class="form-control-file"
name="csv"
type="file"
/>
<!---->
</div>
<div
class="form-group"
>
<button
class="btn btn-primary"
disabled="disabled"
type="submit"
>
Next
</button>
</div>
</div>
<div
class="vue-csv-uploader-part-two"
>
<!---->
</div>
</div>
</div>
`;
exports[`VueCsvImport headers prop removes checkbox and not use headers 1`] = `
<div
class="vue-csv-uploader"
>
<div
class="form"
>
<div
class="vue-csv-uploader-part-one"
>
<div
class="form-check form-group csv-import-checkbox"
>
<input
class="form-check-input"
id="hasHeaders27"
type="checkbox"
value="false"
/>
<label
class="form-check-label"
for="hasHeaders27"
>
File Has Headers
</label>
</div>
<div
class="form-group csv-import-file"
>
<input
class="form-control-file"
name="csv"
type="file"
/>
<!---->
</div>
<div
class="form-group"
>
<button
class="btn btn-primary"
disabled="disabled"
type="submit"
>
Next
</button>
</div>
</div>
<div
class="vue-csv-uploader-part-two"
>
<!---->
</div>
</div>
</div>
`;
exports[`VueCsvImport headers prop removes checkbox and use headers 1`] = `
<div
class="vue-csv-uploader"
>
<div
class="form"
>
<div
class="vue-csv-uploader-part-one"
>
<div
class="form-check form-group csv-import-checkbox"
>
<input
class="form-check-input"
id="hasHeaders23"
type="checkbox"
value="true"
/>
<label
class="form-check-label"
for="hasHeaders23"
>
File Has Headers
</label>
</div>
<div
class="form-group csv-import-file"
>
<input
class="form-control-file"
name="csv"
type="file"
/>
<!---->
</div>
<div
class="form-group"
>
<button
class="btn btn-primary"
disabled="disabled"
type="submit"
>
Next
</button>
</div>
</div>
<div
class="vue-csv-uploader-part-two"
>
<!---->
</div>
</div>
</div>
`;

View File

@@ -0,0 +1,76 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { VueCsvImportPlugin } from '../../src/index';
import VueCsvImport from '../../src/components/VueCsvImport';
describe('VueCsvImport', () => {
let wrapper, objWrapper;
const localVue = createLocalVue();
const csv = [["name", "age", "grade"], ["Susan", "41", "a"], ["Mike", "5", "b"], ["Jake", "33", "c"], ["Jill", "30", "d"]];
const sample = [["name", "age", "grade"], ["Susan", "41", "a"]];
const map = { "name": 0, "age": 1 };
beforeEach(() => {
wrapper = shallowMount(VueCsvImport, { propsData: { mapFields: ['name_map', 'age_map', 'grade_map'], url: '/hello' } });
objWrapper = shallowMount(VueCsvImport, { propsData: { value: [], mapFields: { name: 'Name', age: 'Age' } } });
});
it('is a Vue instance', () => {
expect(wrapper.isVueInstance()).toBeTruthy();
});
it('installs as plugin', () => {
localVue.use(VueCsvImportPlugin);
expect(localVue.options.components["VueCsvImport"]).toBeDefined();
});
it('has expected html', () => {
expect(wrapper.vm.$el).toMatchSnapshot();
});
it('has expected map fields when array', () => {
expect(wrapper.vm.fieldsToMap).toEqual([{ "key": "name_map", "label": "name_map" }, { "key": "age_map", "label": "age_map" }, { "key": "grade_map", "label": "grade_map" }]);
});
it('has expected map fields when object', () => {
expect(objWrapper.vm.fieldsToMap).toEqual([{ "key": "name", "label": "Name" }, { "key": "age", "label": "Age" }]);
});
it('headers prop removes checkbox and use headers', () => {
objWrapper.setData({ hasHeaders: true });
expect(objWrapper.vm.hasHeaders).toEqual(true);
expect(objWrapper.vm.$el).toMatchSnapshot();
});
it('headers prop removes checkbox and not use headers', () => {
objWrapper.setData({ hasHeaders: false });
expect(objWrapper.vm.hasHeaders).toEqual(false);
expect(objWrapper.vm.$el).toMatchSnapshot();
});
it('can map when passed fields are an object', () => {
objWrapper.setData({ hasHeaders: true, sample: sample, csv: csv, map: map });
objWrapper.vm.submit();
expect(objWrapper.emitted().input[0][0]).toEqual([{ "name": "Susan", "age": "41" }, { "name": "Mike", "age": "5" }, { "name": "Jake", "age": "33" }, {
"name": "Jill",
"age": "30"
}]);
});
it('can map when passed fields are an array', () => {
wrapper.setData({ hasHeaders: true, sample: sample, csv: csv, map: map });
wrapper.vm.submit();
expect(wrapper.emitted().input[0][0]).toEqual([{ "name": "Susan", "age": "41" }, { "name": "Mike", "age": "5" }, { "name": "Jake", "age": "33" }, {
"name": "Jill",
"age": "30"
}]);
});
it('validates mime types', () => {
wrapper.setData({ hasHeaders: true, sample: sample, csv: csv, map: map });
expect(wrapper.vm.validateMimeType('peanut')).toEqual(false);
expect(wrapper.vm.validateMimeType('text/csv')).toEqual(true);
expect(wrapper.vm.validateMimeType('text/x-csv')).toEqual(true);
expect(wrapper.vm.validateMimeType('application/vnd.ms-excel')).toEqual(true);
expect(wrapper.vm.validateMimeType('text/plain')).toEqual(true);
});
});

View File

@@ -0,0 +1,26 @@
module.exports = {
lintOnSave: false,
css: {
extract: false,
},
configureWebpack: {
externals: process.env.NODE_ENV === 'production' ? {
axios: {
commonjs: 'axios',
commonjs2: 'axios',
root: 'axios'
},
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
root: '_'
},
papaparse: {
commonjs: 'papaparse',
commonjs2: 'papaparse',
root: 'papaparse'
}
} : {}
},
publicPath: ''
};