new user profile settings UI
Signed-off-by: Unknwon <u@gogs.io>
This commit is contained in:
		
							parent
							
								
									00767a0522
								
							
						
					
					
						commit
						85f34ba538
					
				| @ -13,7 +13,7 @@ watch_dirs = [ | ||||
| watch_exts = [".go"] | ||||
| build_delay = 1500 | ||||
| cmds = [ | ||||
| 	["go", "install", "-tags", "sqlite"],# redis memcache cert pam | ||||
| 	["go", "install", "-tags", "sqlite"],# redis memcache cert pam tidb | ||||
| 	["go", "build", "-tags", "sqlite"], | ||||
| 	["./gogs", "web"] | ||||
| ] | ||||
| @ -241,7 +241,7 @@ location = Location | ||||
| update_profile = Update Profile | ||||
| update_profile_success = Your profile has been updated successfully. | ||||
| change_username = Username Changed | ||||
| change_username_desc = You changed your username. This will affect the way how links relate to your account. Do you want to continue? | ||||
| change_username_prompt = This change will affect the way how links relate to your account. | ||||
| continue = Continue | ||||
| cancel = Cancel | ||||
| 
 | ||||
|  | ||||
| @ -72,6 +72,7 @@ var ( | ||||
| 	} | ||||
| 
 | ||||
| 	EnableSQLite3 bool | ||||
| 	EnableTidb    bool | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| @ -143,6 +144,14 @@ func getEngine() (*xorm.Engine, error) { | ||||
| 			return nil, fmt.Errorf("Fail to create directories: %v", err) | ||||
| 		} | ||||
| 		cnnstr = "file:" + DbCfg.Path + "?cache=shared&mode=rwc" | ||||
| 	case "tidb": | ||||
| 		if !EnableTidb { | ||||
| 			return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) | ||||
| 		} | ||||
| 		if err := os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm); err != nil { | ||||
| 			return nil, fmt.Errorf("Fail to create directories: %v", err) | ||||
| 		} | ||||
| 		cnnstr = "goleveldb://" + DbCfg.Path | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										16
									
								
								models/models_tidb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								models/models_tidb.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| // +build tidb
 | ||||
| 
 | ||||
| // Copyright 2015 The Gogs Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a MIT-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package models | ||||
| 
 | ||||
| import ( | ||||
| 	_ "github.com/go-xorm/tidb" | ||||
| 	_ "github.com/pingcap/tidb" | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	EnableTidb = true | ||||
| } | ||||
| @ -88,12 +88,12 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding | ||||
| //         \/         \/                                   \/        \/        \/
 | ||||
| 
 | ||||
| type UpdateProfileForm struct { | ||||
| 	UserName string `form:"uname" binding:"Required;MaxSize(35)"` | ||||
| 	FullName string `form:"fullname" binding:"MaxSize(100)"` | ||||
| 	Email    string `form:"email" binding:"Required;Email;MaxSize(254)"` | ||||
| 	Website  string `form:"website" binding:"Url;MaxSize(100)"` | ||||
| 	Location string `form:"location" binding:"MaxSize(50)"` | ||||
| 	Avatar   string `form:"avatar" binding:"Required;Email;MaxSize(254)"` | ||||
| 	Name     string `binding:"Required;MaxSize(35)"` | ||||
| 	FullName string `binding:"MaxSize(100)"` | ||||
| 	Email    string `binding:"Required;Email;MaxSize(254)"` | ||||
| 	Website  string `binding:"Url;MaxSize(100)"` | ||||
| 	Location string `binding:"MaxSize(50)"` | ||||
| 	Gravatar string `binding:"Required;Email;MaxSize(254)"` | ||||
| } | ||||
| 
 | ||||
| func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | ||||
| @ -101,8 +101,8 @@ func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) | ||||
| } | ||||
| 
 | ||||
| type UploadAvatarForm struct { | ||||
| 	Enable bool                  `form:"enable"` | ||||
| 	Avatar *multipart.FileHeader `form:"avatar"` | ||||
| 	Enable bool | ||||
| 	Avatar *multipart.FileHeader | ||||
| } | ||||
| 
 | ||||
