[settings]
profile = Profile
account = Account
+appearance = Appearance
password = Password
security = Security
avatar = Avatar
location = Location
update_theme = Update Theme
update_profile = Update Profile
+update_language = Update Language
update_language_not_found = Language '%s' is not available.
+update_language_success = Language has been updated.
update_profile_success = Your profile has been updated.
change_username = Your username has been changed.
change_username_prompt = Note: username changes also change your account URL.
}
}
-// UpdateUIThemePost is used to update users' specific theme
-func UpdateUIThemePost(ctx *context.Context) {
- form := web.GetForm(ctx).(*forms.UpdateThemeForm)
- ctx.Data["Title"] = ctx.Tr("settings")
- ctx.Data["PageIsSettingsAccount"] = true
-
- if ctx.HasError() {
- ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- return
- }
-
- if !form.IsThemeExists() {
- ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
- ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- return
- }
-
- if err := ctx.User.UpdateTheme(form.Theme); err != nil {
- ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
- ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- return
- }
-
- log.Trace("Update user theme: %s", ctx.User.Name)
- ctx.Flash.Success(ctx.Tr("settings.theme_update_success"))
- ctx.Redirect(setting.AppSubURL + "/user/settings/account")
-}
-
func loadAccountData(ctx *context.Context) {
emlist, err := models.GetEmailAddresses(ctx.User.ID)
if err != nil {
const (
tplSettingsProfile base.TplName = "user/settings/profile"
+ tplSettingsAppearance base.TplName = "user/settings/appearance"
tplSettingsOrganization base.TplName = "user/settings/organization"
tplSettingsRepositories base.TplName = "user/settings/repos"
)
ctx.User.KeepEmailPrivate = form.KeepEmailPrivate
ctx.User.Website = form.Website
ctx.User.Location = form.Location
- if len(form.Language) != 0 {
- if !util.IsStringInSlice(form.Language, setting.Langs) {
- ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language))
- ctx.Redirect(setting.AppSubURL + "/user/settings")
- return
- }
- ctx.User.Language = form.Language
- }
ctx.User.Description = form.Description
ctx.User.KeepActivityPrivate = form.KeepActivityPrivate
ctx.User.Visibility = form.Visibility
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, tplSettingsRepositories)
}
+
+// Appearance render user's appearance settings
+func Appearance(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("settings")
+ ctx.Data["PageIsSettingsAppearance"] = true
+
+ ctx.HTML(http.StatusOK, tplSettingsAppearance)
+}
+
+// UpdateUIThemePost is used to update users' specific theme
+func UpdateUIThemePost(ctx *context.Context) {
+ form := web.GetForm(ctx).(*forms.UpdateThemeForm)
+ ctx.Data["Title"] = ctx.Tr("settings")
+ ctx.Data["PageIsSettingsAppearance"] = true
+
+ if ctx.HasError() {
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+ return
+ }
+
+ if !form.IsThemeExists() {
+ ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+ return
+ }
+
+ if err := ctx.User.UpdateTheme(form.Theme); err != nil {
+ ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+ return
+ }
+
+ log.Trace("Update user theme: %s", ctx.User.Name)
+ ctx.Flash.Success(ctx.Tr("settings.theme_update_success"))
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+}
+
+// UpdateUserLang update a user's language
+func UpdateUserLang(ctx *context.Context) {
+ form := web.GetForm(ctx).(*forms.UpdateLanguageForm)
+ ctx.Data["Title"] = ctx.Tr("settings")
+ ctx.Data["PageIsSettingsAppearance"] = true
+
+ if len(form.Language) != 0 {
+ if !util.IsStringInSlice(form.Language, setting.Langs) {
+ ctx.Flash.Error(ctx.Tr("settings.update_language_not_found", form.Language))
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+ return
+ }
+ ctx.User.Language = form.Language
+ }
+
+ if err := models.UpdateUserSetting(ctx.User); err != nil {
+ ctx.ServerError("UpdateUserSetting", err)
+ return
+ }
+
+ // Update the language to the one we just set
+ middleware.SetLocaleCookie(ctx.Resp, ctx.User.Language, 0)
+
+ log.Trace("User settings updated: %s", ctx.User.Name)
+ ctx.Flash.Success(i18n.Tr(ctx.User.Language, "settings.update_language_success"))
+ ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
+
+}
m.Post("/email", bindIgnErr(forms.AddEmailForm{}), userSetting.EmailPost)
m.Post("/email/delete", userSetting.DeleteEmail)
m.Post("/delete", userSetting.DeleteAccount)
+ })
+ m.Group("/appearance", func() {
+ m.Get("", userSetting.Appearance)
+ m.Post("/language", bindIgnErr(forms.UpdateLanguageForm{}), userSetting.UpdateUserLang)
m.Post("/theme", bindIgnErr(forms.UpdateThemeForm{}), userSetting.UpdateUIThemePost)
})
m.Group("/security", func() {
KeepEmailPrivate bool
Website string `binding:"ValidSiteUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
- Language string
Description string `binding:"MaxSize(255)"`
Visibility structs.VisibleType
KeepActivityPrivate bool
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}
+// UpdateLanguageForm form for updating profile
+type UpdateLanguageForm struct {
+ Language string
+}
+
+// Validate validates the fields
+func (f *UpdateLanguageForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
+ ctx := context.GetContext(req)
+ return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
+}
+
// Avatar types
const (
AvatarLocal string = "local"
</form>
</div>
- <h4 class="ui top attached header">
- {{.i18n.Tr "settings.manage_themes"}}
- </h4>
- <div class="ui attached segment">
- <div class="ui email list">
- <div class="item">
- {{.i18n.Tr "settings.theme_desc"}}
- </div>
-
- <form class="ui form" action="{{.Link}}/theme" method="post">
- {{.CsrfTokenHtml}}
- <div class="field">
- <label for="ui">{{.i18n.Tr "settings.ui"}}</label>
- <div class="ui selection dropdown" id="ui">
- <input name="theme" type="hidden" value="{{.SignedUser.Theme}}">
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="text">
- {{range $i,$a := .AllThemes}}
- {{if eq $.SignedUser.Theme $a}}{{$a}}{{end}}
- {{end}}
- </div>
-
- <div class="menu">
- {{range $i,$a := .AllThemes}}
- <div class="item{{if eq $.SignedUser.Theme $a}} active selected{{end}}" data-value="{{$a}}">
- {{$a}}
- </div>
- {{end}}
- </div>
- </div>
- </div>
-
- <div class="field">
- <button class="ui green button">{{$.i18n.Tr "settings.update_theme"}}</button>
- </div>
- </form>
- </div>
- </div>
<h4 class="ui top attached error header">
{{.i18n.Tr "settings.delete_account"}}
</h4>
--- /dev/null
+{{template "base/head" .}}
+<div class="page-content user settings sshkeys">
+ {{template "user/settings/navbar" .}}
+ <div class="ui container">
+ {{template "base/alert" .}}
+
+ <!-- Theme -->
+ <h4 class="ui top attached header">
+ {{.i18n.Tr "settings.manage_themes"}}
+ </h4>
+ <div class="ui attached segment">
+ <div class="ui email list">
+ <div class="item">
+ {{.i18n.Tr "settings.theme_desc"}}
+ </div>
+
+ <form class="ui form" action="{{.Link}}/theme" method="post">
+ {{.CsrfTokenHtml}}
+ <div class="field">
+ <label for="ui">{{.i18n.Tr "settings.ui"}}</label>
+ <div class="ui selection dropdown" id="ui">
+ <input name="theme" type="hidden" value="{{.SignedUser.Theme}}">
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="text">
+ {{range $i,$a := .AllThemes}}
+ {{if eq $.SignedUser.Theme $a}}{{$a}}{{end}}
+ {{end}}
+ </div>
+
+ <div class="menu">
+ {{range $i,$a := .AllThemes}}
+ <div class="item{{if eq $.SignedUser.Theme $a}} active selected{{end}}" data-value="{{$a}}">
+ {{$a}}
+ </div>
+ {{end}}
+ </div>
+ </div>
+ </div>
+
+ <div class="field">
+ <button class="ui green button">{{$.i18n.Tr "settings.update_theme"}}</button>
+ </div>
+ </form>
+ </div>
+ </div>
+
+ <!-- Language -->
+ <h4 class="ui top attached header">
+ {{.i18n.Tr "settings.language"}}
+ </h4>
+ <div class="ui attached segment">
+ <form class="ui form" action="{{.Link}}/language" method="post">
+ {{.CsrfTokenHtml}}
+ <div class="field">
+ <div class="ui language selection dropdown" id="language">
+ <input name="language" type="hidden" value="{{.SignedUser.Language}}">
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="text">{{range .AllLangs}}{{if eq $.SignedUser.Language .Lang}}{{.Name}}{{end}}{{end}}</div>
+ <div class="menu">
+ {{range .AllLangs}}
+ <div class="item{{if eq $.SignedUser.Language .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div>
+ {{end}}
+ </div>
+ </div>
+ </div>
+ <div class="field">
+ <button class="ui green button">{{$.i18n.Tr "settings.update_language"}}</button>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
+
+{{template "base/footer" .}}
<a class="{{if .PageIsSettingsAccount}}active{{end}} item" href="{{AppSubUrl}}/user/settings/account">
{{.i18n.Tr "settings.account"}}
</a>
+ <a class="{{if .PageIsSettingsAppearance}}active{{end}} item" href="{{AppSubUrl}}/user/settings/appearance">
+ {{.i18n.Tr "settings.appearance"}}
+ </a>
<a class="{{if .PageIsSettingsSecurity}}active{{end}} item" href="{{AppSubUrl}}/user/settings/security">
{{.i18n.Tr "settings.security"}}
</a>
<input id="location" name="location" value="{{.SignedUser.Location}}">
</div>
- <div class="field">
- <label for="language">{{.i18n.Tr "settings.language"}}</label>
- <div class="ui language selection dropdown" id="language">
- <input name="language" type="hidden" value="{{.SignedUser.Language}}">
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="text">{{range .AllLangs}}{{if eq $.SignedUser.Language .Lang}}{{.Name}}{{end}}{{end}}</div>
- <div class="menu">
- {{range .AllLangs}}
- <div class="item{{if eq $.SignedUser.Language .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div>
- {{end}}
- </div>
- </div>
- </div>
-
<div class="ui divider"></div>
<!-- private block -->