Show repo activities even if only code unit active or git repo is empty but issue is active (#3455)

When all repository units are deactivated except for the code unit, the activity tab will not be shown.
Since the activities tab also shows contributing stats, it would be good to show the activities tab also when only code is active.
This commit changes the behavior when the activities tab is shown.
Previous it would only be shown when Issues, Pull-Requests or Releases are activated. Now it would additionally be shown when the code unit is activated.

Refs: #3429

| Before (Code + Issues - Owner) | Before (Code - Viewer) | After (Code + Issues - Owner) | After (Code - Viewer) |
| -- | -- | -- | -- |
| ![image](/attachments/2af997bc-1f38-48c6-bdf3-cfbd7087b220)  | ![image](/attachments/ef1797f0-5c9a-4a1a-ba82-749f3ab4f403) | ![image](/attachments/fd28a96c-04ca-407e-a70d-d28b393f223d) | ![image](/attachments/2cd0d559-a6de-4ca0-a736-29c5fea81b5a) |
|  | `/activity` returns 404 for everyone | ![image](/attachments/e0e97d8f-48cb-4c16-a505-1fafa46c4b8e)  | - |

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3455
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-committed-by: Beowulf <beowulf@beocode.eu>
(cherry picked from commit c54896ba70)
This commit is contained in:
Beowulf 2024-04-28 13:47:52 +00:00 committed by GitHub
parent 0160acbc05
commit 135764f244
5 changed files with 137 additions and 9 deletions

View file

@ -57,7 +57,7 @@ func Activity(ctx *context.Context) {
ctx.Repo.CanRead(unit.TypeReleases), ctx.Repo.CanRead(unit.TypeReleases),
ctx.Repo.CanRead(unit.TypeIssues), ctx.Repo.CanRead(unit.TypeIssues),
ctx.Repo.CanRead(unit.TypePullRequests), ctx.Repo.CanRead(unit.TypePullRequests),
ctx.Repo.CanRead(unit.TypeCode)); err != nil { ctx.Repo.CanRead(unit.TypeCode) && !ctx.Repo.Repository.IsEmpty); err != nil {
ctx.ServerError("GetActivityStats", err) ctx.ServerError("GetActivityStats", err)
return return
} }

View file