| func (f *UploadAvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | ||||
|  | ||||
| @ -76,7 +76,6 @@ func ToUtf8WithErr(content []byte) (error, string) { | ||||
| 	} | ||||
| 
 | ||||
| 	encoding, _ := charset.Lookup(charsetLabel) | ||||
| 
 | ||||
| 	if encoding == nil { | ||||
| 		return fmt.Errorf("unknow char decoder %s", charsetLabel), string(content) | ||||
| 	} | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								public/css/gogs.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/css/gogs.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -148,7 +148,7 @@ function initInstall() { | ||||
|     // Database type change detection.
 | ||||
|     $("#db_type").change(function () { | ||||
|         var db_type = $('#db_type').val(); | ||||
|         if (db_type === "SQLite3") { | ||||
|         if (db_type === "SQLite3" || db_type === "TiDB") { | ||||
|             $('#sql_settings').hide(); | ||||
|             $('#pgsql_settings').hide(); | ||||
|             $('#sqlite_settings').show(); | ||||
| @ -389,7 +389,7 @@ function initRepository() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function initOrganization(){ | ||||
| function initOrganization() { | ||||
|     if ($('.organization').length == 0) { | ||||
|         return; | ||||
|     } | ||||
| @ -405,8 +405,24 @@ function initOrganization(){ | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function initUser() { | ||||
|     if ($('.user').length == 0) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Options
 | ||||
|     if ($('.user.settings.profile').length > 0) { | ||||
|         $('#username').keyup(function () { | ||||
|             var $prompt_span = $('#name-change-prompt'); | ||||
|             if ($(this).val().toString().toLowerCase() != $(this).data('name').toString().toLowerCase()) { | ||||
|                 $prompt_span.show(); | ||||
|             } else { | ||||
|                 $prompt_span.hide(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function initWebhook() { | ||||
| @ -545,5 +561,6 @@ $(document).ready(function () { | ||||
|     initInstall(); | ||||
|     initRepository(); | ||||
|     initOrganization(); | ||||
|     initUser(); | ||||
|     initWebhook(); | ||||
| }); | ||||
| @ -80,10 +80,6 @@ | ||||
| 	} | ||||
| 	 | ||||
| 	&.options { | ||||
| 		input { | ||||
| 			width: 50%!important; | ||||
| 			min-width: 300px; | ||||
| 		} | ||||
| 		#interval { | ||||
| 			width: 100px!important; | ||||
| 			min-width: 100px; | ||||
|  | ||||
| @ -85,7 +85,14 @@ func InstallInit(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("install.install") | ||||
| 	ctx.Data["PageIsInstall"] = true | ||||
| 
 | ||||
| 	ctx.Data["DbOptions"] = []string{"MySQL", "PostgreSQL", "SQLite3"} | ||||
| 	dbOpts := []string{"MySQL", "PostgreSQL"} | ||||
| 	if models.EnableSQLite3 { | ||||
| 		dbOpts = append(dbOpts, "SQLite3") | ||||
| 	} | ||||
| 	if models.EnableTidb { | ||||
| 		dbOpts = append(dbOpts, "TiDB") | ||||
| 	} | ||||
| 	ctx.Data["DbOptions"] = dbOpts | ||||
| } | ||||
| 
 | ||||
| func Install(ctx *middleware.Context) { | ||||
| @ -163,7 +170,7 @@ func InstallPost(ctx *middleware.Context, form auth.InstallForm) { | ||||
| 
 | ||||
| 	// Pass basic check, now test configuration.
 | ||||
| 	// Test database setting.
 | ||||
| 	dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3"} | ||||
| 	dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3", "TiDB": "tidb"} | ||||
| 	models.DbCfg.Type = dbTypes[form.DbType] | ||||
| 	models.DbCfg.Host = form.DbHost | ||||
| 	models.DbCfg.User = form.DbUser | ||||
|  | ||||
| @ -47,11 +47,11 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | ||||
| 	} | ||||
| 
 | ||||
| 	// Check if user name has been changed.
 | ||||
| 	if ctx.User.Name != form.UserName { | ||||
| 		if err := models.ChangeUserName(ctx.User, form.UserName); err != nil { | ||||
| 	if ctx.User.Name != form.Name { | ||||
| 		if err := models.ChangeUserName(ctx.User, form.Name); err != nil { | ||||
| 			switch { | ||||
| 			case models.IsErrUserAlreadyExist(err): | ||||
| 				ctx.Flash.Error(ctx.Tr("form.username_been_taken")) | ||||
| 				ctx.Flash.Error(ctx.Tr("form.name_been_taken")) | ||||
| 				ctx.Redirect(setting.AppSubUrl + "/user/settings") | ||||
| 			case models.IsErrEmailAlreadyUsed(err): | ||||
| 				ctx.Flash.Error(ctx.Tr("form.email_been_used")) | ||||
| @ -67,16 +67,16 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		log.Trace("User name changed: %s -> %s", ctx.User.Name, form.UserName) | ||||
| 		ctx.User.Name = form.UserName | ||||
| 		log.Trace("User name changed: %s -> %s", ctx.User.Name, form.Name) | ||||
| 		ctx.User.Name = form.Name | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.User.FullName = form.FullName | ||||
| 	ctx.User.Email = form.Email | ||||
| 	ctx.User.Website = form.Website | ||||
| 	ctx.User.Location = form.Location | ||||
| 	ctx.User.Avatar = base.EncodeMd5(form.Avatar) | ||||
| 	ctx.User.AvatarEmail = form.Avatar | ||||
| 	ctx.User.Avatar = base.EncodeMd5(form.Gravatar) | ||||
| 	ctx.User.AvatarEmail = form.Gravatar | ||||
| 	if err := models.UpdateUser(ctx.User); err != nil { | ||||
| 		ctx.Handle(500, "UpdateUser", err) | ||||
| 		return | ||||
|  | ||||
| @ -26,7 +26,7 @@ | ||||
| 			      </div> | ||||
| 	  	    </div> | ||||
| 
 | ||||
|           <div id="sql_settings" class="{{if eq .CurDbOption "SQLite3"}}hide{{end}}"> | ||||
|           <div id="sql_settings" class="{{if or (eq .CurDbOption "SQLite3") (eq .CurDbOption "TiDB")}}hide{{end}}"> | ||||
|             <div class="inline required field {{if .Err_DbSetting}}error{{end}}"> | ||||
|               <label for="db_host">{{.i18n.Tr "install.host"}}</label> | ||||
|               <input id="db_host" name="db_host" value="{{.db_host}}"> | ||||
| @ -62,7 +62,7 @@ | ||||
|             </div> | ||||
|           </div> | ||||
| 
 | ||||
|           <div id="sqlite_settings" class="{{if not (eq .CurDbOption "SQLite3")}}hide{{end}}"> | ||||
|           <div id="sqlite_settings" class="{{if not (or (eq .CurDbOption "SQLite3") (eq .CurDbOption "TiDB"))}}hide{{end}}"> | ||||
|             <div class="inline required field {{if or .Err_DbPath .Err_DbSetting}}error{{end}}"> | ||||
|               <label for="db_path">{{.i18n.Tr "install.path"}}</label> | ||||
|               <input id="db_path" name="db_path" value="{{.db_path}}"> | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
|         <div class="ui attached segment"> | ||||
|           <form class="ui form" action="{{.Link}}" method="post"> | ||||
|             {{.CsrfTokenHtml}} | ||||
|             <div class="required field {{if .Err_OrgName}}error{{end}}"> | ||||
|             <div class="required field {{if .Err_Name}}error{{end}}"> | ||||
|               <label for="org_name">{{.i18n.Tr "org.org_name_holder"}}<span class="text red hide" id="org-name-change-prompt"> {{.i18n.Tr "org.settings.change_orgname_prompt"}}</span></label> | ||||
|               <input id="org_name" name="name" value="{{.Org.Name}}" data-org-name="{{.Org.Name}}" autofocus required> | ||||
|             </div> | ||||
|  | ||||
| @ -1,82 +1,74 @@ | ||||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="setting-wrapper" class="main-wrapper"> | ||||
|     <div id="user-profile-setting" class="container clear"> | ||||
|         {{template "user/settings/nav" .}} | ||||
|         <div class="grid-4-5 left"> | ||||
|             <div class="setting-content"> | ||||
|                 {{template "ng/base/alert" .}} | ||||
|                 <div id="setting-content"> | ||||
|                     <div id="user-profile-setting-content" class="panel panel-radius"> | ||||
|                         <div class="panel-header"> | ||||
|                             <strong>{{.i18n.Tr "settings.public_profile"}}</strong> | ||||
|                         </div> | ||||
|                         <div class="panel-body"> | ||||
|                             <form class="form form-align" id="user-profile-form" action="{{AppSubUrl}}/user/settings" method="post"> | ||||
|                                 {{.CsrfTokenHtml}} | ||||
|                                 <div class="text-center panel-desc">{{.i18n.Tr "settings.profile_desc"}}</div> | ||||
|                                 <div class="field"> | ||||
|                                     <label>{{.i18n.Tr "settings.uid"}}</label> | ||||
|                                     <label class="text-left">{{.SignedUser.Id}}</label> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label class="req" for="username">{{.i18n.Tr "username"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="username" name="uname" type="text" value="{{.SignedUser.Name}}" data-uname="{{.SignedUser.Name}}" required /> | ||||
|                                 </div> | ||||
|                                 <div class="white-popup-block mfp-hide" id="change-username-modal"> | ||||
|                                     <h1 class="text-red">{{.i18n.Tr "settings.change_username"}}</h1> | ||||
|                                     <p>{{.i18n.Tr "settings.change_username_desc"}}</p> | ||||
|                                     <br> | ||||
|                                     <button class="btn btn-red btn-large btn-radius" id="change-username-submit">{{.i18n.Tr "settings.continue"}}</button> | ||||
|                                     <button class="btn btn-large btn-radius popup-modal-dismiss">{{.i18n.Tr "settings.cancel"}}</button> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label for="full-name">{{.i18n.Tr "settings.full_name"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_FullName}}ipt-error{{end}}" id="full-name" name="fullname" type="text" value="{{.SignedUser.FullName}}" /> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label class="req" for="email">{{.i18n.Tr "email"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_Email}}ipt-error{{end}}" id="email" name="email" type="email" value="{{.SignedUser.Email}}" required /> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label for="website">{{.i18n.Tr "settings.website"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_Website}}ipt-error{{end}}" id="website" name="website" type="url" value="{{.SignedUser.Website}}" /> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label for="location">{{.i18n.Tr "settings.location"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_Location}}ipt-error{{end}}" id="location" name="location" type="text" value="{{.SignedUser.Location}}" /> | ||||
|                                 </div> | ||||
|                                 <div class="field {{if DisableGravatar}}hide{{end}}"> | ||||
|                                     <label class="req" for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label> | ||||
|                                     <input class="ipt ipt-large ipt-radius {{if .Err_Avatar}}ipt-error{{end}}" id="gravatar-email" name="avatar" type="text" value="{{.SignedUser.AvatarEmail}}" /> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label></label> | ||||
|                                     <button class="btn btn-green btn-large btn-radius" id="change-username-btn" href="#change-username-modal">{{.i18n.Tr "settings.update_profile"}}</button> | ||||
|                                 </div> | ||||
|                             </form> | ||||
|                             <hr> | ||||
|                             <form class="form form-align" id="user-profile-form" action="{{AppSubUrl}}/user/settings/avatar" method="post" enctype="multipart/form-data"> | ||||
|                                 {{.CsrfTokenHtml}} | ||||
|                                 <div class="field"> | ||||
|                                     <label for="enable">{{.i18n.Tr "settings.enable_custom_avatar"}}</label> | ||||
|                                     <input class="ipt-chk" id="enable" name="enable" type="checkbox" {{if .SignedUser.UseCustomAvatar}}checked{{end}} /> | ||||
|                                     <span>{{.i18n.Tr "settings.enable_custom_avatar_helper"}}</span> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label>{{.i18n.Tr "settings.choose_new_avatar"}}</label> | ||||
|                                     <input name="avatar" type="file" /> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <label></label> | ||||
|                                     <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "settings.update_avatar"}}</button> | ||||
|                                 </div> | ||||
|                             </form> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings profile"> | ||||
|   <div class="ui container"> | ||||
|     <div class="ui grid"> | ||||
|       {{template "user/settings/navbar" .}} | ||||
|       <div class="twelve wide column content"> | ||||
|         {{template "base/alert" .}} | ||||
|         <h4 class="ui top attached header"> | ||||
|           {{.i18n.Tr "settings.public_profile"}} | ||||
|         </h4> | ||||
|         <div class="ui attached segment"> | ||||
|           <p>{{.i18n.Tr "settings.profile_desc"}}</p> | ||||
|           <form class="ui form" action="{{.Link}}" method="post"> | ||||
|             {{.CsrfTokenHtml}} | ||||
|             <div class="inline field"> | ||||
|               <label>{{.i18n.Tr "settings.uid"}}</label> | ||||
|               <span>{{.SignedUser.Id}}</span> | ||||
|             </div> | ||||
|             <div class="required field {{if .Err_Name}}error{{end}}"> | ||||
|               <label for="username">{{.i18n.Tr "username"}}<span class="text red hide" id="name-change-prompt"> {{.i18n.Tr "settings.change_username_prompt"}}</span></label> | ||||
|               <input id="username" name="name" value="{{.SignedUser.Name}}" data-name="{{.SignedUser.Name}}" autofocus required> | ||||
|             </div> | ||||
|             <div class="field {{if .Err_FullName}}error{{end}}"> | ||||
|               <label for="full_name">{{.i18n.Tr "settings.full_name"}}</label> | ||||
|               <input id="full_name" name="full_name" value="{{.SignedUser.FullName}}"> | ||||
|             </div> | ||||
|             <div class="required field {{if .Err_Email}}error{{end}}"> | ||||
|               <label for="email">{{.i18n.Tr "email"}}</label> | ||||
|               <input id="email" name="email" value="{{.SignedUser.Email}}"> | ||||
|             </div> | ||||
|             <div class="field {{if .Err_Website}}error{{end}}"> | ||||
|               <label for="website">{{.i18n.Tr "settings.website"}}</label> | ||||
|               <input id="website" name="website" type="url" value="{{.SignedUser.Website}}"> | ||||
|             </div> | ||||
|             <div class="field"> | ||||
|               <label for="location">{{.i18n.Tr "settings.location"}}</label> | ||||
|               <input id="location" name="location"  value="{{.SignedUser.Location}}"> | ||||
|             </div> | ||||
|             <div class="required field {{if or DisableGravatar .SignedUser.UseCustomAvatar}}hide{{end}} {{if .Err_Gravatar}}error{{end}}"> | ||||
|                 <label for="gravatar">Gravatar {{.i18n.Tr "email"}}</label> | ||||
|                 <input id="gravatar" name="gravatar" value="{{.SignedUser.AvatarEmail}}" /> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="field"> | ||||
|                <button class="ui green button">{{$.i18n.Tr "settings.update_profile"}}</button> | ||||
|             </div> | ||||
|           </form> | ||||
| 
 | ||||
|           <div class="ui divider"></div> | ||||
| 
 | ||||
|           <form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data"> | ||||
|             {{.CsrfTokenHtml}} | ||||
|             <div class="inline field"> | ||||
|               <label>{{.i18n.Tr "settings.enable_custom_avatar"}}</label> | ||||
|               <div class="ui checkbox"> | ||||
|                 <input name="enable" type="checkbox" {{if .SignedUser.UseCustomAvatar}}checked{{end}}> | ||||
|                 <label>{{.i18n.Tr "settings.enable_custom_avatar_helper"}}</label> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="inline field"> | ||||
|                 <label for="avatar">{{.i18n.Tr "settings.choose_new_avatar"}}</label> | ||||
|                 <input name="avatar" type="file" > | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="field"> | ||||
|                <button class="ui green button">{{$.i18n.Tr "settings.update_avatar"}}</button> | ||||
|             </div> | ||||
|           </form> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
| @ -1,5 +1,5 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings"> | ||||
| <div class="user settings sshkeys"> | ||||
|   <div class="ui container"> | ||||
|     <div class="ui grid"> | ||||
|       {{template "user/settings/navbar" .}} | ||||
| @ -78,15 +78,6 @@ | ||||
|   <div class="content"> | ||||
|     <p>{{.i18n.Tr "settings.ssh_key_deletion_desc"}}</p> | ||||
|   </div> | ||||
|   <div class="actions"> | ||||
|     <div class="ui red basic inverted cancel button"> | ||||
|       <i class="remove icon"></i> | ||||
|       {{.i18n.Tr "modal.no"}} | ||||
|     </div> | ||||
|     <div class="ui green basic inverted ok button"> | ||||
|       <i class="checkmark icon"></i> | ||||
|       {{.i18n.Tr "modal.yes"}} | ||||
|     </div> | ||||
|   </div> | ||||
|   {{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user