Compare commits

..

No commits in common. "b0f18726a34edeb47b6442ce06ebee102b9c8a83" and "1cb8d14bf71e0b8637c9eaa10808b4fd05139f45" have entirely different histories.

45 changed files with 86 additions and 326 deletions

View File

@ -28,7 +28,7 @@ linters:
fast: false fast: false
run: run:
go: "1.20" go: 1.20
timeout: 10m timeout: 10m
skip-dirs: skip-dirs:
- node_modules - node_modules

View File

@ -37,9 +37,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
} }
schemaValue, _ := driver.String.ConvertValue(setting.Database.Schema) schemaValue, _ := driver.String.ConvertValue(setting.Database.Schema)
// golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here if execer, ok := conn.(driver.Execer); ok {
// and in any case pq does not implement it
if execer, ok := conn.(driver.Execer); ok { //nolint
_, err := execer.Exec(`SELECT set_config( _, err := execer.Exec(`SELECT set_config(
'search_path', 'search_path',
$1 || ',' || current_setting('search_path'), $1 || ',' || current_setting('search_path'),
@ -63,8 +61,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
// driver.String.ConvertValue will never return err for string // driver.String.ConvertValue will never return err for string
// golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here _, err = stmt.Exec([]driver.Value{schemaValue})
_, err = stmt.Exec([]driver.Value{schemaValue}) //nolint
if err != nil { if err != nil {
_ = conn.Close() _ = conn.Close()
return nil, err return nil, err

View File

@ -455,8 +455,6 @@ var migrations = []Migration{
NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens), NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens),
// v240 -> v241 // v240 -> v241
NewMigration("Add actions tables", v1_19.AddActionsTables), NewMigration("Add actions tables", v1_19.AddActionsTables),
// v241 -> v242
NewMigration("Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
} }
// GetCurrentDBVersion returns the current db version // GetCurrentDBVersion returns the current db version

View File

@ -1,17 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_19 //nolint
import (
"xorm.io/xorm"
)
// AddCardTypeToProjectTable: add CardType column, setting existing rows to CardTypeTextOnly
func AddCardTypeToProjectTable(x *xorm.Engine) error {
type Project struct {
CardType int `xorm:"NOT NULL DEFAULT 0"`
}
return x.Sync(new(Project))
}

View File

@ -19,9 +19,6 @@ type (
// BoardType is used to represent a project board type // BoardType is used to represent a project board type
BoardType uint8 BoardType uint8
// CardType is used to represent a project board card type
CardType uint8
// BoardList is a list of all project boards in a repository // BoardList is a list of all project boards in a repository
BoardList []*Board BoardList []*Board
) )
@ -37,14 +34,6 @@ const (
BoardTypeBugTriage BoardTypeBugTriage
) )
const (
// CardTypeTextOnly is a project board card type that is text only
CardTypeTextOnly CardType = iota
// CardTypeImagesAndText is a project board card type that has images and text
CardTypeImagesAndText
)
// BoardColorPattern is a regexp witch can validate BoardColor // BoardColorPattern is a regexp witch can validate BoardColor
var BoardColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$") var BoardColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$")
@ -96,16 +85,6 @@ func IsBoardTypeValid(p BoardType) bool {
} }
} }
// IsCardTypeValid checks if the project board card type is valid
func IsCardTypeValid(p CardType) bool {
switch p {
case CardTypeTextOnly, CardTypeImagesAndText:
return true
default:
return false
}
}
func createBoardsForProjectsType(ctx context.Context, project *Project) error { func createBoardsForProjectsType(ctx context.Context, project *Project) error {
var items []string var items []string

View File

@ -19,18 +19,12 @@ import (
) )
type ( type (
// BoardConfig is used to identify the type of board that is being created // ProjectsConfig is used to identify the type of board that is being created
BoardConfig struct { ProjectsConfig struct {
BoardType BoardType BoardType BoardType
Translation string Translation string
} }
// CardConfig is used to identify the type of board card that is being used
CardConfig struct {
CardType CardType
Translation string
}
// Type is used to identify the type of project in question and ownership // Type is used to identify the type of project in question and ownership
Type uint8 Type uint8
) )
@ -97,7 +91,6 @@ type Project struct {
CreatorID int64 `xorm:"NOT NULL"` CreatorID int64 `xorm:"NOT NULL"`
IsClosed bool `xorm:"INDEX"` IsClosed bool `xorm:"INDEX"`
BoardType BoardType BoardType BoardType
CardType CardType
Type Type Type Type
RenderedContent string `xorm:"-"` RenderedContent string `xorm:"-"`
@ -152,23 +145,15 @@ func init() {
db.RegisterModel(new(Project)) db.RegisterModel(new(Project))
} }
// GetBoardConfig retrieves the types of configurations project boards could have // GetProjectsConfig retrieves the types of configurations projects could have
func GetBoardConfig() []BoardConfig { func GetProjectsConfig() []ProjectsConfig {
return []BoardConfig{ return []ProjectsConfig{
{BoardTypeNone, "repo.projects.type.none"}, {BoardTypeNone, "repo.projects.type.none"},
{BoardTypeBasicKanban, "repo.projects.type.basic_kanban"}, {BoardTypeBasicKanban, "repo.projects.type.basic_kanban"},
{BoardTypeBugTriage, "repo.projects.type.bug_triage"}, {BoardTypeBugTriage, "repo.projects.type.bug_triage"},
} }
} }
// GetCardConfig retrieves the types of configurations project board cards could have
func GetCardConfig() []CardConfig {
return []CardConfig{
{CardTypeTextOnly, "repo.projects.card_type.text_only"},
{CardTypeImagesAndText, "repo.projects.card_type.images_and_text"},
}
}
// IsTypeValid checks if a project type is valid // IsTypeValid checks if a project type is valid
func IsTypeValid(p Type) bool { func IsTypeValid(p Type) bool {
switch p { switch p {
@ -252,10 +237,6 @@ func NewProject(p *Project) error {
p.BoardType = BoardTypeNone p.BoardType = BoardTypeNone
} }
if !IsCardTypeValid(p.CardType) {
p.CardType = CardTypeTextOnly
}
if !IsTypeValid(p.Type) { if !IsTypeValid(p.Type) {
return util.NewInvalidArgumentErrorf("project type is not valid") return util.NewInvalidArgumentErrorf("project type is not valid")
} }
@ -299,14 +280,9 @@ func GetProjectByID(ctx context.Context, id int64) (*Project, error) {
// UpdateProject updates project properties // UpdateProject updates project properties
func UpdateProject(ctx context.Context, p *Project) error { func UpdateProject(ctx context.Context, p *Project) error {
if !IsCardTypeValid(p.CardType) {
p.CardType = CardTypeTextOnly
}
_, err := db.GetEngine(ctx).ID(p.ID).Cols( _, err := db.GetEngine(ctx).ID(p.ID).Cols(
"title", "title",
"description", "description",
"card_type",
).Update(p) ).Update(p)
return err return err
} }

View File

@ -53,7 +53,6 @@ func TestProject(t *testing.T) {
project := &Project{ project := &Project{
Type: TypeRepository, Type: TypeRepository,
BoardType: BoardTypeBasicKanban, BoardType: BoardTypeBasicKanban,
CardType: CardTypeTextOnly,
Title: "New Project", Title: "New Project",
RepoID: 1, RepoID: 1,
CreatedUnix: timeutil.TimeStampNow(), CreatedUnix: timeutil.TimeStampNow(),

View File

@ -132,21 +132,6 @@ func GetAttachmentsByIssueID(ctx context.Context, issueID int64) ([]*Attachment,
return attachments, db.GetEngine(ctx).Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments) return attachments, db.GetEngine(ctx).Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
} }
// GetAttachmentsByIssueIDImagesLatest returns the latest image attachments of an issue.
func GetAttachmentsByIssueIDImagesLatest(ctx context.Context, issueID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 5)
return attachments, db.GetEngine(ctx).Where(`issue_id = ? AND (name like '%.apng'
OR name like '%.avif'
OR name like '%.bmp'
OR name like '%.gif'
OR name like '%.jpg'
OR name like '%.jpeg'
OR name like '%.jxl'
OR name like '%.png'
OR name like '%.svg'
OR name like '%.webp')`, issueID).Desc("comment_id").Limit(5).Find(&attachments)
}
// GetAttachmentsByCommentID returns all attachments if comment by given ID. // GetAttachmentsByCommentID returns all attachments if comment by given ID.
func GetAttachmentsByCommentID(ctx context.Context, commentID int64) ([]*Attachment, error) { func GetAttachmentsByCommentID(ctx context.Context, commentID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10) attachments := make([]*Attachment, 0, 10)

View File

@ -274,7 +274,7 @@ func (repo *Repository) CommitLink(commitID string) (result string) {
if commitID == "" || commitID == "0000000000000000000000000000000000000000" { if commitID == "" || commitID == "0000000000000000000000000000000000000000" {
result = "" result = ""
} else { } else {
result = repo.Link() + "/commit/" + url.PathEscape(commitID) result = repo.HTMLURL() + "/commit/" + url.PathEscape(commitID)
} }
return result return result
} }

View File

@ -743,9 +743,9 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if ctx.FormString("go-get") == "1" { if ctx.FormString("go-get") == "1" {
ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name) ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name)
fullURLPrefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName) prefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}" ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}" ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
} }
return cancel return cancel
} }