@ -1423,16 +1423,16 @@ func registerRoutes(m *web.Route) {
m.Group("/contributors", func() { m.Group("/contributors", func() {
m.Get("", repo.Contributors) m.Get("", repo.Contributors)
m.Get("/data", repo.ContributorsData) m.Get("/data", repo.ContributorsData)
}) }, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
m.Group("/code-frequency", func() { m.Group("/code-frequency", func() {
m.Get("", repo.CodeFrequency) m.Get("", repo.CodeFrequency)
m.Get("/data", repo.CodeFrequencyData) m.Get("/data", repo.CodeFrequencyData)
}) }, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
m.Group("/recent-commits", func() { m.Group("/recent-commits", func() {
m.Get("", repo.RecentCommits) m.Get("", repo.RecentCommits)
m.Get("/data", repo.RecentCommitsData) m.Get("/data", repo.RecentCommitsData)
}) }, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases)) }, context.RepoRef(), context.RequireRepoReaderOr(unit.TypeCode, unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases))
m.Group("/activity_author_data", func() { m.Group("/activity_author_data", func() {
m.Get("", repo.ActivityAuthors) m.Get("", repo.ActivityAuthors)

View file

@ -2,9 +2,11 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository commits"> <div role="main" aria-label="{{.Title}}" class="page-content repository commits">
{{template "repo/header" .}} {{template "repo/header" .}}
<div class="ui container flex-container"> <div class="ui container flex-container">
{{if and (not .IsEmptyRepo) (.Permission.CanRead $.UnitTypeCode)}}
<div class="flex-container-nav"> <div class="flex-container-nav">
{{template "repo/navbar" .}} {{template "repo/navbar" .}}
</div> </div>
{{end}}
<div class="flex-container-main"> <div class="flex-container-main">
{{if .PageIsPulse}}{{template "repo/pulse" .}}{{end}} {{if .PageIsPulse}}{{template "repo/pulse" .}}{{end}}
{{if .PageIsContributors}}{{template "repo/contributors" .}}{{end}} {{if .PageIsContributors}}{{template "repo/contributors" .}}{{end}}

View file

@ -159,7 +159,7 @@
</a> </a>
{{end}} {{end}}
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}} {{if and (.Permission.CanReadAny $.UnitTypeCode $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases)}}
<a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity"> <a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity">
{{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}} {{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}}
</a> </a>

View file

@ -4,13 +4,20 @@
package integration package integration
import ( import (
"fmt"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"testing" "testing"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -63,3 +70,122 @@ func TestRepoActivity(t *testing.T) {
assert.Len(t, list.Nodes, 3) assert.Len(t, list.Nodes, 3)
}) })
} }
func TestRepoActivityAllUnitsDisabled(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
session := loginUser(t, user.Name)
unit_model.LoadUnitConfig()
// Create a repo, with no unit enabled.
repo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
Name: "empty-repo",
AutoInit: false,
})
assert.NoError(t, err)
assert.NotEmpty(t, repo)
enabledUnits := make([]repo_model.RepoUnit, 0)
disabledUnits := []unit_model.Type{unit_model.TypeCode, unit_model.TypeIssues, unit_model.TypePullRequests, unit_model.TypeReleases}
err = repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, enabledUnits, disabledUnits)
assert.NoError(t, err)
req := NewRequest(t, "GET", fmt.Sprintf("%s/activity", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/contributors", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/code-frequency", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/recent-commits", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
}
func TestRepoActivityOnlyCodeUnitWithEmptyRepo(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
session := loginUser(t, user.Name)
unit_model.LoadUnitConfig()
// Create a empty repo, with only code unit enabled.
repo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
Name: "empty-repo",
AutoInit: false,
})
assert.NoError(t, err)
assert.NotEmpty(t, repo)
enabledUnits := make([]repo_model.RepoUnit, 1)
enabledUnits[0] = repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeCode}
disabledUnits := []unit_model.Type{unit_model.TypeIssues, unit_model.TypePullRequests, unit_model.TypeReleases}
err = repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, enabledUnits, disabledUnits)
assert.NoError(t, err)
req := NewRequest(t, "GET", fmt.Sprintf("%s/activity", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
// Git repo empty so no activity for contributors etc
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/contributors", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/code-frequency", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/recent-commits", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
}
func TestRepoActivityOnlyCodeUnitWithNonEmptyRepo(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
session := loginUser(t, user.Name)
unit_model.LoadUnitConfig()
// Create a repo, with only code unit enabled.
repo, _, f := CreateDeclarativeRepo(t, user, "", []unit_model.Type{unit_model.TypeCode}, nil, nil)
defer f()
req := NewRequest(t, "GET", fmt.Sprintf("%s/activity", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
// Git repo not empty so activity for contributors etc
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/contributors", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/code-frequency", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/recent-commits", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
}
func TestRepoActivityOnlyIssuesUnit(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
session := loginUser(t, user.Name)
unit_model.LoadUnitConfig()
// Create a empty repo, with only code unit enabled.
repo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
Name: "empty-repo",
AutoInit: false,
})
assert.NoError(t, err)
assert.NotEmpty(t, repo)
enabledUnits := make([]repo_model.RepoUnit, 1)
enabledUnits[0] = repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeIssues}
disabledUnits := []unit_model.Type{unit_model.TypeCode, unit_model.TypePullRequests, unit_model.TypeReleases}
err = repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, enabledUnits, disabledUnits)
assert.NoError(t, err)
req := NewRequest(t, "GET", fmt.Sprintf("%s/activity", repo.Link()))
session.MakeRequest(t, req, http.StatusOK)
// Git repo empty so no activity for contributors etc
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/contributors", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/code-frequency", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/activity/recent-commits", repo.Link()))
session.MakeRequest(t, req, http.StatusNotFound)
}