From a23da02755d2e6d8046014f5cd99bfff2277f512 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Pardou?= <jeremie@baserow.io>
Date: Fri, 29 Mar 2024 08:02:34 +0000
Subject: [PATCH] Fix re-login process with the auth form

---
 ..._are_already_logged_doesnt_require_to.json |  7 ++
 .../components/elements/AuthFormElement.vue   | 96 +++++++++----------
 .../elements/baseComponents/ABFormGroup.vue   |  7 +-
 .../elements/components/InputTextElement.vue  | 25 ++---
 .../modules/builder/mixins/formElement.js     |  7 ++
 5 files changed, 76 insertions(+), 66 deletions(-)
 create mode 100644 changelog/entries/unreleased/bug/2476_using_login_form_if_you_are_already_logged_doesnt_require_to.json

diff --git a/changelog/entries/unreleased/bug/2476_using_login_form_if_you_are_already_logged_doesnt_require_to.json b/changelog/entries/unreleased/bug/2476_using_login_form_if_you_are_already_logged_doesnt_require_to.json
new file mode 100644
index 000000000..b1e57d52b
--- /dev/null
+++ b/changelog/entries/unreleased/bug/2476_using_login_form_if_you_are_already_logged_doesnt_require_to.json
@@ -0,0 +1,7 @@
+{
+    "type": "bug",
+    "message": "Using login form if you are already logged doesn't require to click twice on the button anymore",
+    "issue_number": 2476,
+    "bullet_points": [],
+    "created_at": "2024-03-28"
+}
\ No newline at end of file
diff --git a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue
index 5b468a6f6..461669247 100644
--- a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue
+++ b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue
@@ -131,55 +131,55 @@ export default {
     }),
     async onLogin(event) {
       if (this.isAuthenticated) {
-        this.$store.dispatch('userSourceUser/logoff')
-      } else {
-        this.$v.$touch()
-        if (this.$v.$invalid) {
-          this.focusOnFirstError()
-          return
-        }
-        this.loading = true
-        this.hideError()
-        try {
-          await this.$store.dispatch('userSourceUser/authenticate', {
-            userSource: this.selectedUserSource,
-            credentials: {
-              email: this.values.email,
-              password: this.values.password,
-            },
-            setCookie: this.mode === 'public',
-          })
-          this.values.password = ''
-          this.values.email = ''
-          this.$v.$reset()
-          this.fireAfterLoginEvent()
-        } catch (error) {
-          if (error.handler) {
-            const response = error.handler.response
-            if (response && response.status === 401) {
-              this.values.password = ''
-              this.$v.$reset()
-              this.$v.$touch()
-              this.$refs.passwordRef.focus()
-
-              if (response.data?.error === 'ERROR_INVALID_CREDENTIALS') {
-                this.showError(
-                  this.$t('error.incorrectCredentialTitle'),
-                  this.$t('error.incorrectCredentialMessage')
-                )
-              }
-            } else {
-              const message = error.handler.getMessage('login')
-              this.showError(message)
-            }
-
-            error.handler.handled()
-          } else {
-            throw error
-          }
-        }
-        this.loading = false
+        await this.$store.dispatch('userSourceUser/logoff')
       }
+
+      this.$v.$touch()
+      if (this.$v.$invalid) {
+        this.focusOnFirstError()
+        return
+      }
+      this.loading = true
+      this.hideError()
+      try {
+        await this.$store.dispatch('userSourceUser/authenticate', {
+          userSource: this.selectedUserSource,
+          credentials: {
+            email: this.values.email,
+            password: this.values.password,
+          },
+          setCookie: this.mode === 'public',
+        })
+        this.values.password = ''
+        this.values.email = ''
+        this.$v.$reset()
+        this.fireAfterLoginEvent()
+      } catch (error) {
+        if (error.handler) {
+          const response = error.handler.response
+          if (response && response.status === 401) {
+            this.values.password = ''
+            this.$v.$reset()
+            this.$v.$touch()
+            this.$refs.passwordRef.focus()
+
+            if (response.data?.error === 'ERROR_INVALID_CREDENTIALS') {
+              this.showError(
+                this.$t('error.incorrectCredentialTitle'),
+                this.$t('error.incorrectCredentialMessage')
+              )
+            }
+          } else {
+            const message = error.handler.getMessage('login')
+            this.showError(message)
+          }
+
+          error.handler.handled()
+        } else {
+          throw error
+        }
+      }
+      this.loading = false
     },
   },
   validations: {
diff --git a/web-frontend/modules/builder/components/elements/baseComponents/ABFormGroup.vue b/web-frontend/modules/builder/components/elements/baseComponents/ABFormGroup.vue
index 208a730d0..a80ea1123 100644
--- a/web-frontend/modules/builder/components/elements/baseComponents/ABFormGroup.vue
+++ b/web-frontend/modules/builder/components/elements/baseComponents/ABFormGroup.vue
@@ -37,11 +37,6 @@ export default {
       required: false,
       default: null,
     },
-    isInError: {
-      type: Boolean,
-      required: false,
-      default: null,
-    },
     label: {
       type: String,
       required: false,
@@ -70,7 +65,7 @@ export default {
   },
   computed: {
     hasError() {
-      return this.isInError !== null ? this.isInError : Boolean(this.error)
+      return Boolean(this.errorMessage)
     },
   },
 }
diff --git a/web-frontend/modules/builder/components/elements/components/InputTextElement.vue b/web-frontend/modules/builder/components/elements/components/InputTextElement.vue
index 948dc1ea3..5bb8b3698 100644
--- a/web-frontend/modules/builder/components/elements/components/InputTextElement.vue
+++ b/web-frontend/modules/builder/components/elements/components/InputTextElement.vue
@@ -2,8 +2,7 @@
   <div>
     <ABFormGroup
       :label="resolvedLabel"
-      :is-in-error="displayFormDataError"
-      :error-message="errorForValidationType"
+      :error-message="errorMessage"
       :autocomplete="isEditMode ? 'off' : ''"
       :required="element.required"
     >
@@ -40,16 +39,6 @@ export default {
     },
   },
   computed: {
-    errorForValidationType() {
-      switch (this.element.validation_type) {
-        case 'integer':
-          return this.$t('error.invalidNumber')
-        case 'email':
-          return this.$t('error.invalidEmail')
-        default:
-          return this.$t('error.requiredField')
-      }
-    },
     resolvedDefaultValue() {
       return this.resolveFormula(this.element.default_value)
     },
@@ -68,5 +57,17 @@ export default {
       immediate: true,
     },
   },
+  methods: {
+    getErrorMessage() {
+      switch (this.element.validation_type) {
+        case 'integer':
+          return this.$t('error.invalidNumber')
+        case 'email':
+          return this.$t('error.invalidEmail')
+        default:
+          return this.$t('error.requiredField')
+      }
+    },
+  },
 }
 </script>
diff --git a/web-frontend/modules/builder/mixins/formElement.js b/web-frontend/modules/builder/mixins/formElement.js
index b546b742a..ae7ae1855 100644
--- a/web-frontend/modules/builder/mixins/formElement.js
+++ b/web-frontend/modules/builder/mixins/formElement.js
@@ -25,6 +25,9 @@ export default {
         !this.isEditMode
       )
     },
+    errorMessage() {
+      return this.displayFormDataError ? this.getErrorMessage() : ''
+    },
     formElementTouched() {
       return this.$store.getters['formData/getElementTouched'](
         this.page,
@@ -81,6 +84,10 @@ export default {
         elementId: this.element.id,
       })
     },
+    /** Override this method to display the right error message */
+    getErrorMessage() {
+      return ''
+    },
   },
   watch: {
     /**