Refactor pull request view (6) (#37522)

Clean up legacy logic.

* Use backend logic to choose PR timeline icon color
* Always use the Vue form to merge, remove the "StillCanManualMerge" logic
This commit is contained in:
wxiaoguang
2026-05-04 14:15:33 +08:00
committed by GitHub
parent f26f71f1b2
commit dd17521808
16 changed files with 293 additions and 316 deletions
+5 -13
View File
@@ -102,34 +102,26 @@
</div>
</div>
<h3>Flex List (with "ui segment fitted", items have their own padding)</h3>
<div class="ui attached segment fitted container-divided">
<div class="flex-divided-list container-divided">
<div class="ui fitted segment">
<div class="flex-divided-list items-px-default">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item flex-divided-list">
<div class="item">item nested 1</div>
<div class="item">item nested 2</div>
</div>
<div class="item">item 3</div>
</div>
</div>
<h3>If parent provides padding or items need their own flex and/or padding:</h3>
<div class="container-divided tw-border tw-border-secondary">
<div class="tw-border tw-border-secondary">
<div class="tw-m-3">before divider</div>
<div class="divider"></div>
<div class="flex-divided-list container-divided flex-items-block">
<div class="flex-divided-list flex-items-block items-px-default">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item flex-divided-list">
<div class="item">item nested 1</div>
<div class="item">item nested 2</div>
</div>
</div>
<div class="divider"></div>
<div class="tw-m-3">after divider</div>
</div>
<div class="container-padded tw-border tw-border-secondary tw-p-4 tw-my-2">
<div class="tw-border tw-border-secondary tw-p-4 tw-my-2">
<div>before divider</div>
<div class="divider"></div>
<div class="flex-divided-list">
+2 -4
View File
@@ -9,10 +9,8 @@
</span>
{{end}}
<div class="tippy-target">
<div class="ui segment">
<div class="flex-divided-list">
{{template "repo/pulls/status" (dict "CommitStatuses" .Statuses "CommitStatus" .Status)}}
</div>
<div class="flex-divided-list items-px-default">
{{template "repo/pulls/status_items" (dict "CommitStatuses" .Statuses)}}
</div>
</div>
{{end}}
@@ -9,36 +9,17 @@
>
{{$statusCheckData := .StatusCheckData}}
{{$requiredStatusCheckState := $statusCheckData.RequiredChecksState}}
<div class="timeline-avatar {{if .Issue.PullRequest.HasMerged}}tw-text-purple
{{- else if .Issue.IsClosed}}tw-text-text-light
{{- else if .IsPullWorkInProgress}}tw-text-text-light
{{- else if .IsFilesConflicted}}tw-text-text-light
{{- else if .IsPullRequestBroken}}tw-text-red
{{- else if .IsBlockedByApprovals}}tw-text-red
{{- else if .IsBlockedByRejection}}tw-text-red
{{- else if .IsBlockedByOfficialReviewRequests}}tw-text-red
{{- else if .IsBlockedByOutdatedBranch}}tw-text-red
{{- else if .IsBlockedByChangedProtectedFiles}}tw-text-red
{{- else if and .EnableStatusCheck (or $requiredStatusCheckState.IsFailure $requiredStatusCheckState.IsError)}}tw-text-red
{{- else if and .EnableStatusCheck (or (not $.LatestCommitStatus) $requiredStatusCheckState.IsPending $requiredStatusCheckState.IsWarning)}}tw-text-yellow
{{- else if and .AllowMerge .RequireSigned (not .WillSign)}}tw-text-red
{{- else if .Issue.PullRequest.IsChecking}}tw-text-yellow
{{- else if .Issue.PullRequest.IsEmpty}}tw-text-text-light
{{- else if .Issue.PullRequest.IsStatusMergeable}}tw-text-green
{{- else}}tw-text-red{{end}}">{{svg "octicon-git-merge" 40}}</div>
<div class="timeline-avatar {{$data.TimelineIconClass}}">{{svg "octicon-git-merge" 40}}</div>
<div class="content">
<div class="ui segment fitted avatar-content-left-arrow container-divided">
<div class="merge-section flex-divided-list flex-items-block container-divided">
<div class="ui segment fitted avatar-content-left-arrow">
<div class="merge-section flex-divided-list flex-items-block items-px-default">
{{if .LatestCommitStatus}}
{{template "repo/pulls/status" (dict
"CommitStatus" .LatestCommitStatus
{{template "repo/issue/view_content/pull_merge_status_checks" (dict
"CommitStatuses" .LatestCommitStatuses
"ShowHideChecks" true
"StatusCheckData" $statusCheckData
)}}
{{end}}
{{$showGeneralMergeForm := false}}
{{if .Issue.PullRequest.HasMerged}}
{{if .IsPullBranchDeletable}}
<div class="item item-section text tw-flex-1">
@@ -113,7 +94,7 @@
{{svg "octicon-alert"}}
{{ctx.Locale.Tr "repo.pulls.is_ancestor"}}
</div>
{{else if or .Issue.PullRequest.IsStatusMergeable .Issue.PullRequest.IsEmpty}}
{{else}}
{{if .IsBlockedByApprovals}}
<div class="item">
{{svg "octicon-x"}}
@@ -167,6 +148,15 @@
{{svg "octicon-unlock"}}
{{ctx.Locale.Tr (printf "repo.signing.wont_sign.%s" .WontSignReason)}}
</div>
{{else if not .Issue.PullRequest.IsStatusMergeable}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_desc"}}
</div>
<div class="item">
{{svg "octicon-info"}}
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_helper"}}
</div>
{{end}}
{{$notAllOverridableChecksOk := $data.HasOverridableBlockers}}
@@ -197,112 +187,38 @@
{{end}}
{{end}}
{{template "repo/issue/view_content/update_branch_by_merge" $}}
{{if .Issue.PullRequest.IsEmpty}}
<div class="item">
{{svg "octicon-alert"}}
{{ctx.Locale.Tr "repo.pulls.is_empty"}}
</div>
<div class="item">
{{svg "octicon-alert"}}
{{ctx.Locale.Tr "repo.pulls.is_empty"}}
</div>
{{end}}
{{if .AllowMerge}} {{/* user is allowed to merge */}}
{{if $data.MergeFormProps}}
{{$showGeneralMergeForm = true}}
{{/* The merge form is a Vue component. After mounted, it has a button for choosing merge style, so make it have min-height to avoid layout shifting */}}
<div class="item">
<div id="pull-request-merge-form" class="tw-min-h-[40px]" data-merge-form-props="{{JsonUtils.EncodeToString $data.MergeFormProps}}"></div>
</div>
{{else}}
{{/* no merge style was set in repo setting: not or ($prUnit.PullRequestsConfig.AllowMerge ...) */}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.no_merge_desc"}}
</div>
<div class="item">
{{svg "octicon-info"}}
{{ctx.Locale.Tr "repo.pulls.no_merge_helper"}}
</div>
{{end}} {{/* end if the repo was set to use any merge style */}}
{{else}}
{{template "repo/issue/view_content/update_branch_by_merge" (dict "MergeBoxData" $data "Issue" $.Issue)}}
{{if not .AllowMerge}} {{/* user is allowed to merge */}}
{{/* user is not allowed to merge */}}
<div class="item">
{{svg "octicon-info"}}
{{ctx.Locale.Tr "repo.pulls.no_merge_access"}}
</div>
{{end}} {{/* end if user is allowed to merge or not */}}
{{else}}
{{/* Merge conflict without specific file. Suggest manual merge, only if all reviews and status checks OK. */}}
{{if .IsBlockedByApprovals}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.blocked_by_approvals" .GrantedApprovals .ProtectedBranch.RequiredApprovals}}
</div>
{{else if .IsBlockedByRejection}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.blocked_by_rejection"}}
</div>
{{else if .IsBlockedByOfficialReviewRequests}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.blocked_by_official_review_requests"}}
</div>
{{else if .IsBlockedByOutdatedBranch}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.blocked_by_outdated_branch"}}
</div>
{{else if .IsBlockedByChangedProtectedFiles}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.TrN $.ChangedProtectedFilesNum "repo.pulls.blocked_by_changed_protected_files_1" "repo.pulls.blocked_by_changed_protected_files_n"}}
</div>
<ul class="item">
{{range .ChangedProtectedFiles}}
<li>{{.}}</li>
{{end}}
</ul>
{{else if and .EnableStatusCheck (not $requiredStatusCheckState.IsSuccess)}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.required_status_check_failed"}}
</div>
{{else if and .RequireSigned (not .WillSign)}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.require_signed_wont_sign"}}
</div>
{{else}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_desc"}}
</div>
<div class="item">
{{svg "octicon-info"}}
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_helper"}}
</div>
{{end}}
{{end}}{{/* end if: pull request status */}}
{{/* Manually Merged is not a well-known feature, it is used to mark a non-mergeable PR (already merged, conflicted) as merged
To test it:
* Enable "Manually Merged" feature in the Repository Settings
* Create a pull request, either:
* - Merge the pull request branch locally and push the merged commit to Gitea
* - Make some conflicts between the base branch and the pull request branch
* Then the Manually Merged form will be shown in the merge form
*/}}
{{if and $.StillCanManualMerge (not $showGeneralMergeForm)}}
{{if $data.MergeFormProps}}
{{/* The merge form is a Vue component. After mounted, it has a button for choosing merge style, so make it have min-height to avoid layout shifting */}}
<div class="item">
<form class="ui form form-fetch-action tw-flex-1" action="{{.Issue.Link}}/merge" method="post">{{/* another similar form is in PullRequestMergeForm.vue*/}}
<div class="field">
<input type="text" name="merge_commit_id" placeholder="{{ctx.Locale.Tr "repo.pulls.merge_commit_id"}}">
</div>
<button class="ui red button" type="submit" name="do" value="manually-merged">
{{ctx.Locale.Tr "repo.pulls.merge_manually"}}
</button>
</form>
<div id="pull-request-merge-form" class="tw-min-h-[40px] tw-w-full" data-merge-form-props="{{JsonUtils.EncodeToString $data.MergeFormProps}}"></div>
</div>
{{else if and .AllowMerge .Issue.PullRequest.IsStatusMergeable}}
{{/* no merge style was set in repo setting */}}
<div class="item tw-text-red">
{{svg "octicon-x"}}
{{ctx.Locale.Tr "repo.pulls.no_merge_desc"}}
</div>
<div class="item">
{{svg "octicon-info"}}
{{ctx.Locale.Tr "repo.pulls.no_merge_helper"}}
</div>
{{end}}
@@ -0,0 +1,35 @@
{{/* Template Attributes:
* CommitStatuses: all commit status elements
* StatusCheckData: additional status check data, see backend pullCommitStatusCheckData struct
*/}}
{{$commitStatuses := $.CommitStatuses}}
{{$statusCheckData := $.StatusCheckData}}
{{if $statusCheckData}}
<div class="item flex-left-right commit-status-toggle">
<div>{{$statusCheckData.CommitStatusCheckPrompt ctx.Locale}}</div>
<button data-global-click="onCommitStatusChecksToggle" class="btn interact-fg"
data-show-all="{{ctx.Locale.Tr "repo.pulls.status_checks_show_all"}}"
data-hide-all="{{ctx.Locale.Tr "repo.pulls.status_checks_hide_all"}}"
>{{ctx.Locale.Tr "repo.pulls.status_checks_hide_all"}}</button>
</div>
{{if $statusCheckData.RequireApprovalRunCount}}
<div class="item flex-left-right" id="approve-status-checks">
<div>
<strong>{{ctx.Locale.Tr "repo.pulls.status_checks_need_approvals" $statusCheckData.RequireApprovalRunCount}}</strong>
<p>{{ctx.Locale.Tr "repo.pulls.status_checks_need_approvals_helper"}}</p>
</div>
{{if $statusCheckData.CanApprove}}
<button class="ui basic button link-action" data-url="{{$statusCheckData.ApproveLink}}">
{{ctx.Locale.Tr "repo.pulls.status_checks_approve_all"}}
</button>
{{end}}
</div>
{{end}}
<div class="item tw-p-0">
<div class="commit-status-list flex-divided-list items-px-default">
{{template "repo/pulls/status_items" (dict "CommitStatuses" $commitStatuses "StatusCheckData" $statusCheckData)}}
</div>
</div>
{{end}}
@@ -1,30 +1,30 @@
{{if and (gt $.Issue.PullRequest.CommitsBehind 0) (not $.Issue.IsClosed) (not $.Issue.PullRequest.IsChecking) (not $.IsPullFilesConflicted) (not $.IsPullRequestBroken)}}
<div class="item item-section">
<div class="item-section-left flex-text-inline">
{{$data := $.MergeBoxData}}
{{$issue := $.Issue}}
{{if $data.ShowUpdatePullInfo}}
<div class="item flex-left-right">
<div class="flex-text-block">
{{svg "octicon-alert"}}
{{ctx.Locale.Tr "repo.pulls.outdated_with_base_branch"}}
</div>
<div class="item-section-right">
{{if and $.UpdateAllowed $.UpdateByRebaseAllowed}}
<div class="tw-inline-block">
<div id="update-pr-branch-with-base" class="ui buttons">
<button class="ui button" data-do="{{$.Issue.Link}}/update">
<span class="button-text">
{{ctx.Locale.Tr "repo.pulls.update_branch"}}
</span>
</button>
<div class="ui dropdown icon button">
{{svg "octicon-triangle-down"}}
<div class="menu">
<a class="item active selected" data-do="{{$.Issue.Link}}/update">{{ctx.Locale.Tr "repo.pulls.update_branch"}}</a>
<a class="item" data-do="{{$.Issue.Link}}/update?style=rebase">{{ctx.Locale.Tr "repo.pulls.update_branch_rebase"}}</a>
</div>
<div>
{{if and $data.UpdateAllowed $data.UpdateByRebaseAllowed}}
<div id="update-pr-branch-with-base" class="ui buttons">
<button class="ui button" data-do="{{$issue.Link}}/update">
<span class="button-text">
{{ctx.Locale.Tr "repo.pulls.update_branch"}}
</span>
</button>
<div class="ui dropdown icon button">
{{svg "octicon-triangle-down"}}
<div class="menu">
<a class="item active selected" data-do="{{$issue.Link}}/update">{{ctx.Locale.Tr "repo.pulls.update_branch"}}</a>
<a class="item" data-do="{{$issue.Link}}/update?style=rebase">{{ctx.Locale.Tr "repo.pulls.update_branch_rebase"}}</a>
</div>
</div>
</div>
{{end}}
{{if and $.UpdateAllowed (not $.UpdateByRebaseAllowed)}}
<form action="{{$.Issue.Link}}/update" method="post" class="ui update-branch-form">
{{if and $data.UpdateAllowed (not $data.UpdateByRebaseAllowed)}}
<form action="{{$issue.Link}}/update" method="post">
<button class="ui compact button">
<span class="ui text">{{ctx.Locale.Tr "repo.pulls.update_branch"}}</span>
</button>
-63
View File
@@ -1,63 +0,0 @@
{{/* Template Attributes:
* CommitStatus: summary of all commit status state
* CommitStatuses: all commit status elements
* ShowHideChecks: whether use a button to show/hide the checks
* StatusCheckData: additional status check data, see backend pullCommitStatusCheckData struct
*/}}
{{$statusCheckData := .StatusCheckData}}
{{if .CommitStatus}}
{{if $statusCheckData}}
<div class="item flex-left-right commit-status-toggle">
<div>{{$statusCheckData.CommitStatusCheckPrompt ctx.Locale}}</div>
{{if .ShowHideChecks}}
<button data-global-click="onCommitStatusChecksToggle" class="btn interact-fg"
data-show-all="{{ctx.Locale.Tr "repo.pulls.status_checks_show_all"}}"
data-hide-all="{{ctx.Locale.Tr "repo.pulls.status_checks_hide_all"}}"
>{{ctx.Locale.Tr "repo.pulls.status_checks_hide_all"}}</button>
{{end}}
</div>
{{end}}
{{if and $statusCheckData $statusCheckData.RequireApprovalRunCount}}
<div class="item flex-left-right" id="approve-status-checks">
<div>
<strong>
{{ctx.Locale.Tr "repo.pulls.status_checks_need_approvals" $statusCheckData.RequireApprovalRunCount}}
</strong>
<p>{{ctx.Locale.Tr "repo.pulls.status_checks_need_approvals_helper"}}</p>
</div>
{{if $statusCheckData.CanApprove}}
<button class="ui basic button link-action" data-url="{{$statusCheckData.ApproveLink}}">
{{ctx.Locale.Tr "repo.pulls.status_checks_approve_all"}}
</button>
{{end}}
</div>
{{end}}
<div class="item flex-divided-list commit-status-list">
{{range .CommitStatuses}}
<div class="item commit-status-item">
<div class="flex-text-block">
{{template "repo/commit_status" .}}
<div class="status-context gt-ellipsis">{{.Context}} <span class="tw-text-text-light-2">{{.Description}}</span></div>
</div>
<div class="status-details">
{{if and $statusCheckData $statusCheckData.IsContextRequired}}
{{if (call $statusCheckData.IsContextRequired .Context)}}<div class="ui label">{{ctx.Locale.Tr "repo.pulls.status_checks_requested"}}</div>{{end}}
{{end}}
{{if .TargetURL}}<a href="{{.TargetURL}}">{{ctx.Locale.Tr "repo.pulls.status_checks_details"}}</a>{{end}}
</div>
</div>
{{end}}
{{if $statusCheckData}}
{{range $statusCheckData.MissingRequiredChecks}}
<div class="item commit-status-item">
<div class="flex-text-block">
{{svg "octicon-dot-fill" 16 "commit-status icon tw-text-yellow"}}
<div class="status-context gt-ellipsis">{{.}}</div>
</div>
<div class="ui label">{{ctx.Locale.Tr "repo.pulls.status_checks_requested"}}</div>
</div>
{{end}}
{{end}}
</div>
{{end}}
+32
View File
@@ -0,0 +1,32 @@
{{/* Template Attributes:
* CommitStatuses: all commit status elements
* StatusCheckData: optional, additional status check data, see backend pullCommitStatusCheckData struct
*/}}
{{$statusCheckData := $.StatusCheckData}}
{{range $cs := $.CommitStatuses}}
<div class="item commit-status-item">
<div class="flex-text-block">
{{template "repo/commit_status" $cs}}
<div class="status-context gt-ellipsis">
{{$cs.Context}} <span class="tw-text-text-light-2">{{$cs.Description}}</span>
</div>
</div>
<div class="status-details">
{{if and $statusCheckData $statusCheckData.IsContextRequired}}
{{if (call $statusCheckData.IsContextRequired $cs.Context)}}
<div class="ui label">{{ctx.Locale.Tr "repo.pulls.status_checks_requested"}}</div>
{{end}}
{{end}}
{{if $cs.TargetURL}}<a href="{{$cs.TargetURL}}">{{ctx.Locale.Tr "repo.pulls.status_checks_details"}}</a>{{end}}
</div>
</div>
{{end}}
{{range $missingCheck := $statusCheckData.MissingRequiredChecks}}
<div class="item commit-status-item">
<div class="flex-text-block">
{{svg "octicon-dot-fill" 16 "commit-status icon tw-text-yellow"}}
<div class="status-context gt-ellipsis">{{$missingCheck}}</div>
</div>
<div class="ui label">{{ctx.Locale.Tr "repo.pulls.status_checks_requested"}}</div>
</div>
{{end}}