ui: improve release editing (#9940)

Converted 8 buttons, fixed a few bugs with markdown editor, added some testing for template logic. The fixes are not auto-testable within reasonable effort and the changes like button conversion have nothing specific to be tested for.

### Convert form buttons to new buttons

|Before|After|
|-|-|
|![](/attachments/2e372363-4997-4831-9edb-e1a2c4839eb7)|![](/attachments/31c7be64-8f70-4287-b889-9055bc4a7a42)|

### Justify "Delete release" button away from other buttons

|Before|![](/attachments/e55124ee-b6e0-4098-ac06-d5ad8ada671f)|
|-|-|
|After|![](/attachments/22ea09b5-c6e2-4a02-ae77-d92e1dbe7a72)|

|Before|![](/attachments/2ad14280-676b-4341-ae85-a7036ea5ace2)|
|-|-|
|After|![](/attachments/6cbe7c70-8efd-4b35-bb12-21a19eaafa67)|

### Fix markdown editor on mobile

|Before|After|
|-|-|
|![](/attachments/21ed3b55-ea88-446f-b074-6242b07a38e1)|![](/attachments/d033b67f-c8bb-42e7-96a9-de48289e1ba2)|

### Buttons preview on mobile

|Before|After|Before|After|
|-|-|-|-|
|![](/attachments/2795d62c-e909-457d-9e52-81a76ab6531f)|![](/attachments/af6e534e-5300-42d6-93c3-4b763039e2ae)|![](/attachments/7812d273-c371-4ed1-8054-a80c0cfc2518)|![](/attachments/a98e8ad3-818d-4254-b9cd-70c81dd40fb9)|

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9940
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
0ko
2025-11-30 05:08:24 +01:00
parent 9bca858c42
commit 6edfeb60f9
4 changed files with 80 additions and 39 deletions
+32 -22
View File
@@ -131,34 +131,44 @@
{{end}}
</fieldset>
<div class="divider tw-mt-0"></div>
<div class="tw-flex tw-justify-end button-row">
{{if .PageIsEditRelease}}
<a class="ui small button" href="{{.RepoLink}}/releases">
{{ctx.Locale.Tr "repo.release.cancel"}}
</a>
<a class="ui small red button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}" data-modal-id="delete-release">
{{if .PageIsEditRelease}}
<div class="button-sequence tw-justify-between">
<a class="danger button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}" data-modal-id="delete-release">
{{ctx.Locale.Tr "repo.release.delete_release"}}
</a>
{{if .IsDraft}}
<button class="ui small button" type="submit" name="draft" value="{{ctx.Locale.Tr "repo.release.save_draft"}}">{{ctx.Locale.Tr "repo.release.save_draft"}}</button>
<button class="ui small primary button">
{{ctx.Locale.Tr "repo.release.publish"}}
</button>
{{else}}
<button class="ui small primary button">
{{ctx.Locale.Tr "repo.release.edit_release"}}
</button>
{{end}}
{{else}}
<div class="button-sequence">
<a class="secondary button" href="{{.RepoLink}}/releases">
{{ctx.Locale.Tr "repo.release.cancel"}}
</a>
{{if .IsDraft}}
<button class="secondary button" type="submit" name="draft" value="{{ctx.Locale.Tr "repo.release.save_draft"}}">
{{ctx.Locale.Tr "repo.release.save_draft"}}
</button>
<button class="primary button">
{{ctx.Locale.Tr "repo.release.publish"}}
</button>
{{else}}
<button class="primary button">
{{ctx.Locale.Tr "repo.release.edit_release"}}
</button>
{{end}}
</div>
</div>
{{else}}
<div class="button-sequence tw-justify-end">
{{if not .tag_name}}
<button class="ui small button" name="tag_only" value="1">{{ctx.Locale.Tr "repo.release.add_tag"}}</button>
<button class="secondary button" name="tag_only" value="1">
{{ctx.Locale.Tr "repo.release.add_tag"}}
</button>
{{end}}
<button class="ui small button" name="draft" value="1">{{ctx.Locale.Tr "repo.release.save_draft"}}</button>
<button class="ui small primary button">
<button class="secondary button" name="draft" value="1">
{{ctx.Locale.Tr "repo.release.save_draft"}}
</button>
<button class="primary button">
{{ctx.Locale.Tr "repo.release.publish"}}
</button>
{{end}}
</div>
</div>
{{end}}
</div>
</div>
</form>
+5 -5
View File
@@ -19,9 +19,9 @@ test.describe('Releases', () => {
test('External Release Attachments', async ({page, isMobile}) => {
test.skip(isMobile);
// Click "New Release"
// Click "New release"
await page.goto('/user2/repo2/releases');
await page.click('.button.small.primary');
await page.getByRole('link', {name: 'New release'}).click();
// Fill out form and create new release
await expect(page).toHaveURL('/user2/repo2/releases/new');
@@ -35,7 +35,7 @@ test.describe('Releases', () => {
await page.fill('input[name=attachment-new-exturl-2]', 'https://forgejo.org/');
await page.click('.remove-rel-attach');
await screenshot(page);
await page.click('.button.small.primary');
await page.getByRole('button', {name: 'Publish release'}).click();
// Validate release page and click edit
await expect(page).toHaveURL('/user2/repo2/releases');
@@ -69,7 +69,7 @@ test.describe('Releases', () => {
await page.locator('.attachment_edit:visible').nth(2).fill('Test3');
await page.locator('.attachment_edit:visible').nth(3).fill('https://gitea.com/');
await screenshot(page);
await page.click('.button.small.primary');
await page.getByRole('button', {name: 'Update release'}).click();
// Validate release page and click edit
await expect(page).toHaveURL('/user2/repo2/releases');
@@ -95,7 +95,7 @@ test.describe('Releases', () => {
await page.locator('input[name=title]').pressSequentially('v2.0');
await page.locator('input[name=tag_name]').pressSequentially('2.0');
await page.click('.button.small.primary');
await page.getByRole('button', {name: 'Publish release'}).click();
await page.goto('/user2/repo2/releases/edit/2.0');
+43 -2
View File
@@ -34,9 +34,18 @@ func createNewRelease(t *testing.T, session *TestSession, repoURL, tag, title st
func createNewReleaseTarget(t *testing.T, session *TestSession, repoURL, tag, title, target string, preRelease, draft bool) {
req := NewRequest(t, "GET", repoURL+"/releases/new")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
page := NewHTMLParser(t, resp.Body)
link, exists := htmlDoc.doc.Find("form.ui.form").Attr("action")
// Buttons that should be present
page.AssertElement(t, `form button[name="tag_only"]`, true) // Create tag
page.AssertElement(t, `form button[name="draft"]`, true) // Save draft
assert.Contains(t, page.Find(`form .primary.button`).Text(), "Publish release")
// Buttons that should not be present
page.AssertElement(t, `form a.danger.button[data-modal-id="delete-release"]`, false)
page.AssertElement(t, `form a.button[href$="/releases"]`, false) // Cancel
link, exists := page.Find("form.ui.form").Attr("action")
assert.True(t, exists, "The template has changed")
postData := map[string]string{
@@ -179,6 +188,38 @@ func TestCreateReleaseDraft(t *testing.T) {
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").TrString("repo.release.draft"), 4)
}
func TestEditRelease(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
page := NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases/edit/v1.0"), http.StatusOK).Body)
// Buttons that should be present
page.AssertElement(t, `form .danger.button[data-modal-id="delete-release"]`, true)
page.AssertElement(t, `form a.button[href$="/releases"]`, true) // Cancel
assert.Contains(t, page.Find(`form .primary.button`).Text(), "Update release")
// Buttons that should not be present
page.AssertElement(t, `form button[name="draft"]`, false) // Save draft
page.AssertElement(t, `form button[name="tag_only"]`, false) // Create tag
}
func TestEditReleaseDraft(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
page := NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases/edit/draft-release"), http.StatusOK).Body)
// Buttons that should be present
page.AssertElement(t, `form a.danger.button[data-modal-id="delete-release"]`, true)
page.AssertElement(t, `form a.button[href$="/releases"]`, true) // Cancel
page.AssertElement(t, `form .button[name="draft"]`, true) // Save draft
assert.Contains(t, page.Find(`form .primary.button`).Text(), "Publish release")
// Buttons that should not be present
page.AssertElement(t, `form button[name="tag_only"]`, false) // Create tag
}
func TestCreateReleasePaging(t *testing.T) {
defer tests.PrepareTestEnv(t)()
-10
View File
@@ -99,17 +99,7 @@
padding-bottom: 10px;
}
@media (max-width: 438px) {
.repository.new.release .field button,
.repository.new.release .field input {
width: 100%;
}
}
@media (max-width: 767.98px) {
.repository.new.release .field button {
margin-bottom: 1em;
}
.release-list-search {
order: 2 !important;
}