forgejo/templates/user/settings/profile.tmpl
mhughes9 2024031a7a Simplify pronouns in user settings (#6835)
The main change here is to use `datalist` for pronouns This supports
(see also docs[1]):

* Displaying the value already set by the user (if any), otherwise
* Presenting a list of common options to the user, and
* Allowing them to freely enter any value

This setup requires no additional JS and resolves[2].

This is different from the previous flow which used, if JS was available:

* A menu for a default 'recognised' set of pronouns, and if the user
  wanted another value:
* An extra text div if the user wanted to enter custom pronouns

Without JS enabled both the menu and the custom text div would always be
displayed.

This change means there's no longer a distinction between 'custom' and
'recognised' pronouns (this difference looks to have only been made in
code, and not in any data models).

Link: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist [1]
Link: https://codeberg.org/forgejo/forgejo/issues/6774 [2]

Co-authored-by: Matthew Hughes <matthewhughes934@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6835
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: mhughes9 <mhughes9@noreply.codeberg.org>
Co-committed-by: mhughes9 <mhughes9@noreply.codeberg.org>
2025-02-26 18:46:51 +00:00

149 lines
7 KiB
Go HTML Template

{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings profile")}}
<div class="user-setting-content">
<h4 class="ui top attached header">
{{ctx.Locale.Tr "settings.public_profile"}}
</h4>
<div class="ui attached segment">
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<fieldset>
<legend>{{ctx.Locale.Tr "settings.profile_desc"}}</legend>
<label {{if .Err_Name}}class="field error"{{end}}>
{{ctx.Locale.Tr "username"}}
<input name="name" value="{{.SignedUser.Name}}" data-name="{{.SignedUser.Name}}" autofocus required {{if or (not .SignedUser.IsLocal) .IsReverseProxy}}disabled{{end}} maxlength="40">
{{if or (not .SignedUser.IsLocal) .IsReverseProxy}}
<span class="help">{{ctx.Locale.Tr "settings.password_username_disabled"}}</span>
{{else}}
<span class="help">
{{ctx.Locale.Tr "settings.change_username_prompt"}}
{{if gt .CooldownPeriod 0}}
{{ctx.Locale.TrN .CooldownPeriod "settings.change_username_redirect_prompt.with_cooldown.one" "settings.change_username_redirect_prompt.with_cooldown.few" .CooldownPeriod}}</span>
{{else}}
{{ctx.Locale.Tr "settings.change_username_redirect_prompt"}}
{{end}}
</span>
{{end}}
</label>
<label {{if .Err_FullName}}class="field error"{{end}}>
{{ctx.Locale.Tr "settings.full_name"}}
<input name="full_name" value="{{.SignedUser.FullName}}" maxlength="100">
</label>
<label id="label-pronouns">
{{ctx.Locale.Tr "settings.pronouns"}}
<input name="pronouns" list="pronouns" placeholder="{{ctx.Locale.Tr "settings.pronouns_unspecified"}}" value="{{.SignedUser.Pronouns}}" maxlength="50">
<datalist id="pronouns">
{{range .CommonPronouns}}
<option value="{{.}}"></option>
{{end}}
</datalist>
</label>
<label {{if .Err_Biography}}class="field error"{{end}}>
{{ctx.Locale.Tr "user.user_bio"}}
<textarea name="biography" rows="2" placeholder="{{ctx.Locale.Tr "settings.biography_placeholder"}}" maxlength="255">{{.SignedUser.Description}}</textarea>
</label>
<label {{if .Err_Website}}class="field error"{{end}}>
{{ctx.Locale.Tr "settings.website"}}
<input name="website" type="url" value="{{.SignedUser.Website}}" maxlength="255">
</label>
<label>
{{ctx.Locale.Tr "settings.location"}}
<input name="location" placeholder="{{ctx.Locale.Tr "settings.location_placeholder"}}" value="{{.SignedUser.Location}}" maxlength="50">
</label>
</fieldset>
<fieldset>
<legend id="privacy-user-settings">{{ctx.Locale.Tr "settings.privacy"}}</legend>
<label id="visibility-setting" {{if .Err_Visibility}}class="field error"{{end}}>
{{ctx.Locale.Tr "settings.visibility"}}
<div class="ui selection type dropdown" aria-labelledby="visibility-setting">
{{if .SignedUser.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
{{if .SignedUser.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
{{if .SignedUser.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}}
<div class="text">
{{if .SignedUser.Visibility.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}}
{{if .SignedUser.Visibility.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}}
{{if .SignedUser.Visibility.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}}
</div>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
{{range $mode := .AllowedUserVisibilityModes}}
{{if $mode.IsPublic}}
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{ctx.Locale.Tr "settings.visibility.public"}}</div>
{{else if $mode.IsLimited}}
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{ctx.Locale.Tr "settings.visibility.limited"}}</div>
{{else if $mode.IsPrivate}}
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{ctx.Locale.Tr "settings.visibility.private"}}</div>
{{end}}
{{end}}
</div>
</div>
</label>
<label>
<input name="keep_email_private" type="checkbox" {{if .SignedUser.KeepEmailPrivate}}checked{{end}}>
{{ctx.Locale.Tr "settings.keep_email_private"}}
<span class="help">{{ctx.Locale.Tr "settings.keep_email_private_popup" .SignedUser.GetPlaceholderEmail}}</span>
</label>
<label id="keep-activity-private">
<input name="keep_activity_private" type="checkbox" {{if .SignedUser.KeepActivityPrivate}}checked{{end}}>
{{ctx.Locale.Tr "settings.keep_activity_private"}}
<span class="help">{{ctx.Locale.Tr "settings.keep_activity_private.description" (printf "/%s?tab=activity" .SignedUser.Name)}}</span>
</label>
<label>
<input name="keep_pronouns_private" type="checkbox" {{if .SignedUser.KeepPronounsPrivate}}checked{{end}}>
{{ctx.Locale.Tr "settings.keep_pronouns_private"}}
<span class="help">{{ctx.Locale.Tr "settings.keep_pronouns_private.description"}}</span>
</label>
</fieldset>
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_profile"}}</button>
</form>
</div>
<h4 class="ui top attached header">
{{ctx.Locale.Tr "settings.avatar"}}
</h4>
<div class="ui attached segment">
<form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data">
{{.CsrfTokenHtml}}
{{if not .DisableGravatar}}
<div class="inline field">
<div class="ui radio checkbox">
<input name="source" value="lookup" type="radio" {{if not .SignedUser.UseCustomAvatar}}checked{{end}}>
<label>{{ctx.Locale.Tr "settings.lookup_avatar_by_mail"}}</label>
</div>
</div>
<div class="field tw-pl-4 {{if .Err_Gravatar}}error{{end}}">
<label for="gravatar">Avatar {{ctx.Locale.Tr "email"}}</label>
<input id="gravatar" name="gravatar" value="{{.SignedUser.AvatarEmail}}">
</div>
{{end}}
<div class="inline field">
<div class="ui radio checkbox">
<input name="source" value="local" type="radio" {{if .SignedUser.UseCustomAvatar}}checked{{end}}>
<label>{{ctx.Locale.Tr "settings.enable_custom_avatar"}}</label>
</div>
</div>
<div class="inline field tw-pl-4">
<label for="new-avatar">{{ctx.Locale.Tr "settings.choose_new_avatar"}}</label>
<input id="new-avatar" name="avatar" type="file" accept="image/png,image/jpeg,image/gif,image/webp">
</div>
<div class="field">
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_avatar"}}</button>
<button class="ui red button link-action" data-url="{{.Link}}/avatar/delete">{{ctx.Locale.Tr "settings.delete_current_avatar"}}</button>
</div>
</form>
</div>
</div>
{{template "user/settings/layout_footer" .}}