This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch AIRAVATA-3562
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
The following commit(s) were added to refs/heads/AIRAVATA-3562 by this push:
new 71774e3a AIRAVATA-3565 Better handling of extended user profile
validation
71774e3a is described below
commit 71774e3af3bdb4d65c82c5dd597fa3f169e11afc
Author: Marcus Christie <[email protected]>
AuthorDate: Tue May 17 10:44:16 2022 -0400
AIRAVATA-3565 Better handling of extended user profile validation
---
.../js/components/ExtendedUserProfileEditor.vue | 11 +++++---
.../components/ExtendedUserProfileFieldEditor.vue | 8 ++++++
.../ExtendedUserProfileMultiChoiceFieldEditor.vue | 11 ++++++++
.../ExtendedUserProfileSingleChoiceFieldEditor.vue | 11 ++++++++
.../ExtendedUserProfileTextFieldEditor.vue | 11 ++++++++
...ExtendedUserProfileUserAgreementFieldEditor.vue | 11 ++++++++
.../js/containers/UserProfileContainer.vue | 9 +------
django_airavata/static/common/js/index.js | 2 ++
.../static/common/js/mixins/ValidationParent.js | 30 ++++++++++++++++++++++
9 files changed, 93 insertions(+), 11 deletions(-)
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
index d1a6df0d..0b0b08d8 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
@@ -6,6 +6,8 @@
:key="extendedUserProfileField.id"
:is="getEditor(extendedUserProfileField)"
:extended-user-profile-field="extendedUserProfileField"
+ @valid="recordValidChildComponent(extendedUserProfileField.id)"
+ @invalid="recordInvalidChildComponent(extendedUserProfileField.id)"
/>
</template>
</div>
@@ -17,13 +19,13 @@ import ExtendedUserProfileMultiChoiceFieldEditor from
"./ExtendedUserProfileMult
import ExtendedUserProfileSingleChoiceFieldEditor from
"./ExtendedUserProfileSingleChoiceFieldEditor.vue";
import ExtendedUserProfileTextFieldEditor from
"./ExtendedUserProfileTextFieldEditor.vue";
import ExtendedUserProfileUserAgreementFieldEditor from
"./ExtendedUserProfileUserAgreementFieldEditor.vue";
+import { mixins } from "django-airavata-common-ui";
export default {
+ mixins: [mixins.ValidationParent],
computed: {
...mapGetters("extendedUserProfile", ["extendedUserProfileFields"]),
valid() {
- return this.$refs.extendedUserProfileFieldComponents.every(
- (c) => c.valid
- );
+ return this.childComponentsAreValid;
},
},
methods: {
@@ -45,6 +47,9 @@ export default {
);
}
},
+ touch() {
+ this.$refs.extendedUserProfileFieldComponents.forEach((c) => c.touch());
+ },
},
};
</script>
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue
index 1115ea7e..13b7a664 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue
@@ -3,6 +3,14 @@
:label="extendedUserProfileField.name"
:description="extendedUserProfileField.help_text"
>
+ <template #label>
+ {{ extendedUserProfileField.name }}
+ <small
+ v-if="!extendedUserProfileField.required"
+ class="text-muted text-small"
+ >(Optional)</small
+ >
+ </template>
<b-card
v-for="link in extendedUserProfileField.links"
:key="link.id"
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
index ff02eea7..17faef61 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
@@ -136,6 +136,17 @@ export default {
},
validateState: errors.vuelidateHelpers.validateState,
validateStateErrorOnly: errors.vuelidateHelpers.validateStateErrorOnly,
+ touch() {
+ this.$v.$touch();
+ },
+ },
+ watch: {
+ valid: {
+ handler(valid) {
+ this.$emit(valid ? "valid" : "invalid");
+ },
+ immediate: true,
+ },
},
};
</script>
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
index 40872081..61c672f5 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
@@ -138,6 +138,17 @@ export default {
},
validateState: errors.vuelidateHelpers.validateState,
validateStateErrorOnly: errors.vuelidateHelpers.validateStateErrorOnly,
+ touch() {
+ this.$v.$touch();
+ },
+ },
+ watch: {
+ valid: {
+ handler(valid) {
+ this.$emit(valid ? "valid" : "invalid");
+ },
+ immediate: true,
+ },
},
};
</script>
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
index 37b451d7..3e2a8e69 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
@@ -45,6 +45,17 @@ export default {
methods: {
...mapMutations("extendedUserProfile", ["setTextValue"]),
validateState: errors.vuelidateHelpers.validateState,
+ touch() {
+ this.$v.$touch();
+ },
+ },
+ watch: {
+ valid: {
+ handler(valid) {
+ this.$emit(valid ? "valid" : "invalid");
+ },
+ immediate: true,
+ },
},
};
</script>
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
index 487d6b09..d0fe40a4 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
@@ -65,6 +65,17 @@ export default {
},
validateState: errors.vuelidateHelpers.validateState,
validateStateErrorOnly: errors.vuelidateHelpers.validateStateErrorOnly,
+ touch() {
+ this.$v.$touch();
+ },
+ },
+ watch: {
+ valid: {
+ handler(valid) {
+ this.$emit(valid ? "valid" : "invalid");
+ },
+ immediate: true,
+ },
},
};
</script>
diff --git
a/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
b/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
index 86fbb395..3e8d101f 100644
---
a/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
+++
b/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
@@ -105,14 +105,7 @@ export default {
})
);
} else {
- // TODO: make sure to highlight which fields are invalid
- notifications.NotificationList.add(
- new notifications.Notification({
- type: "WARNING",
- message: "The form is invalid. Please fix and try again.",
- duration: 5,
- })
- );
+ this.$refs.extendedUserProfileEditor.touch();
}
},
async handleResendEmailVerification() {
diff --git a/django_airavata/static/common/js/index.js
b/django_airavata/static/common/js/index.js
index b4bcc5ec..68c9719d 100644
--- a/django_airavata/static/common/js/index.js
+++ b/django_airavata/static/common/js/index.js
@@ -31,6 +31,7 @@ import * as vuelidateHelpers from
"./errors/vuelidateHelpers.js";
import ListLayout from "./layouts/ListLayout.vue";
+import ValidationParent from "./mixins/ValidationParent";
import VModelMixin from "./mixins/VModelMixin";
import Notification from "./notifications/Notification";
@@ -80,6 +81,7 @@ const layouts = {
};
const mixins = {
+ ValidationParent,
VModelMixin,
};
diff --git a/django_airavata/static/common/js/mixins/ValidationParent.js
b/django_airavata/static/common/js/mixins/ValidationParent.js
new file mode 100644
index 00000000..6e89563d
--- /dev/null
+++ b/django_airavata/static/common/js/mixins/ValidationParent.js
@@ -0,0 +1,30 @@
+/**
+ * Aggregate validation state of child components. Child components should
+ * dispatch 'valid' and 'invalid' events and component using this mixin should
+ * call recordValidChildComponent or recordInvalidChildComponent, respectively.
+ */
+export default {
+ data: function () {
+ return {
+ invalidChildComponents: [],
+ };
+ },
+ computed: {
+ childComponentsAreValid() {
+ return this.invalidChildComponents.length === 0;
+ },
+ },
+ methods: {
+ recordInvalidChildComponent(childComponentId) {
+ if (!this.invalidChildComponents.includes(childComponentId)) {
+ this.invalidChildComponents.push(childComponentId);
+ }
+ },
+ recordValidChildComponent(childComponentId) {
+ if (this.invalidChildComponents.includes(childComponentId)) {
+ const index = this.invalidChildComponents.indexOf(childComponentId);
+ this.invalidChildComponents.splice(index, 1);
+ }
+ },
+ },
+};