commit
						50cd67cd4b
					
				| @ -272,8 +272,9 @@ func runWeb(ctx *cli.Context) { | ||||
| 		m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost) | ||||
| 		m.Get("/password", user.SettingsPassword) | ||||
| 		m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost) | ||||
| 		m.Get("/ssh", user.SettingsSSHKeys) | ||||
| 		m.Post("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost) | ||||
| 		m.Combo("/ssh").Get(user.SettingsSSHKeys). | ||||
| 			Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost) | ||||
| 		m.Post("/ssh/delete", user.DeleteSSHKey) | ||||
| 		m.Get("/social", user.SettingsSocial) | ||||
| 		m.Combo("/applications").Get(user.SettingsApplications). | ||||
| 			Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) | ||||
|  | ||||
| @ -276,6 +276,9 @@ key_name = Key Name | ||||
| key_content = Content | ||||
| add_key_success = New SSH key '%s' has been added successfully! | ||||
| delete_key = Delete | ||||
| ssh_key_deletion = SSH Key Deletion | ||||
| ssh_key_deletion_desc = Delete this SSH key will remove all related accesses for your account. Do you want to continue? | ||||
| ssh_key_deletion_success = SSH key has been deleted successfully! | ||||
| add_on = Added on | ||||
| last_used = Last used on | ||||
| no_activity = No recent activity | ||||
|  | ||||
| @ -169,6 +169,12 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff | ||||
| 			beg := len(DIFF_HEAD) | ||||
| 			a := line[beg : (len(line)-beg)/2+beg] | ||||
| 
 | ||||
| 			// In case file name is surrounded by double quotes(it happens only in git-shell).
 | ||||
| 			if a[0] == '"' { | ||||
| 				a = a[1 : len(a)-1] | ||||
| 				a = strings.Replace(a, `\"`, `"`, -1) | ||||
| 			} | ||||
| 
 | ||||
