Merge remote-tracking branch 'upstream/main' into limit-repo-size

This commit is contained in:
DmitryFrolovTri
2023-04-17 06:56:38 +00:00
78 changed files with 432 additions and 302 deletions
+2 -2
View File
@@ -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
}
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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
}
+1 -1
View File
@@ -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)
+2
View File
@@ -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),
}
+49
View File
@@ -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()
}
+3 -1
View File
@@ -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
}
+3 -11
View File
@@ -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
View File
@@ -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 {
+4 -2
View File
@@ -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),
-7
View File
@@ -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.
//
+2 -15
View File
@@ -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
+17 -3
View File
@@ -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
+27
View File
@@ -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)
}
+25 -5
View File
@@ -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))
}
+27
View File
@@ -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))
}
-3
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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 δευτερόλεπτο
-4
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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=۱ ثانیه
-3
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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
-2
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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秒
-3
View File
@@ -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 초
-3
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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ę
-3
View File
@@ -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
+2 -4
View File
@@ -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
+66 -18
View File
@@ -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, выполните следующую команду:
-3
View File
@@ -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
-1
View File
@@ -106,7 +106,6 @@ never=Nikdy
rss_feed=RSS kanál
[aria]
[editor]
-3
View File
@@ -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
-3
View File
@@ -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
-3
View File
@@ -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 секунда
-3
View File
@@ -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 秒
-3
View File
@@ -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 秒
+4 -3
View File
@@ -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 秒
+4 -4
View File
@@ -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
}
+1 -1
View File
@@ -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))
+2 -2
View File
@@ -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
+10
View File
@@ -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"))))
}
+1 -6
View File
@@ -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) {
+5 -1
View File
@@ -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
}
+8 -8
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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))
+4 -4
View File
@@ -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
View File
@@ -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
}
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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
}
+3 -3
View File
@@ -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)
}
+2 -2
View File
@@ -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,
+44 -5
View File
@@ -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" .}}
+3 -3
View File
@@ -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>
+4 -4
View File
@@ -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}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.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}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{$.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{svg "octicon-check" 16 "gt-mr-3"}}
{{LocaleNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
{{$.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
</span>
</div>
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
+4 -4
View File
@@ -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}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.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}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{$.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{svg "octicon-check" 16 "gt-mr-3"}}
{{LocaleNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
{{$.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.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>
+2 -2
View File
@@ -5,10 +5,10 @@
{{else}}
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
{{end}}
{{LocaleNumber .IssueStats.OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
</div>
+4 -4
View File
@@ -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}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.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}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{svg "octicon-check" 16 "gt-mr-3"}}
{{LocaleNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
</span>
</div>
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
+2 -2
View File
@@ -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>
+2 -2
View File
@@ -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}}
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
</div>
</div>
+4 -4
View File
@@ -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}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .MilestoneStats.OpenCount}}&nbsp;{{.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}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .MilestoneStats.ClosedCount}}&nbsp;{{.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}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{.locale.PrettyNumber .NumOpenIssues}}&nbsp;{{$.locale.Tr "repo.issues.open_title"}}
{{svg "octicon-check" 16 "gt-mr-3"}}
{{LocaleNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
{{.locale.PrettyNumber .NumClosedIssues}}&nbsp;{{$.locale.Tr "repo.issues.closed_title"}}
{{if .TotalTrackedTime}}
{{svg "octicon-clock"}} {{.TotalTrackedTime|Sec2Time}}
{{end}}
+1 -1
View File
@@ -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)
+25
View File
@@ -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;
+1 -1
View File
@@ -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();
+3 -2
View File
@@ -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');
}
}
}
+2 -2
View File
@@ -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';