View File

@ -4,6 +4,7 @@
package lfs package lfs
import ( import (
"fmt"
"net/url" "net/url"
"os" "os"
"path" "path"
@ -11,7 +12,6 @@ import (
"strings" "strings"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
) )
// DetermineEndpoint determines an endpoint from the clone url or uses the specified LFS url. // DetermineEndpoint determines an endpoint from the clone url or uses the specified LFS url.
@ -95,7 +95,7 @@ func endpointFromLocalPath(path string) *url.URL {
return nil return nil
} }
path = "file://" + slash + util.PathEscapeSegments(filepath.ToSlash(path)) path = fmt.Sprintf("file://%s%s", slash, filepath.ToSlash(path))
u, _ := url.Parse(path) u, _ := url.Parse(path)

View File

@ -1231,9 +1231,6 @@ projects.board.color = "Color"
projects.open = Open projects.open = Open
projects.close = Close projects.close = Close
projects.board.assigned_to = Assigned to projects.board.assigned_to = Assigned to
projects.card_type.desc = "Card Previews"
projects.card_type.images_and_text = "Images and Text"
projects.card_type.text_only = "Text Only"
issues.desc = Organize bug reports, tasks and milestones. issues.desc = Organize bug reports, tasks and milestones.
issues.filter_assignees = Filter Assignee issues.filter_assignees = Filter Assignee

