]> source.dussan.org Git - gitea.git/commitdiff
Add appearance section in settings (#17433)
authorqwerty287 <80460567+qwerty287@users.noreply.github.com>
Wed, 27 Oct 2021 15:40:08 +0000 (17:40 +0200)
committerGitHub <noreply@github.com>
Wed, 27 Oct 2021 15:40:08 +0000 (23:40 +0800)
* Add appearance section in settings

* Fix lint

* Fix lint

* Apply suggestions from code review

Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: Lauris BH <lauris@nix.lv>
options/locale/locale_en-US.ini
routers/web/user/setting/account.go
routers/web/user/setting/profile.go
routers/web/web.go
services/forms/user_form.go
templates/user/settings/account.tmpl
templates/user/settings/appearance.tmpl [new file with mode: 0644]
templates/user/settings/navbar.tmpl
templates/user/settings/profile.tmpl

index 31d5bf08c63463b70ece133c1f1190345adf8cae..309ff99c431e0da9be4e962c061bf7a4e02203a1 100644 (file)
@@ -490,6 +490,7 @@ form.name_chars_not_allowed = User name '%s' contains invalid characters.
 [settings]
 profile = Profile
 account = Account
+appearance = Appearance
 password = Password
 security = Security
 avatar = Avatar
@@ -514,7 +515,9 @@ website = Website
 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.
index 249793578a1a9ed61f9cb9b6c700b3a3090e52bd..47014dc8143b221bb14cbec4df35787fe1cd6126 100644 (file)
@@ -257,34 +257,6 @@ func DeleteAccount(ctx *context.Context) {
        }
 }
 
-// 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 {
index d75149b8fc717f2a85ea9b1a30dc1b1634b60289..d181ae1720db870199377822dd4d0a62886fd690 100644 (file)
@@ -32,6 +32,7 @@ import (
 
 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"
 )
@@ -115,14 +116,6 @@ func ProfilePost(ctx *context.Context) {
        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
@@ -329,3 +322,68 @@ func Repos(ctx *context.Context) {
        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")
+
+}
index 88565d6d855636942fc1a69c421939de3341fe16..c0bb74da2e3ffe2ac1c7564079a7da435f2d8ce0 100644 (file)
@@ -317,6 +317,10 @@ func RegisterRoutes(m *web.Route) {
                        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() {
index 241ebdc0d9394f69e0973ada41e1b172a65b0ae4..9f86bf61661f662163101e3a6c4fe756d86a92f0 100644 (file)
@@ -240,7 +240,6 @@ type UpdateProfileForm struct {
        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
@@ -252,6 +251,17 @@ func (f *UpdateProfileForm) Validate(req *http.Request, errs binding.Errors) bin
        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"
index 9ed5d3a6dd1adb463178c94224f3a78aa1e57504..3753a77cecb70641c92b48a8f90c1a6f1f21d716 100644 (file)
                        </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>
diff --git a/templates/user/settings/appearance.tmpl b/templates/user/settings/appearance.tmpl
new file mode 100644 (file)
index 0000000..777b89c
--- /dev/null
@@ -0,0 +1,74 @@
+{{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" .}}
index 7255819374e7cd1f9dd721ec75016cef99e083b3..3477a5949b8497f0bc58c55a4a1b58b668145db2 100644 (file)
@@ -6,6 +6,9 @@
                <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>
index 1f1585a78773b85f6a6d4ff94e4193c7e64310d2..0b14e3c0d307fc930e8e662ce4b874f9e5975418 100644 (file)
                                        <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 -->