Skip to content

Commit

Permalink
use a dialog to display errors, fix recovery validation, add more rules
Browse files Browse the repository at this point in the history
  • Loading branch information
hobbitronics committed Jan 29, 2025
1 parent 5e11d69 commit fe8516f
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 8 deletions.
31 changes: 28 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,23 @@
</v-row>

<v-container>
<v-alert v-if="!!message" type="error" icon="mdi-alert" closable class="my-2" @click:close="message = ''">
<span v-sanitize.basic="message" />
</v-alert>
<v-dialog v-model="isModalOpen" max-width="400">
<v-card>
<v-card-title>
<v-icon color="error" class="mr-2">mdi-alert</v-icon>
{{ $t('global.error') }}
</v-card-title>
<v-card-text>
<span v-sanitize.basic="message" />
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn color="primary" @click="closeModal">
{{ $t('global.button.close') }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>

<!-- adding key here helps produce more predictable view behavior (see https://youtu.be/7YZ5DwlLSt8?t=21m22s) -->
<router-view :key="$route.fullPath" />
Expand All @@ -58,15 +72,21 @@ import { useRoute } from 'vue-router'
import { useDisplay } from 'vuetify'
const message = ref('')
const isModalOpen = ref(false)
const { xs } = useDisplay()
const route = useRoute()
watch(message, (newValue) => {
if (newValue) isModalOpen.value = true
})
watch(
() => route.fullPath,
() => {
message.value = ''
isModalOpen.value = false // Close modal (if open)
},
)
Expand All @@ -86,6 +106,11 @@ const logout = () => {
const login = () => {
user.login()
}
const closeModal = () => {
message.value = ''
isModalOpen.value = false
}
</script>

<style scoped>
Expand Down
5 changes: 4 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"close": "Close"
},
"learnMore": "learn more",
"areYouSure": "Are you sure?"
"areYouSure": "Are you sure?",
"error": "Error"
},
"app": {
"login": "Log in",
Expand Down Expand Up @@ -169,6 +170,8 @@
"unsaved": "You have not saved your changes yet.",
"dontRemoveLastOne": "Please add another alternate address before removing this one.",
"invalidEmail": "Invalid email",
"emailTooLong": "The email address needs to be less than 65 characters",
"isPrimaryEmail": "You can't use your primary email address or alias as an alternate",
"personalHeader": "Alternate(s)",
"noPersonalMethods": "None at this time"
},
Expand Down
5 changes: 4 additions & 1 deletion src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"close": "Cerrar"
},
"learnMore": "más información",
"areYouSure": "¿Seguro que quiere continuar?"
"areYouSure": "¿Seguro que quiere continuar?",
"error": "Error"
},
"app": {
"login": "Iniciar sesión",
Expand Down Expand Up @@ -169,6 +170,8 @@
"unsaved": "Aún no ha guardado sus cambios.",
"dontRemoveLastOne": "Por favor agregue una nueva dirección alternativa antes de eliminar esta.",
"invalidEmail": "Dirección de correo electrónica no válida",
"emailTooLong": "La dirección de correo electrónico debe tener menos de 65 caracteres",
"isPrimaryEmail": "No puede utilizar su dirección de correo electrónico principal o alias como alternativa",
"personalHeader": "Alternativo(s)",
"noPersonalMethods": "Ninguno en este momento"
},
Expand Down
5 changes: 4 additions & 1 deletion src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"close": "Fermer"
},
"learnMore": "en savoir plus",
"areYouSure": "Êtes-vous certain ?"
"areYouSure": "Êtes-vous certain ?",
"error": "Erreur"
},
"app": {
"login": "S'identifier",
Expand Down Expand Up @@ -169,6 +170,8 @@
"unsaved": "Vous n'avez pas encore enregistré vos modifications.",
"dontRemoveLastOne": "Veuillez ajouter une autre adresse e-mail alternative avant de supprimer celle-ci.",
"invalidEmail": "Adresse email invalide",
"emailTooLong": "L'adresse e-mail doit comporter moins de 65 caractères",
"isPrimaryEmail": "Vous ne pouvez pas utiliser votre adresse e-mail principale ou votre alias comme alternative",
"personalHeader": "Alternative(s)",
"noPersonalMethods": "Aucun en ce moment"
},
Expand Down
5 changes: 4 additions & 1 deletion src/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"close": "닫기"
},
"learnMore": "자세히 알아보기",
"areYouSure": "계속 진행하시겠습니까?"
"areYouSure": "계속 진행하시겠습니까?",
"error": "오류"
},
"app": {
"login": "로그인",
Expand Down Expand Up @@ -169,6 +170,8 @@
"unsaved": "아직 변경 사항을 저장하지 않았습니다.",
"dontRemoveLastOne": "이 주소를 제거하기 전에 다른 대체 주소를 추가하십시오.",
"invalidEmail": "잘못된 이메일",
"emailTooLong": "이메일 주소는 65자 미만이어야 합니다.",
"isPrimaryEmail": "기본 이메일 주소나 별칭을 대안으로 사용할 수 없습니다.",
"personalHeader": "대체",
"noPersonalMethods": "현재 없음"
},
Expand Down
18 changes: 17 additions & 1 deletion src/password/Recovery.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
(v) =>
/^$|^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(v) ||
$t('password.recovery.invalidEmail'),
(v) => v?.length <= 65 || $t('password.recovery.emailTooLong'),
(v) => !isAlias(v, primary.value) || $t('password.recovery.isPrimaryEmail'),
]"
validate-on-input
autofocus
Expand Down Expand Up @@ -107,12 +109,15 @@ export default {
},
methods: {
async add() {
if (this.$refs.form.validate()) {
const { valid, errors } = await this.$refs.form.validate()
if (valid) {
await add(this.newEmail)
this.newEmail = ''
this.$root.$emit('clear-messages') // listener in App.vue (this is a temporary hack hopefully)
} else {
throw Error(errors[0].errorMessages)
}
},
remove,
Expand All @@ -124,6 +129,17 @@ export default {
this.$refs.wizard.completed()
this.$refs.wizard.next()
},
isAlias(email, primaryEmail) {
const normalizeEmail = (email) => {
const [localPart, domain] = email.split('@')
const cleanedLocalPart = localPart.includes('+') ? localPart.split('+')[0] : localPart
const normalizedLocalPart = cleanedLocalPart.replace(/\./g, '')
return `${normalizedLocalPart}@${domain}`.toLowerCase()
}
return normalizeEmail(email) === normalizeEmail(primaryEmail)
},
},
}
</script>
Expand Down

0 comments on commit fe8516f

Please sign in to comment.