View File

@ -286,18 +286,9 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
r.Get("/symbols/{filename}/{guid:[0-9a-fA-F]{32}[fF]{8}}/{filename2}", nuget.DownloadSymbolFile) r.Get("/symbols/{filename}/{guid:[0-9a-fA-F]{32}[fF]{8}}/{filename2}", nuget.DownloadSymbolFile)
r.Get("/Packages(Id='{id:[^']+}',Version='{version:[^']+}')", nuget.RegistrationLeafV2) r.Get("/Packages(Id='{id:[^']+}',Version='{version:[^']+}')", nuget.RegistrationLeafV2)
r.Group("/Packages()", func() { r.Get("/Packages()", nuget.SearchServiceV2)
r.Get("", nuget.SearchServiceV2) r.Get("/FindPackagesById()", nuget.EnumeratePackageVersionsV2)
r.Get("/$count", nuget.SearchServiceV2Count) r.Get("/Search()", nuget.SearchServiceV2)
})
r.Group("/FindPackagesById()", func() {
r.Get("", nuget.EnumeratePackageVersionsV2)
r.Get("/$count", nuget.EnumeratePackageVersionsV2Count)
})
r.Group("/Search()", func() {
r.Get("", nuget.SearchServiceV2)
r.Get("/$count", nuget.SearchServiceV2Count)
})
}, reqPackageAccess(perm.AccessModeRead)) }, reqPackageAccess(perm.AccessModeRead))
}) })
r.Group("/npm", func() { r.Group("/npm", func() {

View File

@ -10,7 +10,6 @@ import (
"io" "io"
"net/http" "net/http"
"regexp" "regexp"
"strconv"
"strings" "strings"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -95,7 +94,8 @@ func FeedCapabilityResource(ctx *context.Context) {
var searchTermExtract = regexp.MustCompile(`'([^']+)'`) var searchTermExtract = regexp.MustCompile(`'([^']+)'`)
func getSearchTerm(ctx *context.Context) string { // https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs
func SearchServiceV2(ctx *context.Context) {
searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'") searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'")
if searchTerm == "" { if searchTerm == "" {
// $filter contains a query like: // $filter contains a query like:
@ -106,11 +106,7 @@ func getSearchTerm(ctx *context.Context) string {
searchTerm = strings.TrimSpace(match[1]) searchTerm = strings.TrimSpace(match[1])
} }
} }
return searchTerm
}
// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs
func SearchServiceV2(ctx *context.Context) {
skip, take := ctx.FormInt("skip"), ctx.FormInt("take") skip, take := ctx.FormInt("skip"), ctx.FormInt("take")
if skip == 0 { if skip == 0 {
skip = ctx.FormInt("$skip") skip = ctx.FormInt("$skip")
@ -120,11 +116,9 @@ func SearchServiceV2(ctx *context.Context) {
} }
pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNuGet, Type: packages_model.TypeNuGet,
Name: packages_model.SearchValue{ Name: packages_model.SearchValue{Value: searchTerm},
Value: getSearchTerm(ctx),
},
IsInternal: util.OptionalBoolFalse, IsInternal: util.OptionalBoolFalse,
Paginator: db.NewAbsoluteListOptions( Paginator: db.NewAbsoluteListOptions(
skip, skip,
@ -151,24 +145,6 @@ func SearchServiceV2(ctx *context.Context) {
xmlResponse(ctx, http.StatusOK, resp) xmlResponse(ctx, http.StatusOK, resp)
} }
// http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351
func SearchServiceV2Count(ctx *context.Context) {
count, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNuGet,
Name: packages_model.SearchValue{
Value: getSearchTerm(ctx),
},
IsInternal: util.OptionalBoolFalse,
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
ctx.PlainText(http.StatusOK, strconv.FormatInt(count, 10))
}
// https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-for-packages // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-for-packages
func SearchServiceV3(ctx *context.Context) { func SearchServiceV3(ctx *context.Context) {
pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
@ -312,25 +288,6 @@ func EnumeratePackageVersionsV2(ctx *context.Context) {
xmlResponse(ctx, http.StatusOK, resp) xmlResponse(ctx, http.StatusOK, resp)
} }
// http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351
func EnumeratePackageVersionsV2Count(ctx *context.Context) {
count, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNuGet,
Name: packages_model.SearchValue{
ExactMatch: true,
Value: strings.Trim(ctx.FormTrim("id"), "'"),
},
IsInternal: util.OptionalBoolFalse,
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
ctx.PlainText(http.StatusOK, strconv.FormatInt(count, 10))
}
// https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource#enumerate-package-versions // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource#enumerate-package-versions
func EnumeratePackageVersionsV3(ctx *context.Context) { func EnumeratePackageVersionsV3(ctx *context.Context) {
packageName := ctx.Params("id") packageName := ctx.Params("id")

View File

@ -121,7 +121,7 @@ func canWriteUnit(ctx *context.Context) bool {
// NewProject render creating a project page // NewProject render creating a project page
func NewProject(ctx *context.Context) { func NewProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.new") ctx.Data["Title"] = ctx.Tr("repo.projects.new")
ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig()
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx) ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink() ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
shared_user.RenderUserHeader(ctx) shared_user.RenderUserHeader(ctx)
@ -137,7 +137,7 @@ func NewProjectPost(ctx *context.Context) {
if ctx.HasError() { if ctx.HasError() {
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx) ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["PageIsViewProjects"] = true ctx.Data["PageIsViewProjects"] = true
ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig()
ctx.HTML(http.StatusOK, tplProjectsNew) ctx.HTML(http.StatusOK, tplProjectsNew)
return return
} }

View File

@ -70,7 +70,7 @@ func List(ctx *context.Context) {
} }
ctx.Data["workflows"] = workflows ctx.Data["workflows"] = workflows
ctx.Data["RepoLink"] = ctx.Repo.Repository.Link() ctx.Data["RepoLink"] = ctx.Repo.Repository.HTMLURL()
page := ctx.FormInt("page") page := ctx.FormInt("page")
if page <= 0 { if page <= 0 {

View File

@ -100,7 +100,7 @@ func MustAllowUserComment(ctx *context.Context) {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin { if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked")) ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }
} }
@ -927,7 +927,7 @@ func NewIssueChooseTemplate(ctx *context.Context) {
if len(issueTemplates) == 0 { if len(issueTemplates) == 0 {
// The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters. // The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters.
ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.Link(), ctx.Req.URL.RawQuery), http.StatusSeeOther) ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.HTMLURL(), ctx.Req.URL.RawQuery), http.StatusSeeOther)
return return
} }
@ -950,11 +950,11 @@ func DeleteIssue(ctx *context.Context) {
} }
if issue.IsPull { if issue.IsPull {
ctx.Redirect(fmt.Sprintf("%s/pulls", ctx.Repo.Repository.Link()), http.StatusSeeOther) ctx.Redirect(fmt.Sprintf("%s/pulls", ctx.Repo.Repository.HTMLURL()), http.StatusSeeOther)
return return
} }
ctx.Redirect(fmt.Sprintf("%s/issues", ctx.Repo.Repository.Link()), http.StatusSeeOther) ctx.Redirect(fmt.Sprintf("%s/issues", ctx.Repo.Repository.HTMLURL()), http.StatusSeeOther)
} }
// ValidateRepoMetas check and returns repository's meta information // ValidateRepoMetas check and returns repository's meta information
@ -1425,7 +1425,7 @@ func ViewIssue(ctx *context.Context) {
return return
} }
// Add link to the issue of the already running stopwatch // Add link to the issue of the already running stopwatch
ctx.Data["OtherStopwatchURL"] = otherIssue.Link() ctx.Data["OtherStopwatchURL"] = otherIssue.HTMLURL()
} }
} }
ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.Doer) ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.Doer)
@ -2658,7 +2658,7 @@ func NewComment(ctx *context.Context) {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin { if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked")) ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }
@ -2669,7 +2669,7 @@ func NewComment(ctx *context.Context) {
if ctx.HasError() { if ctx.HasError() {
ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) ctx.Flash.Error(ctx.Data["ErrorMsg"].(string))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }

View File

@ -34,7 +34,7 @@ func AddDependency(ctx *context.Context) {
} }
// Redirect // Redirect
defer ctx.Redirect(issue.Link()) defer ctx.Redirect(issue.HTMLURL())
// Dependency // Dependency
dep, err := issues_model.GetIssueByID(ctx, depID) dep, err := issues_model.GetIssueByID(ctx, depID)
@ -124,5 +124,5 @@ func RemoveDependency(ctx *context.Context) {
} }
// Redirect // Redirect
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
} }

