diff --git a/.gitignore b/.gitignore index 921ebb0..03d3c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ dist/ npm-debug.log -json/ \ No newline at end of file +json/ +notes.txt diff --git a/package.json b/package.json index 0226018..78d1e97 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "axios": "^0.16.1", + "validator": "^7.0.0", "vue": "^2.2.2", "vue-awesome": "^2.1.0", "vue-resource": "^1.2.1" diff --git a/src/App.vue b/src/App.vue index a361bbd..eec5ea1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,6 +28,14 @@ title: 'Vorname', name: 'firstname', editable: true, + validator: { + rules: [ + 'ip4', + ], + messages: [ + 'Must be alpha', + ], + }, }, { title: 'Nachname', diff --git a/src/components/VueEditortable.vue b/src/components/VueEditortable.vue index 16237c0..853c548 100644 --- a/src/components/VueEditortable.vue +++ b/src/components/VueEditortable.vue @@ -1,125 +1,126 @@ @@ -137,6 +138,7 @@ import Icon from 'vue-awesome/components/Icon'; import Requests from '../mixins/Requests'; import Pagination from '../mixins/Pagination'; + import Validator from '../mixins/Validator'; export default { props: { @@ -158,7 +160,7 @@ components: { Icon, }, - mixins: [Requests, Pagination], + mixins: [Requests, Pagination, Validator], data() { const sortOrders = {}; this.data.columns.forEach((key) => { @@ -171,9 +173,9 @@ show: true, itemsPerPage: 25, itemsPerPageValues: [ - { text: 25, value: 25 }, - { text: 50, value: 50 }, - { text: 100, value: 100 }, + { text: 25, value: 25 }, + { text: 50, value: 50 }, + { text: 100, value: 100 }, ], }, requests: { @@ -514,7 +516,7 @@ } for (let i = startCol; i < l; i += 1) { if ((sumCols() + vm.columnsWidth[nextCol] <= vm.wrapperWidth) && vm.cols[l - 1].hidden - && vm.cols[nextCol].hidden && vm.cols[nextCol].show) { + && vm.cols[nextCol].hidden && vm.cols[nextCol].show) { vm.$set(vm.cols[nextCol], 'hidden', false); for (let ii = 0; ii < ll; ii += 1) { vm.$set(vm.tableData[ii][vm.cols[nextCol].name], 'isHidden', false); @@ -585,6 +587,11 @@ } else { obj.show = true; } + if (Object.prototype.hasOwnProperty.call(cols[i], 'validator')) { + obj.validator = cols[i].validator; + } else { + obj.validator = false; + } vm.cols.push(obj); obj = {}; } @@ -607,6 +614,7 @@ cell.isEditable = vm.cols[ii].editable; cell.isHidden = vm.cols[ii].hidden; cell.show = vm.cols[ii].show; + cell.hasErrors = []; row[vm.cols[ii].name] = cell; cell = {}; } @@ -627,11 +635,18 @@ } }, // save changed cell / post request - saveData(key, value, id) { + saveData(rowIndex, key, value, id) { const vm = this; - const postData = {}; - postData[key] = value; - const data = postData; + vm.showSavingIcon(key, rowIndex); + let errors = []; + vm.cols.forEach((obj) => { + if (obj.name === key) { + if (obj.validator) { + errors = vm.validate(obj.validator.rules, obj.validator.messages, value); + } + } + }); + vm.$set(vm.filteredData[rowIndex][key], 'hasErrors', errors); function cb() { vm.savingKey = false; vm.savingIndex = false; @@ -640,17 +655,25 @@ vm.savingKey = false; vm.savingIndex = false; } - if (vm.opt.requests.postUrl) { - const url = `${vm.opt.requests.patchUrl}/${id}`; - vm.patchData(url, data, cb, errorCb); - } - for (let i = 0; i < vm.cols.length; i += 1) { - if (vm.cols[i].name === key) { - vm.activeCol = i; - break; + if (errors.length === 0) { + console.log('inside save', errors.length); + const postData = {}; + postData[key] = value; + const data = postData; + if (vm.opt.requests.postUrl) { + const url = `${vm.opt.requests.patchUrl}/${id}`; + vm.patchData(url, data, cb, errorCb); + } + for (let i = 0; i < vm.cols.length; i += 1) { + if (vm.cols[i].name === key) { + vm.activeCol = i; + break; + } } + vm.initTableWidths(); + } else { + errorCb(); } - vm.initTableWidths(); }, // set sorting array and key, data gets filtered (computed) sortBy(key, event) { @@ -822,8 +845,8 @@ && !vm.filteredData[ri][cols[i + 1].name].isHidden) { vm.setTarget(ri, cols[i + 1].name); } else if (vm.filteredData[ri][cols[i + 1].name].isEditable - && vm.filteredData[ri][cols[i + 1].name].show - && vm.filteredData[ri][cols[i + 1].name].isHidden) { + && vm.filteredData[ri][cols[i + 1].name].show + && vm.filteredData[ri][cols[i + 1].name].isHidden) { vm.swipeRight(); vm.setTarget(ri, cols[i + 1].name); } else { @@ -832,8 +855,8 @@ } } else if (ri + 1 <= lastIndex) { if (vm.filteredData[ri + 1][cols[0].name].isEditable - && vm.filteredData[ri + 1][cols[0].name].show - && !vm.filteredData[ri + 1][cols[0].name].isHidden) { + && vm.filteredData[ri + 1][cols[0].name].show + && !vm.filteredData[ri + 1][cols[0].name].isHidden) { vm.tableWidth = vm.initTableWidth; vm.setTableWidth(); vm.setSelection(vm.filteredData[ri + 1][cols[0].name].value, event.key); @@ -851,8 +874,8 @@ vm.setTableWidth(); vm.setPage(vm.currentPage + 2); if (vm.filteredData[0][cols[0].name].isEditable - && vm.filteredData[0][cols[0].name].show - && !vm.filteredData[0][cols[0].name].isHidden) { + && vm.filteredData[0][cols[0].name].show + && !vm.filteredData[0][cols[0].name].isHidden) { vm.setSelection(vm.filteredData[0][cols[0].name].value, event.key); vm.setTarget(0, cols[0].name); } else { @@ -868,12 +891,12 @@ let ri = thisRowIndex; if (i - 1 >= 0) { if (vm.filteredData[ri][cols[i - 1].name].isEditable - && vm.filteredData[ri][cols[i - 1].name].show - && !vm.filteredData[ri][cols[i - 1].name].isHidden) { + && vm.filteredData[ri][cols[i - 1].name].show + && !vm.filteredData[ri][cols[i - 1].name].isHidden) { vm.setTarget(ri, cols[i - 1].name); } else if (vm.filteredData[ri][cols[i - 1].name].isEditable - && vm.filteredData[ri][cols[i - 1].name].show - && vm.filteredData[ri][cols[i - 1].name].isHidden) { + && vm.filteredData[ri][cols[i - 1].name].show + && vm.filteredData[ri][cols[i - 1].name].isHidden) { vm.swipeLeft(); vm.setTarget(ri, cols[i - 1].name); } else { @@ -884,8 +907,8 @@ vm.tableWidth = vm.initTableWidth; vm.setTableWidthReverse(); if (vm.filteredData[ri - 1][cols[lastCol].name].isEditable - && vm.filteredData[ri - 1][cols[lastCol].name].show - && !vm.filteredData[ri - 1][cols[lastCol].name].isHidden) { + && vm.filteredData[ri - 1][cols[lastCol].name].show + && !vm.filteredData[ri - 1][cols[lastCol].name].isHidden) { vm.setSelection(vm.filteredData[ri - 1][cols[0].name].value, event.key); vm.setTarget(ri - 1, cols[lastCol].name); } else { @@ -901,8 +924,8 @@ vm.setTableWidthReverse(); vm.setPage(vm.currentPage); if (vm.filteredData[lastIndex][cols[lastCol].name].isEditable - && vm.filteredData[lastIndex][cols[lastCol].name].show - && !vm.filteredData[lastIndex][cols[lastCol].name].isHidden) { + && vm.filteredData[lastIndex][cols[lastCol].name].show + && !vm.filteredData[lastIndex][cols[lastCol].name].isHidden) { vm.setSelection(vm.filteredData[lastIndex][cols[0].name].value, event.key); vm.setTarget(lastIndex, cols[lastCol].name); } else { @@ -1041,277 +1064,281 @@ diff --git a/src/mixins/Validator.js b/src/mixins/Validator.js new file mode 100644 index 0000000..d68de66 --- /dev/null +++ b/src/mixins/Validator.js @@ -0,0 +1,117 @@ +import validator from 'validator'; + +export default { + methods: { + validate(rules, messages, value) { + const res = []; + rules.forEach((rule, key) => { + if (!this.makeValidation(rule, value)) { + res.push(messages[key]); + } + }); + return res; + }, + makeValidation(str, value) { + let res = false; + const arr = this.checkIfParameter(str); + const l = arr.length; + const string = arr[0]; + let paraOne; + let paraTwo; + if (l > 0) paraOne = arr[1]; + if (l > 1) paraTwo = arr[2]; + switch (string) { + case 'required': + res = !validator.isEmpty(value); + break; + case 'email': + res = validator.isEmail(value); + break; + case 'contains': + res = validator.contains(value, paraOne); + break; + case 'int': + res = validator.isInt(value); + break; + case 'float': + res = validator.isFloat(value); + break; + case 'min': + if (validator.isInt(value)) { + res = validator.isInt(value, { min: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { min: parseFloat(paraOne, 10) }); + } + break; + case 'max': + if (validator.isInt(value)) { + res = validator.isInt(value, { max: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { max: parseFloat(paraOne, 10) }); + } + break; + case 'between': + if (validator.isInt(value)) { + res = validator.isInt(value, { min: parseInt(paraOne, 10), + max: parseInt(paraTwo, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { min: parseFloat(paraOne, 10), + max: parseFloat(paraTwo, 10) }); + } + break; + case 'gt': + if (validator.isInt(value)) { + res = validator.isInt(value, { gt: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { gt: parseFloat(paraOne, 10) }); + } + break; + case 'lt': + if (validator.isInt(value)) { + res = validator.isInt(value, { lt: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { lt: parseFloat(paraOne, 10) }); + } + break; + case 'alpha': + res = validator.isAlpha(value, paraOne); + break; + case 'alphaNum': + res = validator.isAlphanumeric(value, paraOne); + break; + case 'bool': + res = validator.isBoolean(value); + break; + case 'url': + res = validator.isURL(value); + break; + case 'fqdn': + res = validator.isFQDN(value); + break; + case 'hexColor': + res = validator.isHexColor(value); + break; + case 'ip4': + res = validator.isIP(value, 4); + break; + case 'ip6': + res = validator.isIP(value, 6); + break; + default: + res = false; + } + return res; + }, + checkIfParameter(str) { + let i = 0; + let res; + i = str.indexOf(':'); + if (i > -1) { + res = str.split(':'); + } else { + res = [str]; + } + return res; + }, + }, +};