Skip to content
Snippets Groups Projects
Commit d66cf512 authored by Kirill Stytsenko's avatar Kirill Stytsenko
Browse files

Various improvements in csv import. Closes #131

Former-commit-id: ee99e914
parent 9ea2395d
No related branches found
No related tags found
No related merge requests found
...@@ -68,6 +68,8 @@ ...@@ -68,6 +68,8 @@
</template> </template>
<script> <script>
const { notEmpty } = require('@/utils')
export default { export default {
data () { data () {
return { return {
...@@ -120,9 +122,7 @@ export default { ...@@ -120,9 +122,7 @@ export default {
setTimeout(resolve, ms) setTimeout(resolve, ms)
}) })
}, },
notEmpty (str) { notEmpty,
return typeof str === 'string' && str.trim().length > 0
},
async createDB () { async createDB () {
let res let res
// create a container // create a container
......
...@@ -73,11 +73,14 @@ ...@@ -73,11 +73,14 @@
</v-row> </v-row>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-col> <v-btn :disabled="!file" :loading="loading" color="primary" @click="upload">Upload</v-btn>
<v-btn :disabled="!file" :loading="loading" color="primary" @click="upload">Next</v-btn> <v-btn :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}`" outlined>
</v-col> <v-icon>mdi-table</v-icon>
View
</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
<v-breadcrumbs :items="items" class="pa-0 mt-2" />
</div> </div>
</template> </template>
<script> <script>
...@@ -107,7 +110,15 @@ export default { ...@@ -107,7 +110,15 @@ export default {
false_element: null false_element: null
}, },
file: null, file: null,
fileLocation: null fileLocation: null,
items: [
{ text: 'Databases', to: '/container', activeClass: '' },
{
text: `${this.$route.params.database_id}`,
to: `/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/info`,
activeClass: ''
}
]
} }
}, },
computed: { computed: {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<v-col cols="8"> <v-col cols="8">
<v-text-field <v-text-field
v-model="tableCreate.name" v-model="tableCreate.name"
required :rules="[v => notEmpty(v) || $t('Required')]"
autocomplete="off" autocomplete="off"
label="Name *" /> label="Name *" />
</v-col> </v-col>
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
<v-col cols="8"> <v-col cols="8">
<v-text-field <v-text-field
v-model="tableCreate.description" v-model="tableCreate.description"
required :rules="[v => notEmpty(v) || $t('Required')]"
autocomplete="off" autocomplete="off"
label="Description *" /> label="Description *" />
</v-col> </v-col>
</v-row> </v-row>
<v-row dense> <v-row dense>
<v-col cols="8"> <v-col cols="8">
<v-btn :disabled="!step1Valid" color="primary" type="submit" @click="step = 2"> <v-btn :disabled="!validStep1" color="primary" type="submit" @click="step = 2">
Continue Continue
</v-btn> </v-btn>
</v-col> </v-col>
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<v-col cols="8"> <v-col cols="8">
<v-select <v-select
v-model="tableCreate.separator" v-model="tableCreate.separator"
:rules="[rules.required]" :rules="[v => notEmpty(v) || $t('Required')]"
:items="separators" :items="separators"
required required
hint="Character separating the values" hint="Character separating the values"
...@@ -59,10 +59,12 @@ ...@@ -59,10 +59,12 @@
<v-col cols="8"> <v-col cols="8">
<v-text-field <v-text-field
v-model="tableCreate.skip_lines" v-model="tableCreate.skip_lines"
:rules="[rules.required, rules.positive]" :rules="[
v => notEmpty(v) || $t('Required'),
v => isNonNegativeInteger(v) || $t('Number of lines to skip')]"
type="number" type="number"
required required
hint="Skip n lines from the top" hint="Skip n lines from the top. These may include comments or the header of column names."
label="Skip Lines *" label="Skip Lines *"
placeholder="e.g. 0" /> placeholder="e.g. 0" />
</v-col> </v-col>
...@@ -96,7 +98,7 @@ ...@@ -96,7 +98,7 @@
</v-row> </v-row>
<v-row dense> <v-row dense>
<v-col cols="6"> <v-col cols="6">
<v-btn :disabled="!tableCreate.separator || !tableCreate.skip_lines" :loading="loading" color="primary" type="submit" @click="step = 3">Next</v-btn> <v-btn :disabled="!validStep2 || !tableCreate.separator || !tableCreate.skip_lines" :loading="loading" color="primary" type="submit" @click="step = 3">Next</v-btn>
</v-col> </v-col>
</v-row> </v-row>
</v-form> </v-form>
...@@ -216,6 +218,8 @@ ...@@ -216,6 +218,8 @@
</div> </div>
</template> </template>
<script> <script>
const { notEmpty, isNonNegativeInteger } = require('@/utils')
export default { export default {
name: 'TableFromCSV', name: 'TableFromCSV',
components: { components: {
...@@ -245,8 +249,7 @@ export default { ...@@ -245,8 +249,7 @@ export default {
} }
], ],
rules: { rules: {
required: value => !!value || 'Required', required: value => !!value || 'Required'
positive: value => value >= 0 || 'Positive number'
}, },
dateFormats: [], dateFormats: [],
tableCreate: { tableCreate: {
...@@ -257,7 +260,7 @@ export default { ...@@ -257,7 +260,7 @@ export default {
true_element: null, true_element: null,
null_element: null, null_element: null,
separator: ',', separator: ',',
skip_lines: 0 skip_lines: '1'
}, },
loading: false, loading: false,
file: null, file: null,
...@@ -277,9 +280,6 @@ export default { ...@@ -277,9 +280,6 @@ export default {
} }
}, },
computed: { computed: {
step1Valid () {
return this.tableCreate.name !== null && this.tableCreate.name.length > 0 && this.tableCreate.description !== null && this.tableCreate.description.length > 0
},
token () { token () {
return this.$store.state.token return this.$store.state.token
} }
...@@ -288,6 +288,8 @@ export default { ...@@ -288,6 +288,8 @@ export default {
this.loadDateFormats() this.loadDateFormats()
}, },
methods: { methods: {
notEmpty,
isNonNegativeInteger,
submit () { submit () {
this.$refs.form.validate() this.$refs.form.validate()
}, },
...@@ -343,19 +345,24 @@ export default { ...@@ -343,19 +345,24 @@ export default {
}, },
async createTable () { async createTable () {
/* make enum values to array */ /* make enum values to array */
this.tableCreate.columns.forEach((column) => { const validColumns = this.tableCreate.columns.map((column) => {
// validate `id` column: must be a PK // validate `id` column: must be a PK
if (column.name === 'id' && (!column.primary_key)) { if (column.name === 'id' && (!column.primary_key)) {
this.$toast.error('Column `id` has to be a Primary Key') this.$toast.error('Column `id` has to be a Primary Key')
return return false
} }
if (column.enum_values == null) { if (column.enum_values === null) {
return return false
} }
if (column.enum_values.length > 0) { if (column.enum_values.length > 0) {
column.enum_values = column.enum_values.split(',') column.enum_values = column.enum_values.split(',')
} }
return true
}) })
// bail out if there is a problem with one of the columns
if (!validColumns.every(Boolean)) { return }
const createUrl = `/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table` const createUrl = `/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table`
let createResult let createResult
try { try {
......
function notEmpty (str) {
return typeof str === 'string' && str.trim().length > 0
}
/**
* From https://stackoverflow.com/questions/10834796/validate-that-a-string-is-a-positive-integer
Tests:
"0" : true
"23" : true
"-10" : false
"10.30" : false
"-40.1" : false
"string" : false
"1234567890" : true
"129000098131766699.1" : false
"-1e7" : false
"1e7" : true
"1e10" : false
"1edf" : false
" " : false
"" : false
*/
function isNonNegativeInteger (str) {
return str >>> 0 === parseFloat(str)
}
module.exports = {
notEmpty,
isNonNegativeInteger
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment