This is an automated email from the ASF dual-hosted git repository. machristie pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit 874ebb4f2c04370ba6b053291482fe00fa67db9b Author: Marcus Christie <[email protected]> AuthorDate: Mon Apr 23 13:02:47 2018 -0400 AIRAVATA-2611 Exp input editors validate value and dispatch events --- .../django_airavata_api/js/models/Experiment.js | 13 ------- .../js/models/InputDataObjectType.js | 5 ++- .../js/components/experiment/ExperimentEditor.vue | 40 ++++++++++---------- .../experiment/input-editors/FileInputEditor.vue | 44 ++++++++++++++++++++-- .../experiment/input-editors/StringInputEditor.vue | 44 ++++++++++++++++++++-- 5 files changed, 104 insertions(+), 42 deletions(-) diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js b/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js index 90e6637..d45637e 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js @@ -74,19 +74,6 @@ export default class Experiment extends BaseModel { validate() { let validationResults = {}; - const experimentInputsValidation = this.experimentInputs - .map(experimentInput => { - const validation = experimentInput.validate(); - if (validation && 'value' in validation) { - return {[experimentInput.name]: validation}; - } else { - return null; - } - }) - .reduce((accumulator, currentValue) => Object.assign(accumulator, currentValue), {}); - if (Object.keys(experimentInputsValidation).length > 0) { - validationResults['experimentInputs'] = experimentInputsValidation; - } const userConfigurationDataValidation = this.userConfigurationData.validate(); if (Object.keys(userConfigurationDataValidation).length > 0) { validationResults['userConfigurationData'] = userConfigurationDataValidation; diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js b/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js index dfe2846..eb5407b 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js @@ -26,9 +26,10 @@ export default class InputDataObjectType extends BaseModel { super(FIELDS, data); } - validate() { + validate(experiment, value = undefined) { + let inputValue = typeof value != 'undefined' ? value : this.value; let results = {}; - if (this.isRequired && this.isEmpty(this.value)) { + if (this.isRequired && this.isEmpty(inputValue)) { results['value'] = 'This field is required.'; } return results; diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue index 29be831..94a8d44 100644 --- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue +++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue @@ -55,7 +55,9 @@ :experiment="localExperiment" :experiment-input="experimentInput" v-model="experimentInput.value" - :key="experimentInput.name"/> + :key="experimentInput.name" + @invalid="recordInvalidInputEditorValue(experimentInput.name)" + @valid="recordValidInputEditorValue(experimentInput.name)"/> </div> </div> </div> @@ -122,6 +124,7 @@ export default { return { projects: [], localExperiment: this.experiment.clone(), + invalidInputs: [], } }, components: { @@ -141,9 +144,12 @@ export default { text: project.name, })); }, - isSaveDisabled: function() { + valid: function() { const validation = this.localExperiment.validate(); - return Object.keys(validation).length > 0; + return Object.keys(validation).length === 0 && this.invalidInputs.length === 0; + }, + isSaveDisabled: function() { + return !this.valid; }, }, methods: { @@ -192,21 +198,6 @@ export default { }); return Promise.all(uploads); }, - getApplicationInputState: function(applicationInput) { - const validation = this.getApplicationInputValidation(applicationInput); - return validation !== null ? 'invalid' : null; - }, - getApplicationInputFeedback: function(applicationInput) { - const validation = this.getApplicationInputValidation(applicationInput); - return validation !== null ? validation['value'] : null; - }, - getApplicationInputValidation: function(applicationInput) { - const validationResults = applicationInput.validate(); - if (validationResults !== null && 'value' in validationResults) { - return validationResults; - } - return null; - }, getValidationFeedback: function(properties) { return utils.getProperty(this.localExperiment.validate(), properties); }, @@ -221,7 +212,18 @@ export default { } // Default return 'string-input-editor'; - } + }, + recordInvalidInputEditorValue: function(experimentInputName) { + if (!this.invalidInputs.includes(experimentInputName)) { + this.invalidInputs.push(experimentInputName); + } + }, + recordValidInputEditorValue: function(experimentInputName) { + if (this.invalidInputs.includes(experimentInputName)) { + const index = this.invalidInputs.indexOf(experimentInputName); + this.invalidInputs.splice(index, 1); + } + }, }, watch: { experiment: function(newValue) { diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue index 2d5dbeb..4efa9b1 100644 --- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue +++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue @@ -1,8 +1,10 @@ <template> - <b-form-group :label="experimentInput.name" :label-for="experimentInput.name"> - <b-form-file :id="experimentInput.name" v-model="data" required + <b-form-group :label="experimentInput.name" :label-for="experimentInput.name" + :feedback="validationFeedback" :state="validationState"> + <b-form-file :id="experimentInput.name" v-model="data" :placeholder="experimentInput.userFriendlyDescription" - @input="emitValueChanged"/> + :state="validationState" + @input="valueChanged"/> </b-form-group> </template> @@ -26,12 +28,46 @@ export default { data () { return { data: this.value, + inputHasBegun: false, } }, + computed: { + validationResults: function() { + return this.experimentInput.validate(this.experiment, this.data); + }, + valid: function() { + return Object.keys(this.validationResults).length === 0; + }, + validationFeedback: function() { + // Only display validation feedback after the user has provided + // input so that missing required value errors are only displayed + // after interacting with the input editor + return this.inputHasBegun && 'value' in this.validationResults + ? this.validationResults['value'] + : null; + }, + validationState: function() { + return this.inputHasBegun && 'value' in this.validationResults + ? 'invalid' + : null; + }, + }, methods: { - emitValueChanged: function() { + valueChanged: function() { + this.inputHasBegun = true; this.$emit('input', this.data); + this.checkValidation(); }, + checkValidation: function() { + if (this.valid) { + this.$emit('valid'); + } else { + this.$emit('invalid'); + } + } }, + mounted: function() { + this.checkValidation(); + } } </script> diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/StringInputEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/StringInputEditor.vue index 27628b0..4a3a96a 100644 --- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/StringInputEditor.vue +++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/StringInputEditor.vue @@ -1,8 +1,10 @@ <template> - <b-form-group :label="experimentInput.name" :label-for="experimentInput.name"> - <b-form-input :id="experimentInput.name" type="text" v-model="data" required + <b-form-group :label="experimentInput.name" :label-for="experimentInput.name" + :feedback="validationFeedback" :state="validationState"> + <b-form-input :id="experimentInput.name" type="text" v-model="data" :placeholder="experimentInput.userFriendlyDescription" - @input="emitValueChanged"/> + :state="validationState" + @input="valueChanged"/> </b-form-group> </template> @@ -27,12 +29,46 @@ export default { data () { return { data: this.value, + inputHasBegun: false, } }, + computed: { + validationResults: function() { + return this.experimentInput.validate(this.experiment, this.data); + }, + valid: function() { + return Object.keys(this.validationResults).length === 0; + }, + validationFeedback: function() { + // Only display validation feedback after the user has provided + // input so that missing required value errors are only displayed + // after interacting with the input editor + return this.inputHasBegun && 'value' in this.validationResults + ? this.validationResults['value'] + : null; + }, + validationState: function() { + return this.inputHasBegun && 'value' in this.validationResults + ? 'invalid' + : null; + }, + }, methods: { - emitValueChanged: function() { + valueChanged: function() { + this.inputHasBegun = true; this.$emit('input', this.data); + this.checkValidation(); }, + checkValidation: function() { + if (this.valid) { + this.$emit('valid'); + } else { + this.$emit('invalid'); + } + } }, + mounted: function() { + this.checkValidation(); + } } </script> \ No newline at end of file -- To stop receiving notification emails like this one, please contact [email protected].
