feat(webapp): ask for real name (#8605)

* feat(webapp): ask for real name

* fix locales

* function to create name from given and surname

* mock env

* use x2004 to create name from given and surname
This commit is contained in:
Moriz Wahl 2025-05-28 20:41:10 +02:00 committed by GitHub
parent fb2ef852a1
commit ba2e086b4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 158 additions and 44 deletions

View File

@ -8,3 +8,5 @@ INVITE_REGISTRATION=true
BADGES_ENABLED=true
INVITE_LINK_LIMIT=7
NETWORK_NAME="Ocelot.social"
ASK_FOR_REAL_NAME=false

View File

@ -35,7 +35,25 @@
<!-- leave this here in case the scoped variable is needed in the future nobody would remember this -->
<!-- <template v-slot="{ errors }"> -->
<template>
<div v-if="askForRealName" class="full-name">
<!-- <p>{{ $t('settings.data.realNamePlease') }}</p>-->
<ds-input
id="givenName"
model="givenName"
icon="user"
:label="$t('settings.data.givenName')"
:placeholder="$t('settings.data.givenNamePlaceholder')"
/>
<ds-input
id="surName"
model="surName"
icon="user"
:label="$t('settings.data.surName')"
:placeholder="$t('settings.data.surNamePlaceholder')"
/>
</div>
<ds-input
v-else
id="name"
model="name"
icon="user"
@ -102,13 +120,13 @@
<input
id="checkbox1"
type="checkbox"
v-model="recieveCommunicationAsEmailsEtcConfirmed"
:checked="recieveCommunicationAsEmailsEtcConfirmed"
v-model="receiveCommunicationAsEmailsEtcConfirmed"
:checked="receiveCommunicationAsEmailsEtcConfirmed"
/>
<label for="checkbox1">
{{
$t(
'components.registration.create-user-account.recieveCommunicationAsEmailsEtcConfirmed',
'components.registration.create-user-account.receiveCommunicationAsEmailsEtcConfirmed',
)
}}
</label>
@ -131,6 +149,8 @@ import PageParamsLink from '~/components/_new/features/PageParamsLink/PageParams
import PasswordForm from '~/components/utils/PasswordFormHelper'
import ShowPassword from '../ShowPassword/ShowPassword.vue'
const threePerEmSpace = '' // unicode u+2004;
export default {
name: 'RegistrationSlideCreate',
components: {
@ -149,13 +169,25 @@ export default {
links,
supportEmail: emails.SUPPORT_EMAIL,
formData: {
givenName: '',
surName: '',
name: '',
...passwordForm.formData,
},
formSchema: {
givenName: {
type: 'string',
required: this.$env.ASK_FOR_REAL_NAME,
min: 2,
},
surName: {
type: 'string',
required: this.$env.ASK_FOR_REAL_NAME,
min: 2,
},
name: {
type: 'string',
required: true,
required: !this.$env.ASK_FOR_REAL_NAME,
min: 3,
},
...passwordForm.formSchema,
@ -165,15 +197,26 @@ export default {
// Integrate termsAndConditionsConfirmed into `this.formData` once we
// have checkmarks available.
termsAndConditionsConfirmed: false,
recieveCommunicationAsEmailsEtcConfirmed: false,
receiveCommunicationAsEmailsEtcConfirmed: false,
showPassword: false,
showPasswordConfirm: false,
}
},
mounted: function () {
this.formData.name = this.sliderData.collectedInputData.name
? this.sliderData.collectedInputData.name
: ''
if (this.askForRealName) {
if (this.sliderData.collectedInputData.name) {
const split = this.sliderData.collectedInputData.name.split(threePerEmSpace)
this.formData.givenName = split[0]
this.formData.surName = split[1] || ''
} else {
this.formData.surName = ''
this.formData.givenName = ''
}
} else {
this.formData.name = this.sliderData.collectedInputData.name
? this.sliderData.collectedInputData.name
: ''
}
this.formData.password = this.sliderData.collectedInputData.password
? this.sliderData.collectedInputData.password
: ''
@ -184,9 +227,9 @@ export default {
.termsAndConditionsConfirmed
? this.sliderData.collectedInputData.termsAndConditionsConfirmed
: false
this.recieveCommunicationAsEmailsEtcConfirmed = this.sliderData.collectedInputData
.recieveCommunicationAsEmailsEtcConfirmed
? this.sliderData.collectedInputData.recieveCommunicationAsEmailsEtcConfirmed
this.receiveCommunicationAsEmailsEtcConfirmed = this.sliderData.collectedInputData
.receiveCommunicationAsEmailsEtcConfirmed
? this.sliderData.collectedInputData.receiveCommunicationAsEmailsEtcConfirmed
: false
this.sendValidation()
@ -195,13 +238,18 @@ export default {
})
},
computed: {
askForRealName() {
return this.$env.ASK_FOR_REAL_NAME
},
validInput() {
return (
this.formData.name.length >= 3 &&
(this.askForRealName
? this.formData.givenName.length >= 2 && this.formData.surName.length >= 2
: this.formData.name.length >= 3) &&
this.formData.password.length >= 1 &&
this.formData.password === this.formData.passwordConfirmation &&
this.termsAndConditionsConfirmed &&
this.recieveCommunicationAsEmailsEtcConfirmed
this.receiveCommunicationAsEmailsEtcConfirmed
)
},
iconNamePassword() {
@ -215,14 +263,19 @@ export default {
termsAndConditionsConfirmed() {
this.sendValidation()
},
recieveCommunicationAsEmailsEtcConfirmed() {
receiveCommunicationAsEmailsEtcConfirmed() {
this.sendValidation()
},
},
methods: {
buildName(data) {
if (this.askForRealName) return `${data.givenName}${threePerEmSpace}${data.surName}`
return data.name
},
sendValidation() {
const { name, password, passwordConfirmation } = this.formData
const { termsAndConditionsConfirmed, recieveCommunicationAsEmailsEtcConfirmed } = this
const { password, passwordConfirmation } = this.formData
const name = this.buildName(this.formData)
const { termsAndConditionsConfirmed, receiveCommunicationAsEmailsEtcConfirmed } = this
this.sliderData.setSliderValuesCallback(this.validInput, {
collectedInputData: {
@ -230,7 +283,7 @@ export default {
password,
passwordConfirmation,
termsAndConditionsConfirmed,
recieveCommunicationAsEmailsEtcConfirmed,
receiveCommunicationAsEmailsEtcConfirmed,
},
})
},
@ -241,7 +294,8 @@ export default {
this.sendValidation()
},
async submit() {
const { name, password } = this.formData
const { password } = this.formData
const name = this.buildName(this.formData).replace(threePerEmSpace, ' ')
const { email, inviteCode = null, nonce } = this.sliderData.collectedInputData
const termsAndConditionsAgreedVersion = VERSION
const locale = this.$i18n.locale()
@ -354,4 +408,8 @@ export default {
width: 100%;
}
}
.full-name {
padding-bottom: 16px;
}
</style>

View File

@ -101,7 +101,7 @@ storiesOf('RegistrationSlider', module)
password: 'Hello',
passwordConfirmation: 'Hello',
termsAndConditionsConfirmed: true,
recieveCommunicationAsEmailsEtcConfirmed: true,
receiveCommunicationAsEmailsEtcConfirmed: true,
},
},
}),
@ -131,7 +131,7 @@ storiesOf('RegistrationSlider', module)
password: 'Hello',
passwordConfirmation: 'Hello',
termsAndConditionsConfirmed: true,
recieveCommunicationAsEmailsEtcConfirmed: true,
receiveCommunicationAsEmailsEtcConfirmed: true,
},
},
}),
@ -153,7 +153,7 @@ storiesOf('RegistrationSlider', module)
password: null,
passwordConfirmation: null,
termsAndConditionsConfirmed: null,
recieveCommunicationAsEmailsEtcConfirmed: null,
receiveCommunicationAsEmailsEtcConfirmed: null,
},
},
}),
@ -175,7 +175,7 @@ storiesOf('RegistrationSlider', module)
password: 'Hello',
passwordConfirmation: 'Hello',
termsAndConditionsConfirmed: true,
recieveCommunicationAsEmailsEtcConfirmed: true,
receiveCommunicationAsEmailsEtcConfirmed: true,
},
},
}),

