mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-15 00:01:25 -04:00
Compare commits
12 Commits
0bd05a9f1c
...
8f4dafcd4e
Author | SHA1 | Date | |
---|---|---|---|
|
8f4dafcd4e | ||
|
0f52beb6b7 | ||
|
cc84c58aff | ||
|
a18919bba6 | ||
|
cc64a92560 | ||
|
94d6b5b09d | ||
|
f766b00293 | ||
|
241b74f6c5 | ||
|
5a5ab8ef5a | ||
|
72e956b79a | ||
|
fc62992518 | ||
|
9cf721e446 |
@ -1899,11 +1899,6 @@ ROUTER = console
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Specifies the format for fully outputted dates. Defaults to RFC1123
|
|
||||||
;; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
|
|
||||||
;; For more information about the format see http://golang.org/pkg/time/#pkg-constants
|
|
||||||
;FORMAT =
|
|
||||||
;;
|
|
||||||
;; Location the UI time display i.e. Asia/Shanghai
|
;; Location the UI time display i.e. Asia/Shanghai
|
||||||
;; Empty means server's location setting
|
;; Empty means server's location setting
|
||||||
;DEFAULT_UI_LOCATION =
|
;DEFAULT_UI_LOCATION =
|
||||||
|
@ -1207,7 +1207,6 @@ in this mapping or the filetype using heuristics.
|
|||||||
|
|
||||||
## Time (`time`)
|
## Time (`time`)
|
||||||
|
|
||||||
- `FORMAT`: Time format to display on UI. i.e. RFC1123 or 2006-01-02 15:04:05
|
|
||||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
||||||
|
|
||||||
## Task (`task`)
|
## Task (`task`)
|
||||||
|
@ -346,7 +346,7 @@ func GetUserFollowing(ctx context.Context, u, viewer *User, listOptions db.ListO
|
|||||||
Select("`user`.*").
|
Select("`user`.*").
|
||||||
Join("LEFT", "follow", "`user`.id=follow.follow_id").
|
Join("LEFT", "follow", "`user`.id=follow.follow_id").
|
||||||
Where("follow.user_id=?", u.ID).
|
Where("follow.user_id=?", u.ID).
|
||||||
And("`user`.type=?", UserTypeIndividual).
|
And("`user`.type IN (?, ?)", UserTypeIndividual, UserTypeOrganization).
|
||||||
And(isUserVisibleToViewerCond(viewer))
|
And(isUserVisibleToViewerCond(viewer))
|
||||||
|
|
||||||
if listOptions.Page != 0 {
|
if listOptions.Page != 0 {
|
||||||
@ -1210,23 +1210,25 @@ func isUserVisibleToViewerCond(viewer *User) builder.Cond {
|
|||||||
return builder.Neq{
|
return builder.Neq{
|
||||||
"`user`.visibility": structs.VisibleTypePrivate,
|
"`user`.visibility": structs.VisibleTypePrivate,
|
||||||
}.Or(
|
}.Or(
|
||||||
|
// viewer's following
|
||||||
builder.In("`user`.id",
|
builder.In("`user`.id",
|
||||||
builder.
|
builder.
|
||||||
Select("`follow`.user_id").
|
Select("`follow`.user_id").
|
||||||
From("follow").
|
From("follow").
|
||||||
Where(builder.Eq{"`follow`.follow_id": viewer.ID})),
|
Where(builder.Eq{"`follow`.follow_id": viewer.ID})),
|
||||||
builder.In("`user`.id",
|
// viewer's org user
|
||||||
builder.
|
|
||||||
Select("`team_user`.uid").
|
|
||||||
From("team_user").
|
|
||||||
Join("INNER", "`team_user` AS t2", "`team_user`.id = `t2`.id").
|
|
||||||
Where(builder.Eq{"`t2`.uid": viewer.ID})),
|
|
||||||
builder.In("`user`.id",
|
builder.In("`user`.id",
|
||||||
builder.
|
builder.
|
||||||
Select("`team_user`.uid").
|
Select("`team_user`.uid").
|
||||||
From("team_user").
|
From("team_user").
|
||||||
Join("INNER", "`team_user` AS t2", "`team_user`.org_id = `t2`.org_id").
|
Join("INNER", "`team_user` AS t2", "`team_user`.org_id = `t2`.org_id").
|
||||||
Where(builder.Eq{"`t2`.uid": viewer.ID})))
|
Where(builder.Eq{"`t2`.uid": viewer.ID})),
|
||||||
|
// viewer's org
|
||||||
|
builder.In("`user`.id",
|
||||||
|
builder.
|
||||||
|
Select("`team_user`.org_id").
|
||||||
|
From("team_user").
|
||||||
|
Where(builder.Eq{"`team_user`.uid": viewer.ID})))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserVisibleToViewer check if viewer is able to see user profile
|
// IsUserVisibleToViewer check if viewer is able to see user profile
|
||||||
|
@ -187,8 +187,8 @@ func (c *Commit) CommitsCount() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize
|
// CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize
|
||||||
func (c *Commit) CommitsByRange(page, pageSize int) ([]*Commit, error) {
|
func (c *Commit) CommitsByRange(page, pageSize int, not string) ([]*Commit, error) {
|
||||||
return c.repo.commitsByRange(c.ID, page, pageSize)
|
return c.repo.commitsByRange(c.ID, page, pageSize, not)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitsBefore returns all the commits before current revision
|
// CommitsBefore returns all the commits before current revision
|
||||||
|
@ -90,14 +90,22 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
|
|||||||
return commits[0], nil
|
return commits[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) ([]*Commit, error) {
|
func (repo *Repository) commitsByRange(id SHA1, page, pageSize int, not string) ([]*Commit, error) {
|
||||||
stdout, _, err := NewCommand(repo.Ctx, "log").
|
cmd := NewCommand(repo.Ctx, "log").
|
||||||
AddOptionFormat("--skip=%d", (page-1)*pageSize).AddOptionFormat("--max-count=%d", pageSize).AddArguments(prettyLogFormat).
|
AddOptionFormat("--skip=%d", (page-1)*pageSize).
|
||||||
AddDynamicArguments(id.String()).
|
AddOptionFormat("--max-count=%d", pageSize).
|
||||||
RunStdBytes(&RunOpts{Dir: repo.Path})
|
AddArguments(prettyLogFormat).
|
||||||
|
AddDynamicArguments(id.String())
|
||||||
|
|
||||||
|
if not != "" {
|
||||||
|
cmd.AddOptionValues("--not", not)
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return repo.parsePrettyFormatLogToList(stdout)
|
return repo.parsePrettyFormatLogToList(stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package queue
|
package queue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -101,6 +102,9 @@ func TestChannelQueue_Batch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChannelQueue_Pause(t *testing.T) {
|
func TestChannelQueue_Pause(t *testing.T) {
|
||||||
|
if os.Getenv("CI") != "" {
|
||||||
|
t.Skip("Skipping because test is flaky on CI")
|
||||||
|
}
|
||||||
lock := sync.Mutex{}
|
lock := sync.Mutex{}
|
||||||
var queue Queue
|
var queue Queue
|
||||||
var err error
|
var err error
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package queue
|
package queue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@ -15,6 +16,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPersistableChannelUniqueQueue(t *testing.T) {
|
func TestPersistableChannelUniqueQueue(t *testing.T) {
|
||||||
|
if os.Getenv("CI") != "" {
|
||||||
|
t.Skip("Skipping because test is flaky on CI")
|
||||||
|
}
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
|
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
|
||||||
|
|
||||||
|
@ -9,45 +9,10 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// DefaultUILocation is the location on the UI, so that we can display the time on UI.
|
||||||
// Time settings
|
var DefaultUILocation = time.Local
|
||||||
TimeFormat string
|
|
||||||
// UILocation is the location on the UI, so that we can display the time on UI.
|
|
||||||
DefaultUILocation = time.Local
|
|
||||||
)
|
|
||||||
|
|
||||||
func loadTimeFrom(rootCfg ConfigProvider) {
|
func loadTimeFrom(rootCfg ConfigProvider) {
|
||||||
timeFormatKey := rootCfg.Section("time").Key("FORMAT").MustString("")
|
|
||||||
if timeFormatKey != "" {
|
|
||||||
TimeFormat = map[string]string{
|
|
||||||
"ANSIC": time.ANSIC,
|
|
||||||
"UnixDate": time.UnixDate,
|
|
||||||
"RubyDate": time.RubyDate,
|
|
||||||
"RFC822": time.RFC822,
|
|
||||||
"RFC822Z": time.RFC822Z,
|
|
||||||
"RFC850": time.RFC850,
|
|
||||||
"RFC1123": time.RFC1123,
|
|
||||||
"RFC1123Z": time.RFC1123Z,
|
|
||||||
"RFC3339": time.RFC3339,
|
|
||||||
"RFC3339Nano": time.RFC3339Nano,
|
|
||||||
"Kitchen": time.Kitchen,
|
|
||||||
"Stamp": time.Stamp,
|
|
||||||
"StampMilli": time.StampMilli,
|
|
||||||
"StampMicro": time.StampMicro,
|
|
||||||
"StampNano": time.StampNano,
|
|
||||||
}[timeFormatKey]
|
|
||||||
// When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05'
|
|
||||||
if len(TimeFormat) == 0 {
|
|
||||||
TimeFormat = timeFormatKey
|
|
||||||
TestTimeFormat, _ := time.Parse(TimeFormat, TimeFormat)
|
|
||||||
if TestTimeFormat.Format(time.RFC3339) != "2006-01-02T15:04:05Z" {
|
|
||||||
log.Warn("Provided TimeFormat: %s does not create a fully specified date and time.", TimeFormat)
|
|
||||||
log.Warn("In order to display dates and times correctly please check your time format has 2006, 01, 02, 15, 04 and 05")
|
|
||||||
}
|
|
||||||
log.Trace("Custom TimeFormat: %s", TimeFormat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zone := rootCfg.Section("time").Key("DEFAULT_UI_LOCATION").String()
|
zone := rootCfg.Section("time").Key("DEFAULT_UI_LOCATION").String()
|
||||||
if zone != "" {
|
if zone != "" {
|
||||||
var err error
|
var err error
|
||||||
|
@ -5,46 +5,25 @@
|
|||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"html/template"
|
"html/template"
|
||||||
"math"
|
|
||||||
"mime"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
activities_model "code.gitea.io/gitea/models/activities"
|
|
||||||
"code.gitea.io/gitea/models/avatars"
|
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
|
||||||
"code.gitea.io/gitea/models/organization"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
system_model "code.gitea.io/gitea/models/system"
|
system_model "code.gitea.io/gitea/models/system"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/emoji"
|
"code.gitea.io/gitea/modules/emoji"
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
giturl "code.gitea.io/gitea/modules/git/url"
|
|
||||||
gitea_html "code.gitea.io/gitea/modules/html"
|
|
||||||
"code.gitea.io/gitea/modules/json"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/markup/markdown"
|
|
||||||
"code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/svg"
|
"code.gitea.io/gitea/modules/svg"
|
||||||
"code.gitea.io/gitea/modules/templates/eval"
|
"code.gitea.io/gitea/modules/templates/eval"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/services/gitdiff"
|
"code.gitea.io/gitea/services/gitdiff"
|
||||||
|
|
||||||
"github.com/editorconfig/editorconfig-core-go/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used from static.go && dynamic.go
|
// Used from static.go && dynamic.go
|
||||||
@ -53,6 +32,8 @@ var mailSubjectSplit = regexp.MustCompile(`(?m)^-{3,}[\s]*$`)
|
|||||||
// NewFuncMap returns functions for injecting to templates
|
// NewFuncMap returns functions for injecting to templates
|
||||||
func NewFuncMap() []template.FuncMap {
|
func NewFuncMap() []template.FuncMap {
|
||||||
return []template.FuncMap{map[string]interface{}{
|
return []template.FuncMap{map[string]interface{}{
|
||||||
|
"DumpVar": dumpVar,
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// html/template related functions
|
// html/template related functions
|
||||||
"dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names.
|
"dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names.
|
||||||
@ -63,6 +44,7 @@ func NewFuncMap() []template.FuncMap {
|
|||||||
"JSEscape": template.JSEscapeString,
|
"JSEscape": template.JSEscapeString,
|
||||||
"Str2html": Str2html, // TODO: rename it to SanitizeHTML
|
"Str2html": Str2html, // TODO: rename it to SanitizeHTML
|
||||||
"URLJoin": util.URLJoin,
|
"URLJoin": util.URLJoin,
|
||||||
|
"DotEscape": DotEscape,
|
||||||
|
|
||||||
"PathEscape": url.PathEscape,
|
"PathEscape": url.PathEscape,
|
||||||
"PathEscapeSegments": util.PathEscapeSegments,
|
"PathEscapeSegments": util.PathEscapeSegments,
|
||||||
@ -70,30 +52,7 @@ func NewFuncMap() []template.FuncMap {
|
|||||||
// utils
|
// utils
|
||||||
"StringUtils": NewStringUtils,
|
"StringUtils": NewStringUtils,
|
||||||
"SliceUtils": NewSliceUtils,
|
"SliceUtils": NewSliceUtils,
|
||||||
|
"JsonUtils": NewJsonUtils,
|
||||||
// -----------------------------------------------------------------
|
|
||||||
// string / json
|
|
||||||
// TODO: move string helper functions to StringUtils
|
|
||||||
"Join": strings.Join,
|
|
||||||
"DotEscape": DotEscape,
|
|
||||||
"EllipsisString": base.EllipsisString,
|
|
||||||
"DumpVar": dumpVar,
|
|
||||||
|
|
||||||
"Json": func(in interface{}) string {
|
|
||||||
out, err := json.Marshal(in)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(out)
|
|
||||||
},
|
|
||||||
"JsonPrettyPrint": func(in string) string {
|
|
||||||
var out bytes.Buffer
|
|
||||||
err := json.Indent(&out, []byte(in), "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return out.String()
|
|
||||||
},
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// svg / avatar / icon
|
// svg / avatar / icon
|
||||||
@ -107,31 +66,7 @@ func NewFuncMap() []template.FuncMap {
|
|||||||
"MigrationIcon": MigrationIcon,
|
"MigrationIcon": MigrationIcon,
|
||||||
"ActionIcon": ActionIcon,
|
"ActionIcon": ActionIcon,
|
||||||
|
|
||||||
"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML {
|
"SortArrow": SortArrow,
|
||||||
// if needed
|
|
||||||
if len(normSort) == 0 || len(urlSort) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(urlSort) == 0 && isDefault {
|
|
||||||
// if sort is sorted as default add arrow tho this table header
|
|
||||||
if isDefault {
|
|
||||||
return svg.RenderHTML("octicon-triangle-down", 16)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if sort arg is in url test if it correlates with column header sort arguments
|
|
||||||
// the direction of the arrow should indicate the "current sort order", up means ASC(normal), down means DESC(rev)
|
|
||||||
if urlSort == normSort {
|
|
||||||
// the table is sorted with this header normal
|
|
||||||
return svg.RenderHTML("octicon-triangle-up", 16)
|
|
||||||
} else if urlSort == revSort {
|
|
||||||
// the table is sorted with this header reverse
|
|
||||||
return svg.RenderHTML("octicon-triangle-down", 16)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the table is NOT sorted with this header
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// time / number / format
|
// time / number / format
|
||||||
@ -242,32 +177,9 @@ func NewFuncMap() []template.FuncMap {
|
|||||||
"ReactionToEmoji": ReactionToEmoji,
|
"ReactionToEmoji": ReactionToEmoji,
|
||||||
"RenderNote": RenderNote,
|
"RenderNote": RenderNote,
|
||||||
|
|
||||||
"RenderMarkdownToHtml": func(ctx context.Context, input string) template.HTML {
|
"RenderMarkdownToHtml": RenderMarkdownToHtml,
|
||||||
output, err := markdown.RenderString(&markup.RenderContext{
|
"RenderLabel": RenderLabel,
|
||||||
Ctx: ctx,
|
"RenderLabels": RenderLabels,
|
||||||
URLPrefix: setting.AppSubURL,
|
|
||||||
}, input)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderString: %v", err)
|
|
||||||
}
|
|
||||||
return template.HTML(output)
|
|
||||||
},
|
|
||||||
"RenderLabel": func(ctx context.Context, label *issues_model.Label) template.HTML {
|
|
||||||
return template.HTML(RenderLabel(ctx, label))
|
|
||||||
},
|
|
||||||
"RenderLabels": func(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML {
|
|
||||||
htmlCode := `<span class="labels-list">`
|
|
||||||
for _, label := range labels {
|
|
||||||
// Protect against nil value in labels - shouldn't happen but would cause a panic if so
|
|
||||||
if label == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
htmlCode += fmt.Sprintf("<a href='%s/issues?labels=%d'>%s</a> ",
|
|
||||||
repoLink, label.ID, RenderLabel(ctx, label))
|
|
||||||
}
|
|
||||||
htmlCode += "</span>"
|
|
||||||
return template.HTML(htmlCode)
|
|
||||||
},
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// misc
|
// misc
|
||||||
@ -278,124 +190,11 @@ func NewFuncMap() []template.FuncMap {
|
|||||||
"CommentMustAsDiff": gitdiff.CommentMustAsDiff,
|
"CommentMustAsDiff": gitdiff.CommentMustAsDiff,
|
||||||
"MirrorRemoteAddress": mirrorRemoteAddress,
|
"MirrorRemoteAddress": mirrorRemoteAddress,
|
||||||
|
|
||||||
"ParseDeadline": func(deadline string) []string {
|
"FilenameIsImage": FilenameIsImage,
|
||||||
return strings.Split(deadline, "|")
|
"TabSizeClass": TabSizeClass,
|
||||||
},
|
|
||||||
"FilenameIsImage": func(filename string) bool {
|
|
||||||
mimeType := mime.TypeByExtension(filepath.Ext(filename))
|
|
||||||
return strings.HasPrefix(mimeType, "image/")
|
|
||||||
},
|
|
||||||
"TabSizeClass": func(ec interface{}, filename string) string {
|
|
||||||
var (
|
|
||||||
value *editorconfig.Editorconfig
|
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
if ec != nil {
|
|
||||||
if value, ok = ec.(*editorconfig.Editorconfig); !ok || value == nil {
|
|
||||||
return "tab-size-8"
|
|
||||||
}
|
|
||||||
def, err := value.GetDefinitionForFilename(filename)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("tab size class: getting definition for filename: %v", err)
|
|
||||||
return "tab-size-8"
|
|
||||||
}
|
|
||||||
if def.TabWidth > 0 {
|
|
||||||
return fmt.Sprintf("tab-size-%d", def.TabWidth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "tab-size-8"
|
|
||||||
},
|
|
||||||
"SubJumpablePath": func(str string) []string {
|
|
||||||
var path []string
|
|
||||||
index := strings.LastIndex(str, "/")
|
|
||||||
if index != -1 && index != len(str) {
|
|
||||||
path = append(path, str[0:index+1], str[index+1:])
|
|
||||||
} else {
|
|
||||||
path = append(path, str)
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
},
|
|
||||||
"CompareLink": func(baseRepo, repo *repo_model.Repository, branchName string) string {
|
|
||||||
var curBranch string
|
|
||||||
if repo.ID != baseRepo.ID {
|
|
||||||
curBranch += fmt.Sprintf("%s/%s:", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name))
|
|
||||||
}
|
|
||||||
curBranch += util.PathEscapeSegments(branchName)
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s/compare/%s...%s",
|
|
||||||
baseRepo.Link(),
|
|
||||||
util.PathEscapeSegments(baseRepo.DefaultBranch),
|
|
||||||
curBranch,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvatarHTML creates the HTML for an avatar
|
|
||||||
func AvatarHTML(src string, size int, class, name string) template.HTML {
|
|
||||||
sizeStr := fmt.Sprintf(`%d`, size)
|
|
||||||
|
|
||||||
if name == "" {
|
|
||||||
name = "avatar"
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avatar renders user avatars. args: user, size (int), class (string)
|
|
||||||
func Avatar(ctx context.Context, item interface{}, others ...interface{}) template.HTML {
|
|
||||||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
|
||||||
|
|
||||||
switch t := item.(type) {
|
|
||||||
case *user_model.User:
|
|
||||||
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
|
||||||
if src != "" {
|
|
||||||
return AvatarHTML(src, size, class, t.DisplayName())
|
|
||||||
}
|
|
||||||
case *repo_model.Collaborator:
|
|
||||||
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
|
||||||
if src != "" {
|
|
||||||
return AvatarHTML(src, size, class, t.DisplayName())
|
|
||||||
}
|
|
||||||
case *organization.Organization:
|
|
||||||
src := t.AsUser().AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
|
||||||
if src != "" {
|
|
||||||
return AvatarHTML(src, size, class, t.AsUser().DisplayName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// AvatarByAction renders user avatars from action. args: action, size (int), class (string)
|
|
||||||
func AvatarByAction(ctx context.Context, action *activities_model.Action, others ...interface{}) template.HTML {
|
|
||||||
action.LoadActUser(ctx)
|
|
||||||
return Avatar(ctx, action.ActUser, others...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoAvatar renders repo avatars. args: repo, size(int), class (string)
|
|
||||||
func RepoAvatar(repo *repo_model.Repository, others ...interface{}) template.HTML {
|
|
||||||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
|
||||||
|
|
||||||
src := repo.RelAvatarLink()
|
|
||||||
if src != "" {
|
|
||||||
return AvatarHTML(src, size, class, repo.FullName())
|
|
||||||
}
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string)
|
|
||||||
func AvatarByEmail(ctx context.Context, email, name string, others ...interface{}) template.HTML {
|
|
||||||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
|
||||||
src := avatars.GenerateEmailAvatarFastLink(ctx, email, size*setting.Avatar.RenderedSizeFactor)
|
|
||||||
|
|
||||||
if src != "" {
|
|
||||||
return AvatarHTML(src, size, class, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe render raw as HTML
|
// Safe render raw as HTML
|
||||||
func Safe(raw string) template.HTML {
|
func Safe(raw string) template.HTML {
|
||||||
return template.HTML(raw)
|
return template.HTML(raw)
|
||||||
@ -411,342 +210,6 @@ func DotEscape(raw string) string {
|
|||||||
return strings.ReplaceAll(raw, ".", "\u200d.\u200d")
|
return strings.ReplaceAll(raw, ".", "\u200d.\u200d")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderCommitMessage renders commit message with XSS-safe and special links.
|
|
||||||
func RenderCommitMessage(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
|
||||||
return RenderCommitMessageLink(ctx, msg, urlPrefix, "", metas)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCommitMessageLink renders commit message as a XXS-safe link to the provided
|
|
||||||
// default url, handling for special links.
|
|
||||||
func RenderCommitMessageLink(ctx context.Context, msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
|
|
||||||
cleanMsg := template.HTMLEscapeString(msg)
|
|
||||||
// we can safely assume that it will not return any error, since there
|
|
||||||
// shouldn't be any special HTML.
|
|
||||||
fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
|
||||||
Ctx: ctx,
|
|
||||||
URLPrefix: urlPrefix,
|
|
||||||
DefaultLink: urlDefault,
|
|
||||||
Metas: metas,
|
|
||||||
}, cleanMsg)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderCommitMessage: %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n")
|
|
||||||
if len(msgLines) == 0 {
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
return template.HTML(msgLines[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCommitMessageLinkSubject renders commit message as a XXS-safe link to
|
|
||||||
// the provided default url, handling for special links without email to links.
|
|
||||||
func RenderCommitMessageLinkSubject(ctx context.Context, msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
|
|
||||||
msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace)
|
|
||||||
lineEnd := strings.IndexByte(msgLine, '\n')
|
|
||||||
if lineEnd > 0 {
|
|
||||||
msgLine = msgLine[:lineEnd]
|
|
||||||
}
|
|
||||||
msgLine = strings.TrimRightFunc(msgLine, unicode.IsSpace)
|
|
||||||
if len(msgLine) == 0 {
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// we can safely assume that it will not return any error, since there
|
|
||||||
// shouldn't be any special HTML.
|
|
||||||
renderedMessage, err := markup.RenderCommitMessageSubject(&markup.RenderContext{
|
|
||||||
Ctx: ctx,
|
|
||||||
URLPrefix: urlPrefix,
|
|
||||||
DefaultLink: urlDefault,
|
|
||||||
Metas: metas,
|
|
||||||
}, template.HTMLEscapeString(msgLine))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderCommitMessageSubject: %v", err)
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
return template.HTML(renderedMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCommitBody extracts the body of a commit message without its title.
|
|
||||||
func RenderCommitBody(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
|
||||||
msgLine := strings.TrimRightFunc(msg, unicode.IsSpace)
|
|
||||||
lineEnd := strings.IndexByte(msgLine, '\n')
|
|
||||||
if lineEnd > 0 {
|
|
||||||
msgLine = msgLine[lineEnd+1:]
|
|
||||||
} else {
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
msgLine = strings.TrimLeftFunc(msgLine, unicode.IsSpace)
|
|
||||||
if len(msgLine) == 0 {
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
|
|
||||||
renderedMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
|
||||||
Ctx: ctx,
|
|
||||||
URLPrefix: urlPrefix,
|
|
||||||
Metas: metas,
|
|
||||||
}, template.HTMLEscapeString(msgLine))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderCommitMessage: %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return template.HTML(renderedMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match text that is between back ticks.
|
|
||||||
var codeMatcher = regexp.MustCompile("`([^`]+)`")
|
|
||||||
|
|
||||||
// RenderCodeBlock renders "`…`" as highlighted "<code>" block.
|
|
||||||
// Intended for issue and PR titles, these containers should have styles for "<code>" elements
|
|
||||||
func RenderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
|
|
||||||
htmlWithCodeTags := codeMatcher.ReplaceAllString(string(htmlEscapedTextToRender), "<code>$1</code>") // replace with HTML <code> tags
|
|
||||||
return template.HTML(htmlWithCodeTags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderIssueTitle renders issue/pull title with defined post processors
|
|
||||||
func RenderIssueTitle(ctx context.Context, text, urlPrefix string, metas map[string]string) template.HTML {
|
|
||||||
renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
|
|
||||||
Ctx: ctx,
|
|
||||||
URLPrefix: urlPrefix,
|
|
||||||
Metas: metas,
|
|
||||||
}, template.HTMLEscapeString(text))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderIssueTitle: %v", err)
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
return template.HTML(renderedText)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderLabel renders a label
|
|
||||||
func RenderLabel(ctx context.Context, label *issues_model.Label) string {
|
|
||||||
labelScope := label.ExclusiveScope()
|
|
||||||
|
|
||||||
textColor := "#111"
|
|
||||||
if label.UseLightTextColor() {
|
|
||||||
textColor = "#eee"
|
|
||||||
}
|
|
||||||
|
|
||||||
description := emoji.ReplaceAliases(template.HTMLEscapeString(label.Description))
|
|
||||||
|
|
||||||
if labelScope == "" {
|
|
||||||
// Regular label
|
|
||||||
return fmt.Sprintf("<div class='ui label' style='color: %s !important; background-color: %s !important' title='%s'>%s</div>",
|
|
||||||
textColor, label.Color, description, RenderEmoji(ctx, label.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scoped label
|
|
||||||
scopeText := RenderEmoji(ctx, labelScope)
|
|
||||||
itemText := RenderEmoji(ctx, label.Name[len(labelScope)+1:])
|
|
||||||
|
|
||||||
itemColor := label.Color
|
|
||||||
scopeColor := label.Color
|
|
||||||
if r, g, b, err := label.ColorRGB(); err == nil {
|
|
||||||
// Make scope and item background colors slightly darker and lighter respectively.
|
|
||||||
// More contrast needed with higher luminance, empirically tweaked.
|
|
||||||
luminance := (0.299*r + 0.587*g + 0.114*b) / 255
|
|
||||||
contrast := 0.01 + luminance*0.03
|
|
||||||
// Ensure we add the same amount of contrast also near 0 and 1.
|
|
||||||
darken := contrast + math.Max(luminance+contrast-1.0, 0.0)
|
|
||||||
lighten := contrast + math.Max(contrast-luminance, 0.0)
|
|
||||||
// Compute factor to keep RGB values proportional.
|
|
||||||
darkenFactor := math.Max(luminance-darken, 0.0) / math.Max(luminance, 1.0/255.0)
|
|
||||||
lightenFactor := math.Min(luminance+lighten, 1.0) / math.Max(luminance, 1.0/255.0)
|
|
||||||
|
|
||||||
scopeBytes := []byte{
|
|
||||||
uint8(math.Min(math.Round(r*darkenFactor), 255)),
|
|
||||||
uint8(math.Min(math.Round(g*darkenFactor), 255)),
|
|
||||||
uint8(math.Min(math.Round(b*darkenFactor), 255)),
|
|
||||||
}
|
|
||||||
itemBytes := []byte{
|
|
||||||
uint8(math.Min(math.Round(r*lightenFactor), 255)),
|
|
||||||
uint8(math.Min(math.Round(g*lightenFactor), 255)),
|
|
||||||
uint8(math.Min(math.Round(b*lightenFactor), 255)),
|
|
||||||
}
|
|
||||||
|
|
||||||
itemColor = "#" + hex.EncodeToString(itemBytes)
|
|
||||||
scopeColor = "#" + hex.EncodeToString(scopeBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("<span class='ui label scope-parent' title='%s'>"+
|
|
||||||
"<div class='ui label scope-left' style='color: %s !important; background-color: %s !important'>%s</div>"+
|
|
||||||
"<div class='ui label scope-right' style='color: %s !important; background-color: %s !important''>%s</div>"+
|
|
||||||
"</span>",
|
|
||||||
description,
|
|
||||||
textColor, scopeColor, scopeText,
|
|
||||||
textColor, itemColor, itemText)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderEmoji renders html text with emoji post processors
|
|
||||||
func RenderEmoji(ctx context.Context, text string) template.HTML {
|
|
||||||
renderedText, err := markup.RenderEmoji(&markup.RenderContext{Ctx: ctx},
|
|
||||||
template.HTMLEscapeString(text))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderEmoji: %v", err)
|
|
||||||
return template.HTML("")
|
|
||||||
}
|
|
||||||
return template.HTML(renderedText)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionToEmoji renders emoji for use in reactions
|
|
||||||
func ReactionToEmoji(reaction string) template.HTML {
|
|
||||||
val := emoji.FromCode(reaction)
|
|
||||||
if val != nil {
|
|
||||||
return template.HTML(val.Emoji)
|
|
||||||
}
|
|
||||||
val = emoji.FromAlias(reaction)
|
|
||||||
if val != nil {
|
|
||||||
return template.HTML(val.Emoji)
|
|
||||||
}
|
|
||||||
return template.HTML(fmt.Sprintf(`<img alt=":%s:" src="%s/assets/img/emoji/%s.png"></img>`, reaction, setting.StaticURLPrefix, url.PathEscape(reaction)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderNote renders the contents of a git-notes file as a commit message.
|
|
||||||
func RenderNote(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
|
||||||
cleanMsg := template.HTMLEscapeString(msg)
|
|
||||||
fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
|
||||||
Ctx: ctx,
|
|
||||||
URLPrefix: urlPrefix,
|
|
||||||
Metas: metas,
|
|
||||||
}, cleanMsg)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("RenderNote: %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return template.HTML(fullMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines.
|
|
||||||
func IsMultilineCommitMessage(msg string) bool {
|
|
||||||
return strings.Count(strings.TrimSpace(msg), "\n") >= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actioner describes an action
|
|
||||||
type Actioner interface {
|
|
||||||
GetOpType() activities_model.ActionType
|
|
||||||
GetActUserName() string
|
|
||||||
GetRepoUserName() string
|
|
||||||
GetRepoName() string
|
|
||||||
GetRepoPath() string
|
|
||||||
GetRepoLink() string
|
|
||||||
GetBranch() string
|
|
||||||
GetContent() string
|
|
||||||
GetCreate() time.Time
|
|
||||||
GetIssueInfos() []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActionIcon accepts an action operation type and returns an icon class name.
|
|
||||||
func ActionIcon(opType activities_model.ActionType) string {
|
|
||||||
switch opType {
|
|
||||||
case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo:
|
|
||||||
return "repo"
|
|
||||||
case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch:
|
|
||||||
return "git-commit"
|
|
||||||
case activities_model.ActionCreateIssue:
|
|
||||||
return "issue-opened"
|
|
||||||
case activities_model.ActionCreatePullRequest:
|
|
||||||
return "git-pull-request"
|
|
||||||
case activities_model.ActionCommentIssue, activities_model.ActionCommentPull:
|
|
||||||
return "comment-discussion"
|
|
||||||
case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest:
|
|
||||||
return "git-merge"
|
|
||||||
case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest:
|
|
||||||
return "issue-closed"
|
|
||||||
case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest:
|
|
||||||
return "issue-reopened"
|
|
||||||
case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete:
|
|
||||||
return "mirror"
|
|
||||||
case activities_model.ActionApprovePullRequest:
|
|
||||||
return "check"
|
|
||||||
case activities_model.ActionRejectPullRequest:
|
|
||||||
return "diff"
|
|
||||||
case activities_model.ActionPublishRelease:
|
|
||||||
return "tag"
|
|
||||||
case activities_model.ActionPullReviewDismissed:
|
|
||||||
return "x"
|
|
||||||
default:
|
|
||||||
return "question"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActionContent2Commits converts action content to push commits
|
|
||||||
func ActionContent2Commits(act Actioner) *repository.PushCommits {
|
|
||||||
push := repository.NewPushCommits()
|
|
||||||
|
|
||||||
if act == nil || act.GetContent() == "" {
|
|
||||||
return push
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil {
|
|
||||||
log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if push.Len == 0 {
|
|
||||||
push.Len = len(push.Commits)
|
|
||||||
}
|
|
||||||
|
|
||||||
return push
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiffLineTypeToStr returns diff line type name
|
|
||||||
func DiffLineTypeToStr(diffType int) string {
|
|
||||||
switch diffType {
|
|
||||||
case 2:
|
|
||||||
return "add"
|
|
||||||
case 3:
|
|
||||||
return "del"
|
|
||||||
case 4:
|
|
||||||
return "tag"
|
|
||||||
}
|
|
||||||
return "same"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MigrationIcon returns a SVG name matching the service an issue/comment was migrated from
|
|
||||||
func MigrationIcon(hostname string) string {
|
|
||||||
switch hostname {
|
|
||||||
case "github.com":
|
|
||||||
return "octicon-mark-github"
|
|
||||||
default:
|
|
||||||
return "gitea-git"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type remoteAddress struct {
|
|
||||||
Address string
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress {
|
|
||||||
a := remoteAddress{}
|
|
||||||
|
|
||||||
remoteURL := m.OriginalURL
|
|
||||||
if ignoreOriginalURL || remoteURL == "" {
|
|
||||||
var err error
|
|
||||||
remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GetRemoteURL %v", err)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := giturl.Parse(remoteURL)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("giturl.Parse %v", err)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Scheme != "ssh" && u.Scheme != "file" {
|
|
||||||
if u.User != nil {
|
|
||||||
a.Username = u.User.Username()
|
|
||||||
a.Password, _ = u.User.Password()
|
|
||||||
}
|
|
||||||
u.User = nil
|
|
||||||
}
|
|
||||||
a.Address = u.String()
|
|
||||||
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eval the expression and return the result, see the comment of eval.Expr for details.
|
// Eval the expression and return the result, see the comment of eval.Expr for details.
|
||||||
// To use this helper function in templates, pass each token as a separate parameter.
|
// To use this helper function in templates, pass each token as a separate parameter.
|
||||||
//
|
//
|
||||||
|
84
modules/templates/util_avatar.go
Normal file
84
modules/templates/util_avatar.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"html"
|
||||||
|
"html/template"
|
||||||
|
|
||||||
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
|
"code.gitea.io/gitea/models/avatars"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
gitea_html "code.gitea.io/gitea/modules/html"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AvatarHTML creates the HTML for an avatar
|
||||||
|
func AvatarHTML(src string, size int, class, name string) template.HTML {
|
||||||
|
sizeStr := fmt.Sprintf(`%d`, size)
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
name = "avatar"
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avatar renders user avatars. args: user, size (int), class (string)
|
||||||
|
func Avatar(ctx context.Context, item interface{}, others ...interface{}) template.HTML {
|
||||||
|
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
||||||
|
|
||||||
|
switch t := item.(type) {
|
||||||
|
case *user_model.User:
|
||||||
|
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
||||||
|
if src != "" {
|
||||||
|
return AvatarHTML(src, size, class, t.DisplayName())
|
||||||
|
}
|
||||||
|
case *repo_model.Collaborator:
|
||||||
|
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
||||||
|
if src != "" {
|
||||||
|
return AvatarHTML(src, size, class, t.DisplayName())
|
||||||
|
}
|
||||||
|
case *organization.Organization:
|
||||||
|
src := t.AsUser().AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor)
|
||||||
|
if src != "" {
|
||||||
|
return AvatarHTML(src, size, class, t.AsUser().DisplayName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvatarByAction renders user avatars from action. args: action, size (int), class (string)
|
||||||
|
func AvatarByAction(ctx context.Context, action *activities_model.Action, others ...interface{}) template.HTML {
|
||||||
|
action.LoadActUser(ctx)
|
||||||
|
return Avatar(ctx, action.ActUser, others...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoAvatar renders repo avatars. args: repo, size(int), class (string)
|
||||||
|
func RepoAvatar(repo *repo_model.Repository, others ...interface{}) template.HTML {
|
||||||
|
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
||||||
|
|
||||||
|
src := repo.RelAvatarLink()
|
||||||
|
if src != "" {
|
||||||
|
return AvatarHTML(src, size, class, repo.FullName())
|
||||||
|
}
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string)
|
||||||
|
func AvatarByEmail(ctx context.Context, email, name string, others ...interface{}) template.HTML {
|
||||||
|
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...)
|
||||||
|
src := avatars.GenerateEmailAvatarFastLink(ctx, email, size*setting.Avatar.RenderedSizeFactor)
|
||||||
|
|
||||||
|
if src != "" {
|
||||||
|
return AvatarHTML(src, size, class, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
35
modules/templates/util_json.go
Normal file
35
modules/templates/util_json.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JsonUtils struct{} //nolint:revive
|
||||||
|
|
||||||
|
var jsonUtils = JsonUtils{}
|
||||||
|
|
||||||
|
func NewJsonUtils() *JsonUtils { //nolint:revive
|
||||||
|
return &jsonUtils
|
||||||
|
}
|
||||||
|
|
||||||
|
func (su *JsonUtils) EncodeToString(v any) string {
|
||||||
|
out, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (su *JsonUtils) PrettyIndent(s string) string {
|
||||||
|
var out bytes.Buffer
|
||||||
|
err := json.Indent(&out, []byte(s), "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
209
modules/templates/util_misc.go
Normal file
209
modules/templates/util_misc.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"mime"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
giturl "code.gitea.io/gitea/modules/git/url"
|
||||||
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
|
"code.gitea.io/gitea/modules/svg"
|
||||||
|
|
||||||
|
"github.com/editorconfig/editorconfig-core-go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SortArrow(normSort, revSort, urlSort string, isDefault bool) template.HTML {
|
||||||
|
// if needed
|
||||||
|
if len(normSort) == 0 || len(urlSort) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(urlSort) == 0 && isDefault {
|
||||||
|
// if sort is sorted as default add arrow tho this table header
|
||||||
|
if isDefault {
|
||||||
|
return svg.RenderHTML("octicon-triangle-down", 16)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if sort arg is in url test if it correlates with column header sort arguments
|
||||||
|
// the direction of the arrow should indicate the "current sort order", up means ASC(normal), down means DESC(rev)
|
||||||
|
if urlSort == normSort {
|
||||||
|
// the table is sorted with this header normal
|
||||||
|
return svg.RenderHTML("octicon-triangle-up", 16)
|
||||||
|
} else if urlSort == revSort {
|
||||||
|
// the table is sorted with this header reverse
|
||||||
|
return svg.RenderHTML("octicon-triangle-down", 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the table is NOT sorted with this header
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines.
|
||||||
|
func IsMultilineCommitMessage(msg string) bool {
|
||||||
|
return strings.Count(strings.TrimSpace(msg), "\n") >= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actioner describes an action
|
||||||
|
type Actioner interface {
|
||||||
|
GetOpType() activities_model.ActionType
|
||||||
|
GetActUserName() string
|
||||||
|
GetRepoUserName() string
|
||||||
|
GetRepoName() string
|
||||||
|
GetRepoPath() string
|
||||||
|
GetRepoLink() string
|
||||||
|
GetBranch() string
|
||||||
|
GetContent() string
|
||||||
|
GetCreate() time.Time
|
||||||
|
GetIssueInfos() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionIcon accepts an action operation type and returns an icon class name.
|
||||||
|
func ActionIcon(opType activities_model.ActionType) string {
|
||||||
|
switch opType {
|
||||||
|
case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo:
|
||||||
|
return "repo"
|
||||||
|
case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch:
|
||||||
|
return "git-commit"
|
||||||
|
case activities_model.ActionCreateIssue:
|
||||||
|
return "issue-opened"
|
||||||
|
case activities_model.ActionCreatePullRequest:
|
||||||
|
return "git-pull-request"
|
||||||
|
case activities_model.ActionCommentIssue, activities_model.ActionCommentPull:
|
||||||
|
return "comment-discussion"
|
||||||
|
case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest:
|
||||||
|
return "git-merge"
|
||||||
|
case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest:
|
||||||
|
return "issue-closed"
|
||||||
|
case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest:
|
||||||
|
return "issue-reopened"
|
||||||
|
case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete:
|
||||||
|
return "mirror"
|
||||||
|
case activities_model.ActionApprovePullRequest:
|
||||||
|
return "check"
|
||||||
|
case activities_model.ActionRejectPullRequest:
|
||||||
|
return "diff"
|
||||||
|
case activities_model.ActionPublishRelease:
|
||||||
|
return "tag"
|
||||||
|
case activities_model.ActionPullReviewDismissed:
|
||||||
|
return "x"
|
||||||
|
default:
|
||||||
|
return "question"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionContent2Commits converts action content to push commits
|
||||||
|
func ActionContent2Commits(act Actioner) *repository.PushCommits {
|
||||||
|
push := repository.NewPushCommits()
|
||||||
|
|
||||||
|
if act == nil || act.GetContent() == "" {
|
||||||
|
return push
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil {
|
||||||
|
log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if push.Len == 0 {
|
||||||
|
push.Len = len(push.Commits)
|
||||||
|
}
|
||||||
|
|
||||||
|
return push
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiffLineTypeToStr returns diff line type name
|
||||||
|
func DiffLineTypeToStr(diffType int) string {
|
||||||
|
switch diffType {
|
||||||
|
case 2:
|
||||||
|
return "add"
|
||||||
|
case 3:
|
||||||
|
return "del"
|
||||||
|
case 4:
|
||||||
|
return "tag"
|
||||||
|
}
|
||||||
|
return "same"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrationIcon returns a SVG name matching the service an issue/comment was migrated from
|
||||||
|
func MigrationIcon(hostname string) string {
|
||||||
|
switch hostname {
|
||||||
|
case "github.com":
|
||||||
|
return "octicon-mark-github"
|
||||||
|
default:
|
||||||
|
return "gitea-git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type remoteAddress struct {
|
||||||
|
Address string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress {
|
||||||
|
a := remoteAddress{}
|
||||||
|
|
||||||
|
remoteURL := m.OriginalURL
|
||||||
|
if ignoreOriginalURL || remoteURL == "" {
|
||||||
|
var err error
|
||||||
|
remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetRemoteURL %v", err)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := giturl.Parse(remoteURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("giturl.Parse %v", err)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Scheme != "ssh" && u.Scheme != "file" {
|
||||||
|
if u.User != nil {
|
||||||
|
a.Username = u.User.Username()
|
||||||
|
a.Password, _ = u.User.Password()
|
||||||
|
}
|
||||||
|
u.User = nil
|
||||||
|
}
|
||||||
|
a.Address = u.String()
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func FilenameIsImage(filename string) bool {
|
||||||
|
mimeType := mime.TypeByExtension(filepath.Ext(filename))
|
||||||
|
return strings.HasPrefix(mimeType, "image/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TabSizeClass(ec interface{}, filename string) string {
|
||||||
|
var (
|
||||||
|
value *editorconfig.Editorconfig
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
if ec != nil {
|
||||||
|
if value, ok = ec.(*editorconfig.Editorconfig); !ok || value == nil {
|
||||||
|
return "tab-size-8"
|
||||||
|
}
|
||||||
|
def, err := value.GetDefinitionForFilename(filename)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("tab size class: getting definition for filename: %v", err)
|
||||||
|
return "tab-size-8"
|
||||||
|
}
|
||||||
|
if def.TabWidth > 0 {
|
||||||
|
return fmt.Sprintf("tab-size-%d", def.TabWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "tab-size-8"
|
||||||
|
}
|
254
modules/templates/util_render.go
Normal file
254
modules/templates/util_render.go
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"math"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
|
"code.gitea.io/gitea/modules/emoji"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/markup"
|
||||||
|
"code.gitea.io/gitea/modules/markup/markdown"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RenderCommitMessage renders commit message with XSS-safe and special links.
|
||||||
|
func RenderCommitMessage(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||||
|
return RenderCommitMessageLink(ctx, msg, urlPrefix, "", metas)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderCommitMessageLink renders commit message as a XXS-safe link to the provided
|
||||||
|
// default url, handling for special links.
|
||||||
|
func RenderCommitMessageLink(ctx context.Context, msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
|
||||||
|
cleanMsg := template.HTMLEscapeString(msg)
|
||||||
|
// we can safely assume that it will not return any error, since there
|
||||||
|
// shouldn't be any special HTML.
|
||||||
|
fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: urlPrefix,
|
||||||
|
DefaultLink: urlDefault,
|
||||||
|
Metas: metas,
|
||||||
|
}, cleanMsg)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderCommitMessage: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n")
|
||||||
|
if len(msgLines) == 0 {
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
return template.HTML(msgLines[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderCommitMessageLinkSubject renders commit message as a XXS-safe link to
|
||||||
|
// the provided default url, handling for special links without email to links.
|
||||||
|
func RenderCommitMessageLinkSubject(ctx context.Context, msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
|
||||||
|
msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace)
|
||||||
|
lineEnd := strings.IndexByte(msgLine, '\n')
|
||||||
|
if lineEnd > 0 {
|
||||||
|
msgLine = msgLine[:lineEnd]
|
||||||
|
}
|
||||||
|
msgLine = strings.TrimRightFunc(msgLine, unicode.IsSpace)
|
||||||
|
if len(msgLine) == 0 {
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can safely assume that it will not return any error, since there
|
||||||
|
// shouldn't be any special HTML.
|
||||||
|
renderedMessage, err := markup.RenderCommitMessageSubject(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: urlPrefix,
|
||||||
|
DefaultLink: urlDefault,
|
||||||
|
Metas: metas,
|
||||||
|
}, template.HTMLEscapeString(msgLine))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderCommitMessageSubject: %v", err)
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
return template.HTML(renderedMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderCommitBody extracts the body of a commit message without its title.
|
||||||
|
func RenderCommitBody(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||||
|
msgLine := strings.TrimRightFunc(msg, unicode.IsSpace)
|
||||||
|
lineEnd := strings.IndexByte(msgLine, '\n')
|
||||||
|
if lineEnd > 0 {
|
||||||
|
msgLine = msgLine[lineEnd+1:]
|
||||||
|
} else {
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
msgLine = strings.TrimLeftFunc(msgLine, unicode.IsSpace)
|
||||||
|
if len(msgLine) == 0 {
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
|
||||||
|
renderedMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: urlPrefix,
|
||||||
|
Metas: metas,
|
||||||
|
}, template.HTMLEscapeString(msgLine))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderCommitMessage: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return template.HTML(renderedMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match text that is between back ticks.
|
||||||
|
var codeMatcher = regexp.MustCompile("`([^`]+)`")
|
||||||
|
|
||||||
|
// RenderCodeBlock renders "`…`" as highlighted "<code>" block.
|
||||||
|
// Intended for issue and PR titles, these containers should have styles for "<code>" elements
|
||||||
|
func RenderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
|
||||||
|
htmlWithCodeTags := codeMatcher.ReplaceAllString(string(htmlEscapedTextToRender), "<code>$1</code>") // replace with HTML <code> tags
|
||||||
|
return template.HTML(htmlWithCodeTags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderIssueTitle renders issue/pull title with defined post processors
|
||||||
|
func RenderIssueTitle(ctx context.Context, text, urlPrefix string, metas map[string]string) template.HTML {
|
||||||
|
renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: urlPrefix,
|
||||||
|
Metas: metas,
|
||||||
|
}, template.HTMLEscapeString(text))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderIssueTitle: %v", err)
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
return template.HTML(renderedText)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderLabel renders a label
|
||||||
|
func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML {
|
||||||
|
labelScope := label.ExclusiveScope()
|
||||||
|
|
||||||
|
textColor := "#111"
|
||||||
|
if label.UseLightTextColor() {
|
||||||
|
textColor = "#eee"
|
||||||
|
}
|
||||||
|
|
||||||
|
description := emoji.ReplaceAliases(template.HTMLEscapeString(label.Description))
|
||||||
|
|
||||||
|
if labelScope == "" {
|
||||||
|
// Regular label
|
||||||
|
s := fmt.Sprintf("<div class='ui label' style='color: %s !important; background-color: %s !important' title='%s'>%s</div>",
|
||||||
|
textColor, label.Color, description, RenderEmoji(ctx, label.Name))
|
||||||
|
return template.HTML(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scoped label
|
||||||
|
scopeText := RenderEmoji(ctx, labelScope)
|
||||||
|
itemText := RenderEmoji(ctx, label.Name[len(labelScope)+1:])
|
||||||
|
|
||||||
|
itemColor := label.Color
|
||||||
|
scopeColor := label.Color
|
||||||
|
if r, g, b, err := label.ColorRGB(); err == nil {
|
||||||
|
// Make scope and item background colors slightly darker and lighter respectively.
|
||||||
|
// More contrast needed with higher luminance, empirically tweaked.
|
||||||
|
luminance := (0.299*r + 0.587*g + 0.114*b) / 255
|
||||||
|
contrast := 0.01 + luminance*0.03
|
||||||
|
// Ensure we add the same amount of contrast also near 0 and 1.
|
||||||
|
darken := contrast + math.Max(luminance+contrast-1.0, 0.0)
|
||||||
|
lighten := contrast + math.Max(contrast-luminance, 0.0)
|
||||||
|
// Compute factor to keep RGB values proportional.
|
||||||
|
darkenFactor := math.Max(luminance-darken, 0.0) / math.Max(luminance, 1.0/255.0)
|
||||||
|
lightenFactor := math.Min(luminance+lighten, 1.0) / math.Max(luminance, 1.0/255.0)
|
||||||
|
|
||||||
|
scopeBytes := []byte{
|
||||||
|
uint8(math.Min(math.Round(r*darkenFactor), 255)),
|
||||||
|
uint8(math.Min(math.Round(g*darkenFactor), 255)),
|
||||||
|
uint8(math.Min(math.Round(b*darkenFactor), 255)),
|
||||||
|
}
|
||||||
|
itemBytes := []byte{
|
||||||
|
uint8(math.Min(math.Round(r*lightenFactor), 255)),
|
||||||
|
uint8(math.Min(math.Round(g*lightenFactor), 255)),
|
||||||
|
uint8(math.Min(math.Round(b*lightenFactor), 255)),
|
||||||
|
}
|
||||||
|
|
||||||
|
itemColor = "#" + hex.EncodeToString(itemBytes)
|
||||||
|
scopeColor = "#" + hex.EncodeToString(scopeBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := fmt.Sprintf("<span class='ui label scope-parent' title='%s'>"+
|
||||||
|
"<div class='ui label scope-left' style='color: %s !important; background-color: %s !important'>%s</div>"+
|
||||||
|
"<div class='ui label scope-right' style='color: %s !important; background-color: %s !important''>%s</div>"+
|
||||||
|
"</span>",
|
||||||
|
description,
|
||||||
|
textColor, scopeColor, scopeText,
|
||||||
|
textColor, itemColor, itemText)
|
||||||
|
return template.HTML(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderEmoji renders html text with emoji post processors
|
||||||
|
func RenderEmoji(ctx context.Context, text string) template.HTML {
|
||||||
|
renderedText, err := markup.RenderEmoji(&markup.RenderContext{Ctx: ctx},
|
||||||
|
template.HTMLEscapeString(text))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderEmoji: %v", err)
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
|
return template.HTML(renderedText)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReactionToEmoji renders emoji for use in reactions
|
||||||
|
func ReactionToEmoji(reaction string) template.HTML {
|
||||||
|
val := emoji.FromCode(reaction)
|
||||||
|
if val != nil {
|
||||||
|
return template.HTML(val.Emoji)
|
||||||
|
}
|
||||||
|
val = emoji.FromAlias(reaction)
|
||||||
|
if val != nil {
|
||||||
|
return template.HTML(val.Emoji)
|
||||||
|
}
|
||||||
|
return template.HTML(fmt.Sprintf(`<img alt=":%s:" src="%s/assets/img/emoji/%s.png"></img>`, reaction, setting.StaticURLPrefix, url.PathEscape(reaction)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderNote renders the contents of a git-notes file as a commit message.
|
||||||
|
func RenderNote(ctx context.Context, msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||||
|
cleanMsg := template.HTMLEscapeString(msg)
|
||||||
|
fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: urlPrefix,
|
||||||
|
Metas: metas,
|
||||||
|
}, cleanMsg)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderNote: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return template.HTML(fullMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //nolint:revive
|
||||||
|
output, err := markdown.RenderString(&markup.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
|
URLPrefix: setting.AppSubURL,
|
||||||
|
}, input)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("RenderString: %v", err)
|
||||||
|
}
|
||||||
|
return template.HTML(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML {
|
||||||
|
htmlCode := `<span class="labels-list">`
|
||||||
|
for _, label := range labels {
|
||||||
|
// Protect against nil value in labels - shouldn't happen but would cause a panic if so
|
||||||
|
if label == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
htmlCode += fmt.Sprintf("<a href='%s/issues?labels=%d'>%s</a> ",
|
||||||
|
repoLink, label.ID, RenderLabel(ctx, label))
|
||||||
|
}
|
||||||
|
htmlCode += "</span>"
|
||||||
|
return template.HTML(htmlCode)
|
||||||
|
}
|
@ -3,12 +3,18 @@
|
|||||||
|
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
)
|
||||||
|
|
||||||
type StringUtils struct{}
|
type StringUtils struct{}
|
||||||
|
|
||||||
|
var stringUtils = StringUtils{}
|
||||||
|
|
||||||
func NewStringUtils() *StringUtils {
|
func NewStringUtils() *StringUtils {
|
||||||
return &StringUtils{}
|
return &stringUtils
|
||||||
}
|
}
|
||||||
|
|
||||||
func (su *StringUtils) HasPrefix(s, prefix string) bool {
|
func (su *StringUtils) HasPrefix(s, prefix string) bool {
|
||||||
@ -22,3 +28,11 @@ func (su *StringUtils) Contains(s, substr string) bool {
|
|||||||
func (su *StringUtils) Split(s, sep string) []string {
|
func (su *StringUtils) Split(s, sep string) []string {
|
||||||
return strings.Split(s, sep)
|
return strings.Split(s, sep)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (su *StringUtils) Join(a []string, sep string) string {
|
||||||
|
return strings.Join(a, sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (su *StringUtils) EllipsisString(s string, max int) string {
|
||||||
|
return base.EllipsisString(s, max)
|
||||||
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package timeutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
var langTimeFormats = map[string]string{
|
|
||||||
"zh-CN": "2006年01月02日 15时04分05秒",
|
|
||||||
"en-US": time.RFC1123,
|
|
||||||
"lv-LV": "02.01.2006. 15:04:05",
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLangTimeFormat represents the default time format for the language
|
|
||||||
func GetLangTimeFormat(lang string) string {
|
|
||||||
return langTimeFormats[lang]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTimeFormat represents the
|
|
||||||
func GetTimeFormat(lang string) string {
|
|
||||||
if setting.TimeFormat == "" {
|
|
||||||
format := GetLangTimeFormat(lang)
|
|
||||||
if format == "" {
|
|
||||||
format = time.RFC1123
|
|
||||||
}
|
|
||||||
return format
|
|
||||||
}
|
|
||||||
return setting.TimeFormat
|
|
||||||
}
|
|
@ -1901,6 +1901,7 @@ settings.sync_mirror = Synchronize Now
|
|||||||
settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute.
|
settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute.
|
||||||
settings.site = Website
|
settings.site = Website
|
||||||
settings.update_settings = Update Settings
|
settings.update_settings = Update Settings
|
||||||
|
settings.branches.switch_default_branch = Switch Default Branch
|
||||||
settings.branches.update_default_branch = Update Default Branch
|
settings.branches.update_default_branch = Update Default Branch
|
||||||
settings.branches.add_new_rule = Add New Rule
|
settings.branches.add_new_rule = Add New Rule
|
||||||
settings.advanced_settings = Advanced Settings
|
settings.advanced_settings = Advanced Settings
|
||||||
@ -2096,6 +2097,8 @@ settings.event_pull_request_review = Pull Request Reviewed
|
|||||||
settings.event_pull_request_review_desc = Pull request approved, rejected, or review comment.
|
settings.event_pull_request_review_desc = Pull request approved, rejected, or review comment.
|
||||||
settings.event_pull_request_sync = Pull Request Synchronized
|
settings.event_pull_request_sync = Pull Request Synchronized
|
||||||
settings.event_pull_request_sync_desc = Pull request synchronized.
|
settings.event_pull_request_sync_desc = Pull request synchronized.
|
||||||
|
settings.event_pull_request_approvals = Pull Request Approvals
|
||||||
|
settings.event_pull_request_merge = Pull Request Merge
|
||||||
settings.event_package = Package
|
settings.event_package = Package
|
||||||
settings.event_package_desc = Package created or deleted in a repository.
|
settings.event_package_desc = Package created or deleted in a repository.
|
||||||
settings.branch_filter = Branch filter
|
settings.branch_filter = Branch filter
|
||||||
@ -2151,13 +2154,15 @@ settings.protected_branch.delete_rule = Delete Rule
|
|||||||
settings.protected_branch_can_push = Allow push?
|
settings.protected_branch_can_push = Allow push?
|
||||||
settings.protected_branch_can_push_yes = You can push
|
settings.protected_branch_can_push_yes = You can push
|
||||||
settings.protected_branch_can_push_no = You cannot push
|
settings.protected_branch_can_push_no = You cannot push
|
||||||
settings.branch_protection = Branch Protection for Branch '<b>%s</b>'
|
settings.branch_protection = Branch Protection Rules for Branch '<b>%s</b>'
|
||||||
settings.protect_this_branch = Enable Branch Protection
|
settings.protect_this_branch = Enable Branch Protection
|
||||||
settings.protect_this_branch_desc = Prevents deletion and restricts Git pushing and merging to the branch.
|
settings.protect_this_branch_desc = Prevents deletion and restricts Git pushing and merging to the branch.
|
||||||
settings.protect_disable_push = Disable Push
|
settings.protect_disable_push = Disable Push
|
||||||
settings.protect_disable_push_desc = No pushing will be allowed to this branch.
|
settings.protect_disable_push_desc = No pushing will be allowed to this branch.
|
||||||
settings.protect_enable_push = Enable Push
|
settings.protect_enable_push = Enable Push
|
||||||
settings.protect_enable_push_desc = Anyone with write access will be allowed to push to this branch (but not force push).
|
settings.protect_enable_push_desc = Anyone with write access will be allowed to push to this branch (but not force push).
|
||||||
|
settings.protect_enable_merge = Enable Merge
|
||||||
|
settings.protect_enable_merge_desc = Anyone with write access will be allowed to merge the pull requests into this branch.
|
||||||
settings.protect_whitelist_committers = Whitelist Restricted Push
|
settings.protect_whitelist_committers = Whitelist Restricted Push
|
||||||
settings.protect_whitelist_committers_desc = Only whitelisted users or teams will be allowed to push to this branch (but not force push).
|
settings.protect_whitelist_committers_desc = Only whitelisted users or teams will be allowed to push to this branch (but not force push).
|
||||||
settings.protect_whitelist_deploy_keys = Whitelist deploy keys with write access to push.
|
settings.protect_whitelist_deploy_keys = Whitelist deploy keys with write access to push.
|
||||||
@ -2183,6 +2188,7 @@ settings.dismiss_stale_approvals_desc = When new commits that change the content
|
|||||||
settings.require_signed_commits = Require Signed Commits
|
settings.require_signed_commits = Require Signed Commits
|
||||||
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
|
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
|
||||||
settings.protect_branch_name_pattern = Protected Branch Name Pattern
|
settings.protect_branch_name_pattern = Protected Branch Name Pattern
|
||||||
|
settings.protect_patterns = Patterns
|
||||||
settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):"
|
settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):"
|
||||||
settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
|
settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
|
||||||
settings.protect_unprotected_file_patterns = "Unprotected file patterns (separated using semicolon ';'):"
|
settings.protect_unprotected_file_patterns = "Unprotected file patterns (separated using semicolon ';'):"
|
||||||
|
@ -1606,7 +1606,10 @@ pulls.tab_files=変更されたファイル
|
|||||||
pulls.reopen_to_merge=このプルリクエストをマージする場合は再オープンしてください。
|
pulls.reopen_to_merge=このプルリクエストをマージする場合は再オープンしてください。
|
||||||
pulls.cant_reopen_deleted_branch=このプルリクエストはブランチが削除されているため、再オープンできません。
|
pulls.cant_reopen_deleted_branch=このプルリクエストはブランチが削除されているため、再オープンできません。
|
||||||
pulls.merged=マージ済み
|
pulls.merged=マージ済み
|
||||||
|
pulls.merged_success=プルリクエストは正常にマージ、クローズされました
|
||||||
|
pulls.closed=プルリクエストはクローズされました
|
||||||
pulls.manually_merged=手動マージ済み
|
pulls.manually_merged=手動マージ済み
|
||||||
|
pulls.merged_info_text=ブランチ %s を削除できるようになりました。
|
||||||
pulls.is_closed=プルリクエストはクローズされています。
|
pulls.is_closed=プルリクエストはクローズされています。
|
||||||
pulls.title_wip_desc=`誤ってマージされないようにするには、<a href="#">タイトルの頭に <strong>%s</strong> を付けます</a>。`
|
pulls.title_wip_desc=`誤ってマージされないようにするには、<a href="#">タイトルの頭に <strong>%s</strong> を付けます</a>。`
|
||||||
pulls.cannot_merge_work_in_progress=このプルリクエストは作業中(WIP)としてマーキングされています。
|
pulls.cannot_merge_work_in_progress=このプルリクエストは作業中(WIP)としてマーキングされています。
|
||||||
@ -2426,6 +2429,7 @@ team_unit_desc=リポジトリのセクションへのアクセスを許可
|
|||||||
team_unit_disabled=(無効)
|
team_unit_disabled=(無効)
|
||||||
|
|
||||||
form.name_reserved=組織名 "%s" は予約されています。
|
form.name_reserved=組織名 "%s" は予約されています。
|
||||||
|
form.name_pattern_not_allowed=`"%s" の形式は組織名に使用できません。`
|
||||||
form.create_org_not_allowed=組織を作成する権限がありません。
|
form.create_org_not_allowed=組織を作成する権限がありません。
|
||||||
|
|
||||||
settings=設定
|
settings=設定
|
||||||
@ -3392,8 +3396,12 @@ runs.closed_tab=%d クローズ
|
|||||||
runs.commit=コミット
|
runs.commit=コミット
|
||||||
runs.pushed_by=Pushed by
|
runs.pushed_by=Pushed by
|
||||||
runs.invalid_workflow_helper=ワークフロー設定ファイルは無効です。あなたの設定ファイルを確認してください: %s
|
runs.invalid_workflow_helper=ワークフロー設定ファイルは無効です。あなたの設定ファイルを確認してください: %s
|
||||||
|
runs.no_matching_runner_helper=一致するランナーがありません: %s
|
||||||
|
|
||||||
need_approval_desc=フォークプルリクエストのワークフローを実行するには承認が必要です。
|
need_approval_desc=フォークプルリクエストのワークフローを実行するには承認が必要です。
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
|
type-1.display_name=個人プロジェクト
|
||||||
|
type-2.display_name=リポジトリ プロジェクト
|
||||||
|
type-3.display_name=組織プロジェクト
|
||||||
|
|
||||||
|
@ -1833,7 +1833,7 @@ activity.new_issues_count_n=questões novas
|
|||||||
activity.new_issue_label=Em aberto
|
activity.new_issue_label=Em aberto
|
||||||
activity.title.unresolved_conv_1=%d diálogo não concluído
|
activity.title.unresolved_conv_1=%d diálogo não concluído
|
||||||
activity.title.unresolved_conv_n=%d diálogos não concluídos
|
activity.title.unresolved_conv_n=%d diálogos não concluídos
|
||||||
activity.unresolved_conv_desc=Estas questões e estes pedidos de integração que foram modificados recentemente ainda não foram concluídos.
|
activity.unresolved_conv_desc=Estas questões e estes pedidos de integração, que foram modificados recentemente, ainda não foram concluídos.
|
||||||
activity.unresolved_conv_label=Em aberto
|
activity.unresolved_conv_label=Em aberto
|
||||||
activity.title.releases_1=%d lançamento
|
activity.title.releases_1=%d lançamento
|
||||||
activity.title.releases_n=%d Lançamentos
|
activity.title.releases_n=%d Lançamentos
|
||||||
|
@ -115,6 +115,10 @@ func GetAllCommits(ctx *context.APIContext) {
|
|||||||
// in: query
|
// in: query
|
||||||
// description: page size of results (ignored if used with 'path')
|
// description: page size of results (ignored if used with 'path')
|
||||||
// type: integer
|
// type: integer
|
||||||
|
// - name: not
|
||||||
|
// in: query
|
||||||
|
// description: commits that match the given specifier will not be listed.
|
||||||
|
// type: string
|
||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/CommitList"
|
// "$ref": "#/responses/CommitList"
|
||||||
@ -181,7 +185,8 @@ func GetAllCommits(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Query commits
|
// Query commits
|
||||||
commits, err = baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize)
|
not := ctx.FormString("not")
|
||||||
|
commits, err = baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize, not)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "CommitsByRange", err)
|
ctx.Error(http.StatusInternalServerError, "CommitsByRange", err)
|
||||||
return
|
return
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed
|
// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed
|
||||||
func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
|
func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
|
||||||
commits, err := ctx.Repo.Commit.CommitsByRange(0, 10)
|
commits, err := ctx.Repo.Commit.CommitsByRange(0, 10, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ShowBranchFeed", err)
|
ctx.ServerError("ShowBranchFeed", err)
|
||||||
return
|
return
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
@ -143,6 +144,11 @@ func Home(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isFollowing bool
|
||||||
|
if ctx.Doer != nil {
|
||||||
|
isFollowing = user_model.IsFollowing(ctx.Doer.ID, ctx.ContextUser.ID)
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["Repos"] = repos
|
ctx.Data["Repos"] = repos
|
||||||
ctx.Data["Total"] = count
|
ctx.Data["Total"] = count
|
||||||
ctx.Data["MembersTotal"] = membersCount
|
ctx.Data["MembersTotal"] = membersCount
|
||||||
@ -150,6 +156,7 @@ func Home(ctx *context.Context) {
|
|||||||
ctx.Data["Teams"] = ctx.Org.Teams
|
ctx.Data["Teams"] = ctx.Org.Teams
|
||||||
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
|
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
|
||||||
ctx.Data["PageIsViewRepositories"] = true
|
ctx.Data["PageIsViewRepositories"] = true
|
||||||
|
ctx.Data["IsFollowing"] = isFollowing
|
||||||
|
|
||||||
pager := context.NewPagination(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
pager := context.NewPagination(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
||||||
pager.SetDefaultParams(ctx)
|
pager.SetDefaultParams(ctx)
|
||||||
|
@ -70,7 +70,7 @@ func Commits(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Both `git log branchName` and `git log commitId` work.
|
// Both `git log branchName` and `git log commitId` work.
|
||||||
commits, err := ctx.Repo.Commit.CommitsByRange(page, pageSize)
|
commits, err := ctx.Repo.Commit.CommitsByRange(page, pageSize, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CommitsByRange", err)
|
ctx.ServerError("CommitsByRange", err)
|
||||||
return
|
return
|
||||||
|
@ -130,15 +130,6 @@ func SettingsProtectedBranch(c *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.Data["branch_status_check_contexts"] = contexts
|
c.Data["branch_status_check_contexts"] = contexts
|
||||||
c.Data["is_context_required"] = func(context string) bool {
|
|
||||||
for _, c := range rule.StatusCheckContexts {
|
|
||||||
if c == context {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Repo.Owner.IsOrganization() {
|
if c.Repo.Owner.IsOrganization() {
|
||||||
teams, err := organization.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c.Repo.Repository.ID, perm.AccessModeRead)
|
teams, err := organization.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c.Repo.Repository.ID, perm.AccessModeRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -167,9 +167,7 @@ func Profile(ctx *context.Context) {
|
|||||||
language := ctx.FormTrim("language")
|
language := ctx.FormTrim("language")
|
||||||
ctx.Data["Language"] = language
|
ctx.Data["Language"] = language
|
||||||
|
|
||||||
switch tab {
|
followers, numFollowers, err := user_model.GetUserFollowers(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{
|
||||||
case "followers":
|
|
||||||
items, count, err := user_model.GetUserFollowers(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{
|
|
||||||
PageSize: pagingNum,
|
PageSize: pagingNum,
|
||||||
Page: page,
|
Page: page,
|
||||||
})
|
})
|
||||||
@ -177,11 +175,8 @@ func Profile(ctx *context.Context) {
|
|||||||
ctx.ServerError("GetUserFollowers", err)
|
ctx.ServerError("GetUserFollowers", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Cards"] = items
|
ctx.Data["NumFollowers"] = numFollowers
|
||||||
|
following, numFollowing, err := user_model.GetUserFollowing(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{
|
||||||
total = int(count)
|
|
||||||
case "following":
|
|
||||||
items, count, err := user_model.GetUserFollowing(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{
|
|
||||||
PageSize: pagingNum,
|
PageSize: pagingNum,
|
||||||
Page: page,
|
Page: page,
|
||||||
})
|
})
|
||||||
@ -189,8 +184,14 @@ func Profile(ctx *context.Context) {
|
|||||||
ctx.ServerError("GetUserFollowing", err)
|
ctx.ServerError("GetUserFollowing", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Cards"] = items
|
ctx.Data["NumFollowing"] = numFollowing
|
||||||
|
|
||||||
|
switch tab {
|
||||||
|
case "followers":
|
||||||
|
ctx.Data["Cards"] = followers
|
||||||
|
total = int(count)
|
||||||
|
case "following":
|
||||||
|
ctx.Data["Cards"] = following
|
||||||
total = int(count)
|
total = int(count)
|
||||||
case "activity":
|
case "activity":
|
||||||
date := ctx.FormString("date")
|
date := ctx.FormString("date")
|
||||||
|
@ -1093,7 +1093,7 @@ func registerRoutes(m *web.Route) {
|
|||||||
repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
|
repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
|
||||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
||||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
||||||
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
}, ignSignIn, context.RepoAssignment, context.UnitTypes())
|
||||||
|
|
||||||
// Releases
|
// Releases
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{reponame}", func() {
|
||||||
|
@ -334,7 +334,7 @@
|
|||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="oauth2_scopes">{{.locale.Tr "admin.auths.oauth2_scopes"}}</label>
|
<label for="oauth2_scopes">{{.locale.Tr "admin.auths.oauth2_scopes"}}</label>
|
||||||
<input id="oauth2_scopes" name="oauth2_scopes" value="{{if $cfg.Scopes}}{{Join $cfg.Scopes ","}}{{end}}">
|
<input id="oauth2_scopes" name="oauth2_scopes" value="{{if $cfg.Scopes}}{{StringUtils.Join $cfg.Scopes ","}}{{end}}">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="oauth2_required_claim_name">{{.locale.Tr "admin.auths.oauth2_required_claim_name"}}</label>
|
<label for="oauth2_required_claim_name">{{.locale.Tr "admin.auths.oauth2_required_claim_name"}}</label>
|
||||||
|
@ -365,7 +365,7 @@
|
|||||||
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
||||||
<dd>{{.Name}} ({{.Provider}})</dd>
|
<dd>{{.Name}} ({{.Provider}})</dd>
|
||||||
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
||||||
<dd><pre>{{.Config | JsonPrettyPrint}}</pre></dd>
|
<dd><pre>{{JsonUtils.PrettyIndent .Config}}</pre></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<dt>{{$.locale.Tr "admin.config.router_log_mode"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.router_log_mode"}}</dt>
|
||||||
@ -378,7 +378,7 @@
|
|||||||
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
||||||
<dd>{{.Name}} ({{.Provider}})</dd>
|
<dd>{{.Name}} ({{.Provider}})</dd>
|
||||||
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
||||||
<dd><pre>{{.Config | JsonPrettyPrint}}</pre></dd>
|
<dd><pre>{{JsonUtils.PrettyIndent .Config}}</pre></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
||||||
@ -393,7 +393,7 @@
|
|||||||
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
||||||
<dd>{{.Name}} ({{.Provider}})</dd>
|
<dd>{{.Name}} ({{.Provider}})</dd>
|
||||||
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
||||||
<dd><pre>{{.Config | JsonPrettyPrint}}</pre></dd>
|
<dd><pre>{{JsonUtils.PrettyIndent .Config}}</pre></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
||||||
@ -412,7 +412,7 @@
|
|||||||
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_mode"}}</dt>
|
||||||
<dd>{{.Name}} ({{.Provider}})</dd>
|
<dd>{{.Name}} ({{.Provider}})</dd>
|
||||||
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
<dt>{{$.locale.Tr "admin.config.log_config"}}</dt>
|
||||||
<dd><pre>{{.Config | JsonPrettyPrint}}</pre></dd>
|
<dd><pre>{{JsonUtils.PrettyIndent .Config}}</pre></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
<dd>{{$.locale.Tr "admin.config.routes_to_default_logger"}}</dd>
|
||||||
|
@ -23,51 +23,51 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.delete_inactive_accounts"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.delete_inactive_accounts"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="delete_inactive_accounts">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="delete_inactive_accounts">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.delete_repo_archives"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.delete_repo_archives"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="delete_repo_archives">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="delete_repo_archives">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.delete_missing_repos"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.delete_missing_repos"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="delete_missing_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="delete_missing_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.git_gc_repos"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.git_gc_repos"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="git_gc_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="git_gc_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{if and (not .SSH.Disabled) (not .SSH.StartBuiltinServer)}}
|
{{if and (not .SSH.Disabled) (not .SSH.StartBuiltinServer)}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.resync_all_sshkeys"}}<br>
|
<td>{{.locale.Tr "admin.dashboard.resync_all_sshkeys"}}<br>
|
||||||
{{.locale.Tr "admin.dashboard.resync_all_sshkeys.desc"}}</td>
|
{{.locale.Tr "admin.dashboard.resync_all_sshkeys.desc"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="resync_all_sshkeys">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="resync_all_sshkeys">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.resync_all_sshprincipals"}}<br>
|
<td>{{.locale.Tr "admin.dashboard.resync_all_sshprincipals"}}<br>
|
||||||
{{.locale.Tr "admin.dashboard.resync_all_sshprincipals.desc"}}</td>
|
{{.locale.Tr "admin.dashboard.resync_all_sshprincipals.desc"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="resync_all_sshprincipals">{{svg "octicon-play" 16}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="resync_all_sshprincipals">{{svg "octicon-play" 16}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.resync_all_hooks"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.resync_all_hooks"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="resync_all_hooks">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="resync_all_hooks">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.reinit_missing_repos"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.reinit_missing_repos"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="reinit_missing_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="reinit_missing_repos">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.sync_external_users"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.sync_external_users"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="sync_external_users">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="sync_external_users">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.repo_health_check"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.repo_health_check"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="repo_health_check">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="repo_health_check">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.locale.Tr "admin.dashboard.delete_generated_repository_avatars"}}</td>
|
<td>{{.locale.Tr "admin.dashboard.delete_generated_repository_avatars"}}</td>
|
||||||
<td><button type="submit" class="ui green button right" name="op" value="delete_generated_repository_avatars">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
<td class="text right"><button type="submit" class="ui green button" name="op" value="delete_generated_repository_avatars">{{svg "octicon-play"}} {{.locale.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -174,7 +174,7 @@
|
|||||||
{{.locale.Tr "admin.monitor.queue.configuration"}}
|
{{.locale.Tr "admin.monitor.queue.configuration"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
<pre>{{.Queue.Configuration | JsonPrettyPrint}}</pre>
|
<pre>{{JsonUtils.PrettyIndent .Queue.Configuration}}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
{{.locale.Tr "admin.repos.size"}}
|
{{.locale.Tr "admin.repos.size"}}
|
||||||
{{SortArrow "size" "reversesize" $.SortType false}}
|
{{SortArrow "size" "reversesize" $.SortType false}}
|
||||||
</th>
|
</th>
|
||||||
|
<th>{{.locale.Tr "admin.auths.updated"}}</th>
|
||||||
<th>{{.locale.Tr "admin.users.created"}}</th>
|
<th>{{.locale.Tr "admin.users.created"}}</th>
|
||||||
<th>{{.locale.Tr "admin.notices.op"}}</th>
|
<th>{{.locale.Tr "admin.notices.op"}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -80,6 +81,7 @@
|
|||||||
<td>{{.NumForks}}</td>
|
<td>{{.NumForks}}</td>
|
||||||
<td>{{.NumIssues}}</td>
|
<td>{{.NumIssues}}</td>
|
||||||
<td>{{FileSize .Size}}</td>
|
<td>{{FileSize .Size}}</td>
|
||||||
|
<td>{{DateTime "short" .UpdatedUnix}}</td>
|
||||||
<td>{{DateTime "short" .CreatedUnix}}</td>
|
<td>{{DateTime "short" .CreatedUnix}}</td>
|
||||||
<td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.ID}}" data-name="{{.Name}}">{{svg "octicon-trash"}}</a></td>
|
<td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.ID}}" data-name="{{.Name}}">{{svg "octicon-trash"}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<footer role="group" aria-label="{{.locale.Tr "aria.footer"}}">
|
<footer class="page-footer" role="group" aria-label="{{.locale.Tr "aria.footer"}}">
|
||||||
<div class="ui left" role="contentinfo" aria-label="{{.locale.Tr "aria.footer.software"}}">
|
<div class="left-links" role="contentinfo" aria-label="{{.locale.Tr "aria.footer.software"}}">
|
||||||
<a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.locale.Tr "powered_by" "Gitea"}}</a>
|
<a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.locale.Tr "powered_by" "Gitea"}}</a>
|
||||||
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
||||||
{{.locale.Tr "version"}}:
|
{{.locale.Tr "version"}}:
|
||||||
@ -14,7 +14,7 @@
|
|||||||
{{.locale.Tr "template"}}{{if .TemplateName}} {{.TemplateName}}{{end}}: <strong>{{call .TemplateLoadTimes}}</strong>
|
{{.locale.Tr "template"}}{{if .TemplateName}} {{.TemplateName}}{{end}}: <strong>{{call .TemplateLoadTimes}}</strong>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui right links" role="group" aria-label="{{.locale.Tr "aria.footer.links"}}">
|
<div class="right-links" role="group" aria-label="{{.locale.Tr "aria.footer.links"}}">
|
||||||
<div class="ui dropdown upward language">
|
<div class="ui dropdown upward language">
|
||||||
<span>{{svg "octicon-globe"}} {{.locale.LangName}}</span>
|
<span>{{svg "octicon-globe"}} {{.locale.LangName}}</span>
|
||||||
<div class="menu language-menu">
|
<div class="menu language-menu">
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
{{template "custom/body_inner_pre" .}}
|
{{template "custom/body_inner_pre" .}}
|
||||||
|
|
||||||
{{if not .PageIsInstall}}
|
{{if not .PageIsInstall}}
|
||||||
<div class="ui top secondary stackable main menu following bar light no-vertical-tabs">
|
<div class="ui top secondary stackable main menu following bar light">
|
||||||
{{template "base/head_navbar" .}}
|
{{template "base/head_navbar" .}}
|
||||||
</div><!-- end bar -->
|
</div><!-- end bar -->
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -19,6 +19,18 @@
|
|||||||
{{if .Org.Website}}<div class="item">{{svg "octicon-link"}} <a target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
|
{{if .Org.Website}}<div class="item">{{svg "octicon-link"}} <a target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="right stackable menu">
|
||||||
|
<form method="post" action="{{.Link}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}&redirect_to={{$.Link}}">
|
||||||
|
{{$.CsrfTokenHtml}}
|
||||||
|
<button type="submit" class="ui basic button gt-mr-0">
|
||||||
|
{{if $.IsFollowing}}
|
||||||
|
{{.locale.Tr "user.unfollow"}}
|
||||||
|
{{else}}
|
||||||
|
{{.locale.Tr "user.follow"}}
|
||||||
|
{{end}}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "org/menu" .}}
|
{{template "org/menu" .}}
|
||||||
|
@ -50,12 +50,12 @@
|
|||||||
<div class="ui bottom attached table segment members">
|
<div class="ui bottom attached table segment members">
|
||||||
{{range .Invites}}
|
{{range .Invites}}
|
||||||
<div class="item">
|
<div class="item">
|
||||||
|
{{.Email}}
|
||||||
<form action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/remove_invite" method="post">
|
<form action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/remove_invite" method="post">
|
||||||
{{$.CsrfTokenHtml}}
|
{{$.CsrfTokenHtml}}
|
||||||
<input type="hidden" name="iid" value="{{.ID}}">
|
<input type="hidden" name="iid" value="{{.ID}}">
|
||||||
<button class="ui red button right">{{$.locale.Tr "org.members.remove"}}</button>
|
<button class="ui red button gt-float-right">{{$.locale.Tr "org.members.remove"}}</button>
|
||||||
</form>
|
</form>
|
||||||
{{.Email}}
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="inline ui field right">
|
<div class="inline ui field right">
|
||||||
<form class="ui form" id="repo-multiple-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/repositories" method="post">
|
<form class="ui form" id="repo-multiple-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/repositories" method="post">
|
||||||
<button class="ui red button delete-button right" data-modal-id="org-team-remove-all-repo" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/removeall">{{.locale.Tr "remove_all"}}</button>
|
<button class="ui green button add-all-button" data-modal-id="org-team-add-all-repo" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/addall">{{.locale.Tr "add_all"}}</button>
|
||||||
<button class="ui green button add-all-button right" data-modal-id="org-team-add-all-repo" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/addall">{{.locale.Tr "add_all"}}</button>
|
<button class="ui red button delete-button" data-modal-id="org-team-remove-all-repo" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/removeall">{{.locale.Tr "remove_all"}}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
<a class="item" href="{{$.Link}}/rules/{{.ID}}"><strong>{{.Type.Name}}</strong></a>
|
<a class="item" href="{{$.Link}}/rules/{{.ID}}"><strong>{{.Type.Name}}</strong></a>
|
||||||
<div><i>{{if .Enabled}}{{$.locale.Tr "enabled"}}{{else}}{{$.locale.Tr "disabled"}}{{end}}</i></div>
|
<div><i>{{if .Enabled}}{{$.locale.Tr "enabled"}}{{else}}{{$.locale.Tr "disabled"}}{{end}}</i></div>
|
||||||
{{if .KeepCount}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count"}}:</i> {{if eq .KeepCount 1}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.1"}}{{else}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.n" .KeepCount}}{{end}}</div>{{end}}
|
{{if .KeepCount}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count"}}:</i> {{if eq .KeepCount 1}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.1"}}{{else}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.n" .KeepCount}}{{end}}</div>{{end}}
|
||||||
{{if .KeepPattern}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.pattern"}}:</i> {{EllipsisString .KeepPattern 100}}</div>{{end}}
|
{{if .KeepPattern}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.pattern"}}:</i> {{StringUtils.EllipsisString .KeepPattern 100}}</div>{{end}}
|
||||||
{{if .RemoveDays}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.days"}}:</i> {{$.locale.Tr "tool.days" .RemoveDays}}</div>{{end}}
|
{{if .RemoveDays}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.days"}}:</i> {{$.locale.Tr "tool.days" .RemoveDays}}</div>{{end}}
|
||||||
{{if .RemovePattern}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.pattern"}}:</i> {{EllipsisString .RemovePattern 100}}</div>{{end}}
|
{{if .RemovePattern}}<div><i>{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.pattern"}}:</i> {{StringUtils.EllipsisString .RemovePattern 100}}</div>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
{{if .CanWriteProjects}}
|
{{if .CanWriteProjects}}
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="ui compact tiny menu">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
|
||||||
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
|
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
{{if and .CanWriteProjects .PageIsEditProject}}
|
{{if and .CanWriteProjects .PageIsEditProject}}
|
||||||
<div class="ui right floated secondary menu">
|
<div class="ui right floated secondary menu">
|
||||||
<a class="ui green button" href="{{$.HomeLink}}/-/projects/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
<a class="ui small green button" href="{{$.HomeLink}}/-/projects/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="column right aligned">
|
<div class="column right aligned">
|
||||||
{{if .CanWriteProjects}}
|
{{if .CanWriteProjects}}
|
||||||
<a class="ui green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
|
<a class="ui small green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui small modal new-board-modal" id="new-board-item">
|
<div class="ui small modal new-board-modal" id="new-board-item">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="ui compact tiny menu">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?workflow={{.CurWorkflow}}&state=open">
|
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?workflow={{.CurWorkflow}}&state=open">
|
||||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||||
{{.locale.Tr "actions.runs.open_tab" $.NumOpenActionRuns}}
|
{{.locale.Tr "actions.runs.open_tab" $.NumOpenActionRuns}}
|
||||||
|
@ -5,8 +5,13 @@
|
|||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
{{template "repo/sub_menu" .}}
|
{{template "repo/sub_menu" .}}
|
||||||
{{if .DefaultBranchBranch}}
|
{{if .DefaultBranchBranch}}
|
||||||
<h4 class="ui top attached header gt-mt-4">
|
<h4 class="ui top attached header">
|
||||||
{{.locale.Tr "repo.default_branch"}}
|
{{.locale.Tr "repo.default_branch"}}
|
||||||
|
{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}}
|
||||||
|
<a role="button" class="right" href="{{.RepoLink}}/settings/branches" data-tooltip-content="{{.locale.Tr "repo.settings.branches.switch_default_branch"}}">
|
||||||
|
{{svg "octicon-arrow-switch"}}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{{.locale.Tr "repo.cite_this_repo"}}
|
{{.locale.Tr "repo.cite_this_repo"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins no-vertical-tabs">
|
<div class="ui stackable secondary menu">
|
||||||
<div class="fitted item">
|
<div class="fitted item">
|
||||||
<div class="ui action input" id="citation-panel">
|
<div class="ui action input" id="citation-panel">
|
||||||
{{template "repo/cite/cite_buttons" .}}
|
{{template "repo/cite/cite_buttons" .}}
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
<b>{{$resolveDoer.Name}}</b> {{$.locale.Tr "repo.issues.review.resolved_by"}}
|
<b>{{$resolveDoer.Name}}</b> {{$.locale.Tr "repo.issues.review.resolved_by"}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny right labeled button show-outdated gt-df gt-ac">
|
<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny labeled button show-outdated gt-df gt-ac">
|
||||||
{{svg "octicon-unfold" 16 "gt-mr-3"}}
|
{{svg "octicon-unfold" 16 "gt-mr-3"}}
|
||||||
{{$.locale.Tr "repo.issues.review.show_resolved"}}
|
{{$.locale.Tr "repo.issues.review.show_resolved"}}
|
||||||
</button>
|
</button>
|
||||||
<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny right labeled button hide-outdated gt-df gt-ac gt-hidden">
|
<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny labeled button hide-outdated gt-df gt-ac gt-hidden">
|
||||||
{{svg "octicon-fold" 16 "gt-mr-3"}}
|
{{svg "octicon-fold" 16 "gt-mr-3"}}
|
||||||
{{$.locale.Tr "repo.issues.review.hide_resolved"}}
|
{{$.locale.Tr "repo.issues.review.hide_resolved"}}
|
||||||
</button>
|
</button>
|
||||||
|
@ -151,7 +151,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui tabs container">
|
<div class="ui tabs container">
|
||||||
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
|
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
|
||||||
<div class="ui tabular stackable menu navbar">
|
<div class="ui tabular menu navbar gt-overflow-x-auto gt-overflow-y-hidden">
|
||||||
{{if .Permission.CanRead $.UnitTypeCode}}
|
{{if .Permission.CanRead $.UnitTypeCode}}
|
||||||
<a class="{{if .PageIsViewCode}}active {{end}}item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
|
<a class="{{if .PageIsViewCode}}active {{end}}item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
|
||||||
{{svg "octicon-code"}} {{.locale.Tr "repo.code"}}
|
{{svg "octicon-code"}} {{.locale.Tr "repo.code"}}
|
||||||
@ -236,21 +236,17 @@
|
|||||||
{{template "custom/extra_tabs" .}}
|
{{template "custom/extra_tabs" .}}
|
||||||
|
|
||||||
{{if .Permission.IsAdmin}}
|
{{if .Permission.IsAdmin}}
|
||||||
<div class="right menu">
|
<a class="{{if .PageIsRepoSettings}}active {{end}}right item" href="{{.RepoLink}}/settings">
|
||||||
<a class="{{if .PageIsRepoSettings}}active {{end}}item" href="{{.RepoLink}}/settings">
|
|
||||||
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
|
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{else if .Permission.IsAdmin}}
|
{{else if .Permission.IsAdmin}}
|
||||||
<div class="ui tabular stackable menu navbar">
|
<div class="ui tabular menu navbar gt-overflow-x-auto gt-overflow-y-hidden">
|
||||||
<div class="right menu">
|
<a class="{{if .PageIsRepoSettings}}active {{end}}right item" href="{{.RepoLink}}/settings">
|
||||||
<a class="{{if .PageIsRepoSettings}}active {{end}}item" href="{{.RepoLink}}/settings">
|
|
||||||
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
|
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui tabs divider"></div>
|
<div class="ui tabs divider"></div>
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
<div class="ui repo-search">
|
<div class="ui repo-search">
|
||||||
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
|
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui action input{{if .CodeIndexerUnavailable}} disabled left icon{{end}}"{{if .CodeIndexerUnavailable}} data-tooltip-content="{{.locale.Tr "repo.search.code_search_unavailable"}}"{{end}}>
|
<div class="ui small action input{{if .CodeIndexerUnavailable}} disabled left icon{{end}}"{{if .CodeIndexerUnavailable}} data-tooltip-content="{{.locale.Tr "repo.search.code_search_unavailable"}}"{{end}}>
|
||||||
<input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{.locale.Tr "repo.search.search_repo"}}">
|
<input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{.locale.Tr "repo.search.search_repo"}}">
|
||||||
{{if .CodeIndexerUnavailable}}
|
{{if .CodeIndexerUnavailable}}
|
||||||
<i class="icon gt-df gt-ac gt-jc">{{svg "octicon-alert"}}</i>
|
<i class="icon gt-df gt-ac gt-jc">{{svg "octicon-alert"}}</i>
|
||||||
{{end}}
|
{{end}}
|
||||||
<button class="ui icon button"{{if .CodeIndexerUnavailable}} disabled{{end}} type="submit">
|
<button class="ui small icon button"{{if .CodeIndexerUnavailable}} disabled{{end}} type="submit">
|
||||||
{{svg "octicon-search"}}
|
{{svg "octicon-search"}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -68,7 +68,13 @@
|
|||||||
{{$l := Eval $n "-" 1}}
|
{{$l := Eval $n "-" 1}}
|
||||||
<!-- If home page, show new pr. If not, show breadcrumb -->
|
<!-- If home page, show new pr. If not, show breadcrumb -->
|
||||||
{{if and (eq $n 0) .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
{{if and (eq $n 0) .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
||||||
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{CompareLink .BaseRepo .Repository .BranchName}}"
|
{{$cmpBranch := ""}}
|
||||||
|
{{if ne .Repository.ID .BaseRepo.ID}}
|
||||||
|
{{$cmpBranch = printf "%s/%s:" (.Repository.OwnerName|PathEscape) (.Repository.Name|PathEscape)}}
|
||||||
|
{{end}}
|
||||||
|
{{$cmpBranch = printf "%s%s" $cmpBranch (.BranchName|PathEscapeSegments)}}
|
||||||
|
{{$compareLink := printf "%s/compare/%s...%s" .BaseRepo.Link (.BaseRepo.DefaultBranch|PathEscapeSegments) $cmpBranch}}
|
||||||
|
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{$compareLink}}"
|
||||||
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}">
|
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}">
|
||||||
{{svg "octicon-git-pull-request"}}
|
{{svg "octicon-git-pull-request"}}
|
||||||
</a>
|
</a>
|
||||||
@ -103,7 +109,17 @@
|
|||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if ne $n 0}}
|
{{if ne $n 0}}
|
||||||
<span class="ui breadcrumb repo-path gt-ml-2"><a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span>
|
<span class="ui breadcrumb repo-path gt-ml-2">
|
||||||
|
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
|
||||||
|
{{- range $i, $v := .TreeNames -}}
|
||||||
|
<span class="divider">/</span>
|
||||||
|
{{- if eq $i $l -}}
|
||||||
|
<span class="active section" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</span>
|
||||||
|
{{- else -}}
|
||||||
|
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</a></span>
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="gt-df gt-ac">
|
<div class="gt-df gt-ac">
|
||||||
|
@ -20,39 +20,40 @@
|
|||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
<div class="labelspage">
|
|
||||||
{{if and (not $.PageIsOrgSettingsLabels) (or $.CanWriteIssues $.CanWritePulls) (eq .NumLabels 0) (not $.Repository.IsArchived)}}
|
{{if and (not $.PageIsOrgSettingsLabels) (or $.CanWriteIssues $.CanWritePulls) (eq .NumLabels 0) (not $.Repository.IsArchived)}}
|
||||||
{{template "repo/issue/labels/label_load_template" .}}
|
{{template "repo/issue/labels/label_load_template" .}}
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{else if and ($.PageIsOrgSettingsLabels) (eq .NumLabels 0)}}
|
{{else if and ($.PageIsOrgSettingsLabels) (eq .NumLabels 0)}}
|
||||||
{{template "repo/issue/labels/label_load_template" .}}
|
{{template "repo/issue/labels/label_load_template" .}}
|
||||||
|
<div class="ui divider"></div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
<ul class="issue-label-list">
|
||||||
{{range .Labels}}
|
{{range .Labels}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<div class="ui grid middle aligned">
|
<div class="label-title">
|
||||||
<div class="eight wide column">
|
|
||||||
{{RenderLabel $.Context .}}
|
{{RenderLabel $.Context .}}
|
||||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
|
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="five wide column">
|
<div class="label-issues">
|
||||||
{{if $.PageIsOrgSettingsLabels}}
|
{{if $.PageIsOrgSettingsLabels}}
|
||||||
<a class="ui left open-issues" href="{{AppSubUrl}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
|
<a class="open-issues" href="{{AppSubUrl}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a class="ui left open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
|
<a class="open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="three wide column">
|
<div class="label-operation">
|
||||||
{{if and (not $.PageIsOrgSettingsLabels) (not $.Repository.IsArchived) (or $.CanWriteIssues $.CanWritePulls)}}
|
{{if and (not $.PageIsOrgSettingsLabels) (not $.Repository.IsArchived) (or $.CanWriteIssues $.CanWritePulls)}}
|
||||||
<a class="ui right delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||||
<a class="ui right edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
<a class="delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||||
{{else if $.PageIsOrgSettingsLabels}}
|
{{else if $.PageIsOrgSettingsLabels}}
|
||||||
<a class="ui right delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
<a class="edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||||
<a class="ui right edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" {{if .Exclusive}}data-exclusive{{end}} data-num-issues="{{.NumIssues}}" data-description="{{.Description}}" data-color={{.Color}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
<a class="delete-button" href="#" data-url="{{$.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
|
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<div class="ui grid middle aligned">
|
<div class="ui grid middle aligned">
|
||||||
@ -64,25 +65,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{if (not $.PageIsOrgSettingsLabels)}}
|
|
||||||
<div class="orglabel">
|
|
||||||
{{range .OrgLabels}}
|
{{range .OrgLabels}}
|
||||||
<li class="item">
|
<li class="item org-label">
|
||||||
<div class="ui grid middle aligned">
|
<div class="label-title">
|
||||||
<div class="nine wide column">
|
|
||||||
{{RenderLabel $.Context .}}
|
{{RenderLabel $.Context .}}
|
||||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
|
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="four wide column">
|
<div class="label-issues">
|
||||||
<a class="ui left open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenRepoIssues}}</a>
|
<a class="open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenRepoIssues}}</a>
|
||||||
</div>
|
|
||||||
<div class="three wide column">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="label-operation"></div>
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,26 +2,18 @@
|
|||||||
<div role="main" aria-label="{{.Title}}" class="page-content repository issue-list">
|
<div role="main" aria-label="{{.Title}}" class="page-content repository issue-list">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<div class="ui three column grid issue-list-headers">
|
<div class="list-header">
|
||||||
<div class="column">
|
|
||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
</div>
|
|
||||||
<div class="column center aligned">
|
|
||||||
{{template "repo/issue/search" .}}
|
{{template "repo/issue/search" .}}
|
||||||
</div>
|
|
||||||
{{if not .Repository.IsArchived}}
|
{{if not .Repository.IsArchived}}
|
||||||
<div class="column right aligned">
|
|
||||||
{{if .PageIsIssueList}}
|
{{if .PageIsIssueList}}
|
||||||
<a class="ui green button" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.locale.Tr "repo.issues.new"}}</a>
|
<a class="ui small green button" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.locale.Tr "repo.issues.new"}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.Repository.Link}}/compare/{{.Repository.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{.locale.Tr "repo.pulls.new"}}</a>
|
<a class="ui small green button new-pr-button{{if not .PullRequestCtx.Allowed}} disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.Repository.Link}}/compare/{{.Repository.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{.locale.Tr "repo.pulls.new"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if not .PageIsIssueList}}
|
{{if not .PageIsIssueList}}
|
||||||
<div class="column right aligned">
|
<a class="ui small green small button{{if not .PullRequestCtx.Allowed}} disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.PullRequestCtx.BaseRepo.Link}}/compare/{{.PullRequestCtx.BaseRepo.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{$.locale.Tr "action.compare_commits_general"}}</a>
|
||||||
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.PullRequestCtx.BaseRepo.Link}}/compare/{{.PullRequestCtx.BaseRepo.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{$.locale.Tr "action.compare_commits_general"}}</a>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
@ -34,7 +26,7 @@
|
|||||||
{{template "repo/issue/openclose" .}}
|
{{template "repo/issue/openclose" .}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ten wide right aligned column">
|
<div class="ten wide right aligned column">
|
||||||
<div class="ui secondary filter stackable menu labels">
|
<div class="ui secondary filter menu labels gt-overflow-x-auto gt-overflow-y-hidden">
|
||||||
<!-- Label -->
|
<!-- Label -->
|
||||||
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item label-filter" style="margin-left: auto">
|
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item label-filter" style="margin-left: auto">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
@ -176,7 +168,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<div class="ui dropdown downward type jump item">
|
<div class="list-header-sort ui small dropdown downward type jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.locale.Tr "repo.issues.filter_sort"}}
|
{{.locale.Tr "repo.issues.filter_sort"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
|
@ -6,16 +6,15 @@
|
|||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
|
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui green button" href="{{$.Link}}/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
|
||||||
<div class="ui three column stackable grid">
|
<div class="list-header">
|
||||||
<div class="column">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<div class="ui compact tiny menu">
|
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/milestones?state=open&q={{$.Keyword}}">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/milestones?state=open&q={{$.Keyword}}">
|
||||||
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
@ -25,22 +24,20 @@
|
|||||||
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<div class="column center aligned">
|
<form class="list-header-search ui form ignore-dirty">
|
||||||
<form class="ui form ignore-dirty">
|
<div class="ui small search fluid action input">
|
||||||
<div class="ui search fluid action input">
|
|
||||||
<input type="hidden" name="state" value="{{$.State}}">
|
<input type="hidden" name="state" value="{{$.State}}">
|
||||||
<input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
<input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
||||||
<button class="ui primary button" type="submit">{{.locale.Tr "explore.search"}}</button>
|
<button class="ui small icon button" type="submit" aria-label="{{.locale.Tr "explore.search"}}">
|
||||||
|
{{svg "octicon-search"}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column right aligned gt-df gt-ac gt-je">
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<div class="ui dropdown type jump item">
|
<div class="list-header-sort ui small dropdown type jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.locale.Tr "repo.issues.filter_sort"}}
|
{{.locale.Tr "repo.issues.filter_sort"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
@ -55,7 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- milestone list -->
|
<!-- milestone list -->
|
||||||
<div class="milestone list">
|
<div class="milestone list">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<h2 class="ui compact small menu header">
|
<h2 class="ui compact small menu header small-pill-buttons">
|
||||||
<a class="{{if .PageIsLabels}}active {{end}}item" href="{{.RepoLink}}/labels">{{.locale.Tr "repo.labels"}}</a>
|
<a class="{{if .PageIsLabels}}active {{end}}item" href="{{.RepoLink}}/labels">{{.locale.Tr "repo.labels"}}</a>
|
||||||
<a class="{{if .PageIsMilestones}}active {{end}}item" href="{{.RepoLink}}/milestones">{{.locale.Tr "repo.milestones"}}</a>
|
<a class="{{if .PageIsMilestones}}active {{end}}item" href="{{.RepoLink}}/milestones">{{.locale.Tr "repo.milestones"}}</a>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<input name="title" id="issue_title" placeholder="{{.locale.Tr "repo.milestones.title"}}" value="{{if .TitleQuery}}{{.TitleQuery}}{{else if .IssueTemplateTitle}}{{.IssueTemplateTitle}}{{else}}{{.title}}{{end}}" tabindex="3" autofocus required maxlength="255" autocomplete="off">
|
<input name="title" id="issue_title" placeholder="{{.locale.Tr "repo.milestones.title"}}" value="{{if .TitleQuery}}{{.TitleQuery}}{{else if .IssueTemplateTitle}}{{.IssueTemplateTitle}}{{else}}{{.title}}{{end}}" tabindex="3" autofocus required maxlength="255" autocomplete="off">
|
||||||
{{if .PageIsComparePull}}
|
{{if .PageIsComparePull}}
|
||||||
<div class="title_wip_desc" data-wip-prefixes="{{Json .PullRequestWorkInProgressPrefixes}}">{{.locale.Tr "repo.pulls.title_wip_desc" (index .PullRequestWorkInProgressPrefixes 0| Escape) | Safe}}</div>
|
<div class="title_wip_desc" data-wip-prefixes="{{JsonUtils.EncodeToString .PullRequestWorkInProgressPrefixes}}">{{.locale.Tr "repo.pulls.title_wip_desc" (index .PullRequestWorkInProgressPrefixes 0| Escape) | Safe}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{if .Fields}}
|
{{if .Fields}}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="ui compact tiny menu">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&project={{.ProjectID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
|
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&project={{.ProjectID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
|
||||||
{{if .PageIsPullList}}
|
{{if .PageIsPullList}}
|
||||||
{{svg "octicon-git-pull-request" 16 "gt-mr-3"}}
|
{{svg "octicon-git-pull-request" 16 "gt-mr-3"}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<form class="ui form ignore-dirty">
|
<form class="list-header-search ui form ignore-dirty">
|
||||||
<div class="ui search fluid action input">
|
<div class="ui small search fluid action input">
|
||||||
<input type="hidden" name="type" value="{{$.ViewType}}">
|
<input type="hidden" name="type" value="{{$.ViewType}}">
|
||||||
<input type="hidden" name="state" value="{{$.State}}">
|
<input type="hidden" name="state" value="{{$.State}}">
|
||||||
<input type="hidden" name="labels" value="{{.SelectLabels}}">
|
<input type="hidden" name="labels" value="{{.SelectLabels}}">
|
||||||
@ -8,6 +8,8 @@
|
|||||||
<input type="hidden" name="assignee" value="{{$.AssigneeID}}">
|
<input type="hidden" name="assignee" value="{{$.AssigneeID}}">
|
||||||
<input type="hidden" name="poster" value="{{$.PosterID}}">
|
<input type="hidden" name="poster" value="{{$.PosterID}}">
|
||||||
<input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
<input name="q" value="{{.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
||||||
<button class="ui primary button" type="submit">{{.locale.Tr "explore.search"}}</button>
|
<button class="ui small icon button" type="submit" aria-label="{{.locale.Tr "explore.search"}}">
|
||||||
|
{{svg "octicon-search"}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -304,10 +304,12 @@
|
|||||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||||
<span class="text grey muted-links">
|
<span class="text grey muted-links">
|
||||||
{{template "shared/user/authorlink" .Poster}}
|
{{template "shared/user/authorlink" .Poster}}
|
||||||
{{$parsedDeadline := .Content | ParseDeadline}}
|
{{$parsedDeadline := StringUtils.Split .Content "|"}}
|
||||||
|
{{if eq (len $parsedDeadline) 2}}
|
||||||
{{$from := DateTime "long" (index $parsedDeadline 1)}}
|
{{$from := DateTime "long" (index $parsedDeadline 1)}}
|
||||||
{{$to := DateTime "long" (index $parsedDeadline 0)}}
|
{{$to := DateTime "long" (index $parsedDeadline 0)}}
|
||||||
{{$.locale.Tr "repo.issues.due_date_modified" $to $from $createdStr | Safe}}
|
{{$.locale.Tr "repo.issues.due_date_modified" $to $from $createdStr | Safe}}
|
||||||
|
{{end}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Type 18}}
|
{{else if eq .Type 18}}
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
|
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="ui compact tiny menu">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=open">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=open">
|
||||||
{{svg "octicon-project" 16 "gt-mr-3"}}
|
{{svg "octicon-project" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{{template "repo/issue/navbar" .}}
|
{{template "repo/issue/navbar" .}}
|
||||||
{{if and .CanWriteProjects .PageIsEditProject}}
|
{{if and .CanWriteProjects .PageIsEditProject}}
|
||||||
<div class="ui right floated secondary menu">
|
<div class="ui right floated secondary menu">
|
||||||
<a class="ui green button" href="{{$.RepoLink}}/projects/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
<a class="ui small green button" href="{{$.RepoLink}}/projects/new">{{.locale.Tr "repo.milestones.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="column right aligned">
|
<div class="column right aligned">
|
||||||
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
|
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
|
||||||
<a class="ui green button item" href="{{$.RepoLink}}/issues/new/choose?project={{$.Project.ID}}">{{.locale.Tr "repo.issues.new"}}</a>
|
<a class="ui small green button item" href="{{$.RepoLink}}/issues/new/choose?project={{$.Project.ID}}">{{.locale.Tr "repo.issues.new"}}</a>
|
||||||
<a class="ui green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
|
<a class="ui small green button show-modal item" data-modal="#new-board-item">{{.locale.Tr "new_project_column"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui small modal new-board-modal" id="new-board-item">
|
<div class="ui small modal new-board-modal" id="new-board-item">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<b>{{.tag_name}}</b><span class="at">@</span><strong>{{.tag_target}}</strong>
|
<b>{{.tag_name}}</b><span class="at">@</span><strong>{{.tag_target}}</strong>
|
||||||
{{else}}
|
{{else}}
|
||||||
<input id="tag-name" name="tag_name" value="{{.tag_name}}" aria-label="{{.locale.Tr "repo.release.tag_name"}}" placeholder="{{.locale.Tr "repo.release.tag_name"}}" autofocus required maxlength="255">
|
<input id="tag-name" name="tag_name" value="{{.tag_name}}" aria-label="{{.locale.Tr "repo.release.tag_name"}}" placeholder="{{.locale.Tr "repo.release.tag_name"}}" autofocus required maxlength="255">
|
||||||
<input id="tag-name-editor" type="hidden" data-existing-tags={{Json .Tags}} data-tag-helper={{.locale.Tr "repo.release.tag_helper"}} data-tag-helper-new={{.locale.Tr "repo.release.tag_helper_new"}} data-tag-helper-existing={{.locale.Tr "repo.release.tag_helper_existing"}}>
|
<input id="tag-name-editor" type="hidden" data-existing-tags="{{JsonUtils.EncodeToString .Tags}}" data-tag-helper="{{.locale.Tr "repo.release.tag_helper"}}" data-tag-helper-new="{{.locale.Tr "repo.release.tag_helper_new"}}" data-tag-helper-existing="{{.locale.Tr "repo.release.tag_helper_existing"}}">
|
||||||
<div id="tag-target-selector" class="gt-dib">
|
<div id="tag-target-selector" class="gt-dib">
|
||||||
<span class="at">@</span>
|
<span class="at">@</span>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
|
@ -12,18 +12,13 @@
|
|||||||
<p>
|
<p>
|
||||||
{{.locale.Tr "repo.settings.default_branch_desc"}}
|
{{.locale.Tr "repo.settings.default_branch_desc"}}
|
||||||
</p>
|
</p>
|
||||||
<form class="ui form" action="{{.Link}}" method="post">
|
<form class="gt-df" action="{{.Link}}" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<input type="hidden" name="action" value="default_branch">
|
<input type="hidden" name="action" value="default_branch">
|
||||||
{{if not .Repository.IsEmpty}}
|
{{if not .Repository.IsEmpty}}
|
||||||
<div class="required inline field">
|
<div class="ui dropdown selection gt-f1 gt-mr-3 gt-max-width-24rem">
|
||||||
<div class="ui dropdown selection" tabindex="0">
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<select name="branch">
|
<input type="hidden" name="branch" value="{{.Repository.DefaultBranch}}">
|
||||||
<option value="{{.Repository.DefaultBranch}}">{{.Repository.DefaultBranch}}</option>
|
|
||||||
{{range .Branches}}
|
|
||||||
<option value="{{.}}">{{.}}</option>
|
|
||||||
{{end}}
|
|
||||||
</select>{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
|
||||||
<div class="default text">{{.Repository.DefaultBranch}}</div>
|
<div class="default text">{{.Repository.DefaultBranch}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{range .Branches}}
|
{{range .Branches}}
|
||||||
@ -32,7 +27,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="ui green button">{{$.locale.Tr "repo.settings.branches.update_default_branch"}}</button>
|
<button class="ui green button">{{$.locale.Tr "repo.settings.branches.update_default_branch"}}</button>
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,39 +5,49 @@
|
|||||||
{{.locale.Tr "repo.settings.branch_protection" (.Rule.RuleName|Escape) | Str2html}}
|
{{.locale.Tr "repo.settings.branch_protection" (.Rule.RuleName|Escape) | Str2html}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment branch-protection">
|
<div class="ui attached segment branch-protection">
|
||||||
|
<h5 class="ui dividing header">{{.locale.Tr "repo.settings.protect_patterns"}}</h5>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="protected_file_patterns">{{.locale.Tr "repo.settings.protect_branch_name_pattern"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_branch_name_pattern"}}</label>
|
||||||
<input name="rule_name" type="text" value="{{.Rule.RuleName}}">
|
<input name="rule_name" type="text" value="{{.Rule.RuleName}}">
|
||||||
<input name="rule_id" type="hidden" value="{{.Rule.ID}}">
|
<input name="rule_id" type="hidden" value="{{.Rule.ID}}">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
<div class="ui divider"></div>
|
<label>{{.locale.Tr "repo.settings.protect_protected_file_patterns"}}</label>
|
||||||
|
<input name="protected_file_patterns" type="text" value="{{.Rule.ProtectedFilePatterns}}">
|
||||||
|
<p class="help gt-ml-0">{{.locale.Tr "repo.settings.protect_protected_file_patterns_desc" | Safe}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_unprotected_file_patterns"}}</label>
|
||||||
|
<input name="unprotected_file_patterns" type="text" value="{{.Rule.UnprotectedFilePatterns}}">
|
||||||
|
<p class="help gt-ml-0">{{.locale.Tr "repo.settings.protect_unprotected_file_patterns_desc" | Safe}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div id="protection_box" class="fields">
|
<h5 class="ui dividing header">{{.locale.Tr "repo.settings.event_push"}}</h5>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input name="enable_push" type="radio" value="none" class="disable-whitelist" data-target="#whitelist_box" {{if not .Rule.CanPush}}checked{{end}}>
|
<input name="enable_push" type="radio" value="none" class="toggle-target-disabled" data-target="#whitelist_box" {{if not .Rule.CanPush}}checked{{end}}>
|
||||||
<label>{{.locale.Tr "repo.settings.protect_disable_push"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_disable_push"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_disable_push_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.protect_disable_push_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input name="enable_push" type="radio" value="all" class="disable-whitelist" data-target="#whitelist_box" {{if and (.Rule.CanPush) (not .Rule.EnableWhitelist)}}checked{{end}}>
|
<input name="enable_push" type="radio" value="all" class="toggle-target-disabled" data-target="#whitelist_box" {{if and (.Rule.CanPush) (not .Rule.EnableWhitelist)}}checked{{end}}>
|
||||||
<label>{{.locale.Tr "repo.settings.protect_enable_push"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_enable_push"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_enable_push_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.protect_enable_push_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grouped fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui radio checkbox">
|
<div class="ui radio checkbox">
|
||||||
<input name="enable_push" type="radio" value="whitelist" class="enable-whitelist" data-target="#whitelist_box" {{if and (.Rule.CanPush) (.Rule.EnableWhitelist)}}checked{{end}}>
|
<input name="enable_push" type="radio" value="whitelist" class="toggle-target-enabled" data-target="#whitelist_box" {{if and (.Rule.CanPush) (.Rule.EnableWhitelist)}}checked{{end}}>
|
||||||
<label>{{.locale.Tr "repo.settings.protect_whitelist_committers"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_whitelist_committers"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_whitelist_committers_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.protect_whitelist_committers_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="whitelist_box" class="fields {{if not .Rule.EnableWhitelist}}disabled{{end}}">
|
<div id="whitelist_box" class="grouped fields {{if not .Rule.EnableWhitelist}}disabled{{end}}">
|
||||||
<div class="whitelist field">
|
<div class="checkbox-sub-item field">
|
||||||
<label>{{.locale.Tr "repo.settings.protect_whitelist_users"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_whitelist_users"}}</label>
|
||||||
<div class="ui multiple search selection dropdown">
|
<div class="ui multiple search selection dropdown">
|
||||||
<input type="hidden" name="whitelist_users" value="{{.whitelist_users}}">
|
<input type="hidden" name="whitelist_users" value="{{.whitelist_users}}">
|
||||||
@ -52,8 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .Owner.IsOrganization}}
|
{{if .Owner.IsOrganization}}
|
||||||
<br>
|
<div class="checkbox-sub-item field">
|
||||||
<div class="whitelist field">
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_whitelist_teams"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_whitelist_teams"}}</label>
|
||||||
<div class="ui multiple search selection dropdown">
|
<div class="ui multiple search selection dropdown">
|
||||||
<input type="hidden" name="whitelist_teams" value="{{.whitelist_teams}}">
|
<input type="hidden" name="whitelist_teams" value="{{.whitelist_teams}}">
|
||||||
@ -69,105 +78,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<br>
|
<div class="checkbox-sub-item field">
|
||||||
<div class="whitelist field">
|
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="whitelist_deploy_keys" {{if .Rule.WhitelistDeployKeys}}checked{{end}}>
|
<input type="checkbox" name="whitelist_deploy_keys" {{if .Rule.WhitelistDeployKeys}}checked{{end}}>
|
||||||
<label for="whitelist_deploy_keys">{{.locale.Tr "repo.settings.protect_whitelist_deploy_keys"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_whitelist_deploy_keys"}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui divider"></div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui checkbox">
|
|
||||||
<input class="enable-whitelist" name="enable_merge_whitelist" type="checkbox" data-target="#merge_whitelist_box" {{if .Rule.EnableMergeWhitelist}}checked{{end}}>
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_committers"}}</label>
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_merge_whitelist_committers_desc"}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="merge_whitelist_box" class="fields {{if not .Rule.EnableMergeWhitelist}}disabled{{end}}">
|
|
||||||
<div class="whitelist field">
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_users"}}</label>
|
|
||||||
<div class="ui multiple search selection dropdown">
|
|
||||||
<input type="hidden" name="merge_whitelist_users" value="{{.merge_whitelist_users}}">
|
|
||||||
<div class="default text">{{.locale.Tr "repo.settings.protect_whitelist_search_users"}}</div>
|
|
||||||
<div class="menu">
|
|
||||||
{{range .Users}}
|
|
||||||
<div class="item" data-value="{{.ID}}">
|
|
||||||
{{avatar $.Context . 28 "mini"}}{{template "repo/search_name" .}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{if .Owner.IsOrganization}}
|
|
||||||
<br>
|
|
||||||
<div class="whitelist field">
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_teams"}}</label>
|
|
||||||
<div class="ui multiple search selection dropdown">
|
|
||||||
<input type="hidden" name="merge_whitelist_teams" value="{{.merge_whitelist_teams}}">
|
|
||||||
<div class="default text">{{.locale.Tr "repo.settings.protect_whitelist_search_teams"}}</div>
|
|
||||||
<div class="menu">
|
|
||||||
{{range .Teams}}
|
|
||||||
<div class="item" data-value="{{.ID}}">
|
|
||||||
{{svg "octicon-people"}}
|
|
||||||
{{.Name}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui checkbox">
|
|
||||||
<input class="enable-statuscheck" name="enable_status_check" type="checkbox" data-target="#statuscheck_contexts_box" {{if eq (len .branch_status_check_contexts) 0}}disabled{{end}} {{if .Rule.EnableStatusCheck}}checked{{end}}>
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_check_status_contexts"}}</label>
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_check_status_contexts_desc"}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="statuscheck_contexts_box" class="fields {{if not .Rule.EnableStatusCheck}}disabled{{end}}">
|
|
||||||
<div class="field">
|
|
||||||
<table class="ui celled table six column">
|
|
||||||
<thead>
|
|
||||||
<tr><th>
|
|
||||||
{{.locale.Tr "repo.settings.protect_check_status_contexts_list"}}
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{range $.branch_status_check_contexts}}
|
|
||||||
<tr><td>
|
|
||||||
<span class="ui checkbox">
|
|
||||||
<input class="enable-whitelist" name="status_check_contexts" value="{{.}}" type="checkbox" {{if $.is_context_required}}{{if call $.is_context_required .}}checked{{end}}{{end}}>
|
|
||||||
</span>
|
|
||||||
{{.}}
|
|
||||||
{{if $.is_context_required}}{{if call $.is_context_required .}}<div class="ui label right">Required</div>{{end}}{{end}}
|
|
||||||
</td></tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label for="required-approvals">{{.locale.Tr "repo.settings.protect_required_approvals"}}</label>
|
|
||||||
<input name="required_approvals" id="required-approvals" type="number" value="{{.Rule.RequiredApprovals}}">
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_required_approvals_desc"}}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input class="enable-whitelist" name="enable_approvals_whitelist" type="checkbox" data-target="#approvals_whitelist_box" {{if .Rule.EnableApprovalsWhitelist}}checked{{end}}>
|
<input name="require_signed_commits" type="checkbox" {{if .Rule.RequireSignedCommits}}checked{{end}}>
|
||||||
|
<label>{{.locale.Tr "repo.settings.require_signed_commits"}}</label>
|
||||||
|
<p class="help">{{.locale.Tr "repo.settings.require_signed_commits_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h5 class="ui dividing header">{{.locale.Tr "repo.settings.event_pull_request_approvals"}}</h5>
|
||||||
|
<div class="field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_required_approvals"}}</label>
|
||||||
|
<input name="required_approvals" type="number" value="{{.Rule.RequiredApprovals}}">
|
||||||
|
<p class="help gt-ml-0">{{.locale.Tr "repo.settings.protect_required_approvals_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="grouped fields">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="enable_approvals_whitelist" type="checkbox" class="toggle-target-enabled" data-target="#approvals_whitelist_box" {{if .Rule.EnableApprovalsWhitelist}}checked{{end}}>
|
||||||
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_enabled"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_enabled"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_approvals_whitelist_enabled_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.protect_approvals_whitelist_enabled_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="approvals_whitelist_box" class="fields {{if not .Rule.EnableApprovalsWhitelist}}disabled{{end}}">
|
<div id="approvals_whitelist_box" class="grouped fields {{if not .Rule.EnableApprovalsWhitelist}}disabled{{end}}">
|
||||||
<div class="whitelist field">
|
<div class="checkbox-sub-item field">
|
||||||
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_users"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_users"}}</label>
|
||||||
<div class="ui multiple search selection dropdown">
|
<div class="ui multiple search selection dropdown">
|
||||||
<input type="hidden" name="approvals_whitelist_users" value="{{.approvals_whitelist_users}}">
|
<input type="hidden" name="approvals_whitelist_users" value="{{.approvals_whitelist_users}}">
|
||||||
@ -182,8 +123,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{if .Owner.IsOrganization}}
|
{{if .Owner.IsOrganization}}
|
||||||
<br>
|
<div class="checkbox-sub-item field">
|
||||||
<div class="whitelist field">
|
|
||||||
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_teams"}}</label>
|
<label>{{.locale.Tr "repo.settings.protect_approvals_whitelist_teams"}}</label>
|
||||||
<div class="ui multiple search selection dropdown">
|
<div class="ui multiple search selection dropdown">
|
||||||
<input type="hidden" name="approvals_whitelist_teams" value="{{.approvals_whitelist_teams}}">
|
<input type="hidden" name="approvals_whitelist_teams" value="{{.approvals_whitelist_teams}}">
|
||||||
@ -200,53 +140,117 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="dismiss_stale_approvals" type="checkbox" {{if .Rule.DismissStaleApprovals}}checked{{end}}>
|
||||||
|
<label>{{.locale.Tr "repo.settings.dismiss_stale_approvals"}}</label>
|
||||||
|
<p class="help">{{.locale.Tr "repo.settings.dismiss_stale_approvals_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grouped fields">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="enable_status_check" type="checkbox" class="toggle-target-enabled" data-target="#statuscheck_contexts_box" {{if .Rule.EnableStatusCheck}}checked{{end}}>
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_check_status_contexts"}}</label>
|
||||||
|
<p class="help">{{.locale.Tr "repo.settings.protect_check_status_contexts_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="statuscheck_contexts_box" class="checkbox-sub-item field {{if not .Rule.EnableStatusCheck}}disabled{{end}}">
|
||||||
|
<table class="ui celled table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{.locale.Tr "repo.settings.protect_check_status_contexts_list"}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range $.branch_status_check_contexts}}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="ui checkbox">
|
||||||
|
<label>{{.}}</label>
|
||||||
|
<input name="status_check_contexts" value="{{.}}" type="checkbox" {{if SliceUtils.Contains $.Rule.StatusCheckContexts .}}checked{{end}}>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{else}}
|
||||||
|
<tr><td>N/A</td></tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h5 class="ui dividing header">{{.locale.Tr "repo.settings.event_pull_request_merge"}}</h5>
|
||||||
|
<div class="grouped fields">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input name="enable_merge_whitelist" type="radio" value="false" class="toggle-target-disabled" data-target="#merge_whitelist_box" {{if not .Rule.EnableMergeWhitelist}}checked{{end}}>
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_enable_merge"}}</label>
|
||||||
|
<p class="help">{{.locale.Tr "repo.settings.protect_enable_merge_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
<input name="enable_merge_whitelist" type="radio" value="true" class="toggle-target-enabled" data-target="#merge_whitelist_box" {{if .Rule.EnableMergeWhitelist}}checked{{end}}>
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_committers"}}</label>
|
||||||
|
<p class="help">{{.locale.Tr "repo.settings.protect_merge_whitelist_committers_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="merge_whitelist_box" class="grouped fields {{if not .Rule.EnableMergeWhitelist}}disabled{{end}}">
|
||||||
|
<div class="checkbox-sub-item field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_users"}}</label>
|
||||||
|
<div class="ui multiple search selection dropdown">
|
||||||
|
<input type="hidden" name="merge_whitelist_users" value="{{.merge_whitelist_users}}">
|
||||||
|
<div class="default text">{{.locale.Tr "repo.settings.protect_whitelist_search_users"}}</div>
|
||||||
|
<div class="menu">
|
||||||
|
{{range .Users}}
|
||||||
|
<div class="item" data-value="{{.ID}}">
|
||||||
|
{{avatar $.Context . 28 "mini"}}{{template "repo/search_name" .}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{if .Owner.IsOrganization}}
|
||||||
|
<div class="checkbox-sub-item field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.protect_merge_whitelist_teams"}}</label>
|
||||||
|
<div class="ui multiple search selection dropdown">
|
||||||
|
<input type="hidden" name="merge_whitelist_teams" value="{{.merge_whitelist_teams}}">
|
||||||
|
<div class="default text">{{.locale.Tr "repo.settings.protect_whitelist_search_teams"}}</div>
|
||||||
|
<div class="menu">
|
||||||
|
{{range .Teams}}
|
||||||
|
<div class="item" data-value="{{.ID}}">
|
||||||
|
{{svg "octicon-people"}}
|
||||||
|
{{.Name}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input name="block_on_rejected_reviews" type="checkbox" {{if .Rule.BlockOnRejectedReviews}}checked{{end}}>
|
<input name="block_on_rejected_reviews" type="checkbox" {{if .Rule.BlockOnRejectedReviews}}checked{{end}}>
|
||||||
<label for="block_on_rejected_reviews">{{.locale.Tr "repo.settings.block_rejected_reviews"}}</label>
|
<label>{{.locale.Tr "repo.settings.block_rejected_reviews"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.block_rejected_reviews_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.block_rejected_reviews_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input name="block_on_official_review_requests" type="checkbox" {{if .Rule.BlockOnOfficialReviewRequests}}checked{{end}}>
|
<input name="block_on_official_review_requests" type="checkbox" {{if .Rule.BlockOnOfficialReviewRequests}}checked{{end}}>
|
||||||
<label for="block_on_official_review_requests">{{.locale.Tr "repo.settings.block_on_official_review_requests"}}</label>
|
<label>{{.locale.Tr "repo.settings.block_on_official_review_requests"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.block_on_official_review_requests_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.block_on_official_review_requests_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<div class="ui checkbox">
|
|
||||||
<input name="dismiss_stale_approvals" type="checkbox" {{if .Rule.DismissStaleApprovals}}checked{{end}}>
|
|
||||||
<label for="dismiss_stale_approvals">{{.locale.Tr "repo.settings.dismiss_stale_approvals"}}</label>
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.dismiss_stale_approvals_desc"}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui checkbox">
|
|
||||||
<input name="require_signed_commits" type="checkbox" {{if .Rule.RequireSignedCommits}}checked{{end}}>
|
|
||||||
<label for="require_signed_commits">{{.locale.Tr "repo.settings.require_signed_commits"}}</label>
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.require_signed_commits_desc"}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input name="block_on_outdated_branch" type="checkbox" {{if .Rule.BlockOnOutdatedBranch}}checked{{end}}>
|
<input name="block_on_outdated_branch" type="checkbox" {{if .Rule.BlockOnOutdatedBranch}}checked{{end}}>
|
||||||
<label for="block_on_outdated_branch">{{.locale.Tr "repo.settings.block_outdated_branch"}}</label>
|
<label>{{.locale.Tr "repo.settings.block_outdated_branch"}}</label>
|
||||||
<p class="help">{{.locale.Tr "repo.settings.block_outdated_branch_desc"}}</p>
|
<p class="help">{{.locale.Tr "repo.settings.block_outdated_branch_desc"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label for="protected_file_patterns">{{.locale.Tr "repo.settings.protect_protected_file_patterns"}}</label>
|
|
||||||
<input name="protected_file_patterns" id="protected_file_patterns" type="text" value="{{.Rule.ProtectedFilePatterns}}">
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_protected_file_patterns_desc" | Safe}}</p>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label for="unprotected_file_patterns">{{.locale.Tr "repo.settings.protect_unprotected_file_patterns"}}</label>
|
|
||||||
<input name="unprotected_file_patterns" id="unprotected_file_patterns" type="text" value="{{.Rule.UnprotectedFilePatterns}}">
|
|
||||||
<p class="help">{{.locale.Tr "repo.settings.protect_unprotected_file_patterns_desc" | Safe}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{{$canReadCode := $.Permission.CanRead $.UnitTypeCode}}
|
{{$canReadCode := $.Permission.CanRead $.UnitTypeCode}}
|
||||||
|
|
||||||
{{if $canReadReleases}}
|
{{if $canReadReleases}}
|
||||||
<h2 class="ui compact small menu header">
|
<h2 class="ui compact small menu header small-pill-buttons">
|
||||||
<a class="{{if .PageIsReleaseList}}active {{end}}item" href="{{.RepoLink}}/releases">{{.locale.Tr "repo.release.releases"}}</a>
|
<a class="{{if .PageIsReleaseList}}active {{end}}item" href="{{.RepoLink}}/releases">{{.locale.Tr "repo.release.releases"}}</a>
|
||||||
{{if $canReadCode}}
|
{{if $canReadCode}}
|
||||||
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
|
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="ui container user-cards">
|
<div class="user-cards">
|
||||||
{{if .CardsTitle}}
|
{{if .CardsTitle}}
|
||||||
<h2 class="ui dividing header">
|
<h2 class="ui dividing header">
|
||||||
{{.CardsTitle}}
|
{{.CardsTitle}}
|
||||||
|
@ -61,13 +61,15 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
{{if $entry.IsDir}}
|
{{if $entry.IsDir}}
|
||||||
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
|
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
|
||||||
{{$subJumpablePath := SubJumpablePath $subJumpablePathName}}
|
|
||||||
{{svg "octicon-file-directory-fill"}}
|
{{svg "octicon-file-directory-fill"}}
|
||||||
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
|
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
|
||||||
{{if eq (len $subJumpablePath) 2}}
|
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
|
||||||
<span class="color-text-light-2">{{index $subJumpablePath 0}}</span>{{index $subJumpablePath 1}}
|
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
|
||||||
|
{{if eq $subJumpablePathFieldLast 0}}
|
||||||
|
{{$subJumpablePathName}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{index $subJumpablePath 0}}
|
{{$subJumpablePathPrefixes := slice $subJumpablePathFields 0 $subJumpablePathFieldLast}}
|
||||||
|
<span class="color-text-light-2">{{StringUtils.Join $subJumpablePathPrefixes "/"}}</span>/{{index $subJumpablePathFields $subJumpablePathFieldLast}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div role="main" aria-label="{{.Title}}" class="page-content repository watchers">
|
<div role="main" aria-label="{{.Title}}" class="page-content repository watchers">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
|
<div class="ui container">
|
||||||
{{template "repo/user_cards" .}}
|
{{template "repo/user_cards" .}}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field" data-tooltip-content="Labels are comma-separated. Whitespace at the beginning, end, and around the commas are ignored.">
|
<div class="field" data-tooltip-content="Labels are comma-separated. Whitespace at the beginning, end, and around the commas are ignored.">
|
||||||
<label for="custom_labels">{{.locale.Tr "actions.runners.custom_labels"}}</label>
|
<label for="custom_labels">{{.locale.Tr "actions.runners.custom_labels"}}</label>
|
||||||
<input id="custom_labels" name="custom_labels" value="{{Join .Runner.CustomLabels `,`}}">
|
<input id="custom_labels" name="custom_labels" value="{{StringUtils.Join .Runner.CustomLabels `,`}}">
|
||||||
<p class="help">{{.locale.Tr "actions.runners.custom_labels_helper"}}</p>
|
<p class="help">{{.locale.Tr "actions.runners.custom_labels_helper"}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
6
templates/swagger/v1_json.tmpl
generated
6
templates/swagger/v1_json.tmpl
generated
@ -3803,6 +3803,12 @@
|
|||||||
"description": "page size of results (ignored if used with 'path')",
|
"description": "page size of results (ignored if used with 'path')",
|
||||||
"name": "limit",
|
"name": "limit",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "commits that match the given specifier will not be listed.",
|
||||||
|
"name": "not",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
|
@ -60,9 +60,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="twelve wide column content">
|
<div class="twelve wide column content">
|
||||||
<div class="ui three column stackable grid">
|
<div class="list-header">
|
||||||
<div class="column">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<div class="ui compact tiny menu">
|
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?type={{$.ViewType}}&repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?type={{$.ViewType}}&repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
|
||||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
@ -72,22 +71,18 @@
|
|||||||
{{.locale.PrettyNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
{{.locale.PrettyNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<form class="list-header-search ui form ignore-dirty">
|
||||||
<div class="column center aligned">
|
<div class="ui small search fluid action input">
|
||||||
<form class="ui form ignore-dirty">
|
|
||||||
<div class="ui search fluid action input">
|
|
||||||
<input type="hidden" name="type" value="{{$.ViewType}}">
|
<input type="hidden" name="type" value="{{$.ViewType}}">
|
||||||
<input type="hidden" name="repos" value="[{{range $.RepoIDs}}{{.}}%2C{{end}}]">
|
<input type="hidden" name="repos" value="[{{range $.RepoIDs}}{{.}}%2C{{end}}]">
|
||||||
<input type="hidden" name="sort" value="{{$.SortType}}">
|
<input type="hidden" name="sort" value="{{$.SortType}}">
|
||||||
<input type="hidden" name="state" value="{{$.State}}">
|
<input type="hidden" name="state" value="{{$.State}}">
|
||||||
<input name="q" value="{{$.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
<input name="q" value="{{$.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
||||||
<button class="ui primary button" type="submit">{{.locale.Tr "explore.search"}}</button>
|
<button class="ui small icon button" type="submit" aria-label="{{.locale.Tr "explore.search"}}">{{svg "octicon-search"}}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
<div class="column right aligned gt-df gt-ac gt-je">
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<div class="ui dropdown type jump item">
|
<div class="list-header-sort ui small dropdown type jump item">
|
||||||
<span class="text gt-whitespace-nowrap">
|
<span class="text gt-whitespace-nowrap">
|
||||||
{{.locale.Tr "repo.issues.filter_sort"}}
|
{{.locale.Tr "repo.issues.filter_sort"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
@ -111,7 +106,6 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{{template "shared/issuelist" dict "." . "listType" "dashboard"}}
|
{{template "shared/issuelist" dict "." . "listType" "dashboard"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,9 +34,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="twelve wide column content">
|
<div class="twelve wide column content">
|
||||||
<div class="ui three column stackable grid">
|
<div class="list-header">
|
||||||
<div class="column">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<div class="ui compact tiny menu">
|
|
||||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
|
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
|
||||||
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
||||||
{{.locale.PrettyNumber .MilestoneStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
{{.locale.PrettyNumber .MilestoneStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||||
@ -46,22 +45,18 @@
|
|||||||
{{.locale.PrettyNumber .MilestoneStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
{{.locale.PrettyNumber .MilestoneStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<form class="list-header-search ui form ignore-dirty">
|
||||||
<div class="column center aligned">
|
<div class="ui small search fluid action input">
|
||||||
<form class="ui form ignore-dirty">
|
|
||||||
<div class="ui search fluid action input">
|
|
||||||
<input type="hidden" name="type" value="{{$.ViewType}}">
|
<input type="hidden" name="type" value="{{$.ViewType}}">
|
||||||
<input type="hidden" name="repos" value="[{{range $.RepoIDs}}{{.}},{{end}}]">
|
<input type="hidden" name="repos" value="[{{range $.RepoIDs}}{{.}},{{end}}]">
|
||||||
<input type="hidden" name="sort" value="{{$.SortType}}">
|
<input type="hidden" name="sort" value="{{$.SortType}}">
|
||||||
<input type="hidden" name="state" value="{{$.State}}">
|
<input type="hidden" name="state" value="{{$.State}}">
|
||||||
<input name="q" value="{{$.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
<input name="q" value="{{$.Keyword}}" placeholder="{{.locale.Tr "explore.search"}}...">
|
||||||
<button class="ui primary button" type="submit">{{.locale.Tr "explore.search"}}</button>
|
<button class="ui small icon button" type="submit" aria-label="{{.locale.Tr "explore.search"}}">{{svg "octicon-search"}}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
<div class="column right aligned gt-df gt-ac gt-je">
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<div class="ui dropdown type jump item">
|
<div class="list-header-sort ui dropdown type jump item">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{.locale.Tr "repo.issues.filter_sort"}}
|
{{.locale.Tr "repo.issues.filter_sort"}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
@ -76,7 +71,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="milestone list">
|
<div class="milestone list">
|
||||||
{{range .Milestones}}
|
{{range .Milestones}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="dashboard-navbar">
|
<div class="dashboard-navbar">
|
||||||
<div class="ui secondary stackable menu">
|
<div class="ui secondary stackable menu g-menu-stackable-scrollable">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="ui floating dropdown jump">
|
<div class="ui floating dropdown jump">
|
||||||
<span class="text truncated-item-container">
|
<span class="text truncated-item-container">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{{if .HeatmapData}}
|
{{if .HeatmapData}}
|
||||||
<div id="user-heatmap"
|
<div id="user-heatmap"
|
||||||
data-heatmap-data="{{Json .HeatmapData}}"
|
data-heatmap-data="{{JsonUtils.EncodeToString .HeatmapData}}"
|
||||||
data-locale-total-contributions="{{$.locale.Tr "heatmap.number_of_contributions_in_the_last_12_months" ($.locale.PrettyNumber .HeatmapTotalContributions)}}"
|
data-locale-total-contributions="{{$.locale.Tr "heatmap.number_of_contributions_in_the_last_12_months" ($.locale.PrettyNumber .HeatmapTotalContributions)}}"
|
||||||
data-locale-no-contributions="{{.locale.Tr "heatmap.no_contributions"}}"
|
data-locale-no-contributions="{{.locale.Tr "heatmap.no_contributions"}}"
|
||||||
data-locale-more="{{.locale.Tr "heatmap.more"}}"
|
data-locale-more="{{.locale.Tr "heatmap.more"}}"
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
{{if eq .Status 1}}
|
{{if eq .Status 1}}
|
||||||
<div id="issue-filters" class="ui stackable grid">
|
<div id="issue-filters" class="ui stackable grid">
|
||||||
<div class="six wide column">
|
<div class="six wide column">
|
||||||
<div class="ui compact tiny menu">
|
<div class="small-pill-buttons ui compact tiny menu">
|
||||||
<a class="{{if eq .State "all"}}active {{end}}item" href="{{$.Link}}?sort={{$.SortType}}&state=all&issueType={{$.IssueType}}&labels={{$.Labels}}">
|
<a class="{{if eq .State "all"}}active {{end}}item" href="{{$.Link}}?sort={{$.SortType}}&state=all&issueType={{$.IssueType}}&labels={{$.Labels}}">
|
||||||
{{.locale.Tr "all"}}
|
{{.locale.Tr "all"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<a href="{{.ContextUser.HomeLink}}.rss"><i class="ui text grey gt-ml-3" data-tooltip-content="{{.locale.Tr "rss_feed"}}">{{svg "octicon-rss" 18}}</i></a>
|
<a href="{{.ContextUser.HomeLink}}.rss"><i class="ui text grey gt-ml-3" data-tooltip-content="{{.locale.Tr "rss_feed"}}">{{svg "octicon-rss" 18}}</i></a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="gt-mt-3">
|
<div class="gt-mt-3">
|
||||||
<a class="muted" href="{{.ContextUser.HomeLink}}?tab=followers">{{svg "octicon-person" 18 "gt-mr-2"}}{{.ContextUser.NumFollowers}} {{.locale.Tr "user.followers"}}</a> · <a class="muted" href="{{.ContextUser.HomeLink}}?tab=following">{{.ContextUser.NumFollowing}} {{.locale.Tr "user.following"}}</a>
|
<a class="muted" href="{{.ContextUser.HomeLink}}?tab=followers">{{svg "octicon-person" 18 "gt-mr-2"}}{{.NumFollowers}} {{.locale.Tr "user.followers"}}</a> · <a class="muted" href="{{.ContextUser.HomeLink}}?tab=following">{{.NumFollowing}} {{.locale.Tr "user.following"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="extra content gt-word-break">
|
<div class="extra content gt-word-break">
|
||||||
|
@ -19,7 +19,7 @@ func TestPullCompare(t *testing.T) {
|
|||||||
req := NewRequest(t, "GET", "/user2/repo1/pulls")
|
req := NewRequest(t, "GET", "/user2/repo1/pulls")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
link, exists := htmlDoc.doc.Find(".ui.three.column.grid").Find(".ui.green.button").Attr("href")
|
link, exists := htmlDoc.doc.Find(".new-pr-button").Attr("href")
|
||||||
assert.True(t, exists, "The template has changed")
|
assert.True(t, exists, "The template has changed")
|
||||||
|
|
||||||
req = NewRequest(t, "GET", link)
|
req = NewRequest(t, "GET", link)
|
||||||
|
@ -769,6 +769,10 @@ a.label,
|
|||||||
border-color: var(--color-primary);
|
border-color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.action.input .button {
|
||||||
|
border-color: var(--color-input-border);
|
||||||
|
}
|
||||||
|
|
||||||
/* currently used for search bar dropdowns in repo search and explore code */
|
/* currently used for search bar dropdowns in repo search and explore code */
|
||||||
.ui.action.input:not([class*="left action"]) > .ui.dropdown.selection {
|
.ui.action.input:not([class*="left action"]) > .ui.dropdown.selection {
|
||||||
min-width: 10em;
|
min-width: 10em;
|
||||||
@ -778,10 +782,21 @@ a.label,
|
|||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.action.input:not([class*="left action"]) > input:hover {
|
||||||
|
border-right-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.ui.action.input:not([class*="left action"]) > input:focus {
|
.ui.action.input:not([class*="left action"]) > input:focus {
|
||||||
border-right-color: var(--color-primary);
|
border-right-color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fix button enlarged vertically by svg icon */
|
||||||
|
/* TODO: change to just `.small.button:has(svg)` but may have global side effects */
|
||||||
|
.ui.action.input .small.button:has(svg) {
|
||||||
|
padding-top: 7px !important;
|
||||||
|
padding-bottom: 7px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ui.menu,
|
.ui.menu,
|
||||||
.ui.vertical.menu {
|
.ui.vertical.menu {
|
||||||
background: var(--color-menu);
|
background: var(--color-menu);
|
||||||
@ -830,6 +845,10 @@ a.label,
|
|||||||
color: var(--color-text-light-3);
|
color: var(--color-text-light-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.menu .item::before {
|
||||||
|
background: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
/* sub menu of vertical menu */
|
/* sub menu of vertical menu */
|
||||||
.ui.vertical.menu .item .menu .item {
|
.ui.vertical.menu .item .menu .item {
|
||||||
color: var(--color-text-light-2);
|
color: var(--color-text-light-2);
|
||||||
@ -1472,10 +1491,12 @@ img.ui.avatar,
|
|||||||
color: var(--color-gold) !important;
|
color: var(--color-gold) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: this is a serious pollution, do not use this for "float: left" anymore */
|
||||||
.ui.left:not(.action) {
|
.ui.left:not(.action) {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: this is a serious pollution, do not use this for "float: right" anymore */
|
||||||
.ui.right:not(.action) {
|
.ui.right:not(.action) {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
@ -2533,12 +2554,12 @@ a.ui.basic.label:hover {
|
|||||||
right: 0.78571429rem;
|
right: 0.78571429rem;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 30px;
|
display: flex;
|
||||||
margin-top: auto;
|
align-items: center;
|
||||||
margin-bottom: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://github.com/go-gitea/gitea/issues/10210 */
|
/* if a .top.attached.header is followed by a .segment, add some margin */
|
||||||
|
.ui.segments ~ .ui.top.attached.header,
|
||||||
.ui.attached.segment ~ .ui.top.attached.header {
|
.ui.attached.segment ~ .ui.top.attached.header {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
@ -2660,38 +2681,6 @@ table th[data-sortt-desc] .svg {
|
|||||||
background: var(--color-secondary-dark-1) !important;
|
background: var(--color-secondary-dark-1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.labelspage {
|
|
||||||
list-style: none;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .item {
|
|
||||||
border-bottom: 1px solid var(--color-secondary);
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .item a {
|
|
||||||
font-size: 12px;
|
|
||||||
padding-right: 10px;
|
|
||||||
color: var(--color-text-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .item a:hover {
|
|
||||||
color: var(--color-primary-light-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .item a.open-issues {
|
|
||||||
margin-right: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .item:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelspage .orglabel {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://github.com/go-gitea/gitea/pull/11486 */
|
/* https://github.com/go-gitea/gitea/pull/11486 */
|
||||||
.ui.sub.header {
|
.ui.sub.header {
|
||||||
@ -2796,21 +2785,16 @@ table th[data-sortt-desc] .svg {
|
|||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
.g-menu-stackable-scrollable {
|
||||||
.ui.stackable.menu:not(.no-vertical-tabs) {
|
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap !important;
|
|
||||||
}
|
}
|
||||||
.ui.stackable.menu:not(.no-vertical-tabs) .item {
|
|
||||||
width: initial !important;
|
@media (max-width: 767.98px) {
|
||||||
}
|
/* also respect Fomantic's "stackable" definition, use the same breakpoint to reset our styles */
|
||||||
.ui.stackable.menu:not(.no-vertical-tabs) > .dropdown.item {
|
.g-menu-stackable-scrollable {
|
||||||
position: initial;
|
overflow-x: unset;
|
||||||
}
|
overflow-y: unset;
|
||||||
.ui.stackable.menu:not(.no-vertical-tabs) .menu {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,22 +60,30 @@ Gitea's private styles use `g-` prefix.
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gt-max-width-24rem { max-width: 24rem !important; }
|
||||||
|
|
||||||
/* below class names match Tailwind CSS */
|
/* below class names match Tailwind CSS */
|
||||||
.gt-break-all { word-break: break-all !important; }
|
.gt-break-all { word-break: break-all !important; }
|
||||||
.gt-content-center { align-content: center !important; }
|
.gt-content-center { align-content: center !important; }
|
||||||
.gt-cursor-default { cursor: default !important; }
|
.gt-cursor-default { cursor: default !important; }
|
||||||
.gt-invisible { visibility: hidden !important; }
|
.gt-invisible { visibility: hidden !important; }
|
||||||
.gt-items-start { align-items: flex-start !important; }
|
.gt-items-start { align-items: flex-start !important; }
|
||||||
.gt-overflow-x-scroll { overflow-x: scroll !important; }
|
|
||||||
.gt-pointer-events-none { pointer-events: none !important; }
|
.gt-pointer-events-none { pointer-events: none !important; }
|
||||||
.gt-relative { position: relative !important; }
|
.gt-relative { position: relative !important; }
|
||||||
.gt-whitespace-nowrap { white-space: nowrap !important; }
|
.gt-whitespace-nowrap { white-space: nowrap !important; }
|
||||||
.gt-whitespace-pre { white-space: pre !important; }
|
.gt-whitespace-pre { white-space: pre !important; }
|
||||||
.gt-whitespace-pre-wrap { white-space: pre-wrap !important; }
|
.gt-whitespace-pre-wrap { white-space: pre-wrap !important; }
|
||||||
|
|
||||||
|
.gt-overflow-x-auto { overflow-x: auto !important; }
|
||||||
|
.gt-overflow-x-scroll { overflow-x: scroll !important; }
|
||||||
|
.gt-overflow-y-hidden { overflow-y: hidden !important; }
|
||||||
|
|
||||||
.gt-w-screen { width: 100vw !important; }
|
.gt-w-screen { width: 100vw !important; }
|
||||||
.gt-h-screen { height: 100vh !important; }
|
.gt-h-screen { height: 100vh !important; }
|
||||||
|
|
||||||
|
.gt-float-left { float: left !important; }
|
||||||
|
.gt-float-right { float: right !important; }
|
||||||
|
|
||||||
.gt-rounded { border-radius: var(--border-radius) !important; }
|
.gt-rounded { border-radius: var(--border-radius) !important; }
|
||||||
.gt-rounded-top { border-radius: var(--border-radius) var(--border-radius) 0 0 !important; }
|
.gt-rounded-top { border-radius: var(--border-radius) var(--border-radius) 0 0 !important; }
|
||||||
.gt-rounded-bottom { border-radius: 0 0 var(--border-radius) var(--border-radius) !important; }
|
.gt-rounded-bottom { border-radius: 0 0 var(--border-radius) var(--border-radius) !important; }
|
||||||
|
@ -43,39 +43,38 @@
|
|||||||
color: var(--color-green);
|
color: var(--color-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
.page-footer {
|
||||||
|
display: flex;
|
||||||
background-color: var(--color-footer);
|
background-color: var(--color-footer);
|
||||||
border-top: 1px solid var(--color-secondary);
|
border-top: 1px solid var(--color-secondary);
|
||||||
line-height: 39px;
|
line-height: 39px;
|
||||||
flex-basis: 40px;
|
|
||||||
color: var(--color-text-light);
|
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer .right.links {
|
.page-footer .left-links {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-footer .right-links {
|
||||||
min-width: 180px; /* make sure the menu dropdown doesn't overflow horizontally when language name is short */
|
min-width: 180px; /* make sure the menu dropdown doesn't overflow horizontally when language name is short */
|
||||||
}
|
}
|
||||||
|
|
||||||
footer .right.links > a {
|
.page-footer .right-links > a {
|
||||||
border-left: 1px solid var(--color-secondary-dark-1);
|
border-left: 1px solid var(--color-secondary-dark-1);
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer .ui.dropdown.language .menu {
|
.page-footer .ui.dropdown.language .menu {
|
||||||
height: 500px;
|
height: 500px;
|
||||||
max-height: calc(100vh - 60px);
|
max-height: calc(100vh - 60px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 880px) {
|
@media (max-width: 880px) {
|
||||||
footer .ui.left,
|
.page-footer {
|
||||||
footer .ui.right {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
float: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,11 @@
|
|||||||
@import "./install.css";
|
@import "./install.css";
|
||||||
@import "./form.css";
|
@import "./form.css";
|
||||||
@import "./repository.css";
|
@import "./repository.css";
|
||||||
@import "./repository-release-tag.css";
|
@import "./repository/release-tag.css";
|
||||||
|
@import "./repository/issue-label.css";
|
||||||
|
@import "./repository/list-header.css";
|
||||||
@import "./editor.css";
|
@import "./editor.css";
|
||||||
@import "./editor-markdown.css";
|
@import "./editor/combomarkdowneditor.css";
|
||||||
@import "./organization.css";
|
@import "./organization.css";
|
||||||
@import "./user.css";
|
@import "./user.css";
|
||||||
@import "./dashboard.css";
|
@import "./dashboard.css";
|
||||||
|
@ -160,8 +160,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.repository .ui.tabs.divider {
|
.repository .ui.tabs.divider {
|
||||||
margin-top: 0;
|
margin-top: -1px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repository #clone-panel #repo-clone-url {
|
.repository #clone-panel #repo-clone-url {
|
||||||
@ -2012,35 +2012,10 @@
|
|||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repository.settings.branches .protected-branches .selection.dropdown {
|
/* if the element is for a checkbox, then it should have a padding-left to align to the checkbox's text */
|
||||||
width: 300px;
|
.repository.settings.branches .branch-protection .ui.checkbox .help,
|
||||||
}
|
.repository.settings.branches .branch-protection .checkbox-sub-item {
|
||||||
|
padding-left: 26px;
|
||||||
.repository.settings.branches .protected-branches .item {
|
|
||||||
border: 1px solid var(--color-secondary);
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.repository.settings.branches .protected-branches .item:not(:last-child) {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.repository.settings.branches .branch-protection .help {
|
|
||||||
margin-left: 26px;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.repository.settings.branches .branch-protection .fields {
|
|
||||||
margin-left: 20px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.repository.settings.branches .branch-protection .whitelist {
|
|
||||||
margin-left: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.repository.settings.branches .branch-protection .whitelist .dropdown img {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.repository.settings.webhook .events .column {
|
.repository.settings.webhook .events .column {
|
||||||
@ -3314,18 +3289,6 @@ td.blob-excerpt {
|
|||||||
.repository.file.list #repo-files-table .commit-list span.commit-summary {
|
.repository.file.list #repo-files-table .commit-list span.commit-summary {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
.issue-list-headers.ui[class].grid > div:nth-child(1) {
|
|
||||||
order: 1;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.issue-list-headers.ui[class].grid > div:nth-child(2) {
|
|
||||||
order: 3;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.issue-list-headers.ui[class].grid > div.column:not(.row):nth-child(3) {
|
|
||||||
order: 2;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.repository.view.issue .comment-list .timeline,
|
.repository.view.issue .comment-list .timeline,
|
||||||
.repository.view.issue .comment-list .timeline-item {
|
.repository.view.issue .comment-list .timeline-item {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
44
web_src/css/repository/issue-label.css
Normal file
44
web_src/css/repository/issue-label.css
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
.issue-label-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item {
|
||||||
|
border-bottom: 1px solid var(--color-secondary);
|
||||||
|
display: flex;
|
||||||
|
padding: 1em 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item .label-title {
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item .label-issues {
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item .label-operation {
|
||||||
|
width: 33%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item a {
|
||||||
|
font-size: 12px;
|
||||||
|
padding-right: 10px;
|
||||||
|
color: var(--color-text-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.issue-label-list .item.org-label {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
36
web_src/css/repository/list-header.css
Normal file
36
web_src/css/repository/list-header.css
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header-sort {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header-search {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 200px; /* to enable flexbox wrapping on mobile */
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header-search .input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-pill-buttons {
|
||||||
|
min-height: 35.4px !important; /* match .small.button in height */
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-pill-buttons .item {
|
||||||
|
padding-top: 6px !important;
|
||||||
|
padding-bottom: 6px !important;
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import {createMonaco} from './codeeditor.js';
|
import {createMonaco} from './codeeditor.js';
|
||||||
import {initRepoCommonFilterSearchDropdown} from './repo-common.js';
|
|
||||||
|
|
||||||
const {appSubUrl, csrfToken} = window.config;
|
const {appSubUrl, csrfToken} = window.config;
|
||||||
|
|
||||||
@ -73,20 +72,13 @@ export function initRepoSettingGitHook() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function initRepoSettingBranches() {
|
export function initRepoSettingBranches() {
|
||||||
// Branches
|
if (!$('.repository.settings.branches').length) return;
|
||||||
if ($('.repository.settings.branches').length > 0) {
|
$('.toggle-target-enabled').on('change', function () {
|
||||||
initRepoCommonFilterSearchDropdown('.protected-branches .dropdown');
|
const $target = $($(this).attr('data-target'));
|
||||||
$('.enable-protection, .enable-whitelist, .enable-statuscheck').on('change', function () {
|
$target.toggleClass('disabled', !this.checked);
|
||||||
if (this.checked) {
|
|
||||||
$($(this).data('target')).removeClass('disabled');
|
|
||||||
} else {
|
|
||||||
$($(this).data('target')).addClass('disabled');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
$('.disable-whitelist').on('change', function () {
|
$('.toggle-target-disabled').on('change', function () {
|
||||||
if (this.checked) {
|
const $target = $($(this).attr('data-target'));
|
||||||
$($(this).data('target')).addClass('disabled');
|
if (this.checked) $target.addClass('disabled'); // only disable, do not auto enable
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user