Merge branch 'develop' of github.com:gogits/gogs into feature/pull_request2
# Conflicts: # modules/bindata/bindata.go # public/css/gogs.min.css # templates/repo/header.tmpl
This commit is contained in:
commit
a79586cc54
31 changed files with 1240 additions and 466 deletions
|
@ -370,6 +370,7 @@ issues.new = New Issue
|
||||||
issues.create = Create Issue
|
issues.create = Create Issue
|
||||||
issues.new_label = New Label
|
issues.new_label = New Label
|
||||||
issues.new_label_placeholder = Label name...
|
issues.new_label_placeholder = Label name...
|
||||||
|
issues.create_label = Create Label
|
||||||
issues.open_tab = %d Open
|
issues.open_tab = %d Open
|
||||||
issues.close_tab = %d Closed
|
issues.close_tab = %d Closed
|
||||||
issues.filter_label = Label
|
issues.filter_label = Label
|
||||||
|
|
|
@ -658,6 +658,14 @@ type Milestone struct {
|
||||||
ClosedDate time.Time
|
ClosedDate time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Milestone) BeforeUpdate() {
|
||||||
|
if m.NumIssues > 0 {
|
||||||
|
m.Completeness = m.NumClosedIssues * 100 / m.NumIssues
|
||||||
|
} else {
|
||||||
|
m.Completeness = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
|
func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
|
||||||
if colName == "deadline" {
|
if colName == "deadline" {
|
||||||
if m.Deadline.Year() == 9999 {
|
if m.Deadline.Year() == 9999 {
|
||||||
|
@ -804,8 +812,6 @@ func ChangeMilestoneIssueStats(issue *Issue) error {
|
||||||
m.NumClosedIssues--
|
m.NumClosedIssues--
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Completeness = m.NumClosedIssues * 100 / m.NumIssues
|
|
||||||
|
|
||||||
return UpdateMilestone(m)
|
return UpdateMilestone(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,13 +833,8 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
m.NumClosedIssues--
|
m.NumClosedIssues--
|
||||||
}
|
}
|
||||||
if m.NumIssues > 0 {
|
|
||||||
m.Completeness = m.NumClosedIssues * 100 / m.NumIssues
|
|
||||||
} else {
|
|
||||||
m.Completeness = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = sess.Id(m.ID).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil {
|
if _, err = sess.Id(m.ID).AllCols().Update(m); err != nil {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -860,8 +861,7 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
|
||||||
return ErrWrongIssueCounter
|
return ErrWrongIssueCounter
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Completeness = m.NumClosedIssues * 100 / m.NumIssues
|
if _, err = sess.Id(m.ID).AllCols().Update(m); err != nil {
|
||||||
if _, err = sess.Id(m.ID).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil {
|
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
|
_ "image/jpeg"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -116,11 +118,40 @@ func (u *User) HomeLink() string {
|
||||||
|
|
||||||
// AvatarLink returns user gravatar link.
|
// AvatarLink returns user gravatar link.
|
||||||
func (u *User) AvatarLink() string {
|
func (u *User) AvatarLink() string {
|
||||||
|
defaultImgUrl := setting.AppSubUrl + "/img/avatar_default.jpg"
|
||||||
|
imgPath := path.Join(setting.AvatarUploadPath, com.ToStr(u.Id))
|
||||||
switch {
|
switch {
|
||||||
case u.UseCustomAvatar:
|
case u.UseCustomAvatar:
|
||||||
|
if !com.IsExist(imgPath) {
|
||||||
|
return defaultImgUrl
|
||||||
|
}
|
||||||
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
||||||
case setting.DisableGravatar, setting.OfflineMode:
|
case setting.DisableGravatar, setting.OfflineMode:
|
||||||
return setting.AppSubUrl + "/img/avatar_default.jpg"
|
if !com.IsExist(imgPath) {
|
||||||
|
img, err := avatar.RandomImage([]byte(u.Email))
|
||||||
|
if err != nil {
|
||||||
|
log.Error(3, "RandomImage: %v", err)
|
||||||
|
return defaultImgUrl
|
||||||
|
}
|
||||||
|
if err = os.MkdirAll(path.Dir(imgPath), os.ModePerm); err != nil {
|
||||||
|
log.Error(3, "MkdirAll: %v", err)
|
||||||
|
return defaultImgUrl
|
||||||
|
}
|
||||||
|
fw, err := os.Create(imgPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(3, "Create: %v", err)
|
||||||
|
return defaultImgUrl
|
||||||
|
}
|
||||||
|
defer fw.Close()
|
||||||
|
|
||||||
|
if err = jpeg.Encode(fw, img, nil); err != nil {
|
||||||
|
log.Error(3, "Encode: %v", err)
|
||||||
|
return defaultImgUrl
|
||||||
|
}
|
||||||
|
log.Info("New random avatar created: %d", u.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
||||||
case setting.Service.EnableCacheAvatar:
|
case setting.Service.EnableCacheAvatar:
|
||||||
return setting.AppSubUrl + "/avatar/" + u.Avatar
|
return setting.AppSubUrl + "/avatar/" + u.Avatar
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"image/color/palette"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -32,6 +34,7 @@ import (
|
||||||
|
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
|
|
||||||
|
"github.com/gogits/gogs/modules/identicon"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"github.com/gogits/gogs/modules/setting"
|
||||||
)
|
)
|
||||||
|
@ -59,6 +62,27 @@ func HashEmail(email string) string {
|
||||||
return hex.EncodeToString(h.Sum(nil))
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _RANDOM_AVATAR_SIZE = 200
|
||||||
|
|
||||||
|
// RandomImage generates and returns a random avatar image.
|
||||||
|
func RandomImage(data []byte) (image.Image, error) {
|
||||||
|
randExtent := len(palette.WebSafe) - 32
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
colorIndex := rand.Intn(randExtent)
|
||||||
|
backColorIndex := colorIndex - 1
|
||||||
|
if backColorIndex < 0 {
|
||||||
|
backColorIndex = randExtent - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size, background, forecolor
|
||||||
|
imgMaker, err := identicon.New(_RANDOM_AVATAR_SIZE,
|
||||||
|
palette.WebSafe[backColorIndex], palette.WebSafe[colorIndex:colorIndex+32]...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return imgMaker.Make(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Avatar represents the avatar object.
|
// Avatar represents the avatar object.
|
||||||
type Avatar struct {
|
type Avatar struct {
|
||||||
Hash string
|
Hash string
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -20,6 +20,15 @@ func (repo *Repository) IsTagExist(tagName string) bool {
|
||||||
return IsTagExist(repo.Path, tagName)
|
return IsTagExist(repo.Path, tagName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) getTagsReversed() ([]string, error) {
|
||||||
|
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
|
||||||
|
if err != nil {
|
||||||
|
return nil, concatenateError(err, stderr)
|
||||||
|
}
|
||||||
|
tags := strings.Split(stdout, "\n")
|
||||||
|
return tags[:len(tags)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetTags returns all tags of given repository.
|
// GetTags returns all tags of given repository.
|
||||||
func (repo *Repository) GetTags() ([]string, error) {
|
func (repo *Repository) GetTags() ([]string, error) {
|
||||||
if gitVer.AtLeast(MustParseVersion("2.0.0")) {
|
if gitVer.AtLeast(MustParseVersion("2.0.0")) {
|
||||||
|
@ -33,15 +42,6 @@ func (repo *Repository) GetTags() ([]string, error) {
|
||||||
return tags[:len(tags)-1], nil
|
return tags[:len(tags)-1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) getTagsReversed() ([]string, error) {
|
|
||||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New(stderr)
|
|
||||||
}
|
|
||||||
tags := strings.Split(stdout, "\n")
|
|
||||||
return tags[:len(tags)-1], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *Repository) CreateTag(tagName, idStr string) error {
|
func (repo *Repository) CreateTag(tagName, idStr string) error {
|
||||||
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
|
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
405
modules/identicon/block.go
Normal file
405
modules/identicon/block.go
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
// Copyright 2015 by caixw, All rights reserved
|
||||||
|
// Use of this source code is governed by a MIT
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package identicon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// 可以出现在中间的方块,一般为了美观,都是对称图像。
|
||||||
|
centerBlocks = []blockFunc{b0, b1, b2, b3}
|
||||||
|
|
||||||
|
// 所有方块
|
||||||
|
blocks = []blockFunc{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 所有block函数的类型
|
||||||
|
type blockFunc func(img *image.Paletted, x, y, size float64, angle int)
|
||||||
|
|
||||||
|
// 将多边形points旋转angle个角度,然后输出到img上,起点为x,y坐标
|
||||||
|
func drawBlock(img *image.Paletted, x, y, size float64, angle int, points []float64) {
|
||||||
|
if angle > 0 { // 0角度不需要转换
|
||||||
|
// 中心坐标与x,y的距离,方便下面指定中心坐标(x+m,y+m),
|
||||||
|
// 0.5的偏移值不能少,否则坐靠右,非正中央
|
||||||
|
m := size/2 - 0.5
|
||||||
|
rotate(points, x+m, y+m, angle)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := x; i < x+size; i++ {
|
||||||
|
for j := y; j < y+size; j++ {
|
||||||
|
if pointInPolygon(i, j, points) {
|
||||||
|
img.SetColorIndex(int(i), int(j), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全空白
|
||||||
|
//
|
||||||
|
// --------
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// --------
|
||||||
|
func b0(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全填充正方形
|
||||||
|
//
|
||||||
|
// --------
|
||||||
|
// |######|
|
||||||
|
// |######|
|
||||||
|
// |######|
|
||||||
|
// --------
|
||||||
|
func b1(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
isize := int(size)
|
||||||
|
ix := int(x)
|
||||||
|
iy := int(y)
|
||||||
|
for i := ix + 1; i < ix+isize; i++ {
|
||||||
|
for j := iy + 1; j < iy+isize; j++ {
|
||||||
|
img.SetColorIndex(i, j, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中间小方块
|
||||||
|
// ----------
|
||||||
|
// | |
|
||||||
|
// | #### |
|
||||||
|
// | #### |
|
||||||
|
// | |
|
||||||
|
// ----------
|
||||||
|
func b2(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
l := size / 4
|
||||||
|
x = x + l
|
||||||
|
y = y + l
|
||||||
|
|
||||||
|
for i := x; i < x+2*l; i++ {
|
||||||
|
for j := y; j < y+2*l; j++ {
|
||||||
|
img.SetColorIndex(int(i), int(j), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菱形
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// | # |
|
||||||
|
// | ### |
|
||||||
|
// | ##### |
|
||||||
|
// |#######|
|
||||||
|
// | ##### |
|
||||||
|
// | ### |
|
||||||
|
// | # |
|
||||||
|
// ---------
|
||||||
|
func b3(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
m := size / 2
|
||||||
|
points := []float64{}
|
||||||
|
|
||||||
|
drawBlock(img, x, y, size, 0, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+size, y+m,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y+m,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b4
|
||||||
|
//
|
||||||
|
// -------
|
||||||
|
// |#####|
|
||||||
|
// |#### |
|
||||||
|
// |### |
|
||||||
|
// |## |
|
||||||
|
// |# |
|
||||||
|
// |------
|
||||||
|
func b4(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+size, y,
|
||||||
|
x, y+size,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b5
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// | # |
|
||||||
|
// | ### |
|
||||||
|
// | ##### |
|
||||||
|
// |#######|
|
||||||
|
func b5(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+size,
|
||||||
|
y+size,
|
||||||
|
x, y+size,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b6 矩形
|
||||||
|
//
|
||||||
|
// --------
|
||||||
|
// |### |
|
||||||
|
// |### |
|
||||||
|
// |### |
|
||||||
|
// --------
|
||||||
|
func b6(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+m, y,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y+size,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b7 斜放的锥形
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// | # |
|
||||||
|
// | ## |
|
||||||
|
// | #####|
|
||||||
|
// | ####|
|
||||||
|
// |--------
|
||||||
|
func b7(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+size, y+m,
|
||||||
|
x+size, y+size,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b8 三个堆叠的三角形
|
||||||
|
//
|
||||||
|
// -----------
|
||||||
|
// | # |
|
||||||
|
// | ### |
|
||||||
|
// | ##### |
|
||||||
|
// | # # |
|
||||||
|
// | ### ### |
|
||||||
|
// |#########|
|
||||||
|
// -----------
|
||||||
|
func b8(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
mm := m / 2
|
||||||
|
|
||||||
|
// 顶部三角形
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+3*mm, y+m,
|
||||||
|
x+mm, y+m,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
|
||||||
|
// 底下左边
|
||||||
|
drawBlock(img, x, y, size, angle, append(points[:0],
|
||||||
|
x+mm, y+m,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y+size,
|
||||||
|
x+mm, y+m,
|
||||||
|
))
|
||||||
|
|
||||||
|
// 底下右边
|
||||||
|
drawBlock(img, x, y, size, angle, append(points[:0],
|
||||||
|
x+3*mm, y+m,
|
||||||
|
x+size, y+size,
|
||||||
|
x+m, y+size,
|
||||||
|
x+3*mm, y+m,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b9 斜靠的三角形
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// |# |
|
||||||
|
// | #### |
|
||||||
|
// | #####|
|
||||||
|
// | #### |
|
||||||
|
// | # |
|
||||||
|
// ---------
|
||||||
|
func b9(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+size, y+m,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b10
|
||||||
|
//
|
||||||
|
// ----------
|
||||||
|
// | ####|
|
||||||
|
// | ### |
|
||||||
|
// | ## |
|
||||||
|
// | # |
|
||||||
|
// |#### |
|
||||||
|
// |### |
|
||||||
|
// |## |
|
||||||
|
// |# |
|
||||||
|
// ----------
|
||||||
|
func b10(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+size, y,
|
||||||
|
x+m, y+m,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
|
||||||
|
drawBlock(img, x, y, size, angle, append(points[:0],
|
||||||
|
x, y+m,
|
||||||
|
x+m, y+m,
|
||||||
|
x, y+size,
|
||||||
|
x, y+m,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b11 左上角1/4大小的方块
|
||||||
|
//
|
||||||
|
// ----------
|
||||||
|
// |#### |
|
||||||
|
// |#### |
|
||||||
|
// |#### |
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// ----------
|
||||||
|
func b11(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+m, y,
|
||||||
|
x+m, y+m,
|
||||||
|
x, y+m,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b12
|
||||||
|
//
|
||||||
|
// -----------
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// |#########|
|
||||||
|
// | ##### |
|
||||||
|
// | # |
|
||||||
|
// -----------
|
||||||
|
func b12(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y+m,
|
||||||
|
x+size, y+m,
|
||||||
|
x+m, y+size,
|
||||||
|
x, y+m,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b13
|
||||||
|
//
|
||||||
|
// -----------
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// | # |
|
||||||
|
// | ##### |
|
||||||
|
// |#########|
|
||||||
|
// -----------
|
||||||
|
func b13(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y+m,
|
||||||
|
x+size, y+size,
|
||||||
|
x, y+size,
|
||||||
|
x+m, y+m,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b14
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// | # |
|
||||||
|
// | ### |
|
||||||
|
// |#### |
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// ---------
|
||||||
|
func b14(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+m, y+m,
|
||||||
|
x, y+m,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b15
|
||||||
|
//
|
||||||
|
// ----------
|
||||||
|
// |##### |
|
||||||
|
// |### |
|
||||||
|
// |# |
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// ----------
|
||||||
|
func b15(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x, y,
|
||||||
|
x+m, y,
|
||||||
|
x, y+m,
|
||||||
|
x, y,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// b16
|
||||||
|
//
|
||||||
|
// ---------
|
||||||
|
// | # |
|
||||||
|
// | ##### |
|
||||||
|
// |#######|
|
||||||
|
// | # |
|
||||||
|
// | ##### |
|
||||||
|
// |#######|
|
||||||
|
// ---------
|
||||||
|
func b16(img *image.Paletted, x, y, size float64, angle int) {
|
||||||
|
points := []float64{}
|
||||||
|
m := size / 2
|
||||||
|
drawBlock(img, x, y, size, angle, append(points,
|
||||||
|
x+m, y,
|
||||||
|
x+size, y+m,
|
||||||
|
x, y+m,
|
||||||
|
x+m, y,
|
||||||
|
))
|
||||||
|
|
||||||
|
drawBlock(img, x, y, size, angle, append(points[:0],
|
||||||
|
x+m, y+m,
|
||||||
|
x+size, y+size,
|
||||||
|
x, y+size,
|
||||||
|
x+m, y+m,
|
||||||
|
))
|
||||||
|
}
|
39
modules/identicon/doc.go
Normal file
39
modules/identicon/doc.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2015 by caixw, All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// 一个基于hash值生成随机图像的包。
|
||||||
|
//
|
||||||
|
// 关于identicon并没有统一的标准,一般用于在用户注册时,
|
||||||
|
// 取用户的邮箱或是访问IP等数据(也可以是其它任何数据),
|
||||||
|
// 进行hash运算,之后根据hash数据,产生一张图像,
|
||||||
|
// 这样即可以为用户产生一张独特的头像,又不会泄漏用户的隐藏。
|
||||||
|
//
|
||||||
|
// 在identicon中,把图像分成以下九个部分:
|
||||||
|
// -------------
|
||||||
|
// | 1 | 2 | 3 |
|
||||||
|
// -------------
|
||||||
|
// | 4 | 5 | 6 |
|
||||||
|
// -------------
|
||||||
|
// | 7 | 8 | 9 |
|
||||||
|
// -------------
|
||||||
|
// 其中1、3、9、7为不同角度(依次增加90度)的同一张图片,
|
||||||
|
// 2、6、8、4也是如此,这样可以保持图像是对称的,比较美观。
|
||||||
|
// 5则单独使用一张图片。
|
||||||
|
//
|
||||||
|
// // 根据用户访问的IP,为其生成一张头像
|
||||||
|
// img, _ := identicon.Make(128, color.NRGBA{},color.NRGBA{}, []byte("192.168.1.1"))
|
||||||
|
// fi, _ := os.Create("/tmp/u1.png")
|
||||||
|
// png.Encode(fi, img)
|
||||||
|
// fi.Close()
|
||||||
|
//
|
||||||
|
// // 或者
|
||||||
|
// ii, _ := identicon.New(128, color.NRGBA{}, color.NRGBA{}, color.NRGBA{})
|
||||||
|
// img := ii.Make([]byte("192.168.1.1"))
|
||||||
|
// img = ii.Make([]byte("192.168.1.2"))
|
||||||
|
//
|
||||||
|
// NOTE: go test 会在当前目录的testdata文件夹下产生大量的随机图片。
|
||||||
|
// 要运行测试,必须保证该文件夹是存在的,且有相应的写入权限。
|
||||||
|
package identicon
|
||||||
|
|
||||||
|
const Version = "0.2.6.150603"
|
147
modules/identicon/identicon.go
Normal file
147
modules/identicon/identicon.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// Copyright 2015 by caixw, All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package identicon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minSize = 16 // 图片的最小尺寸
|
||||||
|
maxForeColors = 32 // 在New()函数中可以指定的最大颜色数量
|
||||||
|
)
|
||||||
|
|
||||||
|
// Identicon 用于产生统一尺寸的头像。
|
||||||
|
// 可以根据用户提供的数据,经过一定的算法,自动产生相应的图案和颜色。
|
||||||
|
type Identicon struct {
|
||||||
|
foreColors []color.Color
|
||||||
|
backColor color.Color
|
||||||
|
size int
|
||||||
|
rect image.Rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明一个Identicon实例。
|
||||||
|
// size表示整个头像的大小。
|
||||||
|
// back表示前景色。
|
||||||
|
// fore表示所有可能的前景色,会为每个图像随机挑选一个作为其前景色。
|
||||||
|
// NOTE:前景色不要与背景色太相近。
|
||||||
|
func New(size int, back color.Color, fore ...color.Color) (*Identicon, error) {
|
||||||
|
if len(fore) == 0 || len(fore) > maxForeColors {
|
||||||
|
return nil, fmt.Errorf("前景色数量必须介于[1]~[%v]之间,当前为[%v]", maxForeColors, len(fore))
|
||||||
|
}
|
||||||
|
|
||||||
|
if size < minSize {
|
||||||
|
return nil, fmt.Errorf("参数size的值(%v)不能小于%v", size, minSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Identicon{
|
||||||
|
foreColors: fore,
|
||||||
|
backColor: back,
|
||||||
|
size: size,
|
||||||
|
|
||||||
|
// 画布坐标从0开始,其长度应该是size-1
|
||||||
|
rect: image.Rect(0, 0, size, size),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据data数据产生一张唯一性的头像图片。
|
||||||
|
func (i *Identicon) Make(data []byte) image.Image {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write(data)
|
||||||
|
sum := h.Sum(nil)
|
||||||
|
|
||||||
|
// 第一个方块
|
||||||
|
index := int(sum[0]+sum[1]+sum[2]+sum[3]) % len(blocks)
|
||||||
|
b1 := blocks[index]
|
||||||
|
|
||||||
|
// 第二个方块
|
||||||
|
index = int(sum[4]+sum[5]+sum[6]+sum[7]) % len(blocks)
|
||||||
|
b2 := blocks[index]
|
||||||
|
|
||||||
|
// 中间方块
|
||||||
|
index = int(sum[8]+sum[9]+sum[10]+sum[11]) % len(centerBlocks)
|
||||||
|
c := centerBlocks[index]
|
||||||
|
|
||||||
|
// 旋转角度
|
||||||
|
angle := int(sum[12]+sum[13]+sum[14]) % 4
|
||||||
|
|
||||||
|
// 根据最后一个字段,获取前景颜色
|
||||||
|
index = int(sum[15]) % len(i.foreColors)
|
||||||
|
|
||||||
|
p := image.NewPaletted(i.rect, []color.Color{i.backColor, i.foreColors[index]})
|
||||||
|
drawBlocks(p, i.size, c, b1, b2, angle)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据data数据产生一张唯一性的头像图片。
|
||||||
|
// size 头像的大小。
|
||||||
|
// back, fore头像的背景和前景色。
|
||||||
|
func Make(size int, back, fore color.Color, data []byte) (image.Image, error) {
|
||||||
|
if size < minSize {
|
||||||
|
return nil, fmt.Errorf("参数size的值(%v)不能小于%v", size, minSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
h := md5.New()
|
||||||
|
h.Write(data)
|
||||||
|
sum := h.Sum(nil)
|
||||||
|
|
||||||
|
// 第一个方块
|
||||||
|
index := int(sum[0]+sum[1]+sum[2]+sum[3]) % len(blocks)
|
||||||
|
b1 := blocks[index]
|
||||||
|
|
||||||
|
// 第二个方块
|
||||||
|
index = int(sum[4]+sum[5]+sum[6]+sum[7]) % len(blocks)
|
||||||
|
b2 := blocks[index]
|
||||||
|
|
||||||
|
// 中间方块
|
||||||
|
index = int(sum[8]+sum[9]+sum[10]+sum[11]) % len(centerBlocks)
|
||||||
|
c := centerBlocks[index]
|
||||||
|
|
||||||
|
// 旋转角度
|
||||||
|
angle := int(sum[12]+sum[13]+sum[14]+sum[15]) % 4
|
||||||
|
|
||||||
|
// 画布坐标从0开始,其长度应该是size-1
|
||||||
|
p := image.NewPaletted(image.Rect(0, 0, size, size), []color.Color{back, fore})
|
||||||
|
drawBlocks(p, size, c, b1, b2, angle)
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将九个方格都填上内容。
|
||||||
|
// p为画板。
|
||||||
|
// c为中间方格的填充函数。
|
||||||
|
// b1,b2为边上8格的填充函数。
|
||||||
|
// angle为b1,b2的起始旋转角度。
|
||||||
|
func drawBlocks(p *image.Paletted, size int, c, b1, b2 blockFunc, angle int) {
|
||||||
|
// 每个格子的长宽。先转换成float,再计算!
|
||||||
|
blockSize := float64(size) / 3
|
||||||
|
twoBlockSize := 2 * blockSize
|
||||||
|
|
||||||
|
incr := func() { // 增加angle的值,但不会大于3
|
||||||
|
angle++
|
||||||
|
if angle > 3 {
|
||||||
|
angle = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c(p, blockSize, blockSize, blockSize, 0)
|
||||||
|
|
||||||
|
b1(p, 0, 0, blockSize, angle)
|
||||||
|
b2(p, blockSize, 0, blockSize, angle)
|
||||||
|
|
||||||
|
incr()
|
||||||
|
b1(p, twoBlockSize, 0, blockSize, angle)
|
||||||
|
b2(p, twoBlockSize, blockSize, blockSize, angle)
|
||||||
|
|
||||||
|
incr()
|
||||||
|
b1(p, twoBlockSize, twoBlockSize, blockSize, angle)
|
||||||
|
b2(p, blockSize, twoBlockSize, blockSize, angle)
|
||||||
|
|
||||||
|
incr()
|
||||||
|
b1(p, 0, twoBlockSize, blockSize, angle)
|
||||||
|
b2(p, 0, blockSize, blockSize, angle)
|
||||||
|
}
|
114
modules/identicon/identicon_test.go
Normal file
114
modules/identicon/identicon_test.go
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// Copyright 2015 by caixw, All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package identicon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/png"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/issue9/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
back = color.RGBA{255, 0, 0, 100}
|
||||||
|
fore = color.RGBA{0, 255, 255, 100}
|
||||||
|
fores = []color.Color{color.Black, color.RGBA{200, 2, 5, 100}, color.RGBA{2, 200, 5, 100}}
|
||||||
|
size = 128
|
||||||
|
)
|
||||||
|
|
||||||
|
// 依次画出各个网络的图像。
|
||||||
|
func TestBlocks(t *testing.T) {
|
||||||
|
p := []color.Color{back, fore}
|
||||||
|
|
||||||
|
a := assert.New(t)
|
||||||
|
|
||||||
|
for k, v := range blocks {
|
||||||
|
img := image.NewPaletted(image.Rect(0, 0, size*4, size), p) // 横向4张图片大小
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
v(img, float64(i*size), 0, float64(size), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := os.Create("./testdata/block-" + strconv.Itoa(k) + ".png")
|
||||||
|
a.NotError(err).NotNil(fi)
|
||||||
|
a.NotError(png.Encode(fi, img))
|
||||||
|
a.NotError(fi.Close()) // 关闭文件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 产生一组测试图片
|
||||||
|
func TestDrawBlocks(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
p := image.NewPaletted(image.Rect(0, 0, size, size), []color.Color{back, fore})
|
||||||
|
c := (i + 1) % len(centerBlocks)
|
||||||
|
b1 := (i + 2) % len(blocks)
|
||||||
|
b2 := (i + 3) % len(blocks)
|
||||||
|
drawBlocks(p, size, centerBlocks[c], blocks[b1], blocks[b2], 0)
|
||||||
|
|
||||||
|
fi, err := os.Create("./testdata/draw-" + strconv.Itoa(i) + ".png")
|
||||||
|
a.NotError(err).NotNil(fi)
|
||||||
|
a.NotError(png.Encode(fi, p))
|
||||||
|
a.NotError(fi.Close()) // 关闭文件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMake(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
img, err := Make(size, back, fore, []byte("make-"+strconv.Itoa(i)))
|
||||||
|
a.NotError(err).NotNil(img)
|
||||||
|
|
||||||
|
fi, err := os.Create("./testdata/make-" + strconv.Itoa(i) + ".png")
|
||||||
|
a.NotError(err).NotNil(fi)
|
||||||
|
a.NotError(png.Encode(fi, img))
|
||||||
|
a.NotError(fi.Close()) // 关闭文件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIdenticon(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
|
||||||
|
ii, err := New(size, back, fores...)
|
||||||
|
a.NotError(err).NotNil(ii)
|
||||||
|
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
img := ii.Make([]byte("identicon-" + strconv.Itoa(i)))
|
||||||
|
a.NotNil(img)
|
||||||
|
|
||||||
|
fi, err := os.Create("./testdata/identicon-" + strconv.Itoa(i) + ".png")
|
||||||
|
a.NotError(err).NotNil(fi)
|
||||||
|
a.NotError(png.Encode(fi, img))
|
||||||
|
a.NotError(fi.Close()) // 关闭文件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkMake 5000 229378 ns/op
|
||||||
|
func BenchmarkMake(b *testing.B) {
|
||||||
|
a := assert.New(b)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
img, err := Make(size, back, fore, []byte("Make"))
|
||||||
|
a.NotError(err).NotNil(img)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkIdenticon_Make 10000 222127 ns/op
|
||||||
|
func BenchmarkIdenticon_Make(b *testing.B) {
|
||||||
|
a := assert.New(b)
|
||||||
|
|
||||||
|
ii, err := New(size, back, fores...)
|
||||||
|
a.NotError(err).NotNil(ii)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
img := ii.Make([]byte("Make"))
|
||||||
|
a.NotNil(img)
|
||||||
|
}
|
||||||
|
}
|
69
modules/identicon/polygon.go
Normal file
69
modules/identicon/polygon.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright 2015 by caixw, All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package identicon
|
||||||
|
|
||||||
|
var (
|
||||||
|
// 4个元素分别表示cos(0),cos(90),cos(180),cos(270)
|
||||||
|
cos = []float64{1, 0, -1, 0}
|
||||||
|
|
||||||
|
// 4个元素分别表示sin(0),sin(90),sin(180),sin(270)
|
||||||
|
sin = []float64{0, 1, 0, -1}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 将points中的所有点,以x,y为原点旋转angle个角度。
|
||||||
|
// angle取值只能是[0,1,2,3],分别表示[0,90,180,270]
|
||||||
|
func rotate(points []float64, x, y float64, angle int) {
|
||||||
|
if angle > 3 {
|
||||||
|
panic("rotate:参数angle必须0,1,2,3三值之一")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(points); i += 2 {
|
||||||
|
px := points[i] - x
|
||||||
|
py := points[i+1] - y
|
||||||
|
points[i] = px*cos[angle] - py*sin[angle] + x
|
||||||
|
points[i+1] = px*sin[angle] + py*cos[angle] + y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断某个点是否在多边形之内,不包含构成多边形的线和点
|
||||||
|
// x,y 需要判断的点坐标
|
||||||
|
// points 组成多边形的所顶点,每两个元素表示一点顶点,其中最后一个顶点必须与第一个顶点相同。
|
||||||
|
func pointInPolygon(x float64, y float64, points []float64) bool {
|
||||||
|
if len(points) < 8 { // 只有2个以上的点,才能组成闭合多边形
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 大致算法如下:
|
||||||
|
// 把整个平面以给定的测试点为原点分两部分:
|
||||||
|
// - y>0,包含(x>0 && y==0)
|
||||||
|
// - y<0,包含(x<0 && y==0)
|
||||||
|
// 依次扫描每一个点,当该点与前一个点处于不同部分时(即一个在y>0区,一个在y<0区),
|
||||||
|
// 则判断从前一点到当前点是顺时针还是逆时针(以给定的测试点为原点),如果是顺时针r++,否则r--。
|
||||||
|
// 结果为:2==abs(r)。
|
||||||
|
|
||||||
|
r := 0
|
||||||
|
x1, y1 := points[0], points[1]
|
||||||
|
prev := (y1 > y) || ((x1 > x) && (y1 == y))
|
||||||
|
for i := 2; i < len(points); i += 2 {
|
||||||
|
x2, y2 := points[i], points[i+1]
|
||||||
|
curr := (y2 > y) || ((x2 > x) && (y2 == y))
|
||||||
|
|
||||||
|
if curr == prev {
|
||||||
|
x1, y1 = x2, y2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mul := (x1-x)*(y2-y) - (x2-x)*(y1-y)
|
||||||
|
if mul > 0 {
|
||||||
|
r++
|
||||||
|
} else if mul < 0 {
|
||||||
|
r--
|
||||||
|
}
|
||||||
|
x1, y1 = x2, y2
|
||||||
|
prev = curr
|
||||||
|
}
|
||||||
|
|
||||||
|
return r == 2 || r == -2
|
||||||
|
}
|
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
4
public/css/semantic.min.css
vendored
4
public/css/semantic.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -43,6 +43,15 @@ function initRepository() {
|
||||||
|
|
||||||
// Labels
|
// Labels
|
||||||
if ($('.repository.labels').length > 0) {
|
if ($('.repository.labels').length > 0) {
|
||||||
|
// Create label
|
||||||
|
var $new_label_panel = $('.new-label.segment');
|
||||||
|
$('.new-label.button').click(function () {
|
||||||
|
$new_label_panel.show();
|
||||||
|
});
|
||||||
|
$('.new-label.segment .cancel').click(function () {
|
||||||
|
$new_label_panel.hide();
|
||||||
|
});
|
||||||
|
|
||||||
$('.color-picker').each(function () {
|
$('.color-picker').each(function () {
|
||||||
$(this).minicolors();
|
$(this).minicolors();
|
||||||
});
|
});
|
||||||
|
@ -53,8 +62,7 @@ function initRepository() {
|
||||||
});
|
});
|
||||||
$('.edit-label-button').click(function () {
|
$('.edit-label-button').click(function () {
|
||||||
$('#label-modal-id').val($(this).data('id'));
|
$('#label-modal-id').val($(this).data('id'));
|
||||||
$('#label-modal-title').val($(this).data('title'));
|
$('.edit-label .new-label-input').val($(this).data('title'));
|
||||||
$('#label-modal-color').val($(this).data('color'))
|
|
||||||
$('.minicolors-swatch-color').css("background-color", $(this).data('color'));
|
$('.minicolors-swatch-color').css("background-color", $(this).data('color'));
|
||||||
$('.edit-label.modal').modal({
|
$('.edit-label.modal').modal({
|
||||||
onApprove: function () {
|
onApprove: function () {
|
||||||
|
|
17
public/js/semantic.min.js
vendored
17
public/js/semantic.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -9,27 +9,25 @@ img {
|
||||||
}
|
}
|
||||||
.full.height {
|
.full.height {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 0 -87px 0;
|
margin: 0 0 -@footer-margin*2 0;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
.following.bar {
|
.following.bar {
|
||||||
z-index: 900;
|
z-index: 900;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.7em 0;
|
padding: 5px 0;
|
||||||
&.light {
|
&.light {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-bottom: 1px solid #DDDDDD;
|
border-bottom: 1px solid #DDDDDD;
|
||||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.04);
|
||||||
}
|
}
|
||||||
.ui.secondary.menu {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
.column .menu {
|
.column .menu {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.brand {
|
.brand {
|
||||||
float: left;
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
.head.link.item {
|
.head.link.item {
|
||||||
|
@ -41,7 +39,6 @@ img {
|
||||||
}
|
}
|
||||||
.user.avatar {
|
.user.avatar {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: 1px;
|
|
||||||
}
|
}
|
||||||
.searchbox {
|
.searchbox {
|
||||||
background-color: rgb(244, 244, 244)!important;
|
background-color: rgb(244, 244, 244)!important;
|
||||||
|
@ -51,7 +48,6 @@ img {
|
||||||
}
|
}
|
||||||
.octicon {
|
.octicon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
opacity: 1!important;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,14 +64,21 @@ img {
|
||||||
color: #d95c5c!important;
|
color: #d95c5c!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
footer {
|
footer {
|
||||||
margin-top: @footer-margin!important;
|
margin-top: @footer-margin!important;
|
||||||
|
height: @footer-margin;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-top: 1px solid #d6d6d6;
|
border-top: 1px solid #d6d6d6;
|
||||||
clear: both;
|
clear: both;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #888888;
|
color: #888888;
|
||||||
|
.container {
|
||||||
|
padding-top: 10px;
|
||||||
.fa {
|
.fa {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -92,6 +95,7 @@ footer {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide {
|
.hide {
|
||||||
|
@ -101,15 +105,11 @@ footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-error {
|
|
||||||
color: #d95c5c !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generate-img(16);
|
.generate-img(16);
|
||||||
.generate-img(@n, @i: 1) when (@i =< @n) {
|
.generate-img(@n, @i: 1) when (@i =< @n) {
|
||||||
.img-@{i} {
|
.img-@{i} {
|
||||||
width: (2px * @i);
|
width: (2px * @i)!important;
|
||||||
height: (2px * @i);
|
height: (2px * @i)!important;
|
||||||
}
|
}
|
||||||
.generate-img(@n, (@i + 1));
|
.generate-img(@n, (@i + 1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: @footer-margin * 3;
|
padding-bottom: @footer-margin * 3;
|
||||||
.head {
|
.head {
|
||||||
height: 75px;
|
height: 40px;
|
||||||
padding-top: 20px;
|
|
||||||
background-color: #FCFCFC;
|
background-color: #FCFCFC;
|
||||||
.mega-octicon {
|
.mega-octicon {
|
||||||
width: @mega-octicon-width;
|
width: @mega-octicon-width;
|
||||||
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
a,
|
a,
|
||||||
.fork-flag {
|
.fork-flag {
|
||||||
|
@ -25,65 +25,13 @@
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.button {
|
|
||||||
margin-left: 10px;
|
|
||||||
i {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.num {
|
.num {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.octicon {
|
|
||||||
height: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.navbar {
|
|
||||||
height: 60px;
|
|
||||||
padding-top: 20px;
|
|
||||||
.ui.secondary.menu .item {
|
|
||||||
margin-left: -10px;
|
|
||||||
margin-top: -7px;
|
|
||||||
&>.input {
|
|
||||||
.new-label-input,
|
|
||||||
.color-picker {
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid rgba(0,0,0,.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.input {
|
|
||||||
margin-right: -7px;
|
|
||||||
}
|
|
||||||
.new-label-input {
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
.color-picker {
|
|
||||||
height: 35px;
|
|
||||||
width: auto;
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
.minicolors-swatch.minicolors-sprite {
|
|
||||||
top: 10px;
|
|
||||||
left: 10px;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
&.precolors {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
margin-right: 10px;
|
|
||||||
width: 120px;
|
|
||||||
.color {
|
|
||||||
float: left;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.filter.menu {
|
.filter.menu {
|
||||||
.label.color {
|
.label.color {
|
||||||
margin-left: 17px;
|
margin-left: 15px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
.octicon {
|
.octicon {
|
||||||
|
@ -107,8 +55,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.issue.list {
|
.issue.list {
|
||||||
clear: both;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
padding-top: 15px;
|
||||||
>.item {
|
>.item {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
@ -167,8 +115,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.label.list {
|
.label.list {
|
||||||
clear: both;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
padding-top: 15px;
|
||||||
.item {
|
.item {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
@ -189,8 +137,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.milestone.list {
|
.milestone.list {
|
||||||
clear: both;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
padding-top: 15px;
|
||||||
> .item {
|
> .item {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
@ -243,11 +191,8 @@
|
||||||
textarea {
|
textarea {
|
||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
}
|
#deadline {
|
||||||
|
width: 150px;
|
||||||
&.settings {
|
|
||||||
.content {
|
|
||||||
padding-left: 20px!important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,30 +261,47 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-label.modal {
|
.ui.vertical.menu {
|
||||||
|
.header.item {
|
||||||
|
font-size: 1.1em;
|
||||||
|
background: #f0f0f0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-label.modal,
|
||||||
|
.new-label.segment {
|
||||||
|
.form {
|
||||||
|
.column {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
.buttons {
|
||||||
|
margin-left: auto;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
.color.picker.column {
|
||||||
|
width: auto;
|
||||||
.color-picker {
|
.color-picker {
|
||||||
margin-top: -8px!important;
|
|
||||||
height: 35px;
|
height: 35px;
|
||||||
width: auto!important;
|
width: auto;
|
||||||
padding-left: 30px!important;
|
padding-left: 30px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.minicolors-swatch.minicolors-sprite {
|
.minicolors-swatch.minicolors-sprite {
|
||||||
top: 1px;
|
top: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
.precolors {
|
.precolors {
|
||||||
margin-bottom: -11px!important;
|
padding-left: 0;
|
||||||
padding-left: 0!important;
|
padding-right: 0;
|
||||||
padding-right: 0!important;
|
margin: 3px 10px auto 10px;
|
||||||
margin-right: 10px!important;
|
width: 120px;
|
||||||
width: 120px!important;
|
|
||||||
.color {
|
.color {
|
||||||
float: left;
|
float: left;
|
||||||
margin: 0!important;
|
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
</div>
|
</div>
|
||||||
<footer class="ui page grid">
|
<footer>
|
||||||
<div class="sixteen wide column">
|
<div class="ui container">
|
||||||
<div class="ui left">
|
<div class="ui left">
|
||||||
© 2015 Gogs · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> · {{.i18n.Tr "template"}}: <strong>{{call .TmplLoadTimes}}</strong>
|
© 2015 Gogs · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> · {{.i18n.Tr "template"}}: <strong>{{call .TmplLoadTimes}}</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,15 +46,27 @@
|
||||||
<noscript>Please enable JavaScript in your browser!</noscript>
|
<noscript>Please enable JavaScript in your browser!</noscript>
|
||||||
{{if not .PageIsInstall}}
|
{{if not .PageIsInstall}}
|
||||||
<div class="following bar light">
|
<div class="following bar light">
|
||||||
<div class="ui page grid">
|
<div class="ui container">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
<div class="ui secondary menu">
|
||||||
|
<img class="img-15 ui image brand" src="{{AppSubUrl}}/img/favicon.png">
|
||||||
|
<a class="view-ui item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/">{{if .IsSigned}}{{.i18n.Tr "dashboard"}}{{else}}{{.i18n.Tr "home"}}{{end}}</a>
|
||||||
|
<a class="view-ui item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore">{{.i18n.Tr "explore"}}</a>
|
||||||
|
<a class="view-ui item" target="_blank" href="http://gogs.io/docs">{{.i18n.Tr "help"}}</a>
|
||||||
|
<!-- <div class="item">
|
||||||
|
<div class="ui icon input">
|
||||||
|
<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}">
|
||||||
|
<i class="search icon"></i>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
{{if .IsSigned}}
|
{{if .IsSigned}}
|
||||||
<div class="ui right floated secondary menu">
|
<div class="right menu">
|
||||||
<a class="view-ui item user avatar poping up" href="{{AppSubUrl}}/{{.SignedUser.Name}}" data-content="{{.SignedUser.Name}}" data-variation="inverted">
|
<a class="view-ui item user avatar poping up" href="{{AppSubUrl}}/{{.SignedUser.Name}}" data-content="{{.SignedUser.Name}}" data-variation="inverted">
|
||||||
<img class="img-15" src="{{.SignedUser.AvatarLink}}"/>
|
<img class="img-15" src="{{.SignedUser.AvatarLink}}"/>
|
||||||
<span class="sr-only">{{.SignedUser.Name}}</span>
|
<span class="sr-only">{{.SignedUser.Name}}</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="ui pointing dropdown head link jump item">
|
<div class="ui dropdown head link jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<i class="octicon octicon-plus"></i>
|
<i class="octicon octicon-plus"></i>
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
|
@ -79,17 +91,6 @@
|
||||||
<a class="view-ui item {{if .PageIsSignIn}}active{{end}}" href="{{AppSubUrl}}/user/login"><i class="octicon octicon-sign-in"></i> {{.i18n.Tr "sign_in"}}</a>
|
<a class="view-ui item {{if .PageIsSignIn}}active{{end}}" href="{{AppSubUrl}}/user/login"><i class="octicon octicon-sign-in"></i> {{.i18n.Tr "sign_in"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui secondary menu">
|
|
||||||
<img class="img-15 ui image brand" src="{{AppSubUrl}}/img/favicon.png">
|
|
||||||
<a class="view-ui item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/">{{if .IsSigned}}{{.i18n.Tr "dashboard"}}{{else}}{{.i18n.Tr "home"}}{{end}}</a>
|
|
||||||
<a class="view-ui item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore">{{.i18n.Tr "explore"}}</a>
|
|
||||||
<a class="view-ui item" target="_blank" href="http://gogs.io/docs">{{.i18n.Tr "help"}}</a>
|
|
||||||
<!-- <div class="item">
|
|
||||||
<div class="ui icon input">
|
|
||||||
<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}">
|
|
||||||
<i class="search icon"></i>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{{with .Repository}}
|
{{with .Repository}}
|
||||||
<div class="ui middle page head grid">
|
<div class="ui head container">
|
||||||
<h2 class="ui left">
|
<div class="ui huge breadcrumb">
|
||||||
<div class="ui breadcrumb">
|
|
||||||
<i class="mega-octicon octicon-{{if .IsPrivate}}lock{{else if .IsMirror}}repo-clone{{else if .IsFork}}repo-forked{{else}}repo{{end}}"></i>
|
<i class="mega-octicon octicon-{{if .IsPrivate}}lock{{else if .IsMirror}}repo-clone{{else if .IsFork}}repo-forked{{else}}repo{{end}}"></i>
|
||||||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
|
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
|
||||||
<div class="divider"> / </div>
|
<div class="divider"> / </div>
|
||||||
|
@ -9,8 +8,7 @@
|
||||||
{{if .IsMirror}}<div class="ui label">{{$.i18n.Tr "mirror"}}</div>{{end}}
|
{{if .IsMirror}}<div class="ui label">{{$.i18n.Tr "mirror"}}</div>{{end}}
|
||||||
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.RepoLink}}">{{SubStr .BaseRepo.RepoLink 1 -1}}</a></div>{{end}}
|
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.RepoLink}}">{{SubStr .BaseRepo.RepoLink 1 -1}}</a></div>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
<div class="ui right">
|
||||||
<div class="ui right floated secondary menu">
|
|
||||||
<a class="ui black basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
|
<a class="ui black basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
|
||||||
<i class="fa fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>
|
<i class="fa fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>
|
||||||
{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}} <span class="num">{{.NumWatches}}</span>
|
{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}} <span class="num">{{.NumWatches}}</span>
|
||||||
|
@ -19,7 +17,7 @@
|
||||||
<i class="fa fa-star{{if not $.IsStaringRepo}}-o{{end}}"></i>
|
<i class="fa fa-star{{if not $.IsStaringRepo}}-o{{end}}"></i>
|
||||||
{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}} <span class="num">{{.NumStars}}</span>
|
{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}} <span class="num">{{.NumStars}}</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="ui black basic button {{if $.IsRepositoryOwner}}poping up{{end}}" {{if not $.IsRepositoryOwner}}href="{{AppSubUrl}}/repo/fork/{{.Id}}"{{end}} {{if $.IsRepositoryOwner}}data-content="{{$.i18n.Tr "repo.fork_from_self"}}"{{end}}>
|
<a class="ui black basic button {{if $.IsRepositoryOwner}}poping up{{end}}" {{if not $.IsRepositoryOwner}}href="{{AppSubUrl}}/repo/fork/{{.Id}}"{{end}} {{if $.IsRepositoryOwner}}data-content="{{$.i18n.Tr "repo.fork_from_self"}}" data-position="top right"{{end}}>
|
||||||
<i class="octicon octicon-repo-forked"></i>
|
<i class="octicon octicon-repo-forked"></i>
|
||||||
{{$.i18n.Tr "repo.fork"}} <span class="num">{{.NumForks}}</span>
|
{{$.i18n.Tr "repo.fork"}} <span class="num">{{.NumForks}}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{{if .Flash}}
|
|
||||||
<div class="sixteen wide center aligned centered column">
|
|
||||||
{{template "base/alert" .}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
|
@ -1,38 +1,41 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div class="repository labels">
|
<div class="repository labels">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui middle page grid body">
|
<div class="ui container">
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if .IsRepositoryAdmin}}
|
{{if .IsRepositoryAdmin}}
|
||||||
<form class="ui right form" action="{{$.RepoLink}}/labels/new" method="post">
|
<div class="ui right">
|
||||||
{{.CsrfTokenHtml}}
|
<div class="ui green new-label button">{{.i18n.Tr "repo.issues.new_label"}}</div>
|
||||||
<div class="ui right floated secondary menu">
|
|
||||||
<div class="input item">
|
|
||||||
<div class="ui large input">
|
|
||||||
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" required>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<div class="ui large input">
|
|
||||||
<input class="color-picker" name="color" value="#70c24a" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item precolors">
|
|
||||||
{{template "repo/issue/label_precolors"}}
|
|
||||||
</div>
|
|
||||||
<button class="ui green button">{{.i18n.Tr "repo.issues.new_label"}}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui new-label segment hide">
|
||||||
{{template "repo/issue/alert" .}}
|
<form class="ui form" action="{{$.RepoLink}}/labels/new" method="post">
|
||||||
<div class="ui left">
|
{{.CsrfTokenHtml}}
|
||||||
<div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div>
|
<div class="ui grid">
|
||||||
|
<div class="five wide column">
|
||||||
|
<div class="ui small input">
|
||||||
|
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="color picker column">
|
||||||
|
<input class="color-picker" name="color" value="#70c24a" required>
|
||||||
|
</div>
|
||||||
|
<div class="column precolors">
|
||||||
|
{{template "repo/issue/label_precolors"}}
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<div class="ui blue small basic cancel button">{{.i18n.Tr "repo.milestones.cancel"}}</div>
|
||||||
|
<button class="ui green small button">{{.i18n.Tr "repo.issues.create_label"}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
{{template "base/alert" .}}
|
||||||
|
<div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div>
|
||||||
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<div class="label list">
|
<div class="label list">
|
||||||
{{range .Labels}}
|
{{range .Labels}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
|
@ -46,34 +49,27 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .IsRepositoryAdmin}}
|
{{if .IsRepositoryAdmin}}
|
||||||
<div class="ui basic delete modal">
|
<div class="ui small basic delete modal">
|
||||||
<div class="header">
|
<div class="ui icon header">
|
||||||
|
<i class="trash icon"></i>
|
||||||
{{.i18n.Tr "repo.issues.label_deletion"}}
|
{{.i18n.Tr "repo.issues.label_deletion"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="image">
|
|
||||||
<i class="trash icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<p>{{.i18n.Tr "repo.issues.label_deletion_desc"}}</p>
|
<p>{{.i18n.Tr "repo.issues.label_deletion_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="two fluid ui inverted buttons">
|
<div class="ui red basic inverted cancel button">
|
||||||
<div class="ui red basic inverted button">
|
|
||||||
<i class="remove icon"></i>
|
<i class="remove icon"></i>
|
||||||
{{.i18n.Tr "modal.no"}}
|
{{.i18n.Tr "modal.no"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui green basic inverted positive button">
|
<div class="ui green basic inverted ok button">
|
||||||
<i class="checkmark icon"></i>
|
<i class="checkmark icon"></i>
|
||||||
{{.i18n.Tr "modal.yes"}}
|
{{.i18n.Tr "modal.yes"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui small edit-label modal">
|
<div class="ui small edit-label modal">
|
||||||
|
@ -84,14 +80,16 @@
|
||||||
<form class="ui edit-label form" action="{{$.RepoLink}}/labels/edit" method="post">
|
<form class="ui edit-label form" action="{{$.RepoLink}}/labels/edit" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<input id="label-modal-id" name="id" type="hidden">
|
<input id="label-modal-id" name="id" type="hidden">
|
||||||
<div class="inline fields">
|
<div class="ui grid">
|
||||||
<div class="field">
|
<div class="five wide column">
|
||||||
<input id="label-modal-title" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" required>
|
<div class="ui small input">
|
||||||
|
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<input id="label-modal-color" class="color-picker" name="color" value="#70c24a" required>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="field precolors">
|
<div class="color picker column">
|
||||||
|
<input class="color-picker" name="color" value="#70c24a" required>
|
||||||
|
</div>
|
||||||
|
<div class="column precolors">
|
||||||
{{template "repo/issue/label_precolors"}}
|
{{template "repo/issue/label_precolors"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div class="repository">
|
<div class="repository">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui middle page grid body">
|
<div class="ui container">
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
<div class="ui right floated secondary menu">
|
<div class="ui right">
|
||||||
<a class="ui green button" href="{{$.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a>
|
<a class="ui green button" href="{{$.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="ui left">
|
|
||||||
<div class="ui tiny buttons">
|
<div class="ui tiny buttons">
|
||||||
<a class="ui green basic button {{if not .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/issues?type={{$.ViewType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}">
|
<a class="ui green basic button {{if not .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/issues?type={{$.ViewType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}">
|
||||||
<i class="octicon octicon-issue-opened"></i>
|
<i class="octicon octicon-issue-opened"></i>
|
||||||
|
@ -20,9 +19,8 @@
|
||||||
{{.i18n.Tr "repo.issues.close_tab" .IssueStats.ClosedCount}}
|
{{.i18n.Tr "repo.issues.close_tab" .IssueStats.ClosedCount}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="ui right floated secondary filter menu">
|
<div class="ui right floated secondary filter menu">
|
||||||
<div class="ui {{if not .Labels}}disabled{{end}} pointing dropdown jump item">
|
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.i18n.Tr "repo.issues.filter_label"}}
|
{{.i18n.Tr "repo.issues.filter_label"}}
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
|
@ -34,7 +32,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui {{if not .Milestones}}disabled{{end}} pointing dropdown jump item">
|
<div class="ui {{if not .Milestones}}disabled{{end}} dropdown jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.i18n.Tr "repo.issues.filter_milestone"}}
|
{{.i18n.Tr "repo.issues.filter_milestone"}}
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
|
@ -46,7 +44,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="ui {{if not .Assignees}}disabled{{end}} pointing dropdown jump item">
|
<!-- <div class="ui {{if not .Assignees}}disabled{{end}} dropdown jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.i18n.Tr "repo.issues.filter_assignee"}}
|
{{.i18n.Tr "repo.issues.filter_assignee"}}
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
|
@ -57,7 +55,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="ui pointing dropdown type jump item">
|
<div class="ui dropdown type jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.i18n.Tr "repo.issues.filter_type"}}
|
{{.i18n.Tr "repo.issues.filter_type"}}
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
|
@ -71,7 +69,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<div class="issue list">
|
<div class="issue list">
|
||||||
{{range .Issues}}
|
{{range .Issues}}
|
||||||
{{ $timeStr:= TimeSince .Created $.Lang }}
|
{{ $timeStr:= TimeSince .Created $.Lang }}
|
||||||
|
@ -123,6 +120,5 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div class="repository new milestone">
|
<div class="repository new milestone">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui middle page grid body">
|
<div class="ui container">
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if and .IsRepositoryAdmin .PageIsEditMilestone}}
|
{{if and .IsRepositoryAdmin .PageIsEditMilestone}}
|
||||||
|
@ -11,7 +11,6 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="sixteen wide column page grid">
|
|
||||||
<h2 class="ui dividing header">
|
<h2 class="ui dividing header">
|
||||||
{{if .PageIsEditMilestone}}
|
{{if .PageIsEditMilestone}}
|
||||||
{{.i18n.Tr "repo.milestones.edit"}}
|
{{.i18n.Tr "repo.milestones.edit"}}
|
||||||
|
@ -21,13 +20,9 @@
|
||||||
<div class="sub header">{{.i18n.Tr "repo.milestones.new_subheader"}}</div>
|
<div class="sub header">{{.i18n.Tr "repo.milestones.new_subheader"}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</h2>
|
</h2>
|
||||||
|
{{template "base/alert" .}}
|
||||||
<form class="ui form grid" action="{{.Link}}" method="post">
|
<form class="ui form grid" action="{{.Link}}" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
{{if .Flash}}
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
{{template "base/alert" .}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
<div class="eleven wide column">
|
<div class="eleven wide column">
|
||||||
<div class="field {{if .Err_Title}}error{{end}}">
|
<div class="field {{if .Err_Title}}error{{end}}">
|
||||||
<label>{{.i18n.Tr "repo.milestones.title"}}</label>
|
<label>{{.i18n.Tr "repo.milestones.title"}}</label>
|
||||||
|
@ -38,7 +33,7 @@
|
||||||
<textarea name="content">{{.content}}</textarea>
|
<textarea name="content">{{.content}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="three wide column">
|
<div class="four wide column">
|
||||||
<div class="field {{if .Err_Deadline}}error{{end}}">
|
<div class="field {{if .Err_Deadline}}error{{end}}">
|
||||||
<label>
|
<label>
|
||||||
{{.i18n.Tr "repo.milestones.due_date"}}
|
{{.i18n.Tr "repo.milestones.due_date"}}
|
||||||
|
@ -50,21 +45,24 @@
|
||||||
<input class="milestone datepicker" data-lang="{{.DateLang}}" data-start-date="{{.deadline}}">
|
<input class="milestone datepicker" data-lang="{{.DateLang}}" data-start-date="{{.deadline}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ui container">
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
|
<div class="ui right">
|
||||||
{{if .PageIsEditMilestone}}
|
{{if .PageIsEditMilestone}}
|
||||||
<button class="ui right green button">
|
<a class="ui blue basic button" href="{{.RepoLink}}/milestones">
|
||||||
{{.i18n.Tr "repo.milestones.modify"}}
|
|
||||||
</button>
|
|
||||||
<a class="ui right blue basic button" href="{{.RepoLink}}/milestones">
|
|
||||||
{{.i18n.Tr "repo.milestones.cancel"}}
|
{{.i18n.Tr "repo.milestones.cancel"}}
|
||||||
</a>
|
</a>
|
||||||
|
<button class="ui green button">
|
||||||
|
{{.i18n.Tr "repo.milestones.modify"}}
|
||||||
|
</button>
|
||||||
{{else}}
|
{{else}}
|
||||||
<button class="ui right green button">
|
<button class="ui green button">
|
||||||
{{.i18n.Tr "repo.milestones.create"}}
|
{{.i18n.Tr "repo.milestones.create"}}
|
||||||
</button>
|
</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -1,18 +1,17 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div class="repository milestones">
|
<div class="repository milestones">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui middle page grid body">
|
<div class="ui container">
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if .IsRepositoryAdmin}}
|
{{if .IsRepositoryAdmin}}
|
||||||
<div class="ui right floated secondary menu">
|
<div class="ui right">
|
||||||
<a class="ui green button" href="{{$.Link}}/new">{{.i18n.Tr "repo.milestones.new"}}</a>
|
<a class="ui green button" href="{{$.Link}}/new">{{.i18n.Tr "repo.milestones.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{template "repo/issue/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="ui left">
|
|
||||||
<div class="ui tiny buttons">
|
<div class="ui tiny buttons">
|
||||||
<a class="ui green basic button {{if not .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/milestones?state=open">
|
<a class="ui green basic button {{if not .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/milestones?state=open">
|
||||||
<i class="octicon octicon-milestone"></i>
|
<i class="octicon octicon-milestone"></i>
|
||||||
|
@ -23,14 +22,12 @@
|
||||||
{{.i18n.Tr "repo.milestones.close_tab" .ClosedCount}}
|
{{.i18n.Tr "repo.milestones.close_tab" .ClosedCount}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sixteen wide column">
|
|
||||||
<div class="milestone list">
|
<div class="milestone list">
|
||||||
{{range .Milestones}}
|
{{range .Milestones}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<i class="octicon octicon-milestone"></i> <a href="{{$.RepoLink}}/issues?state={{$.State}}&milestone={{.ID}}">{{.Name}}</a>
|
<i class="octicon octicon-milestone"></i> <a href="{{$.RepoLink}}/issues?state={{$.State}}&milestone={{.ID}}">{{.Name}}</a>
|
||||||
<div class="ui right blue progress" data-percent="{{.Completeness}}">
|
<div class="ui right green progress" data-percent="{{.Completeness}}">
|
||||||
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
|
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
|
||||||
<div class="progress"></div>
|
<div class="progress"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -94,34 +91,27 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .IsRepositoryAdmin}}
|
{{if .IsRepositoryAdmin}}
|
||||||
<div class="ui basic delete modal">
|
<div class="ui small basic delete modal">
|
||||||
<div class="header">
|
<div class="ui icon header">
|
||||||
|
<i class="trash icon"></i>
|
||||||
{{.i18n.Tr "repo.milestones.deletion"}}
|
{{.i18n.Tr "repo.milestones.deletion"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="image">
|
|
||||||
<i class="trash icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<p>{{.i18n.Tr "repo.milestones.deletion_desc"}}</p>
|
<p>{{.i18n.Tr "repo.milestones.deletion_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="two fluid ui inverted buttons">
|
<div class="ui red basic inverted cancel button">
|
||||||
<div class="ui red basic inverted button">
|
|
||||||
<i class="remove icon"></i>
|
<i class="remove icon"></i>
|
||||||
{{.i18n.Tr "modal.no"}}
|
{{.i18n.Tr "modal.no"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui green basic inverted positive button">
|
<div class="ui green basic inverted ok button">
|
||||||
<i class="checkmark icon"></i>
|
<i class="checkmark icon"></i>
|
||||||
{{.i18n.Tr "modal.yes"}}
|
{{.i18n.Tr "modal.yes"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -1,7 +1,5 @@
|
||||||
<div class="ui left">
|
<div class="ui compact small menu">
|
||||||
<div class="ui compact menu">
|
|
||||||
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a>
|
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a>
|
||||||
<a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a>
|
<a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a>
|
||||||
<a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a>
|
<a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
|
@ -69,7 +69,9 @@
|
||||||
<a href="{{AppSubUrl}}/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created $.Lang}}</span>
|
<a href="{{AppSubUrl}}/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created $.Lang}}</span>
|
||||||
<!-- <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a>
|
<!-- <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a>
|
||||||
<a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> -->
|
<a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> -->
|
||||||
|
{{if eq .Poster.Id $.Owner.Id}}
|
||||||
<span class="role label label-default pull-right">Owner</span>
|
<span class="role label label-default pull-right">Owner</span>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body markdown">
|
<div class="panel-body markdown">
|
||||||
{{if len .Content}}
|
{{if len .Content}}
|
||||||
|
@ -251,7 +253,7 @@
|
||||||
<h4>Milestone</h4>
|
<h4>Milestone</h4>
|
||||||
{{if .Milestone}}
|
{{if .Milestone}}
|
||||||
<p class="completion{{if eq .Milestone.Completeness 0}} hidden{{end}}"><span style="width:{{.Milestone.Completeness}}%"> </span></p>
|
<p class="completion{{if eq .Milestone.Completeness 0}} hidden{{end}}"><span style="width:{{.Milestone.Completeness}}%"> </span></p>
|
||||||
<p class="name"><strong><a href="{{$.RepoLink}}/issues?milestone={{.Milestone.Index}}{{if $.Issue.IsClosed}}&state=closed{{end}}">{{.Milestone.Name}}</a></strong></p>
|
<p class="name"><strong><a href="{{$.RepoLink}}/issues?milestone={{.Milestone.ID}}{{if $.Issue.IsClosed}}&state=closed{{end}}">{{.Milestone.Name}}</a></strong></p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="name">No milestone</p>
|
<p class="name">No milestone</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -14,19 +14,19 @@
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required>
|
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<img class="ui mini avatar image" src="{{.ContextUser.AvatarLink}}">
|
<img class="ui mini image" src="{{.ContextUser.AvatarLink}}">
|
||||||
{{.ContextUser.Name}}
|
{{.ContextUser.Name}}
|
||||||
</span>
|
</span>
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item" data-value="{{.SignedUser.Id}}">
|
<div class="item" data-value="{{.SignedUser.Id}}">
|
||||||
<img class="ui mini avatar image" src="{{.SignedUser.AvatarLink}}">
|
<img class="ui mini image" src="{{.SignedUser.AvatarLink}}">
|
||||||
{{.SignedUser.Name}}
|
{{.SignedUser.Name}}
|
||||||
</div>
|
</div>
|
||||||
{{range .Orgs}}
|
{{range .Orgs}}
|
||||||
{{if .IsOwnedBy $.SignedUser.Id}}
|
{{if .IsOwnedBy $.SignedUser.Id}}
|
||||||
<div class="item" data-value="{{.Id}}">
|
<div class="item" data-value="{{.Id}}">
|
||||||
<img class="ui mini avatar image" src="{{.AvatarLink}}">
|
<img class="ui mini image" src="{{.AvatarLink}}">
|
||||||
{{.Name}}
|
{{.Name}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div class="repository settings">
|
<div class="repository settings">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui page grid">
|
<div class="ui container">
|
||||||
|
<div class="ui grid">
|
||||||
{{template "repo/settings/navbar" .}}
|
{{template "repo/settings/navbar" .}}
|
||||||
<div class="twelve wide column content">
|
<div class="twelve wide column content">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<h4 class="ui top attached header">
|
<h3 class="ui top attached header">
|
||||||
{{.i18n.Tr "repo.settings.deploy_keys"}}
|
{{.i18n.Tr "repo.settings.deploy_keys"}}
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<div id="add-deploy-key" class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_deploy_key"}}</div>
|
<div id="add-deploy-key" class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_deploy_key"}}</div>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h3>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
{{if .Deploykeys}}
|
{{if .Deploykeys}}
|
||||||
<div class="ui key list">
|
<div class="ui key list">
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
<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>
|
<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>
|
</div>
|
||||||
<div class="three wide column">
|
<div class="two wide column">
|
||||||
<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}">
|
<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}">
|
||||||
{{$.i18n.Tr "settings.delete_key"}}
|
{{$.i18n.Tr "settings.delete_key"}}
|
||||||
</button>
|
</button>
|
||||||
|
@ -67,31 +68,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui basic delete modal">
|
<div class="ui small basic delete modal">
|
||||||
<div class="header">
|
<div class="ui icon header">
|
||||||
|
<i class="trash icon"></i>
|
||||||
{{.i18n.Tr "repo.settings.deploy_key_deletion"}}
|
{{.i18n.Tr "repo.settings.deploy_key_deletion"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="image">
|
|
||||||
<i class="trash icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<p>{{.i18n.Tr "repo.settings.deploy_key_deletion_desc"}}</p>
|
<p>{{.i18n.Tr "repo.settings.deploy_key_deletion_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="two fluid ui inverted buttons">
|
<div class="ui red basic inverted cancel button">
|
||||||
<div class="ui red basic inverted button">
|
|
||||||
<i class="remove icon"></i>
|
<i class="remove icon"></i>
|
||||||
{{.i18n.Tr "modal.no"}}
|
{{.i18n.Tr "modal.no"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui green basic inverted positive button">
|
<div class="ui green basic inverted ok button">
|
||||||
<i class="checkmark icon"></i>
|
<i class="checkmark icon"></i>
|
||||||
{{.i18n.Tr "modal.yes"}}
|
{{.i18n.Tr "modal.yes"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -1,5 +1,6 @@
|
||||||
<div class="four wide column">
|
<div class="four wide column">
|
||||||
<div class="ui vertical menu">
|
<div class="ui vertical menu">
|
||||||
|
<div class="header item">{{.i18n.Tr "repo.settings"}}</div>
|
||||||
<a class="{{if .PageIsSettingsOptions}}active{{end}} item" href="{{.RepoLink}}/settings">
|
<a class="{{if .PageIsSettingsOptions}}active{{end}} item" href="{{.RepoLink}}/settings">
|
||||||
{{.i18n.Tr "repo.settings.options"}}
|
{{.i18n.Tr "repo.settings.options"}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
{{range $push.Commits}}
|
{{range $push.Commits}}
|
||||||
<li><img class="avatar-16" src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text-truncate grid-4-5">{{.Message}}</span></li>
|
<li><img class="avatar-16" src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text-truncate grid-4-5">{{.Message}}</span></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $push.CompareUrl}}<li><a href="{{$.AppSubUrl}}/{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}}
|
{{if $push.CompareUrl}}<li><a href="{{AppSubUrl}}/{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .GetOpType 6}}
|
{{else if eq .GetOpType 6}}
|
||||||
|
|
Reference in a new issue