Refactor "htmx" to "fetch action" (#37208)

The only remaining (hard) part is "templates/repo/editor/edit.tmpl", see the FIXME

By the way:

* Make "user unfollow" use basic color but not red color, indeed it is not dangerous
* Fix "org folllow" layout (use block gap instead of inline gap)
This commit is contained in:
wxiaoguang
2026-04-15 02:38:07 +08:00
committed by GitHub
parent 893df6b265
commit 17f62bfec5
10 changed files with 30 additions and 36 deletions

View File

@@ -5,7 +5,6 @@ package repo
import (
"net/http"
"strconv"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/log"
@@ -46,12 +45,7 @@ func IssueWatch(ctx *context.Context) {
return
}
watch, err := strconv.ParseBool(ctx.Req.PostFormValue("watch"))
if err != nil {
ctx.ServerError("watch is not bool", err)
return
}
watch := ctx.FormBool("watch")
if err := issues_model.CreateOrUpdateIssueWatch(ctx, ctx.Doer.ID, issue.ID, watch); err != nil {
ctx.ServerError("CreateOrUpdateIssueWatch", err)
return

View File

@@ -228,7 +228,7 @@ func (d *DiffLine) RenderBlobExcerptButtons(fileNameHash string, data *DiffBlobE
link += fmt.Sprintf("&pull_issue_index=%d", data.PullIssueIndex)
}
return htmlutil.HTMLFormat(
`<button class="code-expander-button" hx-target="closest tr" hx-get="%s" data-hidden-comment-ids=",%s,">%s</button>`,
`<button class="code-expander-button" data-fetch-sync="$closest(tr)" data-fetch-url="%s" data-hidden-comment-ids=",%s,">%s</button>`,
link, dataHiddenCommentIDs, svg.RenderHTML(svgName),
)
}

View File

@@ -23,7 +23,7 @@
{{template "base/head_script" .}}
{{template "custom/header" .}}
</head>
<body hx-swap="outerHTML" hx-push-url="false">
<body>
{{template "custom/body_outer_pre" .}}
<div class="full height">

View File

@@ -1,4 +1,4 @@
<button class="ui basic button tw-mr-0" hx-post="{{.Org.HomeLink}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}">
<button class="ui basic button" data-fetch-method="post" data-fetch-url="{{.Org.HomeLink}}?action={{if $.IsFollowing}}unfollow{{else}}follow{{end}}">
{{if $.IsFollowing}}
{{ctx.Locale.Tr "user.unfollow"}}
{{else}}

View File

@@ -7,9 +7,9 @@
{{if .Org.Visibility.IsLimited}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.limited_shortname"}}</span>{{end}}
{{if .Org.Visibility.IsPrivate}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.private_shortname"}}</span>{{end}}
</span>
<span class="flex-text-inline tw-ml-auto tw-text-16 tw-whitespace-nowrap">
<span class="flex-text-block tw-ml-auto tw-text-16 tw-whitespace-nowrap">
{{if .EnableFeed}}
<a class="ui basic label button tw-mr-0" href="{{.Org.HomeLink}}.rss" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
<a class="ui basic label button" href="{{.Org.HomeLink}}.rss" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
{{svg "octicon-rss" 24}}
</a>
{{end}}

View File

@@ -23,6 +23,8 @@
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.new_file"}}{{else}}{{ctx.Locale.Tr "repo.editor.edit_file"}}{{end}}</a>
<a class="item{{if not .CodeEditorConfig.Previewable}} tw-hidden{{end}}" data-tab="preview" data-preview-url="{{.Repository.Link}}/markup" data-preview-context-ref="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
{{if not .IsNewFile}}
{{/*FIXME: the related logic is totally a mess, need to completely rewrite, that's also the root reason for
why the "migrate to CodeMirror" PR took very long time on the legacy code and introduced "#file-name (filenameInput)" regressions many times*/}}
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
{{end}}
</div>

View File

@@ -1,12 +1,7 @@
<form hx-boost="true" hx-sync="this:replace" hx-target="this" method="post" action="{{.Issue.Link}}/watch">
<input type="hidden" name="watch" value="{{if $.IssueWatch.IsWatching}}0{{else}}1{{end}}">
<button class="fluid ui button">
{{if $.IssueWatch.IsWatching}}
{{svg "octicon-mute" 16}}
{{ctx.Locale.Tr "repo.issues.unsubscribe"}}
{{else}}
{{svg "octicon-unmute" 16}}
{{ctx.Locale.Tr "repo.issues.subscribe"}}
{{end}}
</button>
</form>
<button class="fluid ui button" type="button" data-fetch-method="post" data-fetch-url="{{.Issue.Link}}/watch?watch={{not $.IssueWatch.IsWatching}}">
{{if $.IssueWatch.IsWatching}}
{{svg "octicon-mute" 16}} {{ctx.Locale.Tr "repo.issues.unsubscribe"}}
{{else}}
{{svg "octicon-unmute" 16}} {{ctx.Locale.Tr "repo.issues.subscribe"}}
{{end}}
</button>

View File

@@ -115,16 +115,19 @@
{{end}}
{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}}
{{if not .UserBlocking}}
<li class="follow" hx-target="#profile-avatar-card" hx-indicator="#profile-avatar-card">
{{if $.IsFollowing}}
<button hx-post="{{.ContextUser.HomeLink}}?action=unfollow" class="ui basic red button">
<li class="follow">
{{$buttonExtraClass := Iif $.IsFollowing "" "primary"}}
{{$followAction := Iif $.IsFollowing "unfollow" "follow"}}
<button class="ui basic {{$buttonExtraClass}} button"
data-fetch-method="post" data-fetch-url="{{.ContextUser.HomeLink}}?action={{$followAction}}"
data-fetch-sync="$body #profile-avatar-card"
>
{{if $.IsFollowing}}
{{svg "octicon-person"}} {{ctx.Locale.Tr "user.unfollow"}}
</button>
{{else}}
<button hx-post="{{.ContextUser.HomeLink}}?action=follow" class="ui basic primary button">
{{else}}
{{svg "octicon-person"}} {{ctx.Locale.Tr "user.follow"}}
</button>
{{end}}
{{end}}
</button>
</li>
{{end}}
<li>

View File

@@ -53,8 +53,8 @@
{{DateUtils.TimeSince $one.UpdatedUnix}}
{{end}}
</div>
<form class="notifications-buttons" action="{{AppSubUrl}}/notifications/status?type={{$.PageType}}&page={{$.Page.Paginater.Current}}&perPage={{$.Page.Paginater.PagingNum}}" method="post"
hx-boost="true" hx-target="#notification_div" hx-swap="outerHTML"
<form class="notifications-buttons form-fetch-action" action="{{AppSubUrl}}/notifications/status?type={{$.PageType}}&page={{$.Page.Paginater.Current}}&perPage={{$.Page.Paginater.PagingNum}}" method="post"
data-fetch-sync="$body #notification_div"
>
<input type="hidden" name="notification_id" value="{{$one.ID}}">
{{if ne $one.Status $statusPinned}}

View File

@@ -147,12 +147,12 @@ func TestCompareCodeExpand(t *testing.T) {
req := NewRequest(t, "GET", "/user1/test_blob_excerpt/compare/main...user2/test_blob_excerpt-fork:forked-branch")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
els := htmlDoc.Find(`button.code-expander-button[hx-get]`)
els := htmlDoc.Find(`button.code-expander-button[data-fetch-url]`)
// all the links in the comparison should be to the forked repo&branch
assert.NotZero(t, els.Length())
for i := 0; i < els.Length(); i++ {
link := els.Eq(i).AttrOr("hx-get", "")
link := els.Eq(i).AttrOr("data-fetch-url", "")
assert.True(t, strings.HasPrefix(link, "/user2/test_blob_excerpt-fork/blob_excerpt/"))
}
})