| 			curFile = &DiffFile{ | ||||
| 				Name:     a[strings.Index(a, "/")+1:], | ||||
| 				Index:    len(diff.Files) + 1, | ||||
|  | ||||
| @ -466,7 +466,15 @@ func deletePublicKey(e *xorm.Session, key *PublicKey) error { | ||||
| } | ||||
| 
 | ||||
| // DeletePublicKey deletes SSH key information both in database and authorized_keys file.
 | ||||
| func DeletePublicKey(key *PublicKey) (err error) { | ||||
| func DeletePublicKey(id int64) (err error) { | ||||
| 	key := &PublicKey{ID: id} | ||||
| 	has, err := x.Id(key.ID).Get(key) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if !has { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	sess := x.NewSession() | ||||
| 	defer sessionRelease(sess) | ||||
| 	if err = sess.Begin(); err != nil { | ||||
|  | ||||
| @ -166,6 +166,13 @@ type Repository struct { | ||||
| 	Updated time.Time `xorm:"UPDATED"` | ||||
| } | ||||
| 
 | ||||
| func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | ||||
| 	switch colName { | ||||
| 	case "updated": | ||||
| 		repo.Updated = regulateTimeZone(repo.Updated) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (repo *Repository) getOwner(e Engine) (err error) { | ||||
| 	if repo.Owner == nil { | ||||
| 		repo.Owner, err = getUserByID(e, repo.OwnerID) | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -275,9 +275,11 @@ func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, erro | ||||
| 	return parsePrettyFormatLog(repo, stdout) | ||||
| } | ||||
| 
 | ||||
| var CommitsRangeSize = 50 | ||||
| 
 | ||||
| func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) { | ||||
| 	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), | ||||
| 		"--skip="+com.ToStr((page-1)*50), "--max-count=50", prettyLogFormat) | ||||
| 		"--skip="+com.ToStr((page-1)*CommitsRangeSize), "--max-count="+com.ToStr(CommitsRangeSize), prettyLogFormat) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New(string(stderr)) | ||||
| 	} | ||||
|  | ||||
| @ -71,6 +71,13 @@ func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) { | ||||
| 
 | ||||
| 		step = bytes.IndexByte(data[pos:], '\n') | ||||
| 		entry.name = string(data[pos : pos+step]) | ||||
| 
 | ||||
| 		// In case entry name is surrounded by double quotes(it happens only in git-shell).
 | ||||
| 		if entry.name[0] == '"' { | ||||
| 			entry.name = string(data[pos+1 : pos+step-1]) | ||||
| 			entry.name = strings.Replace(entry.name, `\"`, `"`, -1) | ||||
| 		} | ||||
| 
 | ||||
| 		pos += step + 1 | ||||
| 		entries = append(entries, entry) | ||||
| 	} | ||||
|  | ||||
| @ -17,6 +17,33 @@ import ( | ||||
| 	"github.com/gogits/gogs/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| type loginAuth struct { | ||||
| 	username, password string | ||||
| } | ||||
| 
 | ||||
| // SMTP AUTH LOGIN Auth Handler
 | ||||
| func LoginAuth(username, password string) smtp.Auth { | ||||
| 	return &loginAuth{username, password} | ||||
| } | ||||
| 
 | ||||
| func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { | ||||
| 	return "LOGIN", []byte{}, nil | ||||
| } | ||||
| 
 | ||||
| func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { | ||||
| 	if more { | ||||
| 		switch string(fromServer) { | ||||
| 		case "Username:": | ||||
| 			return []byte(a.username), nil | ||||
| 		case "Password:": | ||||
| 			return []byte(a.password), nil | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unknwon fromServer: %s", string(fromServer)) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, nil | ||||
| } | ||||
| 
 | ||||
| type Message struct { | ||||
| 	To      []string | ||||
| 	From    string | ||||
| @ -135,6 +162,9 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte) | ||||
| 			auth = smtp.CRAMMD5Auth(settings.User, settings.Passwd) | ||||
| 		} else if strings.Contains(options, "PLAIN") { | ||||
| 			auth = smtp.PlainAuth("", settings.User, settings.Passwd, host) | ||||
| 		} else if strings.Contains(options, "LOGIN") { | ||||
| 			// Patch for AUTH LOGIN
 | ||||
| 			auth = LoginAuth(settings.User, settings.Passwd) | ||||
| 		} | ||||
| 
 | ||||
| 		if auth != nil { | ||||
|  | ||||
							
								
								
									
										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
											
										
									
								
							| @ -339,6 +339,25 @@ function initRepository() { | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     // Diff
 | ||||
|     if ($('.repository.diff').length > 0) { | ||||
|         $('.diff-detail-box .toggle.button').click(function () { | ||||
|             $($(this).data('target')).slideToggle(100); | ||||
|         }) | ||||
| 
 | ||||
|         var $counter = $('.diff-counter'); | ||||
|         if ($counter.length < 1) { | ||||
|             return; | ||||
|         } | ||||
|         $counter.each(function (i, item) { | ||||
|             var $item = $(item); | ||||
|             var addLine = $item.find('span[data-line].add').data("line"); | ||||
|             var delLine = $item.find('span[data-line].del').data("line"); | ||||
|             var addPercent = parseFloat(addLine) / (parseFloat(addLine) + parseFloat(delLine)) * 100; | ||||
|             $item.find(".bar .add").css("width", addPercent + "%"); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     // Pull request
 | ||||
|     if ($('.repository.compare.pull').length > 0) { | ||||
|         var $branch_dropdown = $('.choose.branch .dropdown') | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| .admin { | ||||
| 	padding-top: 15px; | ||||
| 	padding-bottom: @footer-margin * 3; | ||||
| 	padding-bottom: @footer-margin * 2; | ||||
| 
 | ||||
| 	.table.segment { | ||||
| 		padding: 0; | ||||
|  | ||||
| @ -92,6 +92,13 @@ img { | ||||
| 		&.small { | ||||
| 			font-size: 0.75em; | ||||
| 		} | ||||
| 
 | ||||
| 		&.truncate { | ||||
| 			overflow: hidden; | ||||
| 			text-overflow: ellipsis; | ||||
| 			white-space: nowrap; | ||||
| 			display: inline-block; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	.message { | ||||
| @ -111,6 +118,19 @@ img { | ||||
| 	    border-color: #F0C36D; | ||||
| 		} | ||||
| 	} | ||||
| 	.info { | ||||
| 		&.header { | ||||
| 			background-color: #d9edf7!important; | ||||
|     	border-color: #85c5e5; | ||||
| 		} | ||||
| 		&.segment { | ||||
|     	border-color: #85c5e5; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	.normal.header { | ||||
| 		font-weight: normal; | ||||
| 	} | ||||
| 
 | ||||
| 	.avatar.image { | ||||
| 		border-radius: 3px; | ||||
|  | ||||
| @ -9,7 +9,11 @@ | ||||
| .ui.attached.header { | ||||
| 	background: #f0f0f0; | ||||
| 	.right { | ||||
| 		margin-top: -6px; | ||||
| 		margin-top: -5px; | ||||
| 		.button { | ||||
| 			padding: 8px 10px; | ||||
| 			font-weight: normal; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| .repository { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| .home { | ||||
| 	padding-bottom: @footer-margin * 3; | ||||
| 	padding-bottom: @footer-margin * 2; | ||||
| 	.logo { | ||||
| 		max-width: 250px; | ||||
| 	} | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| .install { | ||||
| 	padding-top: 45px; | ||||
| 	padding-bottom: @footer-margin * 3; | ||||
| 	padding-bottom: @footer-margin * 2; | ||||
| 	form { | ||||
| 		@input-padding: 320px !important; | ||||
| 		label { | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| 	@mega-octicon-width: 30px; | ||||
| 
 | ||||
| 	padding-top: 15px; | ||||
| 	padding-bottom: @footer-margin * 3; | ||||
| 	padding-bottom: @footer-margin * 2; | ||||
| 
 | ||||
| 	.head { | ||||
| 		.column { | ||||
| @ -424,6 +424,187 @@ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.commits { | ||||
| 		.header { | ||||
| 			.ui.right { | ||||
| 				.search { | ||||
| 					input { | ||||
| 						font-weight: normal; | ||||
| 						padding: 5px 10px; | ||||
| 					} | ||||
| 				} | ||||
| 				.button { | ||||
| 					float: right; | ||||
| 					margin-left: 5px; | ||||
| 					margin-top: 1px; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	.commits.table { | ||||
| 		font-size: 13px; | ||||
| 		th, td { | ||||
| 			&:first-child { | ||||
| 				padding-left: 15px; | ||||
| 			} | ||||
| 		} | ||||
| 		td { | ||||
| 			line-height: 15px; | ||||
| 		} | ||||
| 		.author { | ||||
| 			min-width: 180px; | ||||
| 		} | ||||
| 		.message span { | ||||
| 			max-width: 500px; | ||||
| 		} | ||||
| 		.date { | ||||
| 	    width: 120px; | ||||
| 		} | ||||
| 	} | ||||
| 	.sha.label { | ||||
| 		font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace; | ||||
| 		font-size: 14px; | ||||
| 		padding: 6px 10px 4px 10px; | ||||
| 		font-weight: normal; | ||||
| 	} | ||||
| 
 | ||||
| 	.diff-detail-box { | ||||
|     margin: 15px 0; | ||||
|     line-height: 30px; | ||||
|     ol { | ||||
|       clear: both; | ||||
|       padding-left: 0; | ||||
|       margin-top: 5px; | ||||
|       margin-bottom: 28px; | ||||
|       li { | ||||
|         list-style: none; | ||||
|         padding-bottom: 4px; | ||||
|         margin-bottom: 4px; | ||||
|         border-bottom: 1px dashed #DDD; | ||||
|         padding-left: 6px; | ||||
|       } | ||||
|     } | ||||
|     span.status{ | ||||
|       display: inline-block; | ||||
|       width: 12px; | ||||
|       height: 12px; | ||||
|       margin-right: 8px; | ||||
|       vertical-align: middle; | ||||
|       &.modify { | ||||
|         background-color: #f0db88; | ||||
|       } | ||||
|       &.add { | ||||
|         background-color: #b4e2b4; | ||||
|       } | ||||
|       &.del { | ||||
|         background-color: #e9aeae; | ||||
|       } | ||||
|       &.rename { | ||||
|         background-color: #dad8ff; | ||||
|       } | ||||
|     } | ||||
| 	} | ||||
| 	.diff-box { | ||||
|     .count { | ||||
|       margin-right: 12px; | ||||
|       .bar { | ||||
|         background-color: #e75316; | ||||
|         height: 12px; | ||||
|         width: 40px; | ||||
|         display: inline-block; | ||||
|         margin: 2px 4px 0 4px; | ||||
|         vertical-align: text-top; | ||||
|         .add { | ||||
|           background-color: #77c64a; | ||||
|           height: 12px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     .file { | ||||
|       color: #888; | ||||
|     } | ||||
| 	} | ||||
| 	.diff-file-box { | ||||
| 		.header { | ||||
| 			border-bottom: 1px solid #d4d4d5!important; | ||||
| 		} | ||||
|     .file-body.file-code { | ||||
|       .lines-num { | ||||
|         text-align: right; | ||||
|         color: #999; | ||||
|         background: #fafafa; | ||||
|         width: 1%; | ||||
|       } | ||||
|       .lines-num-old { | ||||
|         border-right: 1px solid #DDD; | ||||
|       } | ||||
|     } | ||||
|     .code-diff { | ||||
|     	font-size: 13px; | ||||
|     	td { | ||||
|     		padding: 0; | ||||
|     		border-top: none; | ||||
|     	} | ||||
|     	pre { | ||||
|     		margin: 0; | ||||
|     	} | ||||
|     	.lines-num { | ||||
|     		border-right: 1px solid #d4d4d5; | ||||
|     		padding: 0 5px; | ||||
|     	} | ||||
|       tbody { | ||||
|         tr { | ||||
|           &.tag-code { | ||||
|             td, pre { | ||||
|               background-color: #E0E0E0 !important; | ||||
|               border-color: #ADADAD!important; | ||||
|             } | ||||
|             // td.selected-line, td.selected-line pre { | ||||
|             //   background-color: #ffffdd !important; | ||||
|             // } | ||||
|           } | ||||
|           // &.same-code { | ||||
|           //   td.selected-line, td.selected-line pre { | ||||
|           //     background-color: #ffffdd !important; | ||||
|           //   } | ||||
|           // } | ||||
|           &.del-code { | ||||
|             td, pre { | ||||
|               background-color: #ffe2dd !important; | ||||
|               border-color: #e9aeae !important; | ||||
|             } | ||||
|             // td.selected-line, td.selected-line pre { | ||||
|             //   background-color: #ffffdd !important; | ||||
|             // } | ||||
|           } | ||||
|           &.add-code { | ||||
|             td, pre {  | ||||
|               background-color: #d1ffd6 !important; | ||||
|               border-color: #b4e2b4 !important; | ||||
|             } | ||||
|             // td.selected-line, td.selected-line pre { | ||||
|             //   background-color: #ffffdd !important; | ||||
|             // } | ||||
|           } | ||||
|           &:hover { | ||||
|             td { | ||||
|               background-color: #FFF8D2 !important; | ||||
|               border-color: #F0DB88 !important;    | ||||
|             } | ||||
|             pre { | ||||
|               background-color: transparent !important; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 	} | ||||
| 	.code-view { | ||||
| 		overflow: auto; | ||||
| 		overflow-x: auto; | ||||
| 		overflow-y: hidden; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .ui.comments { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| .user { | ||||
| 	padding-top: 15px; | ||||
| 	padding-bottom: @footer-margin * 3; | ||||
| 	padding-bottom: @footer-margin * 2; | ||||
| 
 | ||||
| 	&.settings { | ||||
| 		.key.list { | ||||
|  | ||||
| @ -9,6 +9,7 @@ import ( | ||||
| 	"path" | ||||
| 
 | ||||
| 	"github.com/Unknwon/com" | ||||
| 	"github.com/Unknwon/paginater" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| @ -44,7 +45,7 @@ func RenderIssueLinks(oldCommits *list.List, repoLink string) *list.List { | ||||
| } | ||||
| 
 | ||||
| func Commits(ctx *middleware.Context) { | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	ctx.Data["PageIsCommits"] = true | ||||
| 
 | ||||
| 	userName := ctx.Repo.Owner.Name | ||||
| 	repoName := ctx.Repo.Repository.Name | ||||
| @ -64,19 +65,11 @@ func Commits(ctx *middleware.Context) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Calculate and validate page number.
 | ||||
| 	page, _ := com.StrTo(ctx.Query("p")).Int() | ||||
| 	if page < 1 { | ||||
| 	page := ctx.QueryInt("page") | ||||
| 	if page <= 1 { | ||||
| 		page = 1 | ||||
| 	} | ||||
| 	lastPage := page - 1 | ||||
| 	if lastPage < 0 { | ||||
| 		lastPage = 0 | ||||
| 	} | ||||
| 	nextPage := page + 1 | ||||
| 	if page*50 > commitsCount { | ||||
| 		nextPage = 0 | ||||
| 	} | ||||
| 	ctx.Data["Page"] = paginater.New(commitsCount, git.CommitsRangeSize, page, 5) | ||||
| 
 | ||||
| 	// Both `git log branchName` and `git log commitId` work.
 | ||||
| 	commits, err := ctx.Repo.Commit.CommitsByRange(page) | ||||
| @ -91,14 +84,11 @@ func Commits(ctx *middleware.Context) { | ||||
| 	ctx.Data["Username"] = userName | ||||
| 	ctx.Data["Reponame"] = repoName | ||||
| 	ctx.Data["CommitCount"] = commitsCount | ||||
| 	ctx.Data["LastPageNum"] = lastPage | ||||
| 	ctx.Data["NextPageNum"] = nextPage | ||||
| 	ctx.HTML(200, COMMITS) | ||||
| } | ||||
| 
 | ||||
| func SearchCommits(ctx *middleware.Context) { | ||||
| 	ctx.Data["IsSearchPage"] = true | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	ctx.Data["PageIsCommits"] = true | ||||
| 
 | ||||
| 	keyword := ctx.Query("q") | ||||
| 	if len(keyword) == 0 { | ||||
| @ -199,7 +189,7 @@ func FileHistory(ctx *middleware.Context) { | ||||
| } | ||||
| 
 | ||||
| func Diff(ctx *middleware.Context) { | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	ctx.Data["PageIsDiff"] = true | ||||
| 
 | ||||
| 	userName := ctx.Repo.Owner.Name | ||||
| 	repoName := ctx.Repo.Repository.Name | ||||
| @ -253,7 +243,7 @@ func Diff(ctx *middleware.Context) { | ||||
| 	ctx.Data["Parents"] = parents | ||||
| 	ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 | ||||
| 	ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", commitId) | ||||
| 	if (commit.ParentCount() > 0) { | ||||
| 	if commit.ParentCount() > 0 { | ||||
| 		ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", parents[0]) | ||||
| 	} | ||||
| 	ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", commitId) | ||||
|  | ||||
| @ -677,6 +677,13 @@ func SettingsDeployKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("repo.settings") | ||||
| 	ctx.Data["PageIsSettingsKeys"] = true | ||||
| 
 | ||||
| 	keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "ListDeployKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Deploykeys"] = keys | ||||
| 
 | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, DEPLOY_KEYS) | ||||
| 		return | ||||
|  | ||||
| @ -269,12 +269,12 @@ func SettingsSSHKeys(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSSHKeys"] = true | ||||
| 
 | ||||
| 	var err error | ||||
| 	ctx.Data["Keys"], err = models.ListPublicKeys(ctx.User.Id) | ||||
| 	keys, err := models.ListPublicKeys(ctx.User.Id) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "ssh.ListPublicKey", err) | ||||
| 		ctx.Handle(500, "ListPublicKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Keys"] = keys | ||||
| 
 | ||||
| 	ctx.HTML(200, SETTINGS_SSH_KEYS) | ||||
| } | ||||
| @ -283,66 +283,58 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSSHKeys"] = true | ||||
| 
 | ||||
| 	var err error | ||||
| 	ctx.Data["Keys"], err = models.ListPublicKeys(ctx.User.Id) | ||||
| 	keys, err := models.ListPublicKeys(ctx.User.Id) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "ssh.ListPublicKey", err) | ||||
| 		ctx.Handle(500, "ListPublicKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Keys"] = keys | ||||
| 
 | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, SETTINGS_SSH_KEYS) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Delete SSH key.
 | ||||
| 	if ctx.Query("_method") == "DELETE" { | ||||
| 		id := com.StrTo(ctx.Query("id")).MustInt64() | ||||
| 		if id <= 0 { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if err = models.DeletePublicKey(&models.PublicKey{ID: id}); err != nil { | ||||
| 			ctx.Handle(500, "DeletePublicKey", err) | ||||
| 	content, err := models.CheckPublicKeyString(form.Content) | ||||
| 	if err != nil { | ||||
| 		if err == models.ErrKeyUnableVerify { | ||||
| 			ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) | ||||
| 		} else { | ||||
| 			log.Trace("SSH key deleted: %s", ctx.User.Name) | ||||
| 			ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Add new SSH key.
 | ||||
| 	if ctx.Req.Method == "POST" { | ||||
| 		if ctx.HasError() { | ||||
| 			ctx.HTML(200, SETTINGS_SSH_KEYS) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		content, err := models.CheckPublicKeyString(form.Content) | ||||
| 		if err != nil { | ||||
| 			if err == models.ErrKeyUnableVerify { | ||||
| 				ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) | ||||
| 			} else { | ||||
| 				ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) | ||||
| 				ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if err = models.AddPublicKey(ctx.User.Id, form.Title, content); err != nil { | ||||
| 			switch { | ||||
| 			case models.IsErrKeyAlreadyExist(err): | ||||
| 				ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form) | ||||
| 			case models.IsErrKeyNameAlreadyUsed(err): | ||||
| 				ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &form) | ||||
| 			default: | ||||
| 				ctx.Handle(500, "AddPublicKey", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} else { | ||||
| 			log.Trace("SSH key added: %s", ctx.User.Name) | ||||
| 			ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title)) | ||||
| 			ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) | ||||
| 			ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.HTML(200, SETTINGS_SSH_KEYS) | ||||
| 	if err = models.AddPublicKey(ctx.User.Id, form.Title, content); err != nil { | ||||
| 		ctx.Data["HasError"] = true | ||||
| 		switch { | ||||
| 		case models.IsErrKeyAlreadyExist(err): | ||||
| 			ctx.Data["Err_Content"] = true | ||||
| 			ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form) | ||||
| 		case models.IsErrKeyNameAlreadyUsed(err): | ||||
| 			ctx.Data["Err_Title"] = true | ||||
| 			ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &form) | ||||
| 		default: | ||||
| 			ctx.Handle(500, "AddPublicKey", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title)) | ||||
| 	ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") | ||||
| } | ||||
| 
 | ||||
| func DeleteSSHKey(ctx *middleware.Context) { | ||||
| 	if err := models.DeletePublicKey(ctx.QueryInt64("id")); err != nil { | ||||
| 		ctx.Flash.Error("DeletePublicKey: " + err.Error()) | ||||
| 	} else { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success")) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubUrl + "/user/settings/ssh", | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func SettingsSocial(ctx *middleware.Context) { | ||||
| @ -389,6 +381,12 @@ func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenF | ||||
| 	ctx.Data["PageIsSettingsApplications"] = true | ||||
| 
 | ||||
| 	if ctx.HasError() { | ||||
| 		tokens, err := models.ListAccessTokens(ctx.User.Id) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(500, "ListAccessTokens", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Data["Tokens"] = tokens | ||||
| 		ctx.HTML(200, SETTINGS_APPLICATIONS) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @ -1,9 +1,8 @@ | ||||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="repo-wrapper"> | ||||
|     {{template "repo/header_old" .}} | ||||
| 	<div class="container clear"> | ||||
|   		{{template "repo/commits_table" .}} | ||||
|   	</div> | ||||
| {{template "base/head" .}} | ||||
| <div class="repository commits"> | ||||
| 	{{template "repo/header" .}} | ||||
|   <div class="ui container"> | ||||
| 		{{template "repo/commits_table" .}} | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
|  | ||||
| @ -1,48 +1,68 @@ | ||||
| <div id="commits-list"> | ||||
|     <div class="panel panel-radius"> | ||||
|         <div class="panel-header"> | ||||
|             {{if not .IsDiffCompare}} | ||||
|             <form class="search pull-right" action="{{.RepoLink}}/commits/{{.BranchName}}/search" method="get" id="commits-search-form"> | ||||
|                 <input class="ipt ipt-radius" type="search" name="q" placeholder="{{.i18n.Tr "repo.commits.search"}}" value="{{.Keyword}}" /> | ||||
|                 <button class="btn btn-black btn-small btn-radius">{{.i18n.Tr "repo.commits.find"}}</button> | ||||
|             </form> | ||||
|             {{end}} | ||||
|             <h4>{{.CommitCount}} {{.i18n.Tr "repo.commits.commits"}}</h4> | ||||
|         </div> | ||||
|         <table class="panel-body table commit-list table-striped"> | ||||
|             <thead> | ||||
|                 <tr> | ||||
|                     <th class="author">{{.i18n.Tr "repo.commits.author"}}</th> | ||||
|                     <th class="sha">SHA1</th> | ||||
|                     <th class="message">{{.i18n.Tr "repo.commits.message"}}</th> | ||||
|                     <th class="date">{{.i18n.Tr "repo.commits.date"}}</th> | ||||
|                 </tr> | ||||
|             </thead> | ||||
|             <tbody> | ||||
|             {{ $username := .Username}} | ||||
|             {{ $reponame := .Reponame}} | ||||
|             {{$r := List .Commits}} | ||||
|             {{range $r}} | ||||
|             <tr> | ||||
|                 <td class="author"> | ||||
|                     {{if .User}} | ||||
|                     <img class="avatar-20" src="{{.User.AvatarLink}}" alt=""/>   <a href="{{AppSubUrl}}/{{.User.Name}}">{{.Author.Name}}</a> | ||||
|                     {{else}} | ||||
|                     <img class="avatar-20" src="{{AvatarLink .Author.Email}}" alt=""/>   {{.Author.Name}} | ||||
|                     {{end}} | ||||
|                 </td> | ||||
|                 <td class="sha"><a rel="nofollow" class="label label-green" href="{{AppSubUrl}}/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td> | ||||
|                 <td class="message"><span class="text-truncate">{{RenderCommitMessage .Summary $.RepoLink}}</span></td> | ||||
|                 <td class="date">{{TimeSince .Author.When $.Lang}}</td> | ||||
|             </tr> | ||||
|             {{end}} | ||||
|             </tbody> | ||||
|         </table> | ||||
|     </div> | ||||
|     {{if and (not .IsSearchPage) (not .IsDiffCompare)}} | ||||
|     <ul class="pagination"> | ||||
|         {{if .LastPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.LastPageNum}}" rel="nofollow">« {{.i18n.Tr "repo.commits.newer"}}</a></li>{{end}} | ||||
|         {{if .NextPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.NextPageNum}}" rel="nofollow">» {{.i18n.Tr "repo.commits.older"}}</a></li>{{end}} | ||||
|     </ul> | ||||
| <h4 class="ui top attached header"> | ||||
|   {{.CommitCount}} {{.i18n.Tr "repo.commits.commits"}} | ||||
|   {{if .PageIsCommits}} | ||||
|   <div class="ui right"> | ||||
|     <form action="{{.RepoLink}}/commits/{{.BranchName}}/search"> | ||||
|       <div class="ui tiny search input"> | ||||
|         <input name="q" placeholder="{{.i18n.Tr "repo.commits.search"}}" value="{{.Keyword}}" autofocus> | ||||
|       </div> | ||||
|       <button class="ui black tiny button" data-panel="#add-deploy-key-panel">{{.i18n.Tr "repo.commits.find"}}</button> | ||||
|     </form> | ||||
|   </div> | ||||
|   {{else if .IsDiffCompare}} | ||||
|   <a href="{{$.RepoLink}}/commit/{{.BeforeCommitId}}" class="ui green sha label">{{ShortSha .BeforeCommitId}}</a> ... <a href="{{$.RepoLink}}/commit/{{.AfterCommitId}}" class="ui green sha label">{{ShortSha .AfterCommitId}}</a> | ||||
|   {{end}} | ||||
| </h4> | ||||
| <div class="ui attached table segment"> | ||||
|   <table class="ui very basic striped commits table"> | ||||
|     <thead> | ||||
|       <tr> | ||||
|         <th>{{.i18n.Tr "repo.commits.author"}}</th> | ||||
|         <th>SHA1</th> | ||||
|         <th>{{.i18n.Tr "repo.commits.message"}}</th> | ||||
|         <th>{{.i18n.Tr "repo.commits.date"}}</th> | ||||
|       </tr> | ||||
|     </thead> | ||||
|     <tbody> | ||||
|     {{ $username := .Username}} | ||||
|     {{ $reponame := .Reponame}} | ||||
|     {{  $r:= List .Commits}} | ||||
|     {{range $r}} | ||||
|       <tr> | ||||
|         <td class="author"> | ||||
|           {{if .User}} | ||||
|           <img class="ui avatar image" src="{{.User.AvatarLink}}" alt=""/>  <a href="{{AppSubUrl}}/{{.User.Name}}">{{.Author.Name}}</a> | ||||
|           {{else}} | ||||
|           <img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/>  {{.Author.Name}} | ||||
|           {{end}} | ||||
|         </td> | ||||
|         <td class="sha"><a rel="nofollow" class="ui green sha label" href="{{AppSubUrl}}/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td> | ||||
|         <td class="message"><span class="text truncate">{{RenderCommitMessage .Summary $.RepoLink}}</span></td> | ||||
|         <td class="date">{{TimeSince .Author.When $.Lang}}</td> | ||||
|       </tr> | ||||
|     {{end}} | ||||
|     </tbody> | ||||
|   </table> | ||||
| </div> | ||||
| 
 | ||||
| {{with .Page}} | ||||
| {{if gt .TotalPages 1}} | ||||
| <div class="center page buttons"> | ||||
|   <div class="ui borderless pagination menu"> | ||||
|     <a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.RepoLink}}/commits/{{$.BranchName}}{{if $.FileName}}/{{$.FileName}}{{end}}?page={{.Previous}}"{{end}}> | ||||
|       <i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} | ||||
|     </a> | ||||
|     {{range .Pages}} | ||||
|     {{if eq .Num -1}} | ||||
|     <a class="disabled item">...</a> | ||||
|     {{else}} | ||||
|     <a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.RepoLink}}/commits/{{$.BranchName}}{{if $.FileName}}/{{$.FileName}}{{end}}?page={{.Num}}"{{end}}>{{.Num}}</a> | ||||
|     {{end}} | ||||
|     {{end}} | ||||
|     <a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.RepoLink}}/commits/{{$.BranchName}}{{if $.FileName}}/{{$.FileName}}{{end}}?page={{.Next}}"{{end}}> | ||||
|       {{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> | ||||
|     </a> | ||||
|   </div> | ||||
| </div> | ||||
| {{end}} | ||||
| {{end}} | ||||
| @ -1,134 +1,136 @@ | ||||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="repo-wrapper"> | ||||
|     {{template "repo/header_old" .}} | ||||
|     <div class="container clear" id="diff-page"> | ||||
|         {{if .IsDiffCompare }} | ||||
|         <div class="panel panel-info panel-radius compare-head-box"> | ||||
|             <div class="panel-header"> | ||||
|                 <a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{EscapePound .SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a> | ||||
|                 <h4><a href="{{$.RepoLink}}/commit/{{.BeforeCommitId}}" class="label label-green">{{ShortSha .BeforeCommitId}}</a> ... <a href="{{$.RepoLink}}/commit/{{.AfterCommitId}}" class="label label-green">{{ShortSha .AfterCommitId}}</a></h4> | ||||
|             </div> | ||||
|             <div class="panel-body compare"> | ||||
|                 {{template "repo/commits_table" .}} | ||||
|             </div> | ||||
| {{template "base/head" .}} | ||||
| <div class="repository diff"> | ||||
|   {{template "repo/header" .}} | ||||
|   <div class="ui container"> | ||||
|     {{if .IsDiffCompare }} | ||||
|     {{template "repo/commits_table" .}} | ||||
|     {{else}} | ||||
|     <h4 class="ui top attached info header"> | ||||
|       {{RenderCommitMessage .Commit.Message $.RepoLink}} | ||||
|       <div class="ui right"> | ||||
|         <a class="ui blue tiny button" href="{{EscapePound .SourcePath}}"> | ||||
|           {{.i18n.Tr "repo.diff.browse_source"}} | ||||
|         </a> | ||||
|       </div> | ||||
|     </h4> | ||||
|     <div class="ui attached info segment"> | ||||
|       {{if .Author}} | ||||
|       <img class="ui avatar image" src="{{.Author.AvatarLink}}" /> | ||||
|       <a href="{{.Author.HomeLink}}"><strong>{{.Commit.Author.Name}}</strong></a> | ||||
|       {{else}} | ||||
|       <img class="ui avatar image" src="{{AvatarLink .Commit.Author.Email}}" /> | ||||
|       <strong>{{.Commit.Author.Name}}</strong> | ||||
|       {{end}} | ||||
|       <span class="text grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span> | ||||
|       <div class="ui right"> | ||||
|         <div class="ui horizontal list"> | ||||
|           <div class="item"> | ||||
|             {{.i18n.Tr "repo.diff.parent"}} | ||||
|           </div> | ||||
|           <div class="item"> | ||||
|             {{range .Parents}} | ||||
|             <a class="ui blue sha label" href="{{$.RepoLink}}/commit/{{.}}">{{ShortSha .}}</a> | ||||
|             {{end}} | ||||
|           </div> | ||||
|           <div class="item">{{.i18n.Tr "repo.diff.commit"}}</div> | ||||
|           <div class="item"><span class="ui blue sha label">{{ShortSha .CommitId}}</span></div> | ||||
|         </div> | ||||
|         {{else}} | ||||
|         <div class="panel panel-info panel-radius diff-head-box"> | ||||
|             <div class="panel-header"> | ||||
|                 <a class="pull-right btn btn-blue btn-header btn-medium btn-radius" rel="nofollow" href="{{EscapePound .SourcePath}}">{{.i18n.Tr "repo.diff.browse_source"}}</a> | ||||
|                 <h4 class="commit-message">{{RenderCommitMessage .Commit.Message $.RepoLink}}</h4> | ||||
|             </div> | ||||
|             <div class="panel-body"> | ||||
|                 <span class="pull-right"> | ||||
|                     <ul class="list-unstyled"> | ||||
|                         <li class="inline">{{.i18n.Tr "repo.diff.parent"}}</li> | ||||
|                         {{range .Parents}} | ||||
|                         <li class="inline"><a href="{{$.RepoLink}}/commit/{{.}}"><span class="label label-blue">{{ShortSha .}}</span></a></li> | ||||
|                         {{end}} | ||||
|                         <li class="inline">{{.i18n.Tr "repo.diff.commit"}} <span class="label label-blue">{{ShortSha .CommitId}}</span></li> | ||||
|                     </ul> | ||||
|                 </span> | ||||
|                 <p class="author"> | ||||
|                     {{if .Author}} | ||||
|                     <img class="avatar-30" src="{{.Author.AvatarLink}}" /> | ||||
|                     <a href="{{AppSubUrl}}/{{.Author.Name}}"><strong>{{.Commit.Author.Name}}</strong></a> | ||||
|                     {{else}} | ||||
|                     <img class="avatar-30" src="{{AvatarLink .Commit.Author.Email}}" /> | ||||
|                     <strong>{{.Commit.Author.Name}}</strong> | ||||
|                     {{end}} | ||||
|                     <span class="text-grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span> | ||||
|                 </p> | ||||
|             </div> | ||||
|         </div> | ||||
|         {{end}} | ||||
|         {{if .DiffNotAvailable}} | ||||
|         <h4>{{.i18n.Tr "repo.diff.data_not_available"}}</h4> | ||||
|         {{else}} | ||||
|         <div class="diff-detail-box diff-box"> | ||||
|             <a class="pull-right btn btn-gray btn-header btn-radius text-black" data-target="#diff-files">{{.i18n.Tr "repo.diff.show_diff_stats"}}</a> | ||||
|             <p class="showing"> | ||||
|                 <i class="fa fa-retweet"></i> | ||||
|                 {{.i18n.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}} | ||||
|             </p> | ||||
|             <ol class="detail-files collapse hide" id="diff-files"> | ||||
|                 {{range .Diff.Files}} | ||||
|                 <li> | ||||
|                     <div class="diff-counter count pull-right"> | ||||
|                         {{if not .IsBin}} | ||||
|                         <span class="add" data-line="{{.Addition}}">{{.Addition}}</span> | ||||
|                         <span class="bar"> | ||||
|                             <span class="pull-left add"></span> | ||||
|                             <span class="pull-left del"></span> | ||||
|                         </span> | ||||
|                         <span class="del" data-line="{{.Deletion}}">{{.Deletion}}</span> | ||||
|                         {{else}} | ||||
|                         <span>{{$.i18n.Tr "repo.diff.bin"}}</span> | ||||
|                         {{end}} | ||||
|                     </div> | ||||
|                     <!-- todo finish all file status, now modify, add, delete and rename --> | ||||
|                     <span class="status {{DiffTypeToStr .Type}}" data-toggle="tooltip" data-placement="right" title="{{DiffTypeToStr .Type}}"> </span> | ||||
|                     <a class="file" href="#diff-{{.Index}}">{{.Name}}</a> | ||||
|                 </li> | ||||
|                 {{end}} | ||||
|             </ol> | ||||
|         </div> | ||||
| 
 | ||||
|         {{range $i, $file := .Diff.Files}} | ||||
|         <div class="panel panel-radius diff-file-box diff-box file-content" id="diff-{{.Index}}"> | ||||
|             <div class="panel-header"> | ||||
|                 <div class="diff-counter count pull-left"> | ||||
|                     {{if not $file.IsBin}} | ||||
|                     <span class="add" data-line="{{.Addition}}">+ {{.Addition}}</span> | ||||
|                     <span class="bar"> | ||||
|                         <span class="pull-left add"></span> | ||||
|                         <span class="pull-left del"></span> | ||||
|                     </span> | ||||
|                     <span class="del" data-line="{{.Deletion}}">- {{.Deletion}}</span> | ||||
|                     {{else}} | ||||
|                     {{$.i18n.Tr "repo.diff.bin"}} | ||||
|                     {{end}} | ||||
|                 </div> | ||||
|                 {{if $file.IsDeleted}} | ||||
|                 <a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> | ||||
|                 {{else}} | ||||
|                 <a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> | ||||
|                 {{end}} | ||||
|                 <span class="file">{{$file.Name}}</span> | ||||
|             </div> | ||||
|             {{$isImage := (call $.IsImageFile $file.Name)}} | ||||
|             <div class="panel-body file-body file-code code-view code-diff"> | ||||
|                 {{if $isImage}} | ||||
|                     <div class="text-center"> | ||||
|                         <img src="{{$.RawPath}}/{{EscapePound .Name}}"> | ||||
|                     </div> | ||||
|                 {{else}} | ||||
|                 <table> | ||||
|                     <tbody> | ||||
|                         {{range .Sections}} | ||||
|                         {{range $k, $line := .Lines}} | ||||
|                         <tr class="{{DiffLineTypeToStr .Type}}-code nl-{{$k}} ol-{{$k}}"> | ||||
|                             <td class="lines-num lines-num-old"> | ||||
|                                 <span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span> | ||||
|                             </td> | ||||
|                             <td class="lines-num lines-num-new"> | ||||
|                                 <span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span> | ||||
|                             </td> | ||||
| 
 | ||||
|                             <td class="lines-code"> | ||||
|                                 <pre>{{$line.Content}}</pre> | ||||
|                             </td> | ||||
|                         </tr> | ||||
|                         {{end}} | ||||
|                         {{end}} | ||||
|                     </tbody> | ||||
|                 </table> | ||||
|                 {{end}} | ||||
|             </div> | ||||
|         </div> | ||||
|         <br> | ||||
|         {{end}} | ||||
|         {{end}} | ||||
|       </div> | ||||
|     </div> | ||||
|     {{end}} | ||||
|      | ||||
|     {{if .DiffNotAvailable}} | ||||
|     <h4>{{.i18n.Tr "repo.diff.data_not_available"}}</h4> | ||||
|     {{else}} | ||||
|     <div class="diff-detail-box diff-box"> | ||||
|       <div> | ||||
|         <i class="fa fa-retweet"></i> | ||||
|         {{.i18n.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}} | ||||
|         <div class="ui right"> | ||||
|           <a class="ui tiny basic black toggle button" data-target="#diff-files">{{.i18n.Tr "repo.diff.show_diff_stats"}}</a> | ||||
|         </div> | ||||
|       </div> | ||||
|       <ol class="detail-files hide" id="diff-files"> | ||||
|         {{range .Diff.Files}} | ||||
|         <li> | ||||
|           <div class="diff-counter count pull-right"> | ||||
|             {{if not .IsBin}} | ||||
|             <span class="add" data-line="{{.Addition}}">{{.Addition}}</span> | ||||
|             <span class="bar"> | ||||
|               <span class="pull-left add"></span> | ||||
|               <span class="pull-left del"></span> | ||||
|             </span> | ||||
|             <span class="del" data-line="{{.Deletion}}">{{.Deletion}}</span> | ||||
|             {{else}} | ||||
|             <span>{{$.i18n.Tr "repo.diff.bin"}}</span> | ||||
|             {{end}} | ||||
|           </div> | ||||
|           <!-- todo finish all file status, now modify, add, delete and rename --> | ||||
|           <span class="status {{DiffTypeToStr .Type}} poping up" data-content="{{DiffTypeToStr .Type}}" data-variation="inverted tiny" data-position="right center"> </span> | ||||
|           <a class="file" href="#diff-{{.Index}}">{{.Name}}</a> | ||||
|         </li> | ||||
|         {{end}} | ||||
|       </ol> | ||||
|     </div> | ||||
| 
 | ||||
|     {{range $i, $file := .Diff.Files}} | ||||
|     <div class="diff-file-box diff-box file-content" id="diff-{{.Index}}"> | ||||
|       <h4 class="ui top attached normal header"> | ||||
|         <div class="diff-counter count ui left"> | ||||
|             {{if not $file.IsBin}} | ||||
|             <span class="add" data-line="{{.Addition}}">+ {{.Addition}}</span> | ||||
|             <span class="bar"> | ||||
|               <span class="pull-left add"></span> | ||||
|               <span class="pull-left del"></span> | ||||
|             </span> | ||||
|             <span class="del" data-line="{{.Deletion}}">- {{.Deletion}}</span> | ||||
|             {{else}} | ||||
|             {{$.i18n.Tr "repo.diff.bin"}} | ||||
|             {{end}} | ||||
|         </div> | ||||
|         <span class="file">{{$file.Name}}</span> | ||||
|         <div class="ui right"> | ||||
|           {{if $file.IsDeleted}} | ||||
|           <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> | ||||
|           {{else}} | ||||
|           <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> | ||||
|           {{end}} | ||||
|         </div> | ||||
|       </h4> | ||||
|       <div class="ui attached table segment"> | ||||
|         {{$isImage := (call $.IsImageFile $file.Name)}} | ||||
|         {{if $isImage}} | ||||
|         <div class="center"> | ||||
|           <img src="{{$.RawPath}}/{{EscapePound .Name}}"> | ||||
|         </div> | ||||
|         {{else}} | ||||
|         <div class="file-body file-code code-view code-diff"> | ||||
|           <table> | ||||
|             <tbody> | ||||
|               {{range .Sections}} | ||||
|               {{range $k, $line := .Lines}} | ||||
|               <tr class="{{DiffLineTypeToStr .Type}}-code nl-{{$k}} ol-{{$k}}"> | ||||
|                 <td class="lines-num lines-num-old"> | ||||
|                   <span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span> | ||||
|                 </td> | ||||
|                 <td class="lines-num lines-num-new"> | ||||
|                   <span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span> | ||||
|                 </td> | ||||
|                 <td class="lines-code"> | ||||
|                   <pre>{{$line.Content}}</pre> | ||||
|                 </td> | ||||
|               </tr> | ||||
|               {{end}} | ||||
|               {{end}} | ||||
|             </tbody> | ||||
|           </table> | ||||
|         </div> | ||||
|         {{end}} | ||||
|       </div> | ||||
|     </div> | ||||
|     <br> | ||||
|     {{end}} | ||||
|     {{end}} | ||||
|   </div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
|  | ||||
| @ -102,7 +102,7 @@ | ||||
| 					  	</div> | ||||
| 					  	{{end}} | ||||
| 					  	{{if or $.IsRepositoryAdmin (eq .Poster.Id $.SignedUserID)}} | ||||
| 							<a class="edit-content item" href="#" data-type="comment"><i class="octicon octicon-pencil"></i></a> | ||||
| 							<a class="edit-content item" href="#"><i class="octicon octicon-pencil"></i></a> | ||||
| 					  	{{end}} | ||||
| 					  </div> | ||||
| 					</div> | ||||
|  | ||||
| @ -53,12 +53,12 @@ | ||||
| 						<form class="ui form" action="{{.Link}}" method="post"> | ||||
| 							{{.CsrfTokenHtml}} | ||||
| 							<div class="field {{if .Err_Title}}error{{end}}"> | ||||
| 								<label>{{.i18n.Tr "repo.settings.title"}}</label> | ||||
| 								<input name="title" value="{{.title}}" autofocus required> | ||||
| 								<label for="title">{{.i18n.Tr "repo.settings.title"}}</label> | ||||
| 								<input id="title" name="title" value="{{.title}}" autofocus required> | ||||
| 							</div> | ||||
| 							<div class="field {{if .Err_Content}}error{{end}}"> | ||||
| 								<label>{{.i18n.Tr "repo.settings.deploy_key_content"}}</label> | ||||
| 								<textarea name="content" required>{{.content}}</textarea> | ||||
| 								<label for="content">{{.i18n.Tr "repo.settings.deploy_key_content"}}</label> | ||||
| 								<textarea id="content" name="content" required>{{.content}}</textarea> | ||||
| 							</div> | ||||
| 							<button class="ui green button"> | ||||
| 								{{.i18n.Tr "repo.settings.add_deploy_key"}} | ||||
|  | ||||
| @ -6,7 +6,9 @@ | ||||
|             <li {{if .PageIsSettingsPassword}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/password">{{.i18n.Tr "settings.password"}}</a></li> | ||||
|             <li {{if .PageIsSettingsEmails}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/email">{{.i18n.Tr "settings.emails"}}</a></li> | ||||
|             <li {{if .PageIsSettingsSSHKeys}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/ssh">{{.i18n.Tr "settings.ssh_keys"}}</a></li> | ||||
|             {{if .HasOAuthService}} | ||||
|             <li {{if .PageIsSettingsSocial}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/social">{{.i18n.Tr "settings.social"}}</a></li> | ||||
|             {{end}} | ||||
|             <li {{if .PageIsSettingsApplications}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/applications">{{.i18n.Tr "settings.applications"}}</a></li> | ||||
|             <li {{if .PageIsSettingsDelete}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/delete">{{.i18n.Tr "settings.delete"}}</a></li> | ||||
|         </ul> | ||||
|  | ||||
| @ -1,63 +1,92 @@ | ||||
| {{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="user-ssh-setting-content"> | ||||
|                     <div id="user-ssh-panel" class="panel panel-radius"> | ||||
|                         <div class="panel-header"> | ||||
|                             <a class="show-form-btn" data-target-form="#user-ssh-add-form"> | ||||
|                                 <button class="btn btn-medium btn-black btn-radius right">{{.i18n.Tr "settings.add_key"}}</button> | ||||
|                             </a> | ||||
|                             <strong>{{.i18n.Tr "settings.manage_ssh_keys"}}</strong> | ||||
|                         </div> | ||||
|                         <ul class="panel-body setting-list"> | ||||
|                             <li>{{.i18n.Tr "settings.ssh_desc"}}</li> | ||||
|                             {{range .Keys}} | ||||
|                             <li class="ssh clear"> | ||||
|                                 <span class="active-icon left label label-{{if .HasRecentActivity}}green{{else}}gray{{end}} label-radius"></span> | ||||
|                                 <i class="mega-octicon octicon-key left"></i> | ||||
|                                 <div class="ssh-content left"> | ||||
|                                     <p><strong>{{.Name}}</strong></p> | ||||
|                                     <p class="print">{{.Fingerprint}}</p> | ||||
|                                     <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span> —  <i class="octicon octicon-info"></i>{{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span title="{{DateFmtLong .Updated}}">{{DateFmtShort .Updated}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i></p> | ||||
|                                 </div> | ||||
|                                 <form action="{{AppSubUrl}}/user/settings/ssh" method="post"> | ||||
|                                     {{$.CsrfTokenHtml}} | ||||
|                                     <input name="_method" type="hidden" value="DELETE"> | ||||
|                                     <input name="id" type="hidden" value="{{.ID}}"> | ||||
|                                     <button class="right ssh-btn btn btn-red btn-radius btn-small">{{$.i18n.Tr "settings.delete_key"}}</button> | ||||
|                                 </form> | ||||
|                             </li> | ||||
|                             {{end}} | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                     <p>{{.i18n.Tr "settings.ssh_helper" "https://help.github.com/articles/generating-ssh-keys" "https://help.github.com/ssh-issues/" | Str2html}}</p> | ||||
|                     <br> | ||||
|                     <form class="panel panel-radius form form-align form-settings-add hide" id="user-ssh-add-form" action="{{AppSubUrl}}/user/settings/ssh" method="post"> | ||||
|                         {{.CsrfTokenHtml}} | ||||
|                         <p class="panel-header"><strong>{{.i18n.Tr "settings.add_new_key"}}</strong></p> | ||||
|                         <div class="panel-body"> | ||||
|                             <p class="field"> | ||||
|                                 <label class="req" for="ssh-title">{{.i18n.Tr "settings.key_name"}}</label> | ||||
|                                 <input class="ipt ipt-radius" id="ssh-title" name="title" type="text" required /> | ||||
|                             </p> | ||||
|                             <p class="field clear"> | ||||
|                                 <label class="left req" for="ssh-key">{{.i18n.Tr "settings.key_content"}}</label> | ||||
|                                 <textarea class="ipt ipt-radius left" name="content" id="ssh-key" required></textarea> | ||||
|                             </p> | ||||
|                             <p class="field"> | ||||
|                                 <label></label> | ||||
|                                 <button class="btn btn-green btn-radius" id="ssh-add-btn">{{.i18n.Tr "settings.add_key"}}</button> | ||||
|                             </p> | ||||
|                         </div> | ||||
|                     </form> | ||||
|                 </div> | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings"> | ||||
|   <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.manage_ssh_keys"}} | ||||
|           <div class="ui right"> | ||||
|             <div class="ui blue tiny show-panel button" data-panel="#add-ssh-key-panel">{{.i18n.Tr "settings.add_key"}}</div> | ||||
|           </div> | ||||
|         </h4> | ||||
|         <div class="ui attached segment"> | ||||
|           <div class="ui key list"> | ||||
|             <div class="item"> | ||||
|               {{.i18n.Tr "settings.ssh_desc"}} | ||||
|             </div> | ||||
|             {{range .Keys}} | ||||
|             <div class="item ui grid"> | ||||
|               <div class="one wide column"> | ||||
|                 <i class="ssh-key-state-indicator fa fa-circle{{if .HasRecentActivity}} active invert poping up{{else}}-o{{end}}" {{if .HasRecentActivity}}data-content="{{$.i18n.Tr "settings.key_state_desc"}}" data-variation="inverted"{{end}}></i> | ||||
|               </div> | ||||
|               <div class="one wide column"> | ||||
|                 <i class="mega-octicon octicon-key left"></i> | ||||
|               </div> | ||||
|               <div class="eleven wide column"> | ||||
|                 <strong>{{.Name}}</strong> | ||||
|                 <div class="print meta"> | ||||
|                   {{.Fingerprint}} | ||||
|                 </div> | ||||
|                 <div class="activity meta"> | ||||
|                   <i>{{$.i18n.Tr "settings.add_on"}} <span>{{DateFmtShort .Created}}</span> —  <i class="octicon octicon-info"></i> {{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span>{{DateFmtShort .Updated}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="two wide column"> | ||||
|                 <button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> | ||||
|                   {{$.i18n.Tr "settings.delete_key"}} | ||||
|                 </button> | ||||
|               </div> | ||||
|             </div> | ||||
|             {{end}} | ||||
|           </div> | ||||
|         </div> | ||||
|         <br> | ||||
|         <p>{{.i18n.Tr "settings.ssh_helper" "https://help.github.com/articles/generating-ssh-keys" "https://help.github.com/ssh-issues/" | Str2html}}</p> | ||||
|         <div {{if not .HasError}}class="hide"{{end}} id="add-ssh-key-panel"> | ||||
|           <h4 class="ui top attached header"> | ||||
|             {{.i18n.Tr "settings.add_new_key"}} | ||||
|           </h4> | ||||
|           <div class="ui attached segment"> | ||||
|             <form class="ui form" action="{{.Link}}" method="post"> | ||||
|               {{.CsrfTokenHtml}} | ||||
|               <div class="field {{if .Err_Title}}error{{end}}"> | ||||
|                 <label for="title">{{.i18n.Tr "settings.key_name"}}</label> | ||||
|                 <input id="title" name="title" value="{{.title}}" autofocus required> | ||||
|               </div> | ||||
|               <div class="field {{if .Err_Content}}error{{end}}"> | ||||
|                 <label for="content">{{.i18n.Tr "settings.key_content"}}</label> | ||||
|                 <textarea id="content" name="content" required>{{.content}}</textarea> | ||||
|               </div> | ||||
|               <button class="ui green button"> | ||||
|                 {{.i18n.Tr "settings.add_key"}} | ||||
|               </button> | ||||
|             </form> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
| 
 | ||||
| <div class="ui small basic delete modal"> | ||||
|   <div class="ui icon header"> | ||||
|     <i class="trash icon"></i> | ||||
|     {{.i18n.Tr "settings.ssh_key_deletion"}} | ||||
|   </div> | ||||
|   <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> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user