Skip to content

Commit 71e151c

Browse files
wxiaoguangsilverwindGiteaBot
authored
Refactor head navbar icons (#34922)
Co-authored-by: silverwind <[email protected]> Co-authored-by: Giteabot <[email protected]>
1 parent d6d643f commit 71e151c

File tree

9 files changed

+83
-113
lines changed

9 files changed

+83
-113
lines changed

routers/common/pagetmpl.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package common
66
import (
77
goctx "context"
88
"errors"
9+
"sync"
910

1011
activities_model "code.gitea.io/gitea/models/activities"
1112
"code.gitea.io/gitea/models/db"
@@ -22,8 +23,7 @@ type StopwatchTmplInfo struct {
2223
Seconds int64
2324
}
2425

25-
func getActiveStopwatch(goCtx goctx.Context) *StopwatchTmplInfo {
26-
ctx := context.GetWebContext(goCtx)
26+
func getActiveStopwatch(ctx *context.Context) *StopwatchTmplInfo {
2727
if ctx.Doer == nil {
2828
return nil
2929
}
@@ -48,8 +48,7 @@ func getActiveStopwatch(goCtx goctx.Context) *StopwatchTmplInfo {
4848
}
4949
}
5050

51-
func notificationUnreadCount(goCtx goctx.Context) int64 {
52-
ctx := context.GetWebContext(goCtx)
51+
func notificationUnreadCount(ctx *context.Context) int64 {
5352
if ctx.Doer == nil {
5453
return 0
5554
}
@@ -66,10 +65,19 @@ func notificationUnreadCount(goCtx goctx.Context) int64 {
6665
return count
6766
}
6867

69-
func PageTmplFunctions(ctx *context.Context) {
70-
if ctx.IsSigned {
71-
// defer the function call to the last moment when the tmpl renders
72-
ctx.Data["NotificationUnreadCount"] = notificationUnreadCount
73-
ctx.Data["GetActiveStopwatch"] = getActiveStopwatch
74-
}
68+
type pageGlobalDataType struct {
69+
IsSigned bool
70+
IsSiteAdmin bool
71+
72+
GetNotificationUnreadCount func() int64
73+
GetActiveStopwatch func() *StopwatchTmplInfo
74+
}
75+
76+
func PageGlobalData(ctx *context.Context) {
77+
var data pageGlobalDataType
78+
data.IsSigned = ctx.Doer != nil
79+
data.IsSiteAdmin = ctx.Doer != nil && ctx.Doer.IsAdmin
80+
data.GetNotificationUnreadCount = sync.OnceValue(func() int64 { return notificationUnreadCount(ctx) })
81+
data.GetActiveStopwatch = sync.OnceValue(func() *StopwatchTmplInfo { return getActiveStopwatch(ctx) })
82+
ctx.Data["PageGlobalData"] = data
7583
}

routers/web/web.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func Routes() *web.Router {
281281
}
282282

283283
mid = append(mid, goGet)
284-
mid = append(mid, common.PageTmplFunctions)
284+
mid = append(mid, common.PageGlobalData)
285285

286286
webRoutes := web.NewRouter()
287287
webRoutes.Use(mid...)

templates/base/head_navbar.tmpl

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
{{$notificationUnreadCount := 0}}
2-
{{if and .IsSigned .NotificationUnreadCount}}
3-
{{$notificationUnreadCount = call .NotificationUnreadCount ctx}}
4-
{{end}}
5-
{{$activeStopwatch := NIL}}
6-
{{if and .IsSigned EnableTimetracking .GetActiveStopwatch}}
7-
{{$activeStopwatch = call .GetActiveStopwatch ctx}}
8-
{{end}}
91
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
102
<div class="navbar-left">
113
<!-- the logo -->
@@ -15,22 +7,7 @@
157

168
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
179
<div class="ui secondary menu navbar-mobile-right only-mobile">
18-
{{if $activeStopwatch}}
19-
<a id="mobile-stopwatch-icon" class="active-stopwatch item" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
20-
<div class="tw-relative">
21-
{{svg "octicon-stopwatch"}}
22-
<span class="header-stopwatch-dot"></span>
23-
</div>
24-
</a>
25-
{{end}}
26-
{{if .IsSigned}}
27-
<a id="mobile-notifications-icon" class="item" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
28-
<div class="tw-relative">
29-
{{svg "octicon-bell"}}
30-
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
31-
</div>
32-
</a>
33-
{{end}}
10+
{{template "base/head_navbar_icons" dict "PageGlobalData" .PageGlobalData}}
3411
<button class="item ui icon mini button tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "home.nav_menu"}}">{{svg "octicon-three-bars"}}</button>
3512
</div>
3613

@@ -85,22 +62,7 @@
8562
</div><!-- end content avatar menu -->
8663
</div><!-- end dropdown avatar menu -->
8764
{{else if .IsSigned}}
88-
{{if $activeStopwatch}}
89-
<a class="item not-mobile active-stopwatch" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
90-
<div class="tw-relative">
91-
{{svg "octicon-stopwatch"}}
92-
<span class="header-stopwatch-dot"></span>
93-
</div>
94-
</a>
95-
{{end}}
96-
97-
<a class="item not-mobile" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
98-
<div class="tw-relative">
99-
{{svg "octicon-bell"}}
100-
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
101-
</div>
102-
</a>
103-
65+
{{template "base/head_navbar_icons" dict "ItemExtraClass" "not-mobile" "PageGlobalData" .PageGlobalData}}
10466
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}">
10567
<span class="text">
10668
{{svg "octicon-plus"}}
@@ -130,8 +92,6 @@
13092
<span class="only-mobile">{{.SignedUser.Name}}</span>
13193
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
13294
</span>
133-
{{/* do not localize it, here it needs the fixed length (width) to make UI comfortable */}}
134-
{{if .IsAdmin}}<span class="navbar-profile-admin">admin</span>{{end}}
13595
<div class="menu user-menu">
13696
<div class="header">
13797
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
@@ -160,14 +120,6 @@
160120
{{svg "octicon-question"}}
161121
{{ctx.Locale.Tr "help"}}
162122
</a>
163-
{{if .IsAdmin}}
164-
<div class="divider"></div>
165-
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
166-
{{svg "octicon-server"}}
167-
{{ctx.Locale.Tr "admin_panel"}}
168-
</a>
169-
{{end}}
170-
171123
<div class="divider"></div>
172124
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
173125
{{svg "octicon-sign-out"}}
@@ -189,6 +141,7 @@
189141
{{end}}
190142
</div><!-- end full right menu -->
191143

144+
{{$activeStopwatch := and .PageGlobalData (call .PageGlobalData.GetActiveStopwatch)}}
192145
{{if $activeStopwatch}}
193146
<div class="active-stopwatch-popup tippy-target">
194147
<div class="tw-flex tw-items-center tw-gap-2 tw-p-3">

templates/base/head_navbar_icons.tmpl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{- $itemExtraClass := .ItemExtraClass -}}
2+
{{- $data := .PageGlobalData -}}
3+
{{if and $data $data.IsSigned}}{{/* data may not exist, for example: rendering 503 page before the PageGlobalData middleware */}}
4+
{{- $activeStopwatch := call $data.GetActiveStopwatch -}}
5+
{{- $notificationUnreadCount := call $data.GetNotificationUnreadCount -}}
6+
{{if $activeStopwatch}}
7+
<a class="item active-stopwatch {{$itemExtraClass}}" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
8+
<div class="tw-relative">
9+
{{svg "octicon-stopwatch"}}
10+
<span class="header-stopwatch-dot"></span>
11+
</div>
12+
</a>
13+
{{end}}
14+
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}">
15+
<div class="tw-relative">
16+
{{svg "octicon-bell"}}
17+
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
18+
</div>
19+
</a>
20+
{{if $data.IsSiteAdmin}}
21+
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/-/admin" data-tooltip-content="{{ctx.Locale.Tr "admin_panel"}}">
22+
{{svg "octicon-server"}}
23+
</a>
24+
{{end}}
25+
{{end}}

templates/swagger/ui.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<body>
88
<a class="swagger-back-link" href="{{AppSubUrl}}/">{{svg "octicon-reply"}}{{ctx.Locale.Tr "return_to_gitea"}}</a>
99
<div id="swagger-ui" data-source="{{AppSubUrl}}/swagger.{{.APIJSONVersion}}.json"></div>
10+
<footer class="page-footer"></footer>
1011
<script src="{{AssetUrlPrefix}}/js/swagger.js?v={{AssetVersion}}"></script>
1112
</body>
1213
</html>

templates/user/notification/notification_div.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div role="main" aria-label="{{.Title}}" class="page-content user notification" id="notification_div" data-sequence-number="{{.SequenceNumber}}">
22
<div class="ui container">
3-
{{$notificationUnreadCount := call .NotificationUnreadCount ctx}}
3+
{{$notificationUnreadCount := call .PageGlobalData.GetNotificationUnreadCount}}
44
<div class="tw-flex tw-items-center tw-justify-between tw-mb-[--page-spacing]">
55
<div class="small-menu-items ui compact tiny menu">
66
<a class="{{if eq .Status 1}}active {{end}}item" href="{{AppSubUrl}}/notifications?q=unread">

tests/integration/integration_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ func (s *TestSession) GetCookieFlashMessage() *middleware.Flash {
148148

149149
func (s *TestSession) MakeRequest(t testing.TB, rw *RequestWrapper, expectedStatus int) *httptest.ResponseRecorder {
150150
t.Helper()
151+
if s == nil {
152+
return MakeRequest(t, rw, expectedStatus)
153+
}
151154
req := rw.Request
152155
baseURL, err := url.Parse(setting.AppURL)
153156
assert.NoError(t, err)

tests/integration/links_test.go

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,38 +17,48 @@ import (
1717
"github.com/stretchr/testify/assert"
1818
)
1919

20-
func TestLinksNoLogin(t *testing.T) {
20+
func assertLinkPageComplete(t *testing.T, session *TestSession, link string) {
21+
req := NewRequest(t, "GET", link)
22+
resp := session.MakeRequest(t, req, http.StatusOK)
23+
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()), "Page did not complete: "+link)
24+
}
25+
26+
func TestLinks(t *testing.T) {
2127
defer tests.PrepareTestEnv(t)()
2228

29+
t.Run("NoLogin", testLinksNoLogin)
30+
t.Run("RedirectsNoLogin", testLinksRedirectsNoLogin)
31+
t.Run("NoLoginNotExist", testLinksNoLoginNotExist)
32+
t.Run("AsUser", testLinksAsUser)
33+
t.Run("RepoCommon", testLinksRepoCommon)
34+
}
35+
36+
func testLinksNoLogin(t *testing.T) {
2337
links := []string{
38+
"/",
2439
"/explore/repos",
2540
"/explore/repos?q=test",
2641
"/explore/users",
2742
"/explore/users?q=test",
2843
"/explore/organizations",
2944
"/explore/organizations?q=test",
30-
"/",
3145
"/user/sign_up",
3246
"/user/login",
3347
"/user/forgot_password",
34-
"/api/swagger",
3548
"/user2/repo1",
3649
"/user2/repo1/",
3750
"/user2/repo1/projects",
3851
"/user2/repo1/projects/1",
3952
"/user2/repo1/releases/tag/delete-tag", // It's the only one existing record on release.yml which has is_tag: true
40-
"/.well-known/security.txt",
53+
"/api/swagger",
4154
}
42-
4355
for _, link := range links {
44-
req := NewRequest(t, "GET", link)
45-
MakeRequest(t, req, http.StatusOK)
56+
assertLinkPageComplete(t, nil, link)
4657
}
58+
MakeRequest(t, NewRequest(t, "GET", "/.well-known/security.txt"), http.StatusOK)
4759
}
4860

49-
func TestRedirectsNoLogin(t *testing.T) {
50-
defer tests.PrepareTestEnv(t)()
51-
61+
func testLinksRedirectsNoLogin(t *testing.T) {
5262
redirects := []struct{ from, to string }{
5363
{"/user2/repo1/commits/master", "/user2/repo1/commits/branch/master"},
5464
{"/user2/repo1/src/master", "/user2/repo1/src/branch/master"},
@@ -68,9 +78,7 @@ func TestRedirectsNoLogin(t *testing.T) {
6878
}
6979
}
7080

71-
func TestNoLoginNotExist(t *testing.T) {
72-
defer tests.PrepareTestEnv(t)()
73-
81+
func testLinksNoLoginNotExist(t *testing.T) {
7482
links := []string{
7583
"/user5/repo4/projects",
7684
"/user5/repo4/projects/3",
@@ -82,7 +90,8 @@ func TestNoLoginNotExist(t *testing.T) {
8290
}
8391
}
8492

85-
func testLinksAsUser(userName string, t *testing.T) {
93+
func testLinksAsUser(t *testing.T) {
94+
session := loginUser(t, "user2")
8695
links := []string{
8796
"/explore/repos",
8897
"/explore/repos?q=test",
@@ -130,18 +139,14 @@ func testLinksAsUser(userName string, t *testing.T) {
130139
"/user/settings/repos",
131140
}
132141

133-
session := loginUser(t, userName)
134142
for _, link := range links {
135-
req := NewRequest(t, "GET", link)
136-
session.MakeRequest(t, req, http.StatusOK)
143+
assertLinkPageComplete(t, session, link)
137144
}
138145

139-
reqAPI := NewRequestf(t, "GET", "/api/v1/users/%s/repos", userName)
146+
reqAPI := NewRequestf(t, "GET", "/api/v1/users/user2/repos")
140147
respAPI := MakeRequest(t, reqAPI, http.StatusOK)
141-
142148
var apiRepos []*api.Repository
143149
DecodeJSON(t, respAPI, &apiRepos)
144-
145150
repoLinks := []string{
146151
"",
147152
"/issues",
@@ -164,24 +169,15 @@ func testLinksAsUser(userName string, t *testing.T) {
164169
"/wiki/?action=_new",
165170
"/activity",
166171
}
167-
168172
for _, repo := range apiRepos {
169173
for _, link := range repoLinks {
170-
req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s%s", userName, repo.Name, link))
171-
session.MakeRequest(t, req, http.StatusOK)
174+
link = fmt.Sprintf("/user2/%s%s", repo.Name, link)
175+
assertLinkPageComplete(t, session, link)
172176
}
173177
}
174178
}
175179

176-
func TestLinksLogin(t *testing.T) {
177-
defer tests.PrepareTestEnv(t)()
178-
179-
testLinksAsUser("user2", t)
180-
}
181-
182-
func TestRepoLinks(t *testing.T) {
183-
defer tests.PrepareTestEnv(t)()
184-
180+
func testLinksRepoCommon(t *testing.T) {
185181
// repo1 has enabled almost features, so we can test most links
186182
repoLink := "/user2/repo1"
187183
links := []string{
@@ -192,21 +188,18 @@ func TestRepoLinks(t *testing.T) {
192188

193189
// anonymous user
194190
for _, link := range links {
195-
req := NewRequest(t, "GET", repoLink+link)
196-
MakeRequest(t, req, http.StatusOK)
191+
assertLinkPageComplete(t, nil, repoLink+link)
197192
}
198193

199194
// admin/owner user
200195
session := loginUser(t, "user1")
201196
for _, link := range links {
202-
req := NewRequest(t, "GET", repoLink+link)
203-
session.MakeRequest(t, req, http.StatusOK)
197+
assertLinkPageComplete(t, session, repoLink+link)
204198
}
205199

206200
// non-admin non-owner user
207201
session = loginUser(t, "user2")
208202
for _, link := range links {
209-
req := NewRequest(t, "GET", repoLink+link)
210-
session.MakeRequest(t, req, http.StatusOK)
203+
assertLinkPageComplete(t, session, repoLink+link)
211204
}
212205
}

web_src/css/modules/navbar.css

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,6 @@
101101
}
102102
}
103103

104-
#navbar .ui.dropdown .navbar-profile-admin {
105-
display: block;
106-
position: absolute;
107-
font-size: 9px;
108-
font-weight: var(--font-weight-bold);
109-
color: var(--color-nav-bg);
110-
background: var(--color-primary);
111-
padding: 2px 3px;
112-
border-radius: 10px;
113-
top: -1px;
114-
left: 18px;
115-
}
116-
117104
#navbar a.item:hover .notification_count,
118105
#navbar a.item:hover .header-stopwatch-dot {
119106
border-color: var(--color-nav-hover-bg);

0 commit comments

Comments
 (0)