View File

@ -21,13 +21,13 @@ func LockIssue(ctx *context.Context) {
if issue.IsLocked { if issue.IsLocked {
ctx.Flash.Error(ctx.Tr("repo.issues.lock_duplicate")) ctx.Flash.Error(ctx.Tr("repo.issues.lock_duplicate"))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }
if !form.HasValidReason() { if !form.HasValidReason() {
ctx.Flash.Error(ctx.Tr("repo.issues.lock.unknown_reason")) ctx.Flash.Error(ctx.Tr("repo.issues.lock.unknown_reason"))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }
@ -40,7 +40,7 @@ func LockIssue(ctx *context.Context) {
return return
} }
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
} }
// UnlockIssue unlocks a previously locked issue. // UnlockIssue unlocks a previously locked issue.
@ -52,7 +52,7 @@ func UnlockIssue(ctx *context.Context) {
if !issue.IsLocked { if !issue.IsLocked {
ctx.Flash.Error(ctx.Tr("repo.issues.unlock_error")) ctx.Flash.Error(ctx.Tr("repo.issues.unlock_error"))
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
return return
} }
@ -64,5 +64,5 @@ func UnlockIssue(ctx *context.Context) {
return return
} }
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
} }

View File

@ -40,7 +40,7 @@ func IssueStopwatch(c *context.Context) {
c.Flash.Success(c.Tr("repo.issues.tracker_auto_close")) c.Flash.Success(c.Tr("repo.issues.tracker_auto_close"))
} }
url := issue.Link() url := issue.HTMLURL()
c.Redirect(url, http.StatusSeeOther) c.Redirect(url, http.StatusSeeOther)
} }
@ -72,7 +72,7 @@ func CancelStopwatch(c *context.Context) {
}) })
} }
url := issue.Link() url := issue.HTMLURL()
c.Redirect(url, http.StatusSeeOther) c.Redirect(url, http.StatusSeeOther)
} }

