From 1095e33d4dd1306eff19b2a0ce688161ef19a73e Mon Sep 17 00:00:00 2001 From: Justin Schroeder Date: Wed, 20 Nov 2019 23:16:31 -0500 Subject: [PATCH] File fields no longer upload unless they pass validation rules --- dist/formulate.esm.js | 48 +++++++++++++++++++++++++------ dist/formulate.min.js | 48 +++++++++++++++++++++++++------ dist/formulate.umd.js | 48 +++++++++++++++++++++++++------ src/FileUpload.js | 5 +++- src/FormulateInput.vue | 22 ++++++++++---- src/inputs/FormulateInputFile.vue | 14 +++++++-- src/libs/context.js | 1 + 7 files changed, 151 insertions(+), 35 deletions(-) diff --git a/dist/formulate.esm.js b/dist/formulate.esm.js index b31c712..71cd527 100644 --- a/dist/formulate.esm.js +++ b/dist/formulate.esm.js @@ -159,6 +159,9 @@ FileUpload.prototype.hasUploader = function hasUploader () { return !!this.context.uploader }; +/** + * Check if the given uploader is axios instance. + */ FileUpload.prototype.uploaderIsAxios = function uploaderIsAxios () { if ( this.hasUploader && @@ -207,7 +210,7 @@ FileUpload.prototype.upload = function upload () { return reject(new Error('No uploader has been defined')) } Promise.all(this$1.files.map(function (file) { - return this$1.getUploader( + return file.path ? Promise.resolve(file.path) : this$1.getUploader( file.file, function (progress) { file.progress = progress; @@ -940,7 +943,8 @@ var context = { uploadUrl: this.uploadUrl, uploader: this.uploader || this.$formulate.getUploader(), uploadBehavior: this.uploadBehavior, - preventWindowDrops: this.preventWindowDrops}, + preventWindowDrops: this.preventWindowDrops, + hasValidationErrors: this.hasValidationErrors}, this.typeContext)) }, nameOrFallback: nameOrFallback, @@ -1242,8 +1246,8 @@ var script = { default: false }, uploadBehavior: { - type: Boolean, - default: true + type: String, + default: 'live' }, preventWindowDrops: { type: Boolean, @@ -1256,7 +1260,8 @@ var script = { localAttributes: {}, internalModelProxy: this.formulateValue, behavioralErrorVisibility: (this.errorBehavior === 'live'), - validationErrors: [] + validationErrors: [], + pendingValidation: Promise.resolve() } }, computed: Object.assign({}, context, @@ -1303,7 +1308,7 @@ var script = { var this$1 = this; var rules = parseRules(this.validation, this.$formulate.rules()); - Promise.all( + this.pendingValidation = Promise.all( rules.map(function (ref) { var rule = ref[0]; var args = ref[1]; @@ -1319,7 +1324,20 @@ var script = { }) ) .then(function (result) { return result.filter(function (result) { return result; }); }) - .then(function (errorMessages) { this$1.validationErrors = errorMessages; }); + .then(function (errorMessages) { + console.log('setting validation errors'); + this$1.validationErrors = errorMessages; + }); + return this.pendingValidation + }, + hasValidationErrors: function hasValidationErrors () { + var this$1 = this; + + return new Promise(function (resolve) { + this$1.$nextTick(function () { + this$1.pendingValidation.then(function () { return resolve(!!this$1.validationErrors.length); }); + }); + }) } } }; @@ -2386,12 +2404,24 @@ var script$7 = { } }, handleFile: function handleFile () { + this.isOver = false; var input = this.$refs.file; if (input.files.length) { this.context.model = this.$formulate.createUpload(input, this.context); } - if (this.context.uploadBehavior === 'live' && this.context.model instanceof FileUpload) { - this.context.model.upload(); + this.attemptImmediateUpload(); + }, + attemptImmediateUpload: function attemptImmediateUpload () { + var this$1 = this; + + if (this.context.uploadBehavior === 'live' && + this.context.model instanceof FileUpload) { + this.context.hasValidationErrors().then(function (errors) { + console.log('validation errors', errors); + if (!errors) { + this$1.context.model.upload(); + } + }); } }, handleDragOver: function handleDragOver (e) { diff --git a/dist/formulate.min.js b/dist/formulate.min.js index 9c7985a..be139cf 100644 --- a/dist/formulate.min.js +++ b/dist/formulate.min.js @@ -162,6 +162,9 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { return !!this.context.uploader }; + /** + * Check if the given uploader is axios instance. + */ FileUpload.prototype.uploaderIsAxios = function uploaderIsAxios () { if ( this.hasUploader && @@ -210,7 +213,7 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { return reject(new Error('No uploader has been defined')) } Promise.all(this$1.files.map(function (file) { - return this$1.getUploader( + return file.path ? Promise.resolve(file.path) : this$1.getUploader( file.file, function (progress) { file.progress = progress; @@ -943,7 +946,8 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { uploadUrl: this.uploadUrl, uploader: this.uploader || this.$formulate.getUploader(), uploadBehavior: this.uploadBehavior, - preventWindowDrops: this.preventWindowDrops}, + preventWindowDrops: this.preventWindowDrops, + hasValidationErrors: this.hasValidationErrors}, this.typeContext)) }, nameOrFallback: nameOrFallback, @@ -1245,8 +1249,8 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { default: false }, uploadBehavior: { - type: Boolean, - default: true + type: String, + default: 'live' }, preventWindowDrops: { type: Boolean, @@ -1259,7 +1263,8 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { localAttributes: {}, internalModelProxy: this.formulateValue, behavioralErrorVisibility: (this.errorBehavior === 'live'), - validationErrors: [] + validationErrors: [], + pendingValidation: Promise.resolve() } }, computed: Object.assign({}, context, @@ -1306,7 +1311,7 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { var this$1 = this; var rules = parseRules(this.validation, this.$formulate.rules()); - Promise.all( + this.pendingValidation = Promise.all( rules.map(function (ref) { var rule = ref[0]; var args = ref[1]; @@ -1322,7 +1327,20 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { }) ) .then(function (result) { return result.filter(function (result) { return result; }); }) - .then(function (errorMessages) { this$1.validationErrors = errorMessages; }); + .then(function (errorMessages) { + console.log('setting validation errors'); + this$1.validationErrors = errorMessages; + }); + return this.pendingValidation + }, + hasValidationErrors: function hasValidationErrors () { + var this$1 = this; + + return new Promise(function (resolve) { + this$1.$nextTick(function () { + this$1.pendingValidation.then(function () { return resolve(!!this$1.validationErrors.length); }); + }); + }) } } }; @@ -2389,12 +2407,24 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) { } }, handleFile: function handleFile () { + this.isOver = false; var input = this.$refs.file; if (input.files.length) { this.context.model = this.$formulate.createUpload(input, this.context); } - if (this.context.uploadBehavior === 'live' && this.context.model instanceof FileUpload) { - this.context.model.upload(); + this.attemptImmediateUpload(); + }, + attemptImmediateUpload: function attemptImmediateUpload () { + var this$1 = this; + + if (this.context.uploadBehavior === 'live' && + this.context.model instanceof FileUpload) { + this.context.hasValidationErrors().then(function (errors) { + console.log('validation errors', errors); + if (!errors) { + this$1.context.model.upload(); + } + }); } }, handleDragOver: function handleDragOver (e) { diff --git a/dist/formulate.umd.js b/dist/formulate.umd.js index 374a0f7..4d690e9 100644 --- a/dist/formulate.umd.js +++ b/dist/formulate.umd.js @@ -165,6 +165,9 @@ return !!this.context.uploader }; + /** + * Check if the given uploader is axios instance. + */ FileUpload.prototype.uploaderIsAxios = function uploaderIsAxios () { if ( this.hasUploader && @@ -213,7 +216,7 @@ return reject(new Error('No uploader has been defined')) } Promise.all(this$1.files.map(function (file) { - return this$1.getUploader( + return file.path ? Promise.resolve(file.path) : this$1.getUploader( file.file, function (progress) { file.progress = progress; @@ -946,7 +949,8 @@ uploadUrl: this.uploadUrl, uploader: this.uploader || this.$formulate.getUploader(), uploadBehavior: this.uploadBehavior, - preventWindowDrops: this.preventWindowDrops}, + preventWindowDrops: this.preventWindowDrops, + hasValidationErrors: this.hasValidationErrors}, this.typeContext)) }, nameOrFallback: nameOrFallback, @@ -1248,8 +1252,8 @@ default: false }, uploadBehavior: { - type: Boolean, - default: true + type: String, + default: 'live' }, preventWindowDrops: { type: Boolean, @@ -1262,7 +1266,8 @@ localAttributes: {}, internalModelProxy: this.formulateValue, behavioralErrorVisibility: (this.errorBehavior === 'live'), - validationErrors: [] + validationErrors: [], + pendingValidation: Promise.resolve() } }, computed: Object.assign({}, context, @@ -1309,7 +1314,7 @@ var this$1 = this; var rules = parseRules(this.validation, this.$formulate.rules()); - Promise.all( + this.pendingValidation = Promise.all( rules.map(function (ref) { var rule = ref[0]; var args = ref[1]; @@ -1325,7 +1330,20 @@ }) ) .then(function (result) { return result.filter(function (result) { return result; }); }) - .then(function (errorMessages) { this$1.validationErrors = errorMessages; }); + .then(function (errorMessages) { + console.log('setting validation errors'); + this$1.validationErrors = errorMessages; + }); + return this.pendingValidation + }, + hasValidationErrors: function hasValidationErrors () { + var this$1 = this; + + return new Promise(function (resolve) { + this$1.$nextTick(function () { + this$1.pendingValidation.then(function () { return resolve(!!this$1.validationErrors.length); }); + }); + }) } } }; @@ -2392,12 +2410,24 @@ } }, handleFile: function handleFile () { + this.isOver = false; var input = this.$refs.file; if (input.files.length) { this.context.model = this.$formulate.createUpload(input, this.context); } - if (this.context.uploadBehavior === 'live' && this.context.model instanceof FileUpload) { - this.context.model.upload(); + this.attemptImmediateUpload(); + }, + attemptImmediateUpload: function attemptImmediateUpload () { + var this$1 = this; + + if (this.context.uploadBehavior === 'live' && + this.context.model instanceof FileUpload) { + this.context.hasValidationErrors().then(function (errors) { + console.log('validation errors', errors); + if (!errors) { + this$1.context.model.upload(); + } + }); } }, handleDragOver: function handleDragOver (e) { diff --git a/src/FileUpload.js b/src/FileUpload.js index 85d222c..85480d0 100644 --- a/src/FileUpload.js +++ b/src/FileUpload.js @@ -50,6 +50,9 @@ class FileUpload { return !!this.context.uploader } + /** + * Check if the given uploader is axios instance. + */ uploaderIsAxios () { if ( this.hasUploader && @@ -92,7 +95,7 @@ class FileUpload { return reject(new Error('No uploader has been defined')) } Promise.all(this.files.map(file => { - return this.getUploader( + return file.path ? Promise.resolve(file.path) : this.getUploader( file.file, (progress) => { file.progress = progress diff --git a/src/FormulateInput.vue b/src/FormulateInput.vue index 90f854e..6f4c04a 100644 --- a/src/FormulateInput.vue +++ b/src/FormulateInput.vue @@ -150,8 +150,8 @@ export default { default: false }, uploadBehavior: { - type: Boolean, - default: true + type: String, + default: 'live' }, preventWindowDrops: { type: Boolean, @@ -164,7 +164,8 @@ export default { localAttributes: {}, internalModelProxy: this.formulateValue, behavioralErrorVisibility: (this.errorBehavior === 'live'), - validationErrors: [] + validationErrors: [], + pendingValidation: Promise.resolve() } }, computed: { @@ -211,7 +212,7 @@ export default { }, performValidation () { const rules = parseRules(this.validation, this.$formulate.rules()) - Promise.all( + this.pendingValidation = Promise.all( rules.map(([rule, args]) => { return rule(this.context.model, ...args) .then(res => res ? false : this.$formulate.validationMessage(rule.name, { @@ -224,7 +225,18 @@ export default { }) ) .then(result => result.filter(result => result)) - .then(errorMessages => { this.validationErrors = errorMessages }) + .then(errorMessages => { + console.log('setting validation errors') + this.validationErrors = errorMessages + }) + return this.pendingValidation + }, + hasValidationErrors () { + return new Promise(resolve => { + this.$nextTick(() => { + this.pendingValidation.then(() => resolve(!!this.validationErrors.length)) + }) + }) } } } diff --git a/src/inputs/FormulateInputFile.vue b/src/inputs/FormulateInputFile.vue index 1a7724d..f100ced 100644 --- a/src/inputs/FormulateInputFile.vue +++ b/src/inputs/FormulateInputFile.vue @@ -73,12 +73,22 @@ export default { } }, handleFile () { + this.isOver = false const input = this.$refs.file if (input.files.length) { this.context.model = this.$formulate.createUpload(input, this.context) } - if (this.context.uploadBehavior === 'live' && this.context.model instanceof FileUpload) { - this.context.model.upload() + this.attemptImmediateUpload() + }, + attemptImmediateUpload () { + if (this.context.uploadBehavior === 'live' && + this.context.model instanceof FileUpload) { + this.context.hasValidationErrors().then(errors => { + console.log('validation errors', errors) + if (!errors) { + this.context.model.upload() + } + }) } }, handleDragOver (e) { diff --git a/src/libs/context.js b/src/libs/context.js index 02f2883..ea5a862 100644 --- a/src/libs/context.js +++ b/src/libs/context.js @@ -24,6 +24,7 @@ export default { uploader: this.uploader || this.$formulate.getUploader(), uploadBehavior: this.uploadBehavior, preventWindowDrops: this.preventWindowDrops, + hasValidationErrors: this.hasValidationErrors, ...this.typeContext }) },