1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2025-10-10 19:32:02 +00:00

feat(ui): add links to review request targets in issue comments (#8239)

- Add links to review request targets in issue comments
- Fix links to ghost users/orgs/teams to be empty

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8239
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Robert Wolff <mahlzahn@posteo.de>
Co-committed-by: Robert Wolff <mahlzahn@posteo.de>
This commit is contained in:
Robert Wolff 2025-07-23 04:45:58 +02:00 committed by Gusted
parent 82daae4c7c
commit 7643bdd2b5
11 changed files with 256 additions and 21 deletions

View file

@ -186,6 +186,11 @@ func (org *Organization) CanCreateRepo() bool {
return org.AsUser().CanCreateRepo()
}
// IsGhost returns if the organization is a ghost
func (org *Organization) IsGhost() bool {
return org.AsUser().IsGhost()
}
// FindOrgMembersOpts represensts find org members conditions
type FindOrgMembersOpts struct {
db.ListOptions

View file

@ -1,5 +1,6 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2018 The Gitea Authors. All rights reserved.
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package organization
@ -7,6 +8,7 @@ package organization
import (
"context"
"fmt"
"net/url"
"strings"
"forgejo.org/models/db"
@ -20,13 +22,6 @@ import (
"xorm.io/builder"
)
// ___________
// \__ ___/___ _____ _____
// | |_/ __ \\__ \ / \
// | |\ ___/ / __ \| Y Y \
// |____| \___ >____ /__|_| /
// \/ \/ \/
// ErrTeamAlreadyExist represents a "TeamAlreadyExist" kind of error.
type ErrTeamAlreadyExist struct {
OrgID int64
@ -193,6 +188,27 @@ func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode
return perm.AccessModeNone
}
// GetOrg returns the team's organization
func (t *Team) GetOrg(ctx context.Context) *Organization {
org, err := GetOrgByID(ctx, t.OrgID)
if err != nil {
return OrgFromUser(user_model.NewGhostUser())
}
return org
}
// Link returns the team's page link
func (t *Team) Link(ctx context.Context) string {
if t.IsGhost() {
return ""
}
org := t.GetOrg(ctx)
if org.IsGhost() {
return ""
}
return org.OrganisationLink() + "/teams/" + url.PathEscape(t.Name)
}
// IsUsableTeamName tests if a name could be as team name
func IsUsableTeamName(name string) error {
switch name {
@ -293,10 +309,22 @@ func FixInconsistentOwnerTeams(ctx context.Context) (int64, error) {
return int64(len(teamIDs)), nil
}
const (
GhostTeamID = -1
GhostTeamName = "Ghost team"
GhostTeamLowerName = "ghost team"
)
// NewGhostTeam creates ghost team (for deleted team)
func NewGhostTeam() *Team {
return &Team{
ID: -1,
Name: "Ghost team",
LowerName: "ghost team",
ID: GhostTeamID,
Name: GhostTeamName,
LowerName: GhostTeamLowerName,
}
}
// IsGhost returns if a team is a ghost team
func (t *Team) IsGhost() bool {
return t.ID == GhostTeamID
}

View file

@ -1,4 +1,5 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package organization_test
@ -15,14 +16,33 @@ import (
"github.com/stretchr/testify/require"
)
func TestTeam_IsOwnerTeam(t *testing.T) {
func TestTeam(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1})
assert.True(t, team.IsOwnerTeam())
owners := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1})
assert.Equal(t, int64(3), owners.GetOrg(db.DefaultContext).ID)
assert.Equal(t, "/org/org3/teams/Owners", owners.Link(db.DefaultContext))
assert.False(t, owners.IsGhost())
assert.True(t, owners.IsOwnerTeam())
team = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
assert.False(t, team.IsOwnerTeam())
team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
assert.Equal(t, int64(3), team1.GetOrg(db.DefaultContext).ID)
assert.Equal(t, "/org/org3/teams/team1", team1.Link(db.DefaultContext))
assert.False(t, team1.IsGhost())
assert.False(t, team1.IsOwnerTeam())
ghost := organization.NewGhostTeam()
assert.Equal(t, int64(-1), ghost.ID)
assert.Equal(t, int64(-1), ghost.GetOrg(db.DefaultContext).ID)
assert.Empty(t, ghost.Link(db.DefaultContext))
assert.True(t, ghost.IsGhost())
assert.False(t, ghost.IsOwnerTeam())
ghosted := organization.Team{ID: 10, Name: "Ghosted"}
assert.Equal(t, int64(-1), ghosted.GetOrg(db.DefaultContext).ID)
assert.Empty(t, ghosted.Link(db.DefaultContext))
assert.False(t, ghosted.IsGhost())
assert.False(t, ghosted.IsOwnerTeam())
}
func TestTeam_IsMember(t *testing.T) {