mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-27 09:49:02 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -63,8 +63,8 @@ func IsUserAssignedToIssue(ctx context.Context, issue *Issue, user *user_model.U
|
||||
}
|
||||
|
||||
// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
||||
func ToggleIssueAssignee(issue *Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func ToggleIssueAssignee(ctx context.Context, issue *Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
@@ -24,17 +24,17 @@ func TestUpdateAssignee(t *testing.T) {
|
||||
// Assign multiple users
|
||||
user2, err := user_model.GetUserByID(db.DefaultContext, 2)
|
||||
assert.NoError(t, err)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(issue, &user_model.User{ID: 1}, user2.ID)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, user2.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
user3, err := user_model.GetUserByID(db.DefaultContext, 3)
|
||||
assert.NoError(t, err)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(issue, &user_model.User{ID: 1}, user3.ID)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, user3.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
user1, err := user_model.GetUserByID(db.DefaultContext, 1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him
|
||||
assert.NoError(t, err)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(issue, &user_model.User{ID: 1}, user1.ID)
|
||||
_, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, user1.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if he got removed
|
||||
|
||||
@@ -743,8 +743,8 @@ func ChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User,
|
||||
}
|
||||
|
||||
// ChangeIssueTitle changes the title of this issue, as the given user.
|
||||
func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err error) {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func ChangeIssueTitle(ctx context.Context, issue *Issue, doer *user_model.User, oldTitle string) (err error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func TestXRef_NeuterCrossReferences(t *testing.T) {
|
||||
|
||||
d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
i.Title = "title2, no mentions"
|
||||
assert.NoError(t, issues_model.ChangeIssueTitle(i, d, title))
|
||||
assert.NoError(t, issues_model.ChangeIssueTitle(db.DefaultContext, i, d, title))
|
||||
|
||||
ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0})
|
||||
assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type)
|
||||
|
||||
@@ -483,6 +483,8 @@ var migrations = []Migration{
|
||||
NewMigration("Fix incorrect owner team unit access mode", v1_20.FixIncorrectOwnerTeamUnitAccessMode),
|
||||
// v252 -> v253
|
||||
NewMigration("Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
|
||||
// v253 -> v254
|
||||
NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
|
||||
// to modify later
|
||||
NewMigration("Add size limit on repository", v1_20.AddSizeLimitOnRepo),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_20 //nolint
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam(x *xorm.Engine) error {
|
||||
type UnitType int
|
||||
type AccessMode int
|
||||
|
||||
type TeamUnit struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type UnitType `xorm:"UNIQUE(s)"`
|
||||
AccessMode AccessMode
|
||||
}
|
||||
|
||||
const (
|
||||
// AccessModeRead read access
|
||||
AccessModeRead = 1
|
||||
|
||||
// Unit Type
|
||||
TypeExternalWiki = 6
|
||||
TypeExternalTracker = 7
|
||||
)
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count, err := sess.Table("team_unit").
|
||||
Where("type IN (?, ?) AND access_mode > ?", TypeExternalWiki, TypeExternalTracker, AccessModeRead).
|
||||
Update(&TeamUnit{
|
||||
AccessMode: AccessModeRead,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("Updated %d ExternalTracker and ExternalWiki access mode to belong to owner and admin", count)
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
@@ -194,14 +194,16 @@ func (opts *FindTopicOptions) toConds() builder.Cond {
|
||||
// FindTopics retrieves the topics via FindTopicOptions
|
||||
func FindTopics(opts *FindTopicOptions) ([]*Topic, int64, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).Select("topic.*").Where(opts.toConds())
|
||||
orderBy := "topic.repo_count DESC"
|
||||
if opts.RepoID > 0 {
|
||||
sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
|
||||
orderBy = "topic.name" // when render topics for a repo, it's better to sort them by name, to get consistent result
|
||||
}
|
||||
if opts.PageSize != 0 && opts.Page != 0 {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
||||
}
|
||||
topics := make([]*Topic, 0, 10)
|
||||
total, err := sess.Desc("topic.repo_count").FindAndCount(&topics)
|
||||
total, err := sess.OrderBy(orderBy).FindAndCount(&topics)
|
||||
return topics, total, err
|
||||
}
|
||||
|
||||
|
||||
@@ -132,18 +132,10 @@ then resh (ר), and finally heh (ה) (which should appear leftmost).`,
|
||||
},
|
||||
}
|
||||
|
||||
type nullLocale struct{}
|
||||
|
||||
func (nullLocale) Language() string { return "" }
|
||||
func (nullLocale) Tr(key string, _ ...interface{}) string { return key }
|
||||
func (nullLocale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) string { return "" }
|
||||
|
||||
var _ (translation.Locale) = nullLocale{}
|
||||
|
||||
func TestEscapeControlString(t *testing.T) {
|
||||
for _, tt := range escapeControlTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
status, result := EscapeControlString(tt.text, nullLocale{})
|
||||
status, result := EscapeControlString(tt.text, &translation.MockLocale{})
|
||||
if !reflect.DeepEqual(*status, tt.status) {
|
||||
t.Errorf("EscapeControlString() status = %v, wanted= %v", status, tt.status)
|
||||
}
|
||||
@@ -179,7 +171,7 @@ func TestEscapeControlReader(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
input := strings.NewReader(tt.text)
|
||||
output := &strings.Builder{}
|
||||
status, err := EscapeControlReader(input, output, nullLocale{})
|
||||
status, err := EscapeControlReader(input, output, &translation.MockLocale{})
|
||||
result := output.String()
|
||||
if err != nil {
|
||||
t.Errorf("EscapeControlReader(): err = %v", err)
|
||||
@@ -201,5 +193,5 @@ func TestEscapeControlReader_panic(t *testing.T) {
|
||||
for i := 0; i < 6826; i++ {
|
||||
bs = append(bs, []byte("—")...)
|
||||
}
|
||||
_, _ = EscapeControlString(string(bs), nullLocale{})
|
||||
_, _ = EscapeControlString(string(bs), &translation.MockLocale{})
|
||||
}
|
||||
|
||||
+2
-15
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -550,20 +551,6 @@ a|"he said, ""here I am"""`,
|
||||
}
|
||||
}
|
||||
|
||||
type mockLocale struct{}
|
||||
|
||||
func (l mockLocale) Language() string {
|
||||
return "en"
|
||||
}
|
||||
|
||||
func (l mockLocale) Tr(s string, _ ...interface{}) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func (l mockLocale) TrN(_cnt interface{}, key1, _keyN string, _args ...interface{}) string {
|
||||
return key1
|
||||
}
|
||||
|
||||
func TestFormatError(t *testing.T) {
|
||||
cases := []struct {
|
||||
err error
|
||||
@@ -591,7 +578,7 @@ func TestFormatError(t *testing.T) {
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
message, err := FormatError(c.err, mockLocale{})
|
||||
message, err := FormatError(c.err, &translation.MockLocale{})
|
||||
if c.expectsError {
|
||||
assert.Error(t, err, "case %d: expected an error to be returned", n)
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@ package issues
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -120,10 +121,11 @@ func (b *MeilisearchIndexer) Delete(ids ...int64) error {
|
||||
// Search searches for issues by given conditions.
|
||||
// Returns the matching issue IDs
|
||||
func (b *MeilisearchIndexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*SearchResult, error) {
|
||||
filter := make([][]string, 0, len(repoIDs))
|
||||
repoFilters := make([]string, 0, len(repoIDs))
|
||||
for _, repoID := range repoIDs {
|
||||
filter = append(filter, []string{"repo_id = " + strconv.FormatInt(repoID, 10)})
|
||||
repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
|
||||
}
|
||||
filter := strings.Join(repoFilters, " OR ")
|
||||
searchRes, err := b.client.Index(b.indexerName).Search(keyword, &meilisearch.SearchRequest{
|
||||
Filter: filter,
|
||||
Limit: int64(limit),
|
||||
|
||||
@@ -132,7 +132,6 @@ func NewFuncMap() []template.FuncMap {
|
||||
// -----------------------------------------------------------------
|
||||
// time / number / format
|
||||
"FileSize": base.FileSize,
|
||||
"LocaleNumber": LocaleNumber,
|
||||
"CountFmt": base.FormatNumberSI,
|
||||
"TimeSince": timeutil.TimeSince,
|
||||
"TimeSinceUnix": timeutil.TimeSinceUnix,
|
||||
@@ -782,12 +781,6 @@ func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteNa
|
||||
return a
|
||||
}
|
||||
|
||||
// LocaleNumber renders a number with a Custom Element, browser will render it with a locale number
|
||||
func LocaleNumber(v interface{}) template.HTML {
|
||||
num, _ := util.ToInt64(v)
|
||||
return template.HTML(fmt.Sprintf(`<gitea-locale-number data-number="%d">%d</gitea-locale-number>`, num, num))
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
|
||||
chi "github.com/go-chi/chi/v5"
|
||||
@@ -34,7 +35,7 @@ func MockContext(t *testing.T, path string) *context.Context {
|
||||
Values: make(url.Values),
|
||||
},
|
||||
Resp: context.NewResponse(resp),
|
||||
Locale: &mockLocale{},
|
||||
Locale: &translation.MockLocale{},
|
||||
}
|
||||
defer ctx.Close()
|
||||
|
||||
@@ -91,20 +92,6 @@ func LoadGitRepo(t *testing.T, ctx *context.Context) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
type mockLocale struct{}
|
||||
|
||||
func (l mockLocale) Language() string {
|
||||
return "en"
|
||||
}
|
||||
|
||||
func (l mockLocale) Tr(s string, _ ...interface{}) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func (l mockLocale) TrN(_cnt interface{}, key1, _keyN string, _args ...interface{}) string {
|
||||
return key1
|
||||
}
|
||||
|
||||
type mockResponseWriter struct {
|
||||
httptest.ResponseRecorder
|
||||
size int
|
||||
|
||||
@@ -114,11 +114,25 @@ func timeSincePro(then, now time.Time, lang translation.Locale) string {
|
||||
return strings.TrimPrefix(timeStr, ", ")
|
||||
}
|
||||
|
||||
func timeSinceUnix(then, now time.Time, lang translation.Locale) template.HTML {
|
||||
friendlyText := then.Format("2006-01-02 15:04:05 +07:00")
|
||||
|
||||
// document: https://github.com/github/relative-time-element
|
||||
attrs := `tense="past"`
|
||||
isFuture := now.Before(then)
|
||||
if isFuture {
|
||||
attrs = `tense="future"`
|
||||
}
|
||||
|
||||
// declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip
|
||||
htm := fmt.Sprintf(`<relative-time class="time-since" prefix="" %s datetime="%s" data-tooltip-content data-tooltip-interactive="true">%s</relative-time>`,
|
||||
attrs, then.Format(time.RFC3339), friendlyText)
|
||||
return template.HTML(htm)
|
||||
}
|
||||
|
||||
// TimeSince renders relative time HTML given a time.Time
|
||||
func TimeSince(then time.Time, lang translation.Locale) template.HTML {
|
||||
timestamp := then.UTC().Format(time.RFC3339)
|
||||
// declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip
|
||||
return template.HTML(fmt.Sprintf(`<relative-time class="time-since" prefix="%s" datetime="%s" data-tooltip-content data-tooltip-interactive="true">%s</relative-time>`, lang.Tr("on_date"), timestamp, timestamp))
|
||||
return timeSinceUnix(then, time.Now(), lang)
|
||||
}
|
||||
|
||||
// TimeSinceUnix renders relative time HTML given a TimeStamp
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package translation
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MockLocale provides a mocked locale without any translations
|
||||
type MockLocale struct{}
|
||||
|
||||
var _ Locale = (*MockLocale)(nil)
|
||||
|
||||
func (l MockLocale) Language() string {
|
||||
return "en"
|
||||
}
|
||||
|
||||
func (l MockLocale) Tr(s string, _ ...interface{}) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func (l MockLocale) TrN(_cnt interface{}, key1, _keyN string, _args ...interface{}) string {
|
||||
return key1
|
||||
}
|
||||
|
||||
func (l MockLocale) PrettyNumber(v any) string {
|
||||
return fmt.Sprint(v)
|
||||
}
|
||||
@@ -15,17 +15,20 @@ import (
|
||||
"code.gitea.io/gitea/modules/translation/i18n"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
"golang.org/x/text/number"
|
||||
)
|
||||
|
||||
type contextKey struct{}
|
||||
|
||||
var ContextKey interface{} = &contextKey{}
|
||||
var ContextKey any = &contextKey{}
|
||||
|
||||
// Locale represents an interface to translation
|
||||
type Locale interface {
|
||||
Language() string
|
||||
Tr(string, ...interface{}) string
|
||||
TrN(cnt interface{}, key1, keyN string, args ...interface{}) string
|
||||
Tr(string, ...any) string
|
||||
TrN(cnt any, key1, keyN string, args ...any) string
|
||||
PrettyNumber(v any) string
|
||||
}
|
||||
|
||||
// LangType represents a lang type
|
||||
@@ -135,6 +138,7 @@ func Match(tags ...language.Tag) language.Tag {
|
||||
type locale struct {
|
||||
i18n.Locale
|
||||
Lang, LangName string // these fields are used directly in templates: .i18n.Lang
|
||||
msgPrinter *message.Printer
|
||||
}
|
||||
|
||||
// NewLocale return a locale
|
||||
@@ -147,13 +151,24 @@ func NewLocale(lang string) Locale {
|
||||
langName := "unknown"
|
||||
if l, ok := allLangMap[lang]; ok {
|
||||
langName = l.Name
|
||||
} else if len(setting.Langs) > 0 {
|
||||
lang = setting.Langs[0]
|
||||
langName = setting.Names[0]
|
||||
}
|
||||
|
||||
i18nLocale, _ := i18n.GetLocale(lang)
|
||||
return &locale{
|
||||
l := &locale{
|
||||
Locale: i18nLocale,
|
||||
Lang: lang,
|
||||
LangName: langName,
|
||||
}
|
||||
if langTag, err := language.Parse(lang); err != nil {
|
||||
log.Error("Failed to parse language tag from name %q: %v", l.Lang, err)
|
||||
l.msgPrinter = message.NewPrinter(language.English)
|
||||
} else {
|
||||
l.msgPrinter = message.NewPrinter(langTag)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *locale) Language() string {
|
||||
@@ -199,7 +214,7 @@ var trNLangRules = map[string]func(int64) int{
|
||||
}
|
||||
|
||||
// TrN returns translated message for plural text translation
|
||||
func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) string {
|
||||
func (l *locale) TrN(cnt any, key1, keyN string, args ...any) string {
|
||||
var c int64
|
||||
if t, ok := cnt.(int); ok {
|
||||
c = int64(t)
|
||||
@@ -223,3 +238,8 @@ func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) st
|
||||
}
|
||||
return l.Tr(keyN, args...)
|
||||
}
|
||||
|
||||
func (l *locale) PrettyNumber(v any) string {
|
||||
// TODO: this mechanism is not good enough, the complete solution is to switch the translation system to ICU message format
|
||||
return l.msgPrinter.Sprintf("%v", number.Decimal(v))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package translation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/translation/i18n"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPrettyNumber(t *testing.T) {
|
||||
// TODO: make this package friendly to testing
|
||||
|
||||
i18n.ResetDefaultLocales()
|
||||
|
||||
allLangMap = make(map[string]*LangType)
|
||||
allLangMap["id-ID"] = &LangType{Lang: "id-ID", Name: "Bahasa Indonesia"}
|
||||
|
||||
l := NewLocale("id-ID")
|
||||
assert.EqualValues(t, "1.000.000", l.PrettyNumber(1000000))
|
||||
|
||||
l = NewLocale("nosuch")
|
||||
assert.EqualValues(t, "1,000,000", l.PrettyNumber(1000000))
|
||||
}
|
||||
@@ -110,7 +110,6 @@ never=Nikdy
|
||||
|
||||
rss_feed=RSS kanál
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Navigační lišta
|
||||
footer=Patička
|
||||
@@ -3027,8 +3026,6 @@ starred_repo=si oblíbil/a <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=začal/a sledovat <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=před %s
|
||||
from_now=od teď %s
|
||||
now=nyní
|
||||
future=budoucí
|
||||
1s=1 sekundou
|
||||
|
||||
@@ -107,7 +107,6 @@ never=Niemals
|
||||
|
||||
rss_feed=RSS Feed
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2956,8 +2955,6 @@ starred_repo=markiert <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=beobachtet <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=vor %s
|
||||
from_now=in %s
|
||||
now=jetzt
|
||||
future=Zukunft
|
||||
1s=1 Sekunde
|
||||
|
||||
@@ -110,7 +110,6 @@ never=Ποτέ
|
||||
|
||||
rss_feed=Ροή RSS
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Γραμμή Πλοήγησης
|
||||
footer=Υποσέλιδο
|
||||
@@ -3066,8 +3065,6 @@ starred_repo=έδωσε αστέρι στο <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=άρχισε να παρακολουθεί το <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s πριν
|
||||
from_now=%s από τώρα
|
||||
now=τώρα
|
||||
future=μελλοντικό
|
||||
1s=1 δευτερόλεπτο
|
||||
|
||||
@@ -112,8 +112,6 @@ never = Never
|
||||
|
||||
rss_feed = RSS Feed
|
||||
|
||||
on_date = on
|
||||
|
||||
[aria]
|
||||
navbar = Navigation Bar
|
||||
footer = Footer
|
||||
@@ -3132,8 +3130,6 @@ starred_repo = starred <a href="%[1]s">%[2]s</a>
|
||||
watched_repo = started watching <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago = %s ago
|
||||
from_now = %s from now
|
||||
now = now
|
||||
future = future
|
||||
1s = 1 second
|
||||
|
||||
@@ -107,7 +107,6 @@ never=Nunca
|
||||
|
||||
rss_feed=Fuentes RSS
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2990,8 +2989,6 @@ starred_repo=destacó <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=comenzó a seguir <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=hace %s
|
||||
from_now=desde ahora %s
|
||||
now=ahora
|
||||
future=futuro
|
||||
1s=1 segundo
|
||||
|
||||
@@ -92,7 +92,6 @@ error404=صفحه موردنظر شما یا <strong>وجود ندارد</strong
|
||||
never=هرگز
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2741,8 +2740,6 @@ starred_repo=ستاره دار <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=شروع به تماشای <a href="%[1]s">%[2]s</a> کرد
|
||||
|
||||
[tool]
|
||||
ago=%s پیش
|
||||
from_now=%s از هم اکنون
|
||||
now=حالا
|
||||
future=آینده
|
||||
1s=۱ ثانیه
|
||||
|
||||
@@ -106,7 +106,6 @@ never=Ei koskaan
|
||||
|
||||
rss_feed=RSS-syöte
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -1727,8 +1726,6 @@ compare_commits_general=Vertaa committeja
|
||||
create_branch=loi haaran <a href="%[2]s">%[3]s</a> repossa <a href="%[1]s">%[4]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s sitten
|
||||
from_now=%s alkaen nyt
|
||||
now=nyt
|
||||
1s=1 sekunti
|
||||
1m=1 minuutti
|
||||
|
||||
@@ -107,7 +107,6 @@ never=Jamais
|
||||
|
||||
rss_feed=Flux RSS
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2522,8 +2521,6 @@ publish_release=`a publié <a href="%[2]s"> "%[4]s" </a> à <a href="%[1]s">%[3]
|
||||
review_dismissed_reason=Raison :
|
||||
|
||||
[tool]
|
||||
ago=il y a %s
|
||||
from_now=dans %s
|
||||
now=maintenant
|
||||
future=futur
|
||||
1s=1 seconde
|
||||
|
||||
@@ -82,7 +82,6 @@ error404=Az elérni kívánt oldal vagy <strong>nem létezik</strong>, vagy <str
|
||||
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -1653,8 +1652,6 @@ compare_commits=%d commit összehasonlítása
|
||||
compare_commits_general=Commitok összehasonlítása
|
||||
|
||||
[tool]
|
||||
ago=%s ezelőtt
|
||||
from_now=%s mostantól
|
||||
now=most
|
||||
future=jövőbeli
|
||||
1s=1 másodperccel
|
||||
|
||||
@@ -76,7 +76,6 @@ loading=Memuat…
|
||||
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -1332,8 +1331,6 @@ delete_branch=cabang dihapus %[2]s dari <a href="%[1]s">%[3]s</a>
|
||||
compare_commits=Bandingkan %d melakukan
|
||||
|
||||
[tool]
|
||||
ago=%s yang lalu
|
||||
from_now=%s mulai sekarang
|
||||
now=sekarang
|
||||
future=masa depan
|
||||
1s=1 detik
|
||||
|
||||
@@ -103,7 +103,6 @@ error404=Síðan sem þú ert að reyna að fá annað hvort <strong>er ekki til
|
||||
never=Aldrei
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -1319,7 +1318,6 @@ comment_pull=`gerði ummæli á sameiningarbeiðni <a href="%[1]s">%[3]s#%[2]s</
|
||||
review_dismissed_reason=Ástæða:
|
||||
|
||||
[tool]
|
||||
ago=%s síðan
|
||||
now=núna
|
||||
future=í framtíð
|
||||
1s=1 sekúnda
|
||||
|
||||
@@ -107,7 +107,6 @@ never=Mai
|
||||
|
||||
rss_feed=Feed RSS
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2960,8 +2959,6 @@ starred_repo=ha salvato come preferito <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=ha iniziato a guardare <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s fa
|
||||
from_now=%s da adesso
|
||||
now=ora
|
||||
future=futuro
|
||||
1s=1 secondo
|
||||
|
||||
@@ -112,7 +112,6 @@ never=無し
|
||||
|
||||
rss_feed=RSSフィード
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=ナビゲーションバー
|
||||
footer=フッター
|
||||
@@ -3105,8 +3104,6 @@ starred_repo=が <a href="%[1]s">%[2]s</a> にスターをつけました
|
||||
watched_repo=が <a href="%[1]s">%[2]s</a> のウォッチを開始しました
|
||||
|
||||
[tool]
|
||||
ago=%s前
|
||||
from_now=今から%s後
|
||||
now=たった今
|
||||
future=未来
|
||||
1s=1秒
|
||||
|
||||
@@ -75,7 +75,6 @@ loading=불러오는 중...
|
||||
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -1583,8 +1582,6 @@ transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송
|
||||
compare_commits=%d 커밋들 비교
|
||||
|
||||
[tool]
|
||||
ago=%s 전
|
||||
from_now=%s 지금부터
|
||||
now=현재
|
||||
future=미래
|
||||
1s=1 초
|
||||
|
||||
@@ -110,7 +110,6 @@ never=Nekad
|
||||
|
||||
rss_feed=RSS barotne
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Navigācijas josla
|
||||
footer=Kājene
|
||||
@@ -3060,8 +3059,6 @@ starred_repo=atzīmēja ar zvaigznīti <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=sāka sekot <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=pirms %s
|
||||
from_now=pēc %s no šī brīža
|
||||
now=tagad
|
||||
future=nākotnē
|
||||
1s=1 sekundes
|
||||
|
||||
@@ -107,7 +107,6 @@ never=Nooit
|
||||
|
||||
rss_feed=RSS Feed
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2753,8 +2752,6 @@ compare_commits=Vergelijk %d commits
|
||||
compare_commits_general=Vergelijk commits
|
||||
|
||||
[tool]
|
||||
ago=%s geleden
|
||||
from_now=%s vanaf nu
|
||||
now=nu
|
||||
future=toekomst
|
||||
1s=1 seconde
|
||||
|
||||
@@ -105,7 +105,6 @@ error404=Strona, do której próbujesz dotrzeć <strong>nie istnieje</strong> lu
|
||||
never=Nigdy
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2641,8 +2640,6 @@ mirror_sync_delete=synchronizuje i usuwa odwołanie <code>%[2]s</code> w <a href
|
||||
review_dismissed_reason=Powód:
|
||||
|
||||
[tool]
|
||||
ago=%s temu
|
||||
from_now=%s od teraz
|
||||
now=teraz
|
||||
future=przyszły
|
||||
1s=1 sekundę
|
||||
|
||||
@@ -110,7 +110,6 @@ never=Nunca
|
||||
|
||||
rss_feed=Feed RSS
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Barra de navegação
|
||||
footer=Rodapé
|
||||
@@ -3062,8 +3061,6 @@ starred_repo=favoritou <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=começou a observar <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s atrás
|
||||
from_now=%s a partir de agora
|
||||
now=agora
|
||||
future=futuro
|
||||
1s=1 segundo
|
||||
|
||||
@@ -112,8 +112,6 @@ never=Nunca
|
||||
|
||||
rss_feed=Fonte RSS
|
||||
|
||||
on_date=no dia
|
||||
|
||||
[aria]
|
||||
navbar=Barra de navegação
|
||||
footer=Rodapé
|
||||
@@ -133,6 +131,8 @@ buttons.list.task.tooltip=Adicionar uma lista de tarefas
|
||||
buttons.mention.tooltip=Mencionar um utilizador ou uma equipa
|
||||
buttons.ref.tooltip=Referenciar uma questão ou um pedido de integração
|
||||
buttons.switch_to_legacy.tooltip=Usar o editor clássico
|
||||
buttons.enable_monospace_font=Habilitar tipo de letra mono-espaçado
|
||||
buttons.disable_monospace_font=Desabilitar tipo de letra mono-espaçado
|
||||
|
||||
[filter]
|
||||
string.asc=A - Z
|
||||
@@ -3127,8 +3127,6 @@ starred_repo=juntou <a href="%[1]s">%[2]s</a> aos favoritos
|
||||
watched_repo=começou a vigiar <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=há %s
|
||||
from_now=daqui a %s
|
||||
now=agora
|
||||
future=futuro
|
||||
1s=1 segundo
|
||||
|
||||
@@ -4,7 +4,7 @@ explore=Обзор
|
||||
help=Помощь
|
||||
logo=Логотип
|
||||
sign_in=Вход
|
||||
sign_in_with=Войдите с помощью
|
||||
sign_in_with=Войти с помощью
|
||||
sign_out=Выход
|
||||
sign_up=Регистрация
|
||||
link_account=Привязать аккаунт
|
||||
@@ -25,14 +25,14 @@ licenses=Лицензии
|
||||
return_to_gitea=Вернуться к Gitea
|
||||
|
||||
username=Имя пользователя
|
||||
email=Адрес эл. почты
|
||||
email=Адрес электронной почты
|
||||
password=Пароль
|
||||
access_token=Токен доступа
|
||||
re_type=Введите пароль еще раз
|
||||
captcha=CAPTCHA
|
||||
twofa=Двухфакторная аутентификация
|
||||
twofa_scratch=Двухфакторный scratch-код
|
||||
passcode=Пароль
|
||||
passcode=Код
|
||||
|
||||
webauthn_insert_key=Вставьте ваш ключ безопасности
|
||||
webauthn_sign_in=Нажмите кнопку на ключе безопасности. Если ваш ключ безопасности не имеет кнопки, вставьте его снова.
|
||||
@@ -41,11 +41,11 @@ webauthn_use_twofa=Используйте двухфакторный код с
|
||||
webauthn_error=Не удалось прочитать ваш ключ безопасности.
|
||||
webauthn_unsupported_browser=Ваш браузер в настоящее время не поддерживает WebAuthn.
|
||||
webauthn_error_unknown=Произошла неизвестная ошибка. Повторите попытку.
|
||||
webauthn_error_insecure=`WebAuthn поддерживает только безопасные соединения. Для тестирования по HTTP, вы можете использовать "localhost" или "127.0.0.1"`
|
||||
webauthn_error_insecure=`WebAuthn поддерживает только безопасные соединения. Для тестирования по HTTP можно использовать "localhost" или "127.0.0.1"`
|
||||
webauthn_error_unable_to_process=Сервер не смог обработать ваш запрос.
|
||||
webauthn_error_duplicated=Представленный ключ не подходит для этого запроса. Если вы пытаетесь зарегистрировать его, убедитесь, что ключ ещё не зарегистрирован.
|
||||
webauthn_error_empty=Вы должны указать имя для этого ключа.
|
||||
webauthn_error_timeout=Тайм-аут достигнут до того, как ваш ключ был прочитан. Перезагрузите эту страницу и повторите попытку.
|
||||
webauthn_error_duplicated=Данный ключ безопасности не разрешен для этого запроса. Пожалуйста, убедитесь, что ключ не регистрировался ранее.
|
||||
webauthn_error_empty=Необходимо задать имя для этого ключа.
|
||||
webauthn_error_timeout=Время истекло раньше, чем ключ был прочитан. Перезагрузите эту страницу и повторите попытку.
|
||||
webauthn_reload=Обновить
|
||||
|
||||
repository=Репозиторий
|
||||
@@ -91,7 +91,7 @@ enabled=Включено
|
||||
disabled=Отключен
|
||||
|
||||
copy=Скопировать
|
||||
copy_url=Копировать URL
|
||||
copy_url=Скопировать URL
|
||||
copy_content=Скопировать содержимое
|
||||
copy_branch=Скопировать имя ветки
|
||||
copy_success=Скопировано!
|
||||
@@ -106,13 +106,12 @@ step1=Шаг 1:
|
||||
step2=Шаг 2:
|
||||
|
||||
error=Ошибка
|
||||
error404=Страница, которую вы пытаетесь открыть, либо <strong>не существует</strong>, либо <strong>недостаточно прав</strong> для ее просмотра.
|
||||
error404=Либо страница, которую вы пытаетесь открыть, <strong>не существует</strong>, либо <strong>у вас недостаточно прав</strong> для ее просмотра.
|
||||
|
||||
never=Никогда
|
||||
|
||||
rss_feed=RSS-лента
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Панель навигации
|
||||
footer=Подвал
|
||||
@@ -128,8 +127,8 @@ string.desc=Я - А
|
||||
[error]
|
||||
occurred=Произошла ошибка
|
||||
report_message=Если вы уверены, что это баг Gitea, пожалуйста, поищите задачу на <a href="https://github.com/go-gitea/gitea/issues" target="_blank">GitHub</a> или создайте новую при необходимости.
|
||||
missing_csrf=Некорректный запрос: CSRF токен отсутствует
|
||||
invalid_csrf=Некорректный запрос: неверный CSRF токен
|
||||
missing_csrf=Некорректный запрос: отсутствует токен CSRF
|
||||
invalid_csrf=Некорректный запрос: неверный токен CSRF
|
||||
network_error=Ошибка сети
|
||||
|
||||
[startpage]
|
||||
@@ -137,7 +136,7 @@ app_desc=Удобный сервис собственного хостинга
|
||||
install=Простой в установке
|
||||
install_desc=Просто <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/install-from-binary/">запустите исполняемый файл</a> для вашей платформы, разверните через <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a>, или установите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/install-from-package/">с помощью менеджера пакетов</a>.
|
||||
platform=Кроссплатформенный
|
||||
platform_desc=Gitea работает на любой операционной системе, которая может компилировать <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a>: Windows, macOS, Linux, ARM и т. д. Выбирайте, что вам больше нравится!
|
||||
platform_desc=Gitea работает на любой платформе, поддерживаемой <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a>: Windows, macOS, Linux, ARM и т. д. Выбирайте, что вам больше нравится!
|
||||
lightweight=Легковесный
|
||||
lightweight_desc=Gitea имеет низкие системные требования и может работать на недорогом Raspberry Pi. Экономьте энергию вашей машины!
|
||||
license=Открытый исходный код
|
||||
@@ -154,7 +153,7 @@ host=Хост
|
||||
user=Имя пользователя
|
||||
password=Пароль
|
||||
db_name=Имя базы данных
|
||||
db_helper=Для пользователей MySQL: пожалуйста, используйте движок InnoDB, и если вы используете "utf8mb4" - ваша версия InnoDB должна быть старше 5.6 .
|
||||
db_helper=Для пользователей MySQL: пожалуйста, используйте хранилище InnoDB, и если вы используете "utf8mb4", версия InnoDB должна быть выше 5.6 .
|
||||
db_schema=Схема
|
||||
db_schema_helper=Оставьте пустым для значения по умолчанию ("public").
|
||||
ssl_mode=SSL
|
||||
@@ -179,8 +178,8 @@ app_name=Название сайта
|
||||
app_name_helper=Здесь вы можете ввести название своей компании.
|
||||
repo_path=Путь до корня репозитория
|
||||
repo_path_helper=Все удалённые Git репозитории будут сохранены в эту директорию.
|
||||
lfs_path=Корневой путь Git LFS
|
||||
lfs_path_helper=В этой директории будут храниться файлы Git LFS. Оставьте пустым, чтобы отключить LFS.
|
||||
lfs_path=Путь к корневому каталогу Git LFS
|
||||
lfs_path_helper=В этом каталоге будут храниться файлы Git LFS. Оставьте пустым, чтобы отключить LFS.
|
||||
run_user=Запуск от имени пользователя
|
||||
run_user_helper=Введите имя пользователя операционной системы, под которым работает Gitea. Обратите внимание, что этот пользователь должен иметь доступ к корневому пути репозиториев.
|
||||
domain=Домен сервера
|
||||
@@ -287,6 +286,7 @@ search=Поиск
|
||||
code=Код
|
||||
search.type.tooltip=Тип поиска
|
||||
search.fuzzy=Неточный
|
||||
search.fuzzy.tooltip=Включать результаты, которые не полностью соответствуют поисковому запросу
|
||||
search.match=Соответствие
|
||||
search.match.tooltip=Включать только результаты, которые точно соответствуют поисковому запросу
|
||||
code_search_unavailable=В настоящее время поиск по коду недоступен. Обратитесь к администратору сайта.
|
||||
@@ -1029,6 +1029,7 @@ issues=Задачи
|
||||
pulls=Запросы на слияние
|
||||
project_board=Проекты
|
||||
packages=Пакеты
|
||||
actions=Действия
|
||||
labels=Метки
|
||||
org_labels_desc=Метки уровня организации, которые можно использовать с <strong>всеми репозиториями< / strong> в этой организации
|
||||
org_labels_desc_manage=управлять
|
||||
@@ -1247,6 +1248,7 @@ issues.choose.blank=По умолчанию
|
||||
issues.choose.blank_about=Создать запрос из шаблона по умолчанию.
|
||||
issues.choose.ignore_invalid_templates=Некорректные шаблоны были проигнорированы
|
||||
issues.choose.invalid_templates=Найден(ы) %v неверный(х) шаблон(ов)
|
||||
issues.choose.invalid_config=Конфигурация задачи содержит ошибки:
|
||||
issues.no_ref=Не указана ветка или тэг
|
||||
issues.create=Добавить задачу
|
||||
issues.new_label=Новая метка
|
||||
@@ -1525,6 +1527,8 @@ pulls.allow_edits_from_maintainers=Разрешить редактировани
|
||||
pulls.allow_edits_from_maintainers_desc=Пользователи с доступом на запись в основную ветку могут отправлять изменения и в эту ветку
|
||||
pulls.allow_edits_from_maintainers_err=Не удалось обновить
|
||||
pulls.compare_changes_desc=Сравнить две ветки и создать запрос на слияние для изменений.
|
||||
pulls.has_viewed_file=Просмотрено
|
||||
pulls.viewed_files_label=%[1]d из %[2]d файлов просмотрено
|
||||
pulls.expand_files=Показать все файлы
|
||||
pulls.collapse_files=Свернуть все файлы
|
||||
pulls.compare_base=базовая ветка
|
||||
@@ -1572,6 +1576,7 @@ pulls.can_auto_merge_desc=Этот запрос на слияние может
|
||||
pulls.cannot_auto_merge_desc=Этот запрос на слияние не может быть объединён автоматически.
|
||||
pulls.cannot_auto_merge_helper=Пожалуйста, совершите слияние вручную для урегулирования конфликтов.
|
||||
pulls.num_conflicting_files_1=%d конфликтующий файл
|
||||
pulls.num_conflicting_files_n=%d конфликтующих файлов
|
||||
pulls.approve_count_1=%d одобрение
|
||||
pulls.reject_count_1=%d запрос на изменение
|
||||
pulls.reject_count_n=%d запросов на изменение
|
||||
@@ -1620,10 +1625,23 @@ pulls.reopened_at=`переоткрыл этот запрос на слияни
|
||||
pulls.merge_instruction_hint=`Вы также можете просмотреть инструкции <a class="show-instruction">командной строки</a>.`
|
||||
pulls.merge_instruction_step1_desc=В репозитории вашего проекта посмотрите новую ветку и протестируйте изменения.
|
||||
pulls.merge_instruction_step2_desc=Объединить изменения и обновить на Gitea.
|
||||
pulls.clear_merge_message=Очистить сообщение о слиянии
|
||||
pulls.clear_merge_message_hint=Очистка сообщения о слиянии удалит только содержимое сообщения коммита, но сохранит сгенерированные git добавки, такие как "Co-Authored-By …".
|
||||
|
||||
pulls.auto_merge_button_when_succeed=(При успешных проверках)
|
||||
pulls.auto_merge_when_succeed=Слить автоматически после прохождения всех проверок
|
||||
pulls.auto_merge_newly_scheduled=Запрос был запланирован для слияния после прохождения всех проверок.
|
||||
pulls.auto_merge_has_pending_schedule=%[1]s запланировал этот запрос для автоматического слияния, когда все проверки пройдены %[2]s.
|
||||
|
||||
pulls.auto_merge_cancel_schedule=Отменить автоматическое слияние
|
||||
pulls.auto_merge_not_scheduled=Этот запрос не запланирован для автоматического слияния.
|
||||
pulls.auto_merge_canceled_schedule=Автоматическое слияние для этого запроса было отменено.
|
||||
|
||||
pulls.auto_merge_newly_scheduled_comment=`запланировал этот запрос для автоматического слияния после прохождения всех проверок %[1]s`
|
||||
pulls.auto_merge_canceled_schedule_comment=`отменил автоматическое слияние этого запроса после прохождения всех проверок %[1]s`
|
||||
|
||||
pulls.delete.title=Удалить этот запрос на слияние?
|
||||
pulls.delete.text=Вы действительно хотите удалить этот запрос на слияние? (Это навсегда удалит всё содержимое. Возможно, лучше закрыть запрос в архивных целях.)
|
||||
|
||||
milestones.new=Новый этап
|
||||
milestones.closed=Закрыт %s
|
||||
@@ -1669,6 +1687,7 @@ signing.wont_sign.commitssigned=Слияние не будет подписан
|
||||
signing.wont_sign.approved=Слияние не будет подписано, так как PR не одобрен
|
||||
signing.wont_sign.not_signed_in=Вы не авторизовались
|
||||
|
||||
ext_wiki=Доступ к внешней вики
|
||||
ext_wiki.desc=Ссылка на внешнюю вики.
|
||||
|
||||
wiki=Вики
|
||||
@@ -1765,6 +1784,7 @@ search=Поиск
|
||||
search.search_repo=Поиск по репозиторию
|
||||
search.type.tooltip=Тип поиска
|
||||
search.fuzzy=Неточный
|
||||
search.fuzzy.tooltip=Включать результаты, которые не полностью соответствуют поисковому запросу
|
||||
search.match=Соответствие
|
||||
search.match.tooltip=Включать только результаты, которые точно соответствуют поисковому запросу
|
||||
search.results=Результаты поиска "%s" в <a href="%s">%s</a>
|
||||
@@ -1798,6 +1818,7 @@ settings.mirror_sync_in_progress=Синхронизируются репозит
|
||||
settings.site=Сайт
|
||||
settings.update_settings=Обновить настройки
|
||||
settings.branches.update_default_branch=Обновить ветку по умолчанию
|
||||
settings.branches.add_new_rule=Добавить новое правило
|
||||
settings.advanced_settings=Расширенные настройки
|
||||
settings.wiki_desc=Включить Вики для репозитория
|
||||
settings.use_internal_wiki=Использовать встроенную вики-систему
|
||||
@@ -1816,15 +1837,22 @@ settings.tracker_url_format_error=Формат URL внешнего баг-тр
|
||||
settings.tracker_issue_style=Формат нумерации для внешней системы учета задач
|
||||
settings.tracker_issue_style.numeric=Цифровой
|
||||
settings.tracker_issue_style.alphanumeric=Буквенноцифровой
|
||||
settings.tracker_issue_style.regexp=Регулярное выражение
|
||||
settings.tracker_issue_style.regexp_pattern=Шаблон регулярного выражения
|
||||
settings.tracker_issue_style.regexp_pattern_desc=Вместо <code>{index}</code> будет использоваться первая захваченная группа.
|
||||
settings.tracker_url_format_desc=Вы можете использовать шаблоны <code>{user}</code>, <code>{repo}</code> и <code>{index}</code> для имени пользователя, репозитория и номера задачи.
|
||||
settings.enable_timetracker=Включить отслеживание времени
|
||||
settings.allow_only_contributors_to_track_time=Учитывать только участников разработки в подсчёте времени
|
||||
settings.pulls_desc=Включить запросы на слияние
|
||||
settings.pulls.ignore_whitespace=Игнорировать незначащие изменения (пробелы, табуляция) при проверке на конфликты слияния
|
||||
settings.pulls.enable_autodetect_manual_merge=Включить автоопределение ручного слияния (Примечание: в некоторых особых случаях могут возникнуть ошибки)
|
||||
settings.pulls.allow_rebase_update=Включить обновление ветки из запроса на слияние путём rebase
|
||||
settings.pulls.default_delete_branch_after_merge=Удалить ветку запроса после его слияния по умолчанию
|
||||
settings.pulls.default_allow_edits_from_maintainers=По умолчанию разрешать редактирование сопровождающими
|
||||
settings.releases_desc=Включить релизы
|
||||
settings.packages_desc=Включить реестр пакетов
|
||||
settings.projects_desc=Включить проекты репозитория
|
||||
settings.actions_desc=Включить действия репозитория
|
||||
settings.admin_settings=Настройки администратора
|
||||
settings.admin_enable_health_check=Выполнять проверки целостности этого репозитория (git fsck)
|
||||
settings.admin_code_indexer=Индексатор кода
|
||||
@@ -1886,6 +1914,7 @@ settings.confirm_delete=Удалить репозиторий
|
||||
settings.add_collaborator=Добавить соавтора
|
||||
settings.add_collaborator_success=Соавтор добавлен.
|
||||
settings.add_collaborator_inactive_user=Невозможно добавить неактивного пользователя как соавтора.
|
||||
settings.add_collaborator_owner=Невозможно добавить владельца в качестве соавтора.
|
||||
settings.add_collaborator_duplicate=Соавтор уже добавлен в этот репозиторий.
|
||||
settings.delete_collaborator=Удалить
|
||||
settings.collaborator_deletion=Удалить соавтора
|
||||
@@ -1917,6 +1946,7 @@ settings.webhook.headers=Заголовки
|
||||
settings.webhook.payload=Содержимое
|
||||
settings.webhook.body=Тело ответа
|
||||
settings.webhook.replay.description=Повторить этот веб-хук.
|
||||
settings.webhook.delivery.success=Событие было добавлено в очередь доставки. Может пройти несколько секунд, прежде чем оно отобразится в истории.
|
||||
settings.githooks_desc=Git-хуки предоставляются самим Git. Вы можете изменять файлы хуков из списка ниже, чтобы настроить собственные операции.
|
||||
settings.githook_edit_desc=Если хук не активен, будет подставлен пример содержимого. Пустое значение в этом поле приведёт к отключению хука.
|
||||
settings.githook_name=Название хукa
|
||||
@@ -1981,6 +2011,7 @@ settings.event_package_desc=Пакет создан или удален в ре
|
||||
settings.branch_filter=Фильтр веток
|
||||
settings.branch_filter_desc=Белый список ветвей для событий Push, создания ветвей и удаления ветвей, указанных в виде глоб-шаблона. Если пустой или <code>*</code>, то все событий для всех ветвей будут зарегистрированы. Перейдите по ссылке <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> на документацию по синтаксису. Примеры: <code>master</code>, <code>{master,release*}</code>.
|
||||
settings.authorization_header=Заголовок Authorization
|
||||
settings.authorization_header_desc=Будет включён в качестве заголовка авторизации для запросов. Примеры: %s.
|
||||
settings.active=Активный
|
||||
settings.active_helper=Информация о происходящих событиях будет отправляться на URL этого веб-хука.
|
||||
settings.add_hook_success=Веб-хук был добавлен.
|
||||
@@ -2020,6 +2051,8 @@ settings.key_been_used=Идентичный ключ развёртывания
|
||||
settings.key_name_used=Ключ развёртывания с таким именем уже существует.
|
||||
settings.add_key_success=Новый ключ развёртывания '%s' успешно добавлен.
|
||||
settings.deploy_key_deletion=Удалить ключ развёртывания
|
||||
settings.deploy_key_deletion_desc=Удаление ключа развёртывания сделает невозможным доступ к репозиторию с его помощью. Вы уверены?
|
||||
settings.deploy_key_deletion_success=Ключ развёртывания был успешно удалён.
|
||||
settings.branches=Ветки
|
||||
settings.protected_branch=Защита веток
|
||||
settings.protected_branch.save_rule=Сохранить правило
|
||||
@@ -2962,8 +2995,6 @@ starred_repo=добавил(а) <a href="%[1]s">%[2]s</a> в избранное
|
||||
watched_repo=начала(а) наблюдение за <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s назад
|
||||
from_now=%s с этого момента
|
||||
now=сейчас
|
||||
future=в будущем
|
||||
1s=1 секунду
|
||||
@@ -3035,11 +3066,20 @@ keywords=Ключевые слова
|
||||
details=Подробнее
|
||||
details.author=Автор
|
||||
details.project_site=Сайт проекта
|
||||
details.repository_site=Сайт репозитория
|
||||
details.documentation_site=Сайт документации
|
||||
details.license=Лицензия
|
||||
versions=Версии
|
||||
versions.view_all=Показать всё
|
||||
dependency.version=Версия
|
||||
cargo.registry=Настройте этот реестр в файле конфигурации Cargo (например, <code>~/.cargo/config.toml</code>):
|
||||
cargo.install=Чтобы установить пакет с помощью Cargo, выполните следующую команду:
|
||||
cargo.documentation=Для получения дополнительной информации о реестре Cargo смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">документацию</a>.
|
||||
cargo.details.repository_site=Сайт репозитория
|
||||
cargo.details.documentation_site=Сайт документации
|
||||
chef.registry=Настройте этот реестр в своём файле <code>~/.chef/config.rb</code>:
|
||||
chef.install=Чтобы установить пакет, выполните следующую команду:
|
||||
chef.documentation=Для получения дополнительной информации о реестре Chef смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">документацию</a>.
|
||||
composer.registry=Настройте этот реестр в файле <code>~/.composer/config.json</code>:
|
||||
composer.install=Чтобы установить пакет с помощью Composer, выполните следующую команду:
|
||||
composer.documentation=Для получения дополнительной информации о реестре Composer смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">документацию</a>.
|
||||
@@ -3048,6 +3088,11 @@ conan.details.repository=Репозиторий
|
||||
conan.registry=Настроить реестр из командной строки:
|
||||
conan.install=Чтобы установить пакет с помощью Conan, выполните следующую команду:
|
||||
conan.documentation=Для получения дополнительной информации о реестре Conan смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">документацию</a>.
|
||||
conda.registry=Пропишите этот реестр в качестве репозитория Conda в своём файле <code>.condarc</code>:
|
||||
conda.install=Чтобы установить пакет с помощью Conda, выполните следующую команду:
|
||||
conda.documentation=Для получения дополнительной информации о реестре Conda смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">документацию</a>.
|
||||
conda.details.repository_site=Сайт репозитория
|
||||
conda.details.documentation_site=Сайт документации
|
||||
container.details.type=Тип образа
|
||||
container.details.platform=Платформа
|
||||
container.digest=Отпечаток:
|
||||
@@ -3061,6 +3106,7 @@ helm.registry=Настроить реестр из командной строк
|
||||
helm.install=Чтобы установить пакет, выполните следующую команду:
|
||||
helm.documentation=Для получения дополнительной информации о реестре Helm смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/helm/">документацию</a>.
|
||||
maven.install2=Выполнить через командную строку:
|
||||
maven.download=Чтобы скачать зависимость, запустите в командной строке:
|
||||
nuget.registry=Настроить реестр из командной строки:
|
||||
nuget.install=Чтобы установить пакет с помощью NuGet, выполните следующую команду:
|
||||
nuget.documentation=Для получения дополнительной информации о реестре NuGet смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/nuget/">документацию</a>.
|
||||
@@ -3071,6 +3117,8 @@ npm.dependencies=Зависимости
|
||||
npm.dependencies.peer=Одноранговые зависимости
|
||||
npm.dependencies.optional=Необязательные зависимости
|
||||
npm.details.tag=Тег
|
||||
pub.install=Чтобы установить пакет с помощью Dart, выполните следующую команду:
|
||||
pub.documentation=Для получения дополнительной информации о реестре Conda смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">документацию</a>.
|
||||
pypi.requires=Требуется Python
|
||||
pypi.documentation=Для получения дополнительной информации о реестре PyPI смотрите <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">документацию</a>.
|
||||
rubygems.install=Чтобы установить пакет с помощью gem, выполните следующую команду:
|
||||
|
||||
@@ -92,7 +92,6 @@ error404=ඔබ ළඟා වීමට උත්සාහ කරන පිටු
|
||||
never=කිසි විටෙකත්
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2678,8 +2677,6 @@ create_branch=නිර්මාණය කරන ලද ශාඛාව <a href=
|
||||
watched_repo=<a href="%[1]s">%[2]s</a>නැරඹීමට පටන් ගත්තා
|
||||
|
||||
[tool]
|
||||
ago=%s කලින්
|
||||
from_now=%s මෙතැන් සිට
|
||||
now=දැන්
|
||||
future=අනාගතය
|
||||
1s=තත්පර 1
|
||||
|
||||
@@ -106,7 +106,6 @@ never=Nikdy
|
||||
|
||||
rss_feed=RSS kanál
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
|
||||
@@ -81,7 +81,6 @@ error404=Sidan du försöker nå <strong>finns inte</strong> eller så <strong>h
|
||||
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2110,8 +2109,6 @@ compare_commits_general=Jämför commits
|
||||
mirror_sync_delete=synkade och raderade referens <code>%[2]s</code> på <a href="%[1]s">%[3]s</a> från spegel
|
||||
|
||||
[tool]
|
||||
ago=%s sedan
|
||||
from_now=%s från och med nu
|
||||
now=nu
|
||||
future=framtiden
|
||||
1s=1 sekund
|
||||
|
||||
@@ -110,7 +110,6 @@ never=Asla
|
||||
|
||||
rss_feed=RSS Beslemesi
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=Gezinti Çubuğu
|
||||
footer=Alt Bilgi
|
||||
@@ -2988,8 +2987,6 @@ starred_repo=<a href="%[1]s">%[2]s</a> deposuna yıldız bıraktı
|
||||
watched_repo=<a href="%[1]s">%[2]s</a> deposunu izlemeye başladı
|
||||
|
||||
[tool]
|
||||
ago=%s önce
|
||||
from_now=%s şu andan
|
||||
now=şimdi
|
||||
future=gelecek
|
||||
1s=1 saniye
|
||||
|
||||
@@ -93,7 +93,6 @@ error404=Сторінка, до якої ви намагаєтеся зверн
|
||||
never=Ніколи
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -2750,8 +2749,6 @@ starred_repo=додав <a href="%[1]s">%[2]s</a> у обране
|
||||
watched_repo=почав слідкувати за <a href="%[1]s">%[2]</a>
|
||||
|
||||
[tool]
|
||||
ago=%s тому
|
||||
from_now=%s з цього моменту
|
||||
now=зараз
|
||||
future=в майбутньому
|
||||
1s=1 секунда
|
||||
|
||||
@@ -112,7 +112,6 @@ never=从不
|
||||
|
||||
rss_feed=RSS 订阅源
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=导航栏
|
||||
footer=页脚
|
||||
@@ -3095,8 +3094,6 @@ starred_repo=点赞了 <a href="%[1]s">%[2]s</a>
|
||||
watched_repo=开始关注 <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s前
|
||||
from_now=%s 之后
|
||||
now=现在
|
||||
future=将来
|
||||
1s=1 秒
|
||||
|
||||
@@ -51,7 +51,6 @@ enabled=已啟用
|
||||
|
||||
|
||||
|
||||
|
||||
[aria]
|
||||
|
||||
[editor]
|
||||
@@ -926,8 +925,6 @@ transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
|
||||
compare_commits=比較 %d 提交
|
||||
|
||||
[tool]
|
||||
ago=%s之前
|
||||
from_now=%s之後
|
||||
now=現在
|
||||
future=未來
|
||||
1s=1 秒
|
||||
|
||||
@@ -112,7 +112,6 @@ never=從來沒有
|
||||
|
||||
rss_feed=RSS 摘要
|
||||
|
||||
|
||||
[aria]
|
||||
navbar=導航列
|
||||
footer=頁尾
|
||||
@@ -120,6 +119,8 @@ footer.software=關於軟體
|
||||
footer.links=連結
|
||||
|
||||
[editor]
|
||||
buttons.enable_monospace_font=啟用等寬字型
|
||||
buttons.disable_monospace_font=停用等寬字型
|
||||
|
||||
[filter]
|
||||
string.asc=A - Z
|
||||
@@ -1748,6 +1749,8 @@ wiki.create_first_page=建立第一個頁面
|
||||
wiki.page=頁面
|
||||
wiki.filter_page=過濾頁面
|
||||
wiki.new_page=頁面
|
||||
wiki.page_title=頁面標題
|
||||
wiki.page_content=頁面內容
|
||||
wiki.default_commit_message=關於此次頁面修改的說明(非必要)。
|
||||
wiki.save_page=儲存頁面
|
||||
wiki.last_commit_info=%s 於 %s 修改了此頁面
|
||||
@@ -3105,8 +3108,6 @@ starred_repo=為 <a href="%[1]s">%[2]s</a> 加上星號
|
||||
watched_repo=開始關注 <a href="%[1]s">%[2]s</a>
|
||||
|
||||
[tool]
|
||||
ago=%s前
|
||||
from_now=%s之後
|
||||
now=現在
|
||||
future=未來
|
||||
1s=1 秒
|
||||
|
||||
@@ -651,7 +651,7 @@ func CreateIssue(ctx *context.APIContext) {
|
||||
form.Labels = make([]int64, 0)
|
||||
}
|
||||
|
||||
if err := issue_service.NewIssue(ctx.Repo.Repository, issue, form.Labels, nil, assigneeIDs); err != nil {
|
||||
if err := issue_service.NewIssue(ctx, ctx.Repo.Repository, issue, form.Labels, nil, assigneeIDs); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err)
|
||||
return
|
||||
@@ -752,7 +752,7 @@ func EditIssue(ctx *context.APIContext) {
|
||||
issue.Content = *form.Body
|
||||
}
|
||||
if form.Ref != nil {
|
||||
err = issue_service.ChangeIssueRef(issue, ctx.Doer, *form.Ref)
|
||||
err = issue_service.ChangeIssueRef(ctx, issue, ctx.Doer, *form.Ref)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateRef", err)
|
||||
return
|
||||
@@ -790,7 +790,7 @@ func EditIssue(ctx *context.APIContext) {
|
||||
oneAssignee = *form.Assignee
|
||||
}
|
||||
|
||||
err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.Doer)
|
||||
err = issue_service.UpdateAssignees(ctx, issue, oneAssignee, form.Assignees, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateAssignees", err)
|
||||
return
|
||||
@@ -887,7 +887,7 @@ func DeleteIssue(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = issue_service.DeleteIssue(ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
|
||||
if err = issue_service.DeleteIssue(ctx, ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteIssueByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ func EditPullRequest(ctx *context.APIContext) {
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
|
||||
if ctx.Repo.CanWrite(unit.TypePullRequests) && (form.Assignees != nil || len(form.Assignee) > 0) {
|
||||
err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.Doer)
|
||||
err = issue_service.UpdateAssignees(ctx, issue, form.Assignee, form.Assignees, ctx.Doer)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
|
||||
|
||||
@@ -706,7 +706,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
}
|
||||
|
||||
for _, reviewer := range reviewers {
|
||||
comment, err := issue_service.ReviewRequest(pr.Issue, ctx.Doer, reviewer, isAdd)
|
||||
comment, err := issue_service.ReviewRequest(ctx, pr.Issue, ctx.Doer, reviewer, isAdd)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
|
||||
return
|
||||
@@ -750,7 +750,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
}
|
||||
|
||||
for _, teamReviewer := range teamReviewers {
|
||||
comment, err := issue_service.TeamReviewRequest(pr.Issue, ctx.Doer, teamReviewer, isAdd)
|
||||
comment, err := issue_service.TeamReviewRequest(ctx, pr.Issue, ctx.Doer, teamReviewer, isAdd)
|
||||
if err != nil {
|
||||
ctx.ServerError("TeamReviewRequest", err)
|
||||
return
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
@@ -32,5 +33,14 @@ func List(ctx *context.Context) {
|
||||
}
|
||||
|
||||
func Tmpl(ctx *context.Context) {
|
||||
now := time.Now()
|
||||
ctx.Data["TimeNow"] = now
|
||||
ctx.Data["TimePast5s"] = now.Add(-5 * time.Second)
|
||||
ctx.Data["TimeFuture5s"] = now.Add(5 * time.Second)
|
||||
ctx.Data["TimePast2m"] = now.Add(-2 * time.Minute)
|
||||
ctx.Data["TimeFuture2m"] = now.Add(2 * time.Minute)
|
||||
ctx.Data["TimePast1y"] = now.Add(-1 * 366 * 86400 * time.Second)
|
||||
ctx.Data["TimeFuture1y"] = now.Add(1 * 366 * 86400 * time.Second)
|
||||
|
||||
ctx.HTML(http.StatusOK, base.TplName("devtest"+path.Clean("/"+ctx.Params("sub"))))
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
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/charset"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
@@ -23,10 +22,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
const (
|
||||
tplBlame base.TplName = "repo/home"
|
||||
)
|
||||
|
||||
type blameRow struct {
|
||||
RowNumber int
|
||||
Avatar gotemplate.HTML
|
||||
@@ -140,7 +135,7 @@ func RefBlame(ctx *context.Context) {
|
||||
|
||||
renderBlame(ctx, blameParts, commitNames, previousCommits)
|
||||
|
||||
ctx.HTML(http.StatusOK, tplBlame)
|
||||
ctx.HTML(http.StatusOK, tplRepoHome)
|
||||
}
|
||||
|
||||
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) {
|
||||
|
||||
@@ -551,7 +551,11 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||
ctx.ServerError("GetCompareInfo", err)
|
||||
return nil
|
||||
}
|
||||
ctx.Data["BeforeCommitID"] = ci.CompareInfo.MergeBase
|
||||
if ci.DirectComparison {
|
||||
ctx.Data["BeforeCommitID"] = ci.CompareInfo.BaseCommitID
|
||||
} else {
|
||||
ctx.Data["BeforeCommitID"] = ci.CompareInfo.MergeBase
|
||||
}
|
||||
|
||||
return ci
|
||||
}
|
||||
|
||||
@@ -964,7 +964,7 @@ func DeleteIssue(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := issue_service.DeleteIssue(ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
|
||||
if err := issue_service.DeleteIssue(ctx, ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
|
||||
ctx.ServerError("DeleteIssueByID", err)
|
||||
return
|
||||
}
|
||||
@@ -1132,7 +1132,7 @@ func NewIssuePost(ctx *context.Context) {
|
||||
Ref: form.Ref,
|
||||
}
|
||||
|
||||
if err := issue_service.NewIssue(repo, issue, labelIDs, attachments, assigneeIDs); err != nil {
|
||||
if err := issue_service.NewIssue(ctx, repo, issue, labelIDs, attachments, assigneeIDs); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err.Error())
|
||||
return
|
||||
@@ -2013,7 +2013,7 @@ func UpdateIssueTitle(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := issue_service.ChangeTitle(issue, ctx.Doer, title); err != nil {
|
||||
if err := issue_service.ChangeTitle(ctx, issue, ctx.Doer, title); err != nil {
|
||||
ctx.ServerError("ChangeTitle", err)
|
||||
return
|
||||
}
|
||||
@@ -2037,7 +2037,7 @@ func UpdateIssueRef(ctx *context.Context) {
|
||||
|
||||
ref := ctx.FormTrim("ref")
|
||||
|
||||
if err := issue_service.ChangeIssueRef(issue, ctx.Doer, ref); err != nil {
|
||||
if err := issue_service.ChangeIssueRef(ctx, issue, ctx.Doer, ref); err != nil {
|
||||
ctx.ServerError("ChangeRef", err)
|
||||
return
|
||||
}
|
||||
@@ -2161,7 +2161,7 @@ func UpdateIssueAssignee(ctx *context.Context) {
|
||||
for _, issue := range issues {
|
||||
switch action {
|
||||
case "clear":
|
||||
if err := issue_service.DeleteNotPassedAssignee(issue, ctx.Doer, []*user_model.User{}); err != nil {
|
||||
if err := issue_service.DeleteNotPassedAssignee(ctx, issue, ctx.Doer, []*user_model.User{}); err != nil {
|
||||
ctx.ServerError("ClearAssignees", err)
|
||||
return
|
||||
}
|
||||
@@ -2182,7 +2182,7 @@ func UpdateIssueAssignee(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, err = issue_service.ToggleAssignee(issue, ctx.Doer, assigneeID)
|
||||
_, _, err = issue_service.ToggleAssignee(ctx, issue, ctx.Doer, assigneeID)
|
||||
if err != nil {
|
||||
ctx.ServerError("ToggleAssignee", err)
|
||||
return
|
||||
@@ -2269,7 +2269,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = issue_service.TeamReviewRequest(issue, ctx.Doer, team, action == "attach")
|
||||
_, err = issue_service.TeamReviewRequest(ctx, issue, ctx.Doer, team, action == "attach")
|
||||
if err != nil {
|
||||
ctx.ServerError("TeamReviewRequest", err)
|
||||
return
|
||||
@@ -2307,7 +2307,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = issue_service.ReviewRequest(issue, ctx.Doer, reviewer, action == "attach")
|
||||
_, err = issue_service.ReviewRequest(ctx, issue, ctx.Doer, reviewer, action == "attach")
|
||||
if err != nil {
|
||||
ctx.ServerError("ReviewRequest", err)
|
||||
return
|
||||
|
||||
@@ -24,6 +24,7 @@ func Search(ctx *context.Context) {
|
||||
Keyword: ctx.FormTrim("q"),
|
||||
UID: ctx.FormInt64("uid"),
|
||||
Type: user_model.UserTypeIndividual,
|
||||
IsActive: ctx.FormOptionalBool("active"),
|
||||
ListOptions: listOptions,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
+12
-13
@@ -6,7 +6,6 @@ package issue
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
@@ -18,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// DeleteNotPassedAssignee deletes all assignees who aren't passed via the "assignees" array
|
||||
func DeleteNotPassedAssignee(issue *issues_model.Issue, doer *user_model.User, assignees []*user_model.User) (err error) {
|
||||
func DeleteNotPassedAssignee(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, assignees []*user_model.User) (err error) {
|
||||
var found bool
|
||||
oriAssignes := make([]*user_model.User, len(issue.Assignees))
|
||||
_ = copy(oriAssignes, issue.Assignees)
|
||||
@@ -34,7 +33,7 @@ func DeleteNotPassedAssignee(issue *issues_model.Issue, doer *user_model.User, a
|
||||
|
||||
if !found {
|
||||
// This function also does comments and hooks, which is why we call it separately instead of directly removing the assignees here
|
||||
if _, _, err := ToggleAssignee(issue, doer, assignee.ID); err != nil {
|
||||
if _, _, err := ToggleAssignee(ctx, issue, doer, assignee.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -44,25 +43,25 @@ func DeleteNotPassedAssignee(issue *issues_model.Issue, doer *user_model.User, a
|
||||
}
|
||||
|
||||
// ToggleAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
||||
func ToggleAssignee(issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *issues_model.Comment, err error) {
|
||||
removed, comment, err = issues_model.ToggleIssueAssignee(issue, doer, assigneeID)
|
||||
func ToggleAssignee(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *issues_model.Comment, err error) {
|
||||
removed, comment, err = issues_model.ToggleIssueAssignee(ctx, issue, doer, assigneeID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
assignee, err1 := user_model.GetUserByID(db.DefaultContext, assigneeID)
|
||||
assignee, err1 := user_model.GetUserByID(ctx, assigneeID)
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyIssueChangeAssignee(db.DefaultContext, doer, issue, assignee, removed, comment)
|
||||
notification.NotifyIssueChangeAssignee(ctx, doer, issue, assignee, removed, comment)
|
||||
|
||||
return removed, comment, err
|
||||
}
|
||||
|
||||
// ReviewRequest add or remove a review request from a user for this PR, and make comment for it.
|
||||
func ReviewRequest(issue *issues_model.Issue, doer, reviewer *user_model.User, isAdd bool) (comment *issues_model.Comment, err error) {
|
||||
func ReviewRequest(ctx context.Context, issue *issues_model.Issue, doer, reviewer *user_model.User, isAdd bool) (comment *issues_model.Comment, err error) {
|
||||
if isAdd {
|
||||
comment, err = issues_model.AddReviewRequest(issue, reviewer, doer)
|
||||
} else {
|
||||
@@ -74,7 +73,7 @@ func ReviewRequest(issue *issues_model.Issue, doer, reviewer *user_model.User, i
|
||||
}
|
||||
|
||||
if comment != nil {
|
||||
notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, reviewer, isAdd, comment)
|
||||
notification.NotifyPullReviewRequest(ctx, doer, issue, reviewer, isAdd, comment)
|
||||
}
|
||||
|
||||
return comment, err
|
||||
@@ -229,7 +228,7 @@ func IsValidTeamReviewRequest(ctx context.Context, reviewer *organization.Team,
|
||||
}
|
||||
|
||||
// TeamReviewRequest add or remove a review request from a team for this PR, and make comment for it.
|
||||
func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewer *organization.Team, isAdd bool) (comment *issues_model.Comment, err error) {
|
||||
func TeamReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, reviewer *organization.Team, isAdd bool) (comment *issues_model.Comment, err error) {
|
||||
if isAdd {
|
||||
comment, err = issues_model.AddTeamReviewRequest(issue, reviewer, doer)
|
||||
} else {
|
||||
@@ -245,11 +244,11 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe
|
||||
}
|
||||
|
||||
// notify all user in this team
|
||||
if err = comment.LoadIssue(db.DefaultContext); err != nil {
|
||||
if err = comment.LoadIssue(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
members, err := organization.GetTeamMembers(db.DefaultContext, &organization.SearchMembersOptions{
|
||||
members, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{
|
||||
TeamID: reviewer.ID,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -261,7 +260,7 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe
|
||||
continue
|
||||
}
|
||||
comment.AssigneeID = member.ID
|
||||
notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, member, isAdd, comment)
|
||||
notification.NotifyPullReviewRequest(ctx, doer, issue, member, isAdd, comment)
|
||||
}
|
||||
|
||||
return comment, err
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestDeleteNotPassedAssignee(t *testing.T) {
|
||||
assert.True(t, isAssigned)
|
||||
|
||||
// Clean everyone
|
||||
err = DeleteNotPassedAssignee(issue, user1, []*user_model.User{})
|
||||
err = DeleteNotPassedAssignee(db.DefaultContext, issue, user1, []*user_model.User{})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, len(issue.Assignees))
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
)
|
||||
|
||||
// CreateComment creates comment of issue or commit.
|
||||
func CreateComment(opts *issues_model.CreateCommentOptions) (comment *issues_model.Comment, err error) {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func CreateComment(ctx context.Context, opts *issues_model.CreateCommentOptions) (comment *issues_model.Comment, err error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = CreateComment(&issues_model.CreateCommentOptions{
|
||||
_, err = CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
|
||||
Type: issues_model.CommentTypeCommitRef,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
@@ -66,7 +66,7 @@ func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue
|
||||
|
||||
// CreateIssueComment creates a plain issue comment.
|
||||
func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) {
|
||||
comment, err := CreateComment(&issues_model.CreateCommentOptions{
|
||||
comment, err := CreateComment(ctx, &issues_model.CreateCommentOptions{
|
||||
Type: issues_model.CommentTypeComment,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
|
||||
+29
-28
@@ -4,6 +4,7 @@
|
||||
package issue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
@@ -20,49 +21,49 @@ import (
|
||||
)
|
||||
|
||||
// NewIssue creates new issue with labels for repository.
|
||||
func NewIssue(repo *repo_model.Repository, issue *issues_model.Issue, labelIDs []int64, uuids []string, assigneeIDs []int64) error {
|
||||
func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_model.Issue, labelIDs []int64, uuids []string, assigneeIDs []int64) error {
|
||||
if err := issues_model.NewIssue(repo, issue, labelIDs, uuids); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, assigneeID := range assigneeIDs {
|
||||
if err := AddAssigneeIfNotAssigned(issue, issue.Poster, assigneeID); err != nil {
|
||||
if err := AddAssigneeIfNotAssigned(ctx, issue, issue.Poster, assigneeID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
mentions, err := issues_model.FindAndUpdateIssueMentions(db.DefaultContext, issue, issue.Poster, issue.Content)
|
||||
mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, issue.Poster, issue.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
notification.NotifyNewIssue(db.DefaultContext, issue, mentions)
|
||||
notification.NotifyNewIssue(ctx, issue, mentions)
|
||||
if len(issue.Labels) > 0 {
|
||||
notification.NotifyIssueChangeLabels(db.DefaultContext, issue.Poster, issue, issue.Labels, nil)
|
||||
notification.NotifyIssueChangeLabels(ctx, issue.Poster, issue, issue.Labels, nil)
|
||||
}
|
||||
if issue.Milestone != nil {
|
||||
notification.NotifyIssueChangeMilestone(db.DefaultContext, issue.Poster, issue, 0)
|
||||
notification.NotifyIssueChangeMilestone(ctx, issue.Poster, issue, 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeTitle changes the title of this issue, as the given user.
|
||||
func ChangeTitle(issue *issues_model.Issue, doer *user_model.User, title string) (err error) {
|
||||
func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, title string) (err error) {
|
||||
oldTitle := issue.Title
|
||||
issue.Title = title
|
||||
|
||||
if err = issues_model.ChangeIssueTitle(issue, doer, oldTitle); err != nil {
|
||||
if err = issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyIssueChangeTitle(db.DefaultContext, doer, issue, oldTitle)
|
||||
notification.NotifyIssueChangeTitle(ctx, doer, issue, oldTitle)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeIssueRef changes the branch of this issue, as the given user.
|
||||
func ChangeIssueRef(issue *issues_model.Issue, doer *user_model.User, ref string) error {
|
||||
func ChangeIssueRef(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, ref string) error {
|
||||
oldRef := issue.Ref
|
||||
issue.Ref = ref
|
||||
|
||||
@@ -70,7 +71,7 @@ func ChangeIssueRef(issue *issues_model.Issue, doer *user_model.User, ref string
|
||||
return err
|
||||
}
|
||||
|
||||
notification.NotifyIssueChangeRef(db.DefaultContext, doer, issue, oldRef)
|
||||
notification.NotifyIssueChangeRef(ctx, doer, issue, oldRef)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -81,7 +82,7 @@ func ChangeIssueRef(issue *issues_model.Issue, doer *user_model.User, ref string
|
||||
// "assignees" (array): Logins for Users to assign to this issue.
|
||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssignees []string, doer *user_model.User) (err error) {
|
||||
func UpdateAssignees(ctx context.Context, issue *issues_model.Issue, oneAssignee string, multipleAssignees []string, doer *user_model.User) (err error) {
|
||||
var allNewAssignees []*user_model.User
|
||||
|
||||
// Keep the old assignee thingy for compatibility reasons
|
||||
@@ -102,7 +103,7 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi
|
||||
|
||||
// Loop through all assignees to add them
|
||||
for _, assigneeName := range multipleAssignees {
|
||||
assignee, err := user_model.GetUserByName(db.DefaultContext, assigneeName)
|
||||
assignee, err := user_model.GetUserByName(ctx, assigneeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -111,7 +112,7 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi
|
||||
}
|
||||
|
||||
// Delete all old assignees not passed
|
||||
if err = DeleteNotPassedAssignee(issue, doer, allNewAssignees); err != nil {
|
||||
if err = DeleteNotPassedAssignee(ctx, issue, doer, allNewAssignees); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi
|
||||
// has access to the repo.
|
||||
for _, assignee := range allNewAssignees {
|
||||
// Extra method to prevent double adding (which would result in removing)
|
||||
err = AddAssigneeIfNotAssigned(issue, doer, assignee.ID)
|
||||
err = AddAssigneeIfNotAssigned(ctx, issue, doer, assignee.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -131,42 +132,42 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi
|
||||
}
|
||||
|
||||
// DeleteIssue deletes an issue
|
||||
func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue) error {
|
||||
func DeleteIssue(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue) error {
|
||||
// load issue before deleting it
|
||||
if err := issue.LoadAttributes(gitRepo.Ctx); err != nil {
|
||||
if err := issue.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := issue.LoadPullRequest(gitRepo.Ctx); err != nil {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete entries in database
|
||||
if err := deleteIssue(issue); err != nil {
|
||||
if err := deleteIssue(ctx, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete pull request related git data
|
||||
if issue.IsPull {
|
||||
if issue.IsPull && gitRepo != nil {
|
||||
if err := gitRepo.RemoveReference(fmt.Sprintf("%s%d/head", git.PullPrefix, issue.PullRequest.Index)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
notification.NotifyDeleteIssue(gitRepo.Ctx, doer, issue)
|
||||
notification.NotifyDeleteIssue(ctx, doer, issue)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddAssigneeIfNotAssigned adds an assignee only if he isn't already assigned to the issue.
|
||||
// Also checks for access of assigned user
|
||||
func AddAssigneeIfNotAssigned(issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (err error) {
|
||||
assignee, err := user_model.GetUserByID(db.DefaultContext, assigneeID)
|
||||
func AddAssigneeIfNotAssigned(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (err error) {
|
||||
assignee, err := user_model.GetUserByID(ctx, assigneeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the user is already assigned
|
||||
isAssigned, err := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, assignee)
|
||||
isAssigned, err := issues_model.IsUserAssignedToIssue(ctx, issue, assignee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -175,7 +176,7 @@ func AddAssigneeIfNotAssigned(issue *issues_model.Issue, doer *user_model.User,
|
||||
return nil
|
||||
}
|
||||
|
||||
valid, err := access_model.CanBeAssigned(db.DefaultContext, assignee, issue.Repo, issue.IsPull)
|
||||
valid, err := access_model.CanBeAssigned(ctx, assignee, issue.Repo, issue.IsPull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -183,7 +184,7 @@ func AddAssigneeIfNotAssigned(issue *issues_model.Issue, doer *user_model.User,
|
||||
return repo_model.ErrUserDoesNotHaveAccessToRepo{UserID: assigneeID, RepoName: issue.Repo.Name}
|
||||
}
|
||||
|
||||
_, _, err = ToggleAssignee(issue, doer, assigneeID)
|
||||
_, _, err = ToggleAssignee(ctx, issue, doer, assigneeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -206,8 +207,8 @@ func GetRefEndNamesAndURLs(issues []*issues_model.Issue, repoLink string) (map[i
|
||||
}
|
||||
|
||||
// deleteIssue deletes the issue
|
||||
func deleteIssue(issue *issues_model.Issue) error {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func deleteIssue(ctx context.Context, issue *issues_model.Issue) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestIssue_DeleteIssue(t *testing.T) {
|
||||
ID: issueIDs[2],
|
||||
}
|
||||
|
||||
err = deleteIssue(issue)
|
||||
err = deleteIssue(db.DefaultContext, issue)
|
||||
assert.NoError(t, err)
|
||||
issueIDs, err = issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
@@ -55,7 +55,7 @@ func TestIssue_DeleteIssue(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
issue, err = issues_model.GetIssueByID(db.DefaultContext, 4)
|
||||
assert.NoError(t, err)
|
||||
err = deleteIssue(issue)
|
||||
err = deleteIssue(db.DefaultContext, issue)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 2, len(attachments))
|
||||
for i := range attachments {
|
||||
@@ -78,7 +78,7 @@ func TestIssue_DeleteIssue(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, left)
|
||||
|
||||
err = deleteIssue(issue2)
|
||||
err = deleteIssue(db.DefaultContext, issue2)
|
||||
assert.NoError(t, err)
|
||||
left, err = issues_model.IssueNoDependenciesLeft(db.DefaultContext, issue1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -90,7 +90,7 @@ func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *iss
|
||||
|
||||
ops.Content = string(dataJSON)
|
||||
|
||||
comment, err = issue_service.CreateComment(ops)
|
||||
comment, err = issue_service.CreateComment(ctx, ops)
|
||||
|
||||
return comment, err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu
|
||||
}
|
||||
|
||||
for _, assigneeID := range assigneeIDs {
|
||||
if err := issue_service.AddAssigneeIfNotAssigned(pull, pull.Poster, assigneeID); err != nil {
|
||||
if err := issue_service.AddAssigneeIfNotAssigned(ctx, pull, pull.Poster, assigneeID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu
|
||||
Content: string(dataJSON),
|
||||
}
|
||||
|
||||
_, _ = issue_service.CreateComment(ops)
|
||||
_, _ = issue_service.CreateComment(ctx, ops)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -221,7 +221,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
|
||||
OldRef: oldBranch,
|
||||
NewRef: targetBranch,
|
||||
}
|
||||
if _, err = issue_service.CreateComment(options); err != nil {
|
||||
if _, err = issue_service.CreateComment(ctx, options); err != nil {
|
||||
return fmt.Errorf("CreateChangeTargetBranchComment: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return issue_service.CreateComment(&issues_model.CreateCommentOptions{
|
||||
return issue_service.CreateComment(ctx, &issues_model.CreateCommentOptions{
|
||||
Type: issues_model.CommentTypeCode,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
@@ -368,7 +368,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
||||
return
|
||||
}
|
||||
|
||||
comment, err = issue_service.CreateComment(&issues_model.CreateCommentOptions{
|
||||
comment, err = issue_service.CreateComment(ctx, &issues_model.CreateCommentOptions{
|
||||
Doer: doer,
|
||||
Content: message,
|
||||
Type: issues_model.CommentTypeDismissReview,
|
||||
|
||||
@@ -1,12 +1,51 @@
|
||||
{{template "base/head" .}}
|
||||
<div class="page-content devtest">
|
||||
<div class="page-content devtest ui container">
|
||||
|
||||
<div>
|
||||
<gitea-origin-url data-url="test/url"></gitea-origin-url>
|
||||
<gitea-origin-url data-url="/test/url"></gitea-origin-url>
|
||||
<h1>Tooltip</h1>
|
||||
<div><span data-tooltip-content="test tooltip">text with tooltip</span></div>
|
||||
<div><span data-tooltip-content="test tooltip" data-tooltip-interactive="true">text with interactive tooltip</span></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span data-tooltip-content="test tooltip">text with tooltip</span>
|
||||
<h1>GiteaOriginUrl</h1>
|
||||
<div><gitea-origin-url data-url="test/url"></gitea-origin-url></div>
|
||||
<div><gitea-origin-url data-url="/test/url"></gitea-origin-url></div>
|
||||
</div>
|
||||
{{template "shared/combomarkdowneditor" .}}
|
||||
|
||||
<div>
|
||||
<h1>LocaleNumber</h1>
|
||||
<div>{{.locale.PrettyNumber 1}}</div>
|
||||
<div>{{.locale.PrettyNumber 12}}</div>
|
||||
<div>{{.locale.PrettyNumber 123}}</div>
|
||||
<div>{{.locale.PrettyNumber 1234}}</div>
|
||||
<div>{{.locale.PrettyNumber 12345}}</div>
|
||||
<div>{{.locale.PrettyNumber 123456}}</div>
|
||||
<div>{{.locale.PrettyNumber 1234567}}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>TimeSince</h1>
|
||||
<div>Now: {{TimeSince .TimeNow $.locale}}</div>
|
||||
<div>5s past: {{TimeSince .TimePast5s $.locale}}</div>
|
||||
<div>5s future: {{TimeSince .TimeFuture5s $.locale}}</div>
|
||||
<div>2m past: {{TimeSince .TimePast2m $.locale}}</div>
|
||||
<div>2m future: {{TimeSince .TimeFuture2m $.locale}}</div>
|
||||
<div>1y past: {{TimeSince .TimePast1y $.locale}}</div>
|
||||
<div>1y future: {{TimeSince .TimeFuture1y $.locale}}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>ComboMarkdownEditor</h1>
|
||||
<div>ps: no JS code attached, so just a layout</div>
|
||||
{{template "shared/combomarkdowneditor" .}}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
||||
@@ -84,9 +84,9 @@
|
||||
<a class="ui right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{.locale.Tr "packages.versions.view_all"}}</a>
|
||||
<div class="ui relaxed list">
|
||||
{{range .LatestVersions}}
|
||||
<div class="item">
|
||||
<a href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
|
||||
<span class="text small">{{$.locale.Tr "on_date"}} {{.CreatedUnix.FormatDate}}</span>
|
||||
<div class="item gt-df">
|
||||
<a class="gt-f1" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
|
||||
<span class="text small">{{template "shared/datetime/short" (dict "Datetime" (.CreatedUnix.FormatDate) "Fallback" (.CreatedUnix.FormatDate))}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
<div class="ui compact tiny menu">
|
||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
|
||||
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
{{end}}
|
||||
<span class="issue-stats">
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{$.locale.PrettyNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{$.locale.PrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
</span>
|
||||
</div>
|
||||
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
<div class="ui compact tiny menu">
|
||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/milestones?state=open&q={{$.Keyword}}">
|
||||
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/milestones?state=closed&q={{$.Keyword}}">
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,9 +84,9 @@
|
||||
{{end}}
|
||||
<span class="issue-stats">
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{$.locale.PrettyNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{$.locale.PrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{if .TotalTrackedTime}}{{svg "octicon-clock"}} {{.TotalTrackedTime|Sec2Time}}{{end}}
|
||||
{{if .UpdatedUnix}}{{svg "octicon-clock"}} {{$.locale.Tr "repo.milestones.update_ago" (TimeSinceUnix .UpdatedUnix $.locale) | Safe}}{{end}}
|
||||
</span>
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
{{else}}
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{end}}
|
||||
{{LocaleNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="{{if .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&project={{.ProjectID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
<div class="ui compact tiny menu">
|
||||
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=open">
|
||||
{{svg "octicon-project" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=closed">
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
{{end}}
|
||||
<span class="issue-stats">
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
</span>
|
||||
</div>
|
||||
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||
|
||||
@@ -161,9 +161,9 @@
|
||||
<li>
|
||||
<span class="ui text middle aligned right">
|
||||
<span class="ui text grey">{{.Size | FileSize}}</span>
|
||||
<gitea-locale-number data-number-in-tooltip="{{dict "message" ($.locale.Tr "repo.release.download_count") "number" .DownloadCount | Json}}">
|
||||
<span data-tooltip-content="{{$.locale.Tr "repo.release.download_count" ($.locale.PrettyNumber .DownloadCount)}}">
|
||||
{{svg "octicon-info"}}
|
||||
</gitea-locale-number>
|
||||
</span>
|
||||
</span>
|
||||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
|
||||
<strong>{{svg "octicon-package" 16 "gt-mr-2"}}{{.Name}}</strong>
|
||||
|
||||
@@ -71,9 +71,9 @@
|
||||
<input name="attachment-edit-{{.UUID}}" class="gt-mr-3 attachment_edit" required value="{{.Name}}">
|
||||
<input name="attachment-del-{{.UUID}}" type="hidden" value="false">
|
||||
<span class="ui text grey gt-mr-3">{{.Size | FileSize}}</span>
|
||||
<gitea-locale-number data-number-in-tooltip="{{dict "message" ($.locale.Tr "repo.release.download_count") "number" .DownloadCount | Json}}">
|
||||
<span data-tooltip-content="{{$.locale.Tr "repo.release.download_count" ($.locale.PrettyNumber .DownloadCount)}}">
|
||||
{{svg "octicon-info"}}
|
||||
</gitea-locale-number>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="ui two horizontal center list">
|
||||
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}}
|
||||
<div class="item{{if .PageIsCommits}} active{{end}}">
|
||||
<a href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">{{svg "octicon-history"}} <b>{{LocaleNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}</a>
|
||||
<a href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">{{svg "octicon-history"}} <b>{{.locale.PrettyNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}</a>
|
||||
</div>
|
||||
<div class="item{{if .PageIsBranches}} active{{end}}">
|
||||
<a href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}</a>
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
<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}}">
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .IssueStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.Link}}?type={{$.ViewType}}&repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=closed&q={{$.Keyword}}">
|
||||
{{svg "octicon-issue-closed" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .IssueStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
<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}}">
|
||||
{{svg "octicon-milestone" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .MilestoneStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .MilestoneStats.OpenCount}} {{.locale.Tr "repo.issues.open_title"}}
|
||||
</a>
|
||||
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=closed&q={{$.Keyword}}">
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .MilestoneStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .MilestoneStats.ClosedCount}} {{.locale.Tr "repo.issues.closed_title"}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -104,9 +104,9 @@
|
||||
{{end}}
|
||||
<span class="issue-stats">
|
||||
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{.locale.PrettyNumber .NumOpenIssues}} {{$.locale.Tr "repo.issues.open_title"}}
|
||||
{{svg "octicon-check" 16 "gt-mr-3"}}
|
||||
{{LocaleNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{.locale.PrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
{{if .TotalTrackedTime}}
|
||||
{{svg "octicon-clock"}} {{.TotalTrackedTime|Sec2Time}}
|
||||
{{end}}
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestAPIMergePullWIP(t *testing.T) {
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Status: issues_model.PullRequestStatusMergeable}, unittest.Cond("has_merged = ?", false))
|
||||
pr.LoadIssue(db.DefaultContext)
|
||||
issue_service.ChangeTitle(pr.Issue, owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title)
|
||||
issue_service.ChangeTitle(db.DefaultContext, pr.Issue, owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title)
|
||||
|
||||
// force reload
|
||||
pr.LoadAttributes(db.DefaultContext)
|
||||
|
||||
@@ -44,6 +44,31 @@
|
||||
max-height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
/* use the same styles as markup/content.css */
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-4 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-5 {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.combo-markdown-editor .CodeMirror-scroll .cm-header-6 {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
text-expander {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
@@ -11,7 +11,7 @@ export function initCompSearchUserBox() {
|
||||
$searchUserBox.search({
|
||||
minCharacters: 2,
|
||||
apiSettings: {
|
||||
url: `${appSubUrl}/user/search?q={query}`,
|
||||
url: `${appSubUrl}/user/search?active=1&q={query}`,
|
||||
onResponse(response) {
|
||||
const items = [];
|
||||
const searchQuery = $searchUserBox.find('input').val();
|
||||
|
||||
@@ -41,6 +41,7 @@ export function initRepoTopicBar() {
|
||||
viewDiv.children('.topic').remove();
|
||||
if (topics.length) {
|
||||
const topicArray = topics.split(',');
|
||||
topicArray.sort();
|
||||
for (let i = 0; i < topicArray.length; i++) {
|
||||
const link = $('<a class="ui repo-topic large label topic"></a>');
|
||||
link.attr('href', `${appSubUrl}/explore/repos?q=${encodeURIComponent(topicArray[i])}&topic=1`);
|
||||
@@ -57,12 +58,12 @@ export function initRepoTopicBar() {
|
||||
topicPrompts.formatPrompt = xhr.responseJSON.message;
|
||||
|
||||
const {invalidTopics} = xhr.responseJSON;
|
||||
const topicLables = topicDropdown.children('a.ui.label');
|
||||
const topicLabels = topicDropdown.children('a.ui.label');
|
||||
|
||||
for (const [index, value] of topics.split(',').entries()) {
|
||||
for (let i = 0; i < invalidTopics.length; i++) {
|
||||
if (invalidTopics[i] === value) {
|
||||
topicLables.eq(index).removeClass('green').addClass('red');
|
||||
topicLabels.eq(index).removeClass('green').addClass('red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,8 +148,8 @@ function attachInit($dropdown) {
|
||||
// Since #19861 we have prepared the "combobox" solution, but didn't get enough time to put it into practice and test before.
|
||||
const isComboBox = $dropdown.find('input').length > 0;
|
||||
|
||||
dropdown[ariaPatchKey].focusableRole = isComboBox ? 'combobox' : 'button';
|
||||
dropdown[ariaPatchKey].listPopupRole = isComboBox ? 'listbox' : 'menu';
|
||||
dropdown[ariaPatchKey].focusableRole = isComboBox ? 'combobox' : 'menu';
|
||||
dropdown[ariaPatchKey].listPopupRole = isComboBox ? 'listbox' : '';
|
||||
dropdown[ariaPatchKey].listItemRole = isComboBox ? 'option' : 'menuitem';
|
||||
|
||||
attachDomEvents($dropdown, $focusable, $menu);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Convert a number to a locale string by data-number attribute.
|
||||
// Or add a tooltip by data-number-in-tooltip attribute. JSON: {message: "count: %s", number: 123}
|
||||
window.customElements.define('gitea-locale-number', class extends HTMLElement {
|
||||
connectedCallback() {
|
||||
// ideally, the number locale formatting and plural processing should be done by backend with translation strings.
|
||||
// if we have complete backend locale support (eg: Golang "x/text" package), we can drop this component.
|
||||
const number = this.getAttribute('data-number');
|
||||
if (number) {
|
||||
this.attachShadow({mode: 'open'});
|
||||
this.shadowRoot.textContent = new Intl.NumberFormat().format(Number(number));
|
||||
}
|
||||
const numberInTooltip = this.getAttribute('data-number-in-tooltip');
|
||||
if (numberInTooltip) {
|
||||
// TODO: only 2 usages of this, we can replace it with Golang's "x/text/number" package in the future
|
||||
const {message, number} = JSON.parse(numberInTooltip);
|
||||
const tooltipContent = message.replace(/%[ds]/, new Intl.NumberFormat().format(Number(number)));
|
||||
this.setAttribute('data-tooltip-content', tooltipContent);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,4 +1,3 @@
|
||||
import '@webcomponents/custom-elements'; // polyfill for some browsers like Pale Moon
|
||||
import '@github/relative-time-element';
|
||||
import './GiteaLocaleNumber.js';
|
||||
import './GiteaOriginUrl.js';
|
||||
|
||||
Reference in New Issue
Block a user