View File

@ -26,7 +26,7 @@ func AddTimeManually(c *context.Context) {
c.NotFound("CanUseTimetracker", nil) c.NotFound("CanUseTimetracker", nil)
return return
} }
url := issue.Link() url := issue.HTMLURL()
if c.HasError() { if c.HasError() {
c.Flash.Error(c.GetErrMsg()) c.Flash.Error(c.GetErrMsg())
@ -83,5 +83,5 @@ func DeleteTime(c *context.Context) {
} }
c.Flash.Success(c.Tr("repo.issues.del_time_history", util.SecToTime(t.Time))) c.Flash.Success(c.Tr("repo.issues.del_time_history", util.SecToTime(t.Time)))
c.Redirect(issue.Link()) c.Redirect(issue.HTMLURL())
} }

View File

@ -52,5 +52,5 @@ func IssueWatch(ctx *context.Context) {
return return
} }
ctx.Redirect(issue.Link()) ctx.Redirect(issue.HTMLURL())
} }

View File

@ -13,7 +13,6 @@ import (
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
project_model "code.gitea.io/gitea/models/project" project_model "code.gitea.io/gitea/models/project"
attachment_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
@ -124,8 +123,7 @@ func Projects(ctx *context.Context) {
// NewProject render creating a project page // NewProject render creating a project page
func NewProject(ctx *context.Context) { func NewProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.new") ctx.Data["Title"] = ctx.Tr("repo.projects.new")
ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig()
ctx.Data["CardTypes"] = project_model.GetCardConfig()
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
ctx.HTML(http.StatusOK, tplProjectsNew) ctx.HTML(http.StatusOK, tplProjectsNew)
} }
@ -137,8 +135,7 @@ func NewProjectPost(ctx *context.Context) {
if ctx.HasError() { if ctx.HasError() {
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig()
ctx.Data["CardTypes"] = project_model.GetCardConfig()
ctx.HTML(http.StatusOK, tplProjectsNew) ctx.HTML(http.StatusOK, tplProjectsNew)
return return
} }
@ -149,7 +146,6 @@ func NewProjectPost(ctx *context.Context) {
Description: form.Content, Description: form.Content,
CreatorID: ctx.Doer.ID, CreatorID: ctx.Doer.ID,
BoardType: form.BoardType, BoardType: form.BoardType,
CardType: form.CardType,
Type: project_model.TypeRepository, Type: project_model.TypeRepository,
}); err != nil { }); err != nil {
ctx.ServerError("NewProject", err) ctx.ServerError("NewProject", err)
@ -216,7 +212,6 @@ func EditProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true ctx.Data["PageIsEditProjects"] = true
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
ctx.Data["CardTypes"] = project_model.GetCardConfig()
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
if err != nil { if err != nil {
@ -234,7 +229,6 @@ func EditProject(ctx *context.Context) {
ctx.Data["title"] = p.Title ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description ctx.Data["content"] = p.Description
ctx.Data["card_type"] = p.CardType
ctx.HTML(http.StatusOK, tplProjectsNew) ctx.HTML(http.StatusOK, tplProjectsNew)
} }
@ -245,7 +239,6 @@ func EditProjectPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true ctx.Data["PageIsEditProjects"] = true
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
ctx.Data["CardTypes"] = project_model.GetCardConfig()
if ctx.HasError() { if ctx.HasError() {
ctx.HTML(http.StatusOK, tplProjectsNew) ctx.HTML(http.StatusOK, tplProjectsNew)
@ -268,7 +261,6 @@ func EditProjectPost(ctx *context.Context) {
p.Title = form.Title p.Title = form.Title
p.Description = form.Content p.Description = form.Content
p.CardType = form.CardType
if err = project_model.UpdateProject(ctx, p); err != nil { if err = project_model.UpdateProject(ctx, p); err != nil {
ctx.ServerError("UpdateProjects", err) ctx.ServerError("UpdateProjects", err)
return return
@ -310,18 +302,6 @@ func ViewProject(ctx *context.Context) {
return return
} }
if project.CardType != project_model.CardTypeTextOnly {
issuesAttachmentMap := make(map[int64][]*attachment_model.Attachment)
for _, issuesList := range issuesMap {
for _, issue := range issuesList {
if issueAttachment, err := attachment_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil {
issuesAttachmentMap[issue.ID] = issueAttachment
}
}
}
ctx.Data["issuesAttachmentMap"] = issuesAttachmentMap
}
linkedPrsMap := make(map[int64][]*issues_model.Issue) linkedPrsMap := make(map[int64][]*issues_model.Issue)
for _, issuesList := range issuesMap { for _, issuesList := range issuesMap {
for _, issue := range issuesList { for _, issue := range issuesList {

View File

@ -98,7 +98,7 @@ func CreateCodeComment(ctx *context.Context) {
renderConversation(ctx, comment) renderConversation(ctx, comment)
return return
} }
ctx.Redirect(comment.Link()) ctx.Redirect(comment.HTMLURL())
} }
// UpdateResolveConversation add or remove an Conversation resolved mark // UpdateResolveConversation add or remove an Conversation resolved mark

View File

@ -295,7 +295,7 @@ func LatestRelease(ctx *context.Context) {
return return
} }
ctx.Redirect(release.Link()) ctx.Redirect(release.HTMLURL())
} }
// NewRelease render creating or edit release page // NewRelease render creating or edit release page

View File

@ -344,7 +344,7 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected")) ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected"))
} }
ctx.Redirect(ctx.Repo.Repository.Link()) ctx.Redirect(ctx.Repo.Repository.HTMLURL())
return nil return nil
} }