View File

@ -179,7 +179,7 @@ export default {
password: null,
passwordConfirmation: null,
termsAndConditionsConfirmed: null,
recieveCommunicationAsEmailsEtcConfirmed: null,
receiveCommunicationAsEmailsEtcConfirmed: null,
},
sliderIndex:
this.activePage === null ? 0 : sliders.findIndex((el) => el.name === this.activePage),

View File

@ -37,6 +37,7 @@ const options = {
BADGES_ENABLED: process.env.BADGES_ENABLED === 'true' || false,
INVITE_LINK_LIMIT: process.env.INVITE_LINK_LIMIT || 7,
NETWORK_NAME: process.env.NETWORK_NAME || 'Ocelot.social',
ASK_FOR_REAL_NAME: process.env.ASK_FOR_REAL_NAME === 'true' || false,
}
const language = {

View File

@ -208,7 +208,7 @@
"buttonTitle": "Erstellen",
"error": "Es konnte kein Nutzerkonto erstellt werden!",
"help": "Vielleicht war der Bestätigungscode falsch oder abgelaufen? Wenn das Problem weiterhin besteht, schicke uns gerne eine E-Mail an:",
"recieveCommunicationAsEmailsEtcConfirmed": "Ich stimme auch dem Erhalt von E-Mails und anderen Formen der Kommunikation (z.B. Push-Benachrichtigungen) zu.",
"receiveCommunicationAsEmailsEtcConfirmed": "Ich stimme auch dem Erhalt von E-Mails und anderen Formen der Kommunikation (z.B. Push-Benachrichtigungen) zu.",
"success": "Dein Nutzerkonto wurde erstellt!",
"termsAndCondsEtcConfirmed": "Ich habe folgendes gelesen, verstanden und stimme zu:",
"title": "Nutzerkonto anlegen"
@ -1030,6 +1030,8 @@
"unblocked": "{name} ist wieder entsperrt"
},
"data": {
"givenName": "Dein Vorname",
"givenNamePlaceholder": "Petra",
"labelBio": "Über dich",
"labelCity": "Deine Stadt oder Region",
"labelCityHint": "(zeigt ungefähre Position auf der Landkarte)",
@ -1037,7 +1039,10 @@
"labelSlug": "Dein eindeutiger Nutzername",
"name": "Deine Daten",
"namePlaceholder": "Petra Lustig",
"success": "Deine Daten wurden erfolgreich aktualisiert!"
"realNamePlease": "Bitte gib deinen Klarnamen an",
"success": "Deine Daten wurden erfolgreich aktualisiert!",
"surName": "Dein Nachname",
"surNamePlaceholder": "Lustig"
},
"deleteUserAccount": {
"accountDescription": "Sei dir bewusst, dass deine Beiträge und Kommentare für unsere Community wichtig sind. Wenn du sie trotzdem löschen möchtest, musst du sie unten markieren.",

View File

@ -208,7 +208,7 @@
"buttonTitle": "Create",
"error": "No user account could be created!",
"help": " Maybe the confirmation was invalid? In case of problems, feel free to ask for help by sending us a mail to:",
"recieveCommunicationAsEmailsEtcConfirmed": "I also agree to receive e-mails and other forms of communication (e.g. push notifications).",
"receiveCommunicationAsEmailsEtcConfirmed": "I also agree to receive e-mails and other forms of communication (e.g. push notifications).",
"success": "Your account has been created!",
"termsAndCondsEtcConfirmed": "I have read, understand and agree to the following:",
"title": "Create user account"
@ -1030,14 +1030,19 @@
"unblocked": "{name} is unblocked again"
},
"data": {
"givenName": "Your given name",
"givenNamePlaceholder": "Femanon",
"labelBio": "About You",
"labelCity": "Your City or Region",
"labelCityHint": "(shows approximate position on map)",
"labelName": "Your Name",
"labelName": "Your name",
"labelSlug": "Your unique user name",
"name": "Your data",
"namePlaceholder": "Femanon Funny",
"success": "Your data was successfully updated!"
"realNamePlease": "Please enter your real name",
"success": "Your data was successfully updated!",
"surName": "Your surname",
"surNamePlaceholder": "Funny"
},
"deleteUserAccount": {
"accountDescription": "Be aware that your Posts and Comments are important to our community. If you still choose to delete them, you have to mark them below.",

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": "¡No se ha podido crear una cuenta de usuario!",
"help": "¿Tal vez el código de verificación era incorrecto o expiró? Si el problema persiste, por favor envíenos un correo electrónico a:",
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": "¡Su cuenta de usuario ha sido creada!",
"termsAndCondsEtcConfirmed": null,
"title": "Crear una cuenta de usuario"
@ -1030,6 +1030,8 @@
"unblocked": "{name} está desbloqueado nuevamente"
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "Acerca de usted",
"labelCity": "Su ciudad o región",
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": "Su nombre de usuario único",
"name": "Sus datos",
"namePlaceholder": "Femanon Funny",
"success": "¡Sus datos han sido actualizados con éxito!"
"realNamePlease": null,
"success": "¡Sus datos han sido actualizados con éxito!",
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Tenga en cuenta que su contribución y sus comentarios son importantes para nuestra comunidad. Si aún decide borrarlos, debe marcarlos a continuación.",

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": "Compte d'utilisateur n'a pas pu être créé!",
"help": " Peut-être que la confirmation n'était pas valide? En cas de problème, n'hésitez pas à nous demander de l'aide en nous envoyant un mail à:",
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": "Votre compte a été créé!",
"termsAndCondsEtcConfirmed": null,
"title": "Créer un compte utilisateur"
@ -1030,6 +1030,8 @@
"unblocked": "{name} est à nouveau débloqué"
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "À propos de vous",
"labelCity": "Votre ville ou région",
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": "Votre nom d'utilisateur unique",
"name": "Vos données",
"namePlaceholder": "Fémanon Funny",
"success": "Vos données ont été mises à jour avec succès !"
"realNamePlease": null,
"success": "Vos données ont été mises à jour avec succès !",
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Sachez que vos postes et commentaires sont importants pour notre communauté. Si vous voulez quand même les supprimer, vous devez les marquer ci-dessous.",

View File

@ -53,7 +53,7 @@
"invites": "Inviti",
"locations": null,
"name": "Cruscotto",
"organizations": "Organizzazioni",
"notifications": null,
"posts": "Messaggi",
"reports": null,
"shouts": "Gridi",
@ -208,7 +208,7 @@
"buttonTitle": null,
"error": null,
"help": null,
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": null,
"termsAndCondsEtcConfirmed": null,
"title": null
@ -809,6 +809,7 @@
"followed_user_posted": null,
"mentioned_in_comment": null,
"mentioned_in_post": null,
"on_date": null,
"post_in_group": null,
"removed_user_from_group": null,
"user_joined_group": null,
@ -1029,6 +1030,8 @@
"unblocked": null
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "Su di te",
"labelCity": "La tua città o regione",
"labelCityHint": null,
@ -1036,7 +1039,10 @@
"labelSlug": null,
"name": "I tuoi dati",
"namePlaceholder": "Anonymous",
"success": null
"realNamePlease": null,
"success": null,
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Essere consapevoli che i tuoi post e commenti sono importanti per la nostra comunità. Se cancelli il tuo account utente, tutto scomparirà per sempre - e sarebbe un vero peccato!",

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": null,
"help": null,
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": null,
"termsAndCondsEtcConfirmed": null,
"title": null
@ -1030,6 +1030,8 @@
"unblocked": null
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": null,
"labelCity": null,
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": null,
"name": "Uw gegevens",
"namePlaceholder": null,
"success": null
"realNamePlease": null,
"success": null,
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": null,

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": null,
"help": null,
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": null,
"termsAndCondsEtcConfirmed": null,
"title": null
@ -1030,6 +1030,8 @@
"unblocked": null
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "O Tobie",
"labelCity": "Twoje miasto lub region",
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": null,
"name": "Twoje dane",
"namePlaceholder": "Anonymous",
"success": "Twoje dane zostały pomyślnie zaktualizowane!"
"realNamePlease": null,
"success": "Twoje dane zostały pomyślnie zaktualizowane!",
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.",

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": "Nenhuma conta de usuário pode ser criada!",
"help": " Talvez a confirmação tenha sido inválida? Em caso de problemas, sinta-se à vontade para pedir ajuda, enviando um e-mail para:",
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": "A sua conta foi criada!",
"termsAndCondsEtcConfirmed": null,
"title": "Criar uma conta de usuário"
@ -1030,6 +1030,8 @@
"unblocked": "{name} está desbloqueado novamente"
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "Sobre você",
"labelCity": "Sua cidade ou estado",
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": "Seu nome de usuário exclusivo",
"name": "Seus dados",
"namePlaceholder": "Anonymous",
"success": "Seus dados foram atualizados com sucesso!"
"realNamePlease": null,
"success": "Seus dados foram atualizados com sucesso!",
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Esteja ciente de que o suas Publicações e Comentários são importantes para a nossa comunidade. Se você ainda optar por excluí-los, você tem que marcá-los abaixo.",

View File

@ -208,7 +208,7 @@
"buttonTitle": null,
"error": "Не удалось создать учетную запись!",
"help": "Может быть, подтверждение было недействительным? В случае возникновения проблем, не стесняйтесь обращаться за помощью, отправив нам письмо по электронной почте:",
"recieveCommunicationAsEmailsEtcConfirmed": null,
"receiveCommunicationAsEmailsEtcConfirmed": null,
"success": "Учетная запись успешно создана!",
"termsAndCondsEtcConfirmed": null,
"title": "Создать учетную запись"
@ -1030,6 +1030,8 @@
"unblocked": "{name} - снова разблокирован"
},
"data": {
"givenName": null,
"givenNamePlaceholder": null,
"labelBio": "О себе",
"labelCity": "Город или регион",
"labelCityHint": null,
@ -1037,7 +1039,10 @@
"labelSlug": "Уникальное имя пользователя",
"name": "Персональные данные",
"namePlaceholder": "Маша Медведева",
"success": "Персональные данные были успешно обновлены!"
"realNamePlease": null,
"success": "Персональные данные были успешно обновлены!",
"surName": null,
"surNamePlaceholder": null
},
"deleteUserAccount": {
"accountDescription": "Обратите внимание, что ваши посты и комментарии важны для сообщества. Если вы все равно хотите их удалить, то вы должны отметить соответствующие опции ниже.",

View File

@ -67,6 +67,9 @@ describe('index.vue', () => {
error: jest.fn(),
success: jest.fn(),
},
$env: {
ASK_FOR_REAL_NAME: false,
},
}
getters = {
'auth/user': () => ({}),

View File

@ -7,7 +7,11 @@
id="name"
model="name"
icon="user"
:label="$t('settings.data.labelName')"
:label="
$env.ASK_FOR_REAL_NAME
? $t('settings.data.realNamePlease')
: $t('settings.data.labelName')
"
:placeholder="$t('settings.data.namePlaceholder')"
/>
<ds-input id="slug" model="slug" icon="at" :label="$t('settings.data.labelSlug')" />