mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-04-23 15:39:22 +00:00
fix(ui): Fix disabled create repository button on create repo form (#7341)
- Previously, the Create Repository button was only enabled if a user was able to create a repo in their own namespace. However, if they had reached the repo limit, but were stll able to create a repo in an org, the button would still be disabled. - Resolves #7341 - Add Integration Tests to the create repo form Signed-off-by: Ryan Lerch <rlerch@redhat.com>
This commit is contained in:
parent
442958df1d
commit
fe657f5faa
5 changed files with 116 additions and 42 deletions
|
@ -93,7 +93,7 @@
|
||||||
login_name: org3
|
login_name: org3
|
||||||
type: 1
|
type: 1
|
||||||
salt: ZogKvWdyEx
|
salt: ZogKvWdyEx
|
||||||
max_repo_creation: -1
|
max_repo_creation: 1000
|
||||||
is_active: false
|
is_active: false
|
||||||
is_admin: false
|
is_admin: false
|
||||||
is_restricted: false
|
is_restricted: false
|
||||||
|
|
|
@ -21,5 +21,6 @@
|
||||||
"alert.asset_load_failed": "Failed to load asset files from {path}. Please make sure the asset files can be accessed.",
|
"alert.asset_load_failed": "Failed to load asset files from {path}. Please make sure the asset files can be accessed.",
|
||||||
"alert.range_error": " must be a number between %[1]s and %[2]s.",
|
"alert.range_error": " must be a number between %[1]s and %[2]s.",
|
||||||
"install.invalid_lfs_path": "Unable to create the LFS root at the specified path: %[1]s",
|
"install.invalid_lfs_path": "Unable to create the LFS root at the specified path: %[1]s",
|
||||||
|
"repo.form.cannot_create": "The owner has already reached the repository limit. If you can create organization repositories, those organizations have also reached their limit.",
|
||||||
"meta.last_line": "Thank you for translating Forgejo! This line isn't seen by the users but it serves other purposes in the translation management. You can place a fun fact in the translation instead of translating it."
|
"meta.last_line": "Thank you for translating Forgejo! This line isn't seen by the users but it serves other purposes in the translation management. You can place a fun fact in the translation instead of translating it."
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,42 +8,48 @@
|
||||||
{{ctx.Locale.Tr "new_repo.title"}}
|
{{ctx.Locale.Tr "new_repo.title"}}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
{{template "base/alert" .}}
|
{{if or .CanCreateRepo .Orgs}}
|
||||||
{{template "repo/create_helper" .}}
|
{{template "base/alert" .}}
|
||||||
|
{{template "repo/create_helper" .}}
|
||||||
|
|
||||||
{{if not .CanCreateRepo}}
|
{{if and (not .CanCreateRepo) (ne .MaxCreationLimit 0)}}
|
||||||
|
<div class="ui negative message">
|
||||||
|
<p>{{ctx.Locale.TrN .MaxCreationLimit "repo.form.reach_limit_of_creation_1" "repo.form.reach_limit_of_creation_n" .MaxCreationLimit}}</p>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<fieldset>
|
||||||
|
{{template "repo/create_basic" .}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
{{ctx.Locale.Tr "repo.new_from_template"}}
|
||||||
|
<span class="help">{{ctx.Locale.Tr "repo.new_from_template_description"}}</span>
|
||||||
|
</legend>
|
||||||
|
{{template "repo/create_from_template" .}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div id="non_template">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{ctx.Locale.Tr "repo.auto_init"}}</legend>
|
||||||
|
{{template "repo/create_init" .}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{ctx.Locale.Tr "repo.new_advanced"}}</legend>
|
||||||
|
<details><summary>{{ctx.Locale.Tr "repo.new_advanced_expand"}}</summary>
|
||||||
|
{{template "repo/create_advanced" .}}
|
||||||
|
</details>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<button class="ui primary button">
|
||||||
|
{{ctx.Locale.Tr "repo.create_repo"}}
|
||||||
|
</button>
|
||||||
|
{{else}}
|
||||||
<div class="ui negative message">
|
<div class="ui negative message">
|
||||||
<p>{{ctx.Locale.TrN .MaxCreationLimit "repo.form.reach_limit_of_creation_1" "repo.form.reach_limit_of_creation_n" .MaxCreationLimit}}</p>
|
{{ctx.Locale.Tr "repo.form.cannot_create"}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<fieldset>
|
|
||||||
{{template "repo/create_basic" .}}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>
|
|
||||||
{{ctx.Locale.Tr "repo.new_from_template"}}
|
|
||||||
<span class="help">{{ctx.Locale.Tr "repo.new_from_template_description"}}</span>
|
|
||||||
</legend>
|
|
||||||
{{template "repo/create_from_template" .}}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div id="non_template">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{ctx.Locale.Tr "repo.auto_init"}}</legend>
|
|
||||||
{{template "repo/create_init" .}}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{ctx.Locale.Tr "repo.new_advanced"}}</legend>
|
|
||||||
<details><summary>{{ctx.Locale.Tr "repo.new_advanced_expand"}}</summary>
|
|
||||||
{{template "repo/create_advanced" .}}
|
|
||||||
</details>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<button class="ui primary button{{if not .CanCreateRepo}} disabled{{end}}">
|
|
||||||
{{ctx.Locale.Tr "repo.create_repo"}}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,17 +2,27 @@
|
||||||
{{ctx.Locale.Tr "repo.owner"}}
|
{{ctx.Locale.Tr "repo.owner"}}
|
||||||
<div class="ui selection required dropdown" aria-labelledby="repo_owner_label">
|
<div class="ui selection required dropdown" aria-labelledby="repo_owner_label">
|
||||||
{{/* uid id is used by the repo-template code */}}
|
{{/* uid id is used by the repo-template code */}}
|
||||||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
|
{{if .CanCreateRepo}}
|
||||||
<span class="text truncated-item-container" title="{{.ContextUser.Name}}">
|
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
|
||||||
{{ctx.AvatarUtils.Avatar .ContextUser 28 "mini"}}
|
<span class="text truncated-item-container" title="{{.ContextUser.Name}}">
|
||||||
<span class="truncated-item-name">{{.ContextUser.ShortName 40}}</span>
|
{{ctx.AvatarUtils.Avatar .ContextUser 28 "mini"}}
|
||||||
</span>
|
<span class="truncated-item-name">{{.ContextUser.ShortName 40}}</span>
|
||||||
|
</span>
|
||||||
|
{{else if .Orgs}}
|
||||||
|
<input type="hidden" id="uid" name="uid" value="{{(index .Orgs 0).ID}}" required>
|
||||||
|
<span class="text truncated-item-container" title="{{(index .Orgs 0).Name}}">
|
||||||
|
{{ctx.AvatarUtils.Avatar (index .Orgs 0) 28 "mini"}}
|
||||||
|
<span class="truncated-item-name">{{(index .Orgs 0).ShortName 40}}</span>
|
||||||
|
</span>
|
||||||
|
{{end}}
|
||||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item truncated-item-container" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}">
|
{{if .CanCreateRepo}}
|
||||||
{{ctx.AvatarUtils.Avatar .SignedUser 28 "mini"}}
|
<div class="item truncated-item-container" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}">
|
||||||
<span class="truncated-item-name">{{.SignedUser.ShortName 40}}</span>
|
{{ctx.AvatarUtils.Avatar .SignedUser 28 "mini"}}
|
||||||
</div>
|
<span class="truncated-item-name">{{.SignedUser.ShortName 40}}</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
{{range .Orgs}}
|
{{range .Orgs}}
|
||||||
<div class="item truncated-item-container" data-value="{{.ID}}" title="{{.Name}}">
|
<div class="item truncated-item-container" data-value="{{.ID}}" title="{{.Name}}">
|
||||||
{{ctx.AvatarUtils.Avatar . 28 "mini"}}
|
{{ctx.AvatarUtils.Avatar . 28 "mini"}}
|
||||||
|
|
|
@ -126,6 +126,63 @@ func TestRepoCreateForm(t *testing.T) {
|
||||||
assertRepoCreateForm(t, htmlDoc, user, "")
|
assertRepoCreateForm(t, htmlDoc, user, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRepoCreateFormRepoLimit(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "org3"})
|
||||||
|
userName := "user2"
|
||||||
|
session := loginUser(t, userName)
|
||||||
|
locale := translation.NewLocale("en-US")
|
||||||
|
cannotCreateTr := locale.Tr("repo.form.cannot_create")
|
||||||
|
|
||||||
|
// Test the case where a user has hit the global max creation limit, but can still create
|
||||||
|
// a repo in an organization. Because the limit is greater than 0 we also show an alert
|
||||||
|
// to tell the user they have hit the limit.
|
||||||
|
t.Run("Limit above zero", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
maxCreationLimit := 1
|
||||||
|
creationLimitTr := locale.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
|
||||||
|
defer test.MockVariableValue(&setting.Repository.MaxCreationLimit, maxCreationLimit)()
|
||||||
|
|
||||||
|
resp := session.MakeRequest(t, NewRequest(t, "GET", "/repo/create"), http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
assertRepoCreateForm(t, htmlDoc, org, "")
|
||||||
|
|
||||||
|
alert := htmlDoc.doc.Find("div.ui.negative.message").Text()
|
||||||
|
assert.Contains(t, alert, creationLimitTr)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test the case where a user has hit the global max creation limit, but can still create
|
||||||
|
// a repo in an organization. Because the limit is 0 we DO NOT show the alert.
|
||||||
|
t.Run("Limit is zero", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
maxCreationLimit := 0
|
||||||
|
defer test.MockVariableValue(&setting.Repository.MaxCreationLimit, maxCreationLimit)()
|
||||||
|
|
||||||
|
resp := session.MakeRequest(t, NewRequest(t, "GET", "/repo/create"), http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
assertRepoCreateForm(t, htmlDoc, org, "")
|
||||||
|
|
||||||
|
htmlDoc.AssertElement(t, "div.ui.negative.message", false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test the case where a user has hit the global max creation limit, and also cannot create
|
||||||
|
// a repo in any of their orgs. The form isnt shown, and we deisplay an alert telling the user
|
||||||
|
// they can't create a repo.
|
||||||
|
t.Run("Global limit", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
maxCreationLimit := 0
|
||||||
|
defer test.MockVariableValue(&setting.Repository.MaxCreationLimit, maxCreationLimit)()
|
||||||
|
|
||||||
|
session := loginUser(t, "user8")
|
||||||
|
|
||||||
|
resp := session.MakeRequest(t, NewRequest(t, "GET", "/repo/create"), http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
|
alert := htmlDoc.doc.Find("div.ui.negative.message").Text()
|
||||||
|
assert.Contains(t, alert, cannotCreateTr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestRepoGenerate(t *testing.T) {
|
func TestRepoGenerate(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
userName := "user1"
|
userName := "user1"
|
||||||
|
|
Loading…
Add table
Reference in a new issue