View File

@ -54,7 +54,7 @@ func Search(ctx *context.Context) {
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable() ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
} }
ctx.Data["SourcePath"] = ctx.Repo.Repository.Link() ctx.Data["SourcePath"] = ctx.Repo.Repository.HTMLURL()
ctx.Data["SearchResults"] = searchResults ctx.Data["SearchResults"] = searchResults
ctx.Data["SearchResultLanguages"] = searchResultLanguages ctx.Data["SearchResultLanguages"] = searchResultLanguages

View File

@ -318,7 +318,7 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
if fInfo.isLFSFile { if fInfo.isLFSFile {
filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name)) filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name))
ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.Link(), url.PathEscape(fInfo.lfsMeta.Oid), url.PathEscape(filenameBase64)) ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(fInfo.lfsMeta.Oid), url.PathEscape(filenameBase64))
} }
if !fInfo.isTextFile { if !fInfo.isTextFile {
@ -738,7 +738,7 @@ func Home(ctx *context.Context) {
} }
ctx.Data["EnableFeed"] = true ctx.Data["EnableFeed"] = true
ctx.Data["FeedURL"] = ctx.Repo.Repository.Link() ctx.Data["FeedURL"] = ctx.Repo.Repository.HTMLURL()
} }
checkHomeCodeViewable(ctx) checkHomeCodeViewable(ctx)

View File

@ -376,7 +376,7 @@ func PackageSettingsPost(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
} }
ctx.Redirect(ctx.Package.Owner.HomeLink() + "/-/packages") ctx.Redirect(ctx.Package.Owner.HTMLURL() + "/-/packages")
return return
} }
} }

View File

@ -47,7 +47,7 @@ func Profile(ctx *context.Context) {
} }
// advertise feed via meta tag // advertise feed via meta tag
ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink() ctx.Data["FeedURL"] = ctx.ContextUser.HTMLURL()
// Show OpenID URIs // Show OpenID URIs
openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID) openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID)

View File

@ -59,7 +59,7 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
Creator: creator, Creator: creator,
CommitStatus: &git_model.CommitStatus{ CommitStatus: &git_model.CommitStatus{
SHA: sha, SHA: sha,
TargetURL: run.Link(), TargetURL: run.HTMLURL(),
Description: "", Description: "",
Context: ctxname, Context: ctxname,
CreatorID: payload.Pusher.ID, CreatorID: payload.Pusher.ID,

View File

@ -512,7 +512,6 @@ type CreateProjectForm struct {
Title string `binding:"Required;MaxSize(100)"` Title string `binding:"Required;MaxSize(100)"`
Content string Content string
BoardType project_model.BoardType BoardType project_model.BoardType
CardType project_model.CardType
} }
// UserCreateProjectForm is a from for creating an individual or organization // UserCreateProjectForm is a from for creating an individual or organization
@ -521,7 +520,6 @@ type UserCreateProjectForm struct {
Title string `binding:"Required;MaxSize(100)"` Title string `binding:"Required;MaxSize(100)"`
Content string Content string
BoardType project_model.BoardType BoardType project_model.BoardType
CardType project_model.CardType
UID int64 `binding:"Required"` UID int64 `binding:"Required"`
} }

View File

