Skip to content

Commit f4fd294

Browse files
committed
optimize ui
1 parent 0bd9c09 commit f4fd294

File tree

8 files changed

+98
-87
lines changed

8 files changed

+98
-87
lines changed

models/auth/access_token_scope.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package auth
55

66
import (
77
"fmt"
8+
"slices"
89
"strings"
910

1011
"code.gitea.io/gitea/models/perm"
@@ -197,6 +198,7 @@ func GetAccessTokenCategories() (res []string) {
197198
for _, cat := range accessTokenScopes[Read] {
198199
res = append(res, strings.TrimPrefix(string(cat), "read:"))
199200
}
201+
slices.Sort(res)
200202
return res
201203
}
202204

options/locale/locale_en-US.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,6 @@ delete_token_success = The token has been deleted. Applications using it no long
917917
repo_and_org_access = Repository and Organization Access
918918
permissions_public_only = Public only
919919
permissions_access_all = All (public, private, and limited)
920-
select_permissions = Select permissions
921920
permission_not_set = Not set
922921
permission_no_access = No Access
923922
permission_read = Read

routers/web/user/setting/applications.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package setting
66

77
import (
88
"net/http"
9+
"strings"
910

1011
auth_model "code.gitea.io/gitea/models/auth"
1112
"code.gitea.io/gitea/models/db"
@@ -40,18 +41,29 @@ func ApplicationsPost(ctx *context.Context) {
4041
ctx.Data["PageIsSettingsApplications"] = true
4142
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
4243

43-
if ctx.HasError() {
44-
loadApplicationsData(ctx)
45-
46-
ctx.HTML(http.StatusOK, tplSettingsApplications)
47-
return
44+
_ = ctx.Req.ParseForm()
45+
var scopeNames []string
46+
for k, v := range ctx.Req.Form {
47+
if strings.HasPrefix(k, "scope-") {
48+
scopeNames = append(scopeNames, v...)
49+
}
4850
}
4951

50-
scope, err := form.GetScope()
52+
scope, err := auth_model.AccessTokenScope(strings.Join(scopeNames, ",")).Normalize()
5153
if err != nil {
5254
ctx.ServerError("GetScope", err)
5355
return
5456
}
57+
if scope == "" {
58+
ctx.Flash.Error(ctx.Tr("settings.at_least_one_permission"), true)
59+
}
60+
61+
if ctx.HasError() {
62+
loadApplicationsData(ctx)
63+
ctx.HTML(http.StatusOK, tplSettingsApplications)
64+
return
65+
}
66+
5567
t := &auth_model.AccessToken{
5668
UID: ctx.Doer.ID,
5769
Name: form.Name,

services/context/context.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ func Contexter() func(next http.Handler) http.Handler {
213213
// Attention: this function changes ctx.Data and ctx.Flash
214214
// If HasError is called, then before Redirect, the error message should be stored by ctx.Flash.Error(ctx.GetErrMsg()) again.
215215
func (ctx *Context) HasError() bool {
216-
hasErr, ok := ctx.Data["HasError"]
217-
if !ok {
218-
return false
216+
hasErr, _ := ctx.Data["HasError"].(bool)
217+
hasErr = hasErr || ctx.Flash.ErrorMsg != ""
218+
if ctx.Flash.ErrorMsg == "" {
219+
ctx.Flash.ErrorMsg = ctx.GetErrMsg()
219220
}
220-
ctx.Flash.ErrorMsg = ctx.GetErrMsg()
221221
ctx.Data["Flash"] = ctx.Flash
222-
return hasErr.(bool)
222+
return hasErr
223223
}
224224

225225
// GetErrMsg returns error message in form validation.

services/forms/user_form.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ package forms
77
import (
88
"mime/multipart"
99
"net/http"
10-
"strings"
1110

12-
auth_model "code.gitea.io/gitea/models/auth"
1311
user_model "code.gitea.io/gitea/models/user"
1412
"code.gitea.io/gitea/modules/structs"
1513
"code.gitea.io/gitea/modules/web/middleware"
@@ -347,8 +345,7 @@ func (f *EditVariableForm) Validate(req *http.Request, errs binding.Errors) bind
347345

348346
// NewAccessTokenForm form for creating access token
349347
type NewAccessTokenForm struct {
350-
Name string `binding:"Required;MaxSize(255)" locale:"settings.token_name"`
351-
Scope []string
348+
Name string `binding:"Required;MaxSize(255)" locale:"settings.token_name"`
352349
}
353350

354351
// Validate validates the fields
@@ -357,12 +354,6 @@ func (f *NewAccessTokenForm) Validate(req *http.Request, errs binding.Errors) bi
357354
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
358355
}
359356

360-
func (f *NewAccessTokenForm) GetScope() (auth_model.AccessTokenScope, error) {
361-
scope := strings.Join(f.Scope, ",")
362-
s, err := auth_model.AccessTokenScope(scope).Normalize()
363-
return s, err
364-
}
365-
366357
// EditOAuth2ApplicationForm form for editing oauth2 applications
367358
type EditOAuth2ApplicationForm struct {
368359
Name string `binding:"Required;MaxSize(255)" form:"application_name"`

templates/user/settings/applications.tmpl

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -50,44 +50,41 @@
5050
</div>
5151
</div>
5252
<div class="ui bottom attached segment">
53-
<h5 class="ui top header">
54-
{{ctx.Locale.Tr "settings.generate_new_token"}}
55-
</h5>
56-
<form id="scoped-access-form" class="ui form ignore-dirty" action="{{.Link}}" method="post">
57-
{{.CsrfTokenHtml}}
58-
<div class="field {{if .Err_Name}}error{{end}}">
59-
<label for="name">{{ctx.Locale.Tr "settings.token_name"}}</label>
60-
<input id="name" name="name" value="{{.name}}" autofocus required maxlength="255">
61-
</div>
62-
<div class="field">
63-
<label>{{ctx.Locale.Tr "settings.repo_and_org_access"}}</label>
64-
<label class="tw-cursor-pointer">
65-
<input class="enable-system tw-mt-1 tw-mr-1" type="radio" name="scope" value="{{$.AccessTokenScopePublicOnly}}">
66-
{{ctx.Locale.Tr "settings.permissions_public_only"}}
67-
</label>
68-
<label class="tw-cursor-pointer">
69-
<input class="enable-system tw-mt-1 tw-mr-1" type="radio" name="scope" value="" checked>
70-
{{ctx.Locale.Tr "settings.permissions_access_all"}}
71-
</label>
72-
</div>
73-
<details class="ui field tw-pl-1">
74-
<summary>{{ctx.Locale.Tr "settings.select_permissions"}}</summary>
75-
<i class="tw-block tw-my-2">{{ctx.Locale.Tr "settings.access_token_desc" (HTMLFormat `href="%s/api/swagger" target="_blank"` AppSubUrl) (`href="https://docs.gitea.com/development/oauth2-provider#scopes" target="_blank"`|SafeHTML)}}</i>
76-
{{range $category := .TokenCategories}}
77-
<div class="tw-my-2">
78-
<label for="access-token-scope-{{$category}}">{{$category}}</label>
79-
<select name="scope" id="access-token-scope-{{$category}}">
80-
<option value="">{{ctx.Locale.Tr "settings.permission_no_access"}}</option>
81-
<option value="read:{{$category}}">{{ctx.Locale.Tr "settings.permission_read"}}</option>
82-
<option value="write:{{$category}}">{{ctx.Locale.Tr "settings.permission_write"}}</option>
83-
</select>
84-
</div>
85-
{{end}}
86-
</details>
87-
<button class="ui primary button">
88-
{{ctx.Locale.Tr "settings.generate_token"}}
89-
</button>
90-
</form>
53+
<details {{if or .name (not .Tokens)}}open{{end}}>
54+
<summary><h4 class="ui header tw-inline-block tw-my-2">{{ctx.Locale.Tr "settings.generate_new_token"}}</h4></summary>
55+
<form class="ui form ignore-dirty" action="{{.Link}}" method="post">
56+
{{.CsrfTokenHtml}}
57+
<div class="field {{if .Err_Name}}error{{end}}">
58+
<label for="name">{{ctx.Locale.Tr "settings.token_name"}}</label>
59+
<input id="name" name="name" value="{{.name}}" required maxlength="255">
60+
</div>
61+
<div class="field">
62+
<div class="tw-my-2">{{ctx.Locale.Tr "settings.repo_and_org_access"}}</div>
63+
<label class="gt-checkbox">
64+
<input type="radio" name="scope" value="{{$.AccessTokenScopePublicOnly}}"> {{ctx.Locale.Tr "settings.permissions_public_only"}}
65+
</label>
66+
<label class="gt-checkbox">
67+
<input type="radio" name="scope" value="" checked> {{ctx.Locale.Tr "settings.permissions_access_all"}}
68+
</label>
69+
</div>
70+
<div>
71+
<div class="tw-my-2">{{ctx.Locale.Tr "settings.access_token_desc" (HTMLFormat `href="%s/api/swagger" target="_blank"` AppSubUrl) (`href="https://docs.gitea.com/development/oauth2-provider#scopes" target="_blank"`|SafeHTML)}}</div>
72+
<table class="ui table unstackable tw-my-2">
73+
{{range $category := .TokenCategories}}
74+
<tr>
75+
<td>{{$category}}</td>
76+
<td><label class="gt-checkbox"><input type="radio" name="scope-{{$category}}" value="" checked> {{ctx.Locale.Tr "settings.permission_no_access"}}</label></td>
77+
<td><label class="gt-checkbox"><input type="radio" name="scope-{{$category}}" value="read:{{$category}}"> {{ctx.Locale.Tr "settings.permission_read"}}</label></td>
78+
<td><label class="gt-checkbox"><input type="radio" name="scope-{{$category}}" value="write:{{$category}}"> {{ctx.Locale.Tr "settings.permission_write"}}</label></td>
79+
</tr>
80+
{{end}}
81+
</table>
82+
</div>
83+
<button class="ui primary button">
84+
{{ctx.Locale.Tr "settings.generate_token"}}
85+
</button>
86+
</form>
87+
</details>
9188
</div>
9289

9390
{{if .EnableOAuth2}}

templates/user/settings/applications_oauth2_list.tmpl

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,33 @@
4848
</div>
4949

5050
<div class="ui bottom attached segment">
51-
<h5 class="ui top header">
52-
{{ctx.Locale.Tr "settings.create_oauth2_application"}}
53-
</h5>
54-
<form class="ui form ignore-dirty" action="{{.Link}}/oauth2" method="post">
55-
{{.CsrfTokenHtml}}
56-
<div class="field {{if .Err_AppName}}error{{end}}">
57-
<label for="application-name">{{ctx.Locale.Tr "settings.oauth2_application_name"}}</label>
58-
<input id="application-name" name="application_name" value="{{.application_name}}" required maxlength="255">
59-
</div>
60-
<div class="field {{if .Err_RedirectURI}}error{{end}}">
61-
<label for="redirect-uris">{{ctx.Locale.Tr "settings.oauth2_redirect_uris"}}</label>
62-
<textarea name="redirect_uris" id="redirect-uris"></textarea>
63-
</div>
64-
<div class="field {{if .Err_ConfidentialClient}}error{{end}}">
65-
<div class="ui checkbox">
66-
<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label>
67-
<input class="disable-setting" type="checkbox" name="confidential_client" data-target="#skip-secondary-authorization" checked>
51+
<details {{if .application_name}}open{{end}}>
52+
<summary><h4 class="ui header tw-inline-block tw-my-2">{{ctx.Locale.Tr "settings.create_oauth2_application"}}</h4></summary>
53+
<form class="ui form ignore-dirty" action="{{.Link}}/oauth2" method="post">
54+
{{.CsrfTokenHtml}}
55+
<div class="field {{if .Err_AppName}}error{{end}}">
56+
<label for="application-name">{{ctx.Locale.Tr "settings.oauth2_application_name"}}</label>
57+
<input id="application-name" name="application_name" value="{{.application_name}}" required maxlength="255">
6858
</div>
69-
</div>
70-
<div class="field {{if .Err_SkipSecondaryAuthorization}}error{{end}} disabled" id="skip-secondary-authorization">
71-
<div class="ui checkbox">
72-
<label>{{ctx.Locale.Tr "settings.oauth2_skip_secondary_authorization"}}</label>
73-
<input type="checkbox" name="skip_secondary_authorization">
59+
<div class="field {{if .Err_RedirectURI}}error{{end}}">
60+
<label for="redirect-uris">{{ctx.Locale.Tr "settings.oauth2_redirect_uris"}}</label>
61+
<textarea name="redirect_uris" id="redirect-uris"></textarea>
7462
</div>
75-
</div>
76-
<button class="ui primary button">
77-
{{ctx.Locale.Tr "settings.create_oauth2_application_button"}}
78-
</button>
79-
</form>
63+
<div class="field {{if .Err_ConfidentialClient}}error{{end}}">
64+
<div class="ui checkbox">
65+
<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label>
66+
<input class="disable-setting" type="checkbox" name="confidential_client" data-target="#skip-secondary-authorization" checked>
67+
</div>
68+
</div>
69+
<div class="field {{if .Err_SkipSecondaryAuthorization}}error{{end}} disabled" id="skip-secondary-authorization">
70+
<div class="ui checkbox">
71+
<label>{{ctx.Locale.Tr "settings.oauth2_skip_secondary_authorization"}}</label>
72+
<input type="checkbox" name="skip_secondary_authorization">
73+
</div>
74+
</div>
75+
<button class="ui primary button">
76+
{{ctx.Locale.Tr "settings.create_oauth2_application_button"}}
77+
</button>
78+
</form>
79+
</details>
8080
</div>

web_src/css/modules/checkbox.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,13 @@ input[type="radio"] {
119119
.ui.toggle.checkbox input:focus:checked ~ label::before {
120120
background: var(--color-primary) !important;
121121
}
122+
123+
label.gt-checkbox {
124+
display: inline-flex;
125+
align-items: center;
126+
gap: 0.25em;
127+
}
128+
129+
.ui.form .field > label.gt-checkbox {
130+
display: flex;
131+
}

0 commit comments

Comments
 (0)