@ -15,7 +15,6 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
) )
// ContentType repo content type // ContentType repo content type
@ -159,7 +158,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref) return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref)
} }
selfURL, err := url.Parse(repo.APIURL() + "/contents/" + util.PathEscapeSegments(treePath) + "?ref=" + url.QueryEscape(origRef)) selfURL, err := url.Parse(fmt.Sprintf("%s/contents/%s?ref=%s", repo.APIURL(), treePath, origRef))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -218,7 +217,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
} }
// Handle links // Handle links
if entry.IsRegular() || entry.IsLink() { if entry.IsRegular() || entry.IsLink() {
downloadURL, err := url.Parse(repo.HTMLURL() + "/raw/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath)) downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -226,7 +225,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
contentsResponse.DownloadURL = &downloadURLString contentsResponse.DownloadURL = &downloadURLString
} }
if !entry.IsSubModule() { if !entry.IsSubModule() {
htmlURL, err := url.Parse(repo.HTMLURL() + "/src/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath)) htmlURL, err := url.Parse(fmt.Sprintf("%s/src/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -234,7 +233,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
contentsResponse.HTMLURL = &htmlURLString contentsResponse.HTMLURL = &htmlURLString
contentsResponse.Links.HTMLURL = &htmlURLString contentsResponse.Links.HTMLURL = &htmlURLString
gitURL, err := url.Parse(repo.APIURL() + "/git/blobs/" + url.PathEscape(entry.ID.String())) gitURL, err := url.Parse(fmt.Sprintf("%s/git/blobs/%s", repo.APIURL(), entry.ID.String()))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -36,7 +36,7 @@
<input type="hidden" name="board_type" value="{{.type}}"> <input type="hidden" name="board_type" value="{{.type}}">
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div> <div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
<div class="menu"> <div class="menu">
{{range $element := .BoardTypes}} {{range $element := .ProjectTypes}}
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div> <div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}} {{end}}
</div> </div>

View File

@ -62,9 +62,9 @@
{{range .Milestones}} {{range .Milestones}}
<li class="item"> <li class="item">
<div class="df ac sb"> <div class="df ac sb">
<h3 class="df ac m-0 fw"> <h2 class="df ac m-0 fw">
{{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a> {{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a>
</h3> </h2>
<div class="df ac"> <div class="df ac">
<span class="mr-3">{{.Completeness}}%</span> <span class="mr-3">{{.Completeness}}%</span>
<progress value="{{.Completeness}}" max="100"></progress> <progress value="{{.Completeness}}" max="100"></progress>

View File

@ -34,38 +34,17 @@
</div> </div>
{{if not .PageIsEditProjects}} {{if not .PageIsEditProjects}}
<div class="field"> <label>{{.locale.Tr "repo.projects.template.desc"}}</label>
<label>{{.locale.Tr "repo.projects.template.desc"}}</label> <div class="ui selection dropdown">
<div class="ui selection dropdown"> <input type="hidden" name="board_type" value="{{.type}}">
<input type="hidden" name="board_type" value="{{.type}}"> <div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div> <div class="menu">
<div class="menu"> {{range $element := .ProjectTypes}}
{{range $element := .BoardTypes}} <div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div> {{end}}
{{end}}
</div>
</div> </div>
</div> </div>
{{end}} {{end}}
<div class="field">
<label>{{.locale.Tr "repo.projects.card_type.desc"}}</label>
<div class="ui selection dropdown">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{range $element := .CardTypes}}
{{if or (eq $.card_type $element.CardType) (and (not $.card_type) (eq $element.CardType 2))}}
<input type="hidden" name="card_type" value="{{$element.CardType}}">
<div class="default text">{{$.locale.Tr $element.Translation}}</div>
{{end}}
{{end}}
<div class="menu">
{{range $element := .CardTypes}}
<div class="item" data-id="{{$element.CardType}}" data-value="{{$element.CardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}}
</div>
</div>
</div>
</div> </div>
<div class="ui container"> <div class="ui container">
<div class="ui divider"></div> <div class="ui divider"></div>

View File

@ -179,13 +179,6 @@
<!-- start issue card --> <!-- start issue card -->
<div class="card board-card" data-issue="{{.ID}}"> <div class="card board-card" data-issue="{{.ID}}">
{{if eq $.Project.CardType 1}}{{/* Images and Text*/}}
<div class="card-attachment-images">
{{range (index $.issuesAttachmentMap .ID)}}
<img src="{{.DownloadURL}}" alt="{{.Name}}" />
{{end}}
</div>
{{end}}
<div class="content p-0"> <div class="content p-0">
<div class="header"> <div class="header">
<span class="dif ac vm {{if .IsClosed}}red{{else}}green{{end}}"> <span class="dif ac vm {{if .IsClosed}}red{{else}}green{{end}}">

View File

@ -81,10 +81,10 @@
{{range .Milestones}} {{range .Milestones}}
<li class="item"> <li class="item">
<div class="df ac sb"> <div class="df ac sb">
<h3 class="df ac m-0 fw"> <h2 class="df ac m-0 fw">
<span class="ui large label">{{.Repo.FullName}}</span> <span class="ui large label">{{.Repo.FullName}}</span>
{{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{.Repo.Link}}/milestone/{{.ID}}">{{.Name}}</a> {{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{.Repo.Link}}/milestone/{{.ID}}">{{.Name}}</a>
</h3> </h2>
<div class="df ac"> <div class="df ac">
<span class="mr-3">{{.Completeness}}%</span> <span class="mr-3">{{.Completeness}}%</span>
<progress value="{{.Completeness}}" max="100"></progress> <progress value="{{.Completeness}}" max="100"></progress>

View File

@ -48,7 +48,7 @@
<input type="hidden" name="board_type" value="{{.type}}"> <input type="hidden" name="board_type" value="{{.type}}">
<div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div> <div class="default text">{{.locale.Tr "repo.projects.template.desc_helper"}}</div>
<div class="menu"> <div class="menu">
{{range $element := .BoardTypes}} {{range $element := .ProjectTypes}}
<div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div> <div class="item" data-id="{{$element.BoardType}}" data-value="{{$element.BoardType}}">{{$.locale.Tr $element.Translation}}</div>
{{end}} {{end}}
</div> </div>

View File

@ -12,7 +12,6 @@ import (
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"strconv"
"testing" "testing"
"time" "time"
@ -110,6 +109,8 @@ func TestPackageNuGet(t *testing.T) {
url := fmt.Sprintf("/api/packages/%s/nuget", user.Name) url := fmt.Sprintf("/api/packages/%s/nuget", user.Name)
t.Run("ServiceIndex", func(t *testing.T) { t.Run("ServiceIndex", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("v2", func(t *testing.T) { t.Run("v2", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
@ -373,6 +374,8 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
}) })
t.Run("SearchService", func(t *testing.T) { t.Run("SearchService", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
cases := []struct { cases := []struct {
Query string Query string
Skip int Skip int
@ -388,6 +391,8 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
} }
t.Run("v2", func(t *testing.T) { t.Run("v2", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("Search()", func(t *testing.T) { t.Run("Search()", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
@ -401,12 +406,6 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i)
assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i)
req = NewRequest(t, "GET", fmt.Sprintf("%s/Search()/$count?searchTerm='%s'&skip=%d&take=%d", url, c.Query, c.Skip, c.Take))
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i)
} }
}) })
@ -414,7 +413,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
for i, c := range cases { for i, c := range cases {
req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)) req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take))
req = AddBasicAuthHeader(req, user.Name) req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)
@ -423,12 +422,6 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i)
assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i)
req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take))
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i)
} }
}) })
}) })
@ -519,6 +512,8 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
}) })
t.Run("RegistrationLeaf", func(t *testing.T) { t.Run("RegistrationLeaf", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("v2", func(t *testing.T) { t.Run("v2", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
@ -554,6 +549,8 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
}) })
t.Run("PackageService", func(t *testing.T) { t.Run("PackageService", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("v2", func(t *testing.T) { t.Run("v2", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
@ -566,12 +563,6 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
assert.Len(t, result.Entries, 1) assert.Len(t, result.Entries, 1)
assert.Equal(t, packageVersion, result.Entries[0].Properties.Version) assert.Equal(t, packageVersion, result.Entries[0].Properties.Version)
req = NewRequest(t, "GET", fmt.Sprintf("%s/FindPackagesById()/$count?id='%s'", url, packageName))
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "1", resp.Body.String())
}) })
t.Run("v3", func(t *testing.T) { t.Run("v3", func(t *testing.T) {

View File

@ -10,7 +10,7 @@
/> />
<a <a
v-if="item.isFile" v-if="item.isFile"
class="file ellipsis muted" class="file ellipsis"
:href="item.isFile ? '#diff-' + item.file.NameHash : ''" :href="item.isFile ? '#diff-' + item.file.NameHash : ''"
>{{ item.name }}</a> >{{ item.name }}</a>
<SvgIcon <SvgIcon
@ -63,7 +63,7 @@ export default {
if (itemIsFile) { if (itemIsFile) {
return; return;
} }
this.collapsed = !this.collapsed; this.$set(this, 'collapsed', !this.collapsed);
}, },
getIconForDiffType(pType) { getIconForDiffType(pType) {
const diffTypes = { const diffTypes = {
@ -83,7 +83,6 @@ export default {
span.svg-icon.status { span.svg-icon.status {
float: right; float: right;
} }
span.svg-icon.file { span.svg-icon.file {
color: var(--color-secondary-dark-7); color: var(--color-secondary-dark-7);
} }
@ -123,8 +122,6 @@ span.svg-icon.octicon-diff-renamed {
div.directory { div.directory {
display: grid; display: grid;
grid-template-columns: 18px 20px auto; grid-template-columns: 18px 20px auto;
user-select: none;
cursor: pointer;
} }
div.directory:hover { div.directory:hover {

View File

@ -1803,7 +1803,6 @@ footer {
} }
} }
/* TODO: remove in favor of .hidden helper */
.hide { .hide {
display: none; display: none;

View File

@ -1614,20 +1614,6 @@
margin-right: .25rem; margin-right: .25rem;
} }
// Because the translations contain the <strong> we need to style with nth-of-type
.diff-detail-stats strong:nth-of-type(1) {
color: var(--color-yellow);
}
.diff-detail-stats strong:nth-of-type(2) {
color: var(--color-green);
}
.diff-detail-stats strong:nth-of-type(3) {
color: var(--color-red);
}
.diff-detail-stats { .diff-detail-stats {
@media (max-width: 480px) { @media (max-width: 480px) {
font-size: 0; font-size: 0;

View File

@ -72,10 +72,6 @@
margin-right: auto !important; margin-right: auto !important;
} }
.board-column .ui.cards > .card > .content {
border: none;
}
.board-card { .board-card {
margin: 4px 2px !important; margin: 4px 2px !important;
border-radius: 5px !important; border-radius: 5px !important;
@ -94,25 +90,6 @@
font-size: 16px !important; font-size: 16px !important;
} }
.board-card .card-attachment-images {
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-align: center;
}
.board-card .card-attachment-images img {
display: inline-block;
max-height: 50px;
border-radius: var(--border-radius);
margin-right: 2px;
}
.board-card .card-attachment-images img:only-child {
max-height: 90px;
margin: auto;
}
.card-ghost { .card-ghost {
border-style: dashed !important; border-style: dashed !important;
background: none !important; background: none !important;

View File

@ -22,7 +22,6 @@
/* below class names match Tailwind CSS */ /* below class names match Tailwind CSS */
.pointer-events-none { pointer-events: none !important; } .pointer-events-none { pointer-events: none !important; }
.relative { position: relative !important; } .relative { position: relative !important; }
.hidden { display: none !important; }
.mono { .mono {
font-family: var(--fonts-monospace) !important; font-family: var(--fonts-monospace) !important;