Refactor htmx and fetch-action related code (#37186)
This is the first step (the hardest part): * repo file list last commit message lazy load * admin server status monitor * watch/unwatch (normal page, watchers page) * star/unstar (normal page, watchers page) * project view, delete column * workflow dispatch, switch the branch * commit page: load branches and tags referencing this commit The legacy "data-redirect" attribute is removed, it only makes the page reload (sometimes using an incorrect link). Also did cleanup for some devtest pages.
This commit is contained in:
@@ -76,10 +76,7 @@
|
||||
</h4>
|
||||
{{/* TODO: make these stats work in multi-server deployments, likely needs per-server stats in DB */}}
|
||||
<div class="ui attached table segment">
|
||||
<div class="no-loading-indicator tw-hidden"></div>
|
||||
<div hx-get="{{$.Link}}/system_status" hx-swap="morph:innerHTML" hx-trigger="every 5s" hx-indicator=".no-loading-indicator">
|
||||
{{template "admin/system_status" .}}
|
||||
</div>
|
||||
{{template "admin/system_status" .}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "admin/layout_footer" .}}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui small button" id="delete-selection" data-link="{{.Link}}/delete" data-redirect="?page={{.Page.Paginater.Current}}">
|
||||
<button class="ui small button" id="delete-selection" data-link="{{.Link}}/delete">
|
||||
<span class="text">{{ctx.Locale.Tr "admin.notices.delete_selected"}}</span>
|
||||
</button>
|
||||
</th>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<dl class="admin-dl-horizontal">
|
||||
<dl class="admin-dl-horizontal" data-fetch-url="{{AppSubUrl}}/-/admin/system_status" data-fetch-sync="$morph" data-fetch-trigger="every 5s">
|
||||
<dt>{{ctx.Locale.Tr "admin.dashboard.server_uptime"}}</dt>
|
||||
<dd><relative-time format="duration" datetime="{{.SysStatus.StartTime}}">{{.SysStatus.StartTime}}</relative-time></dd>
|
||||
<dt>{{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}</dt>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{{template "base/head_script" .}}
|
||||
{{template "custom/header" .}}
|
||||
</head>
|
||||
<body hx-swap="outerHTML" hx-ext="morph" hx-push-url="false">
|
||||
<body hx-swap="outerHTML" hx-push-url="false">
|
||||
{{template "custom/body_outer_pre" .}}
|
||||
|
||||
<div class="full height">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div>
|
||||
<h1>link-action</h1>
|
||||
<div>
|
||||
Use "window.fetch" to send a request to backend, the request is defined in an "A" or "BUTTON" element.
|
||||
The request is defined in an "A" or "BUTTON" element.
|
||||
It might be renamed to "link-fetch-action" to match the "form-fetch-action".
|
||||
</div>
|
||||
<div>
|
||||
@@ -15,7 +15,6 @@
|
||||
</div>
|
||||
<div>
|
||||
<h1>form-fetch-action</h1>
|
||||
<div>Use "window.fetch" to send a form request to backend</div>
|
||||
<div class="flex-relaxed-list fetch-action-demo-forms">
|
||||
<form method="get" action="./fetch-action-test?k=1" class="form-fetch-action">
|
||||
<button name="btn">submit get</button>
|
||||
@@ -25,7 +24,7 @@
|
||||
<div><label><input name="check" type="checkbox"> check</label></div>
|
||||
<div><button name="btn">submit post</button></div>
|
||||
</form>
|
||||
<form method="post" action="./no-such-uri" class="form-fetch-action">
|
||||
<form method="post" action="/-/no-such-uri" class="form-fetch-action">
|
||||
<div class="tw-py-8">bad action url</div>
|
||||
<div><button name="btn">submit test</button></div>
|
||||
</form>
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
{{template "devtest/devtest-header"}}
|
||||
<div class="page-content devtest ui container">
|
||||
{{template "base/alert" .}}
|
||||
<div class="modal-buttons flex-text-block tw-flex-wrap"></div>
|
||||
<script>
|
||||
document.addEventListener('gitea:index-ready', () => {
|
||||
for (const el of $('.ui.modal:not([data-skip-button])')) {
|
||||
const $btn = $('<button class="ui button">').text(`${el.id}`).on('click', () => {
|
||||
$(el).modal({onApprove() {alert('confirmed')}}).modal('show');
|
||||
});
|
||||
$('.modal-buttons').append($btn);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="test-modal-form-1" class="ui mini modal">
|
||||
<div class="header">Form dialog (layout 1)</div>
|
||||
<form class="content" method="post">
|
||||
<form class="content" method="post" action="?mock_response_delay=1">
|
||||
<div class="ui input tw-w-full"><input name="user_input"></div>
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
</form>
|
||||
@@ -23,7 +11,7 @@
|
||||
|
||||
<div id="test-modal-form-2" class="ui mini modal">
|
||||
<div class="header">Form dialog (layout 2)</div>
|
||||
<form method="post">
|
||||
<form method="post" action="?mock_response_delay=1">
|
||||
<div class="content">
|
||||
<div class="ui input tw-w-full"><input name="user_input"></div>
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
@@ -33,7 +21,7 @@
|
||||
|
||||
<div id="test-modal-form-3" class="ui mini modal">
|
||||
<div class="header">Form dialog (layout 3)</div>
|
||||
<form method="post">
|
||||
<form method="post" action="?mock_response_delay=1">
|
||||
<div class="content">
|
||||
<div class="ui input tw-w-full"><input name="user_input"></div>
|
||||
</div>
|
||||
@@ -46,7 +34,7 @@
|
||||
<div class="content">
|
||||
<div class="ui input tw-w-full"><input name="user_input"></div>
|
||||
</div>
|
||||
<form method="post">
|
||||
<form method="post" action="?mock_response_delay=1">
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
</form>
|
||||
</div>
|
||||
@@ -54,7 +42,7 @@
|
||||
<div id="test-modal-form-5" class="ui mini modal">
|
||||
<div class="header">Form dialog (layout 5)</div>
|
||||
<div class="content">
|
||||
<form method="post">
|
||||
<form method="post" action="?mock_response_delay=1">
|
||||
<div class="ui input tw-w-full"><input name="user_input"></div>
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
</form>
|
||||
|
||||
@@ -45,17 +45,6 @@
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<script>
|
||||
document.addEventListener('gitea:index-ready', () => {
|
||||
const $buttons = $('#devtest-button-samples').find('button.ui');
|
||||
|
||||
const $buttonStyles = $('input[name*="button-style"]');
|
||||
$buttonStyles.on('click', () => $buttonStyles.map((_, el) => $buttons.toggleClass(el.value, el.checked)));
|
||||
|
||||
const $buttonStates = $('input[name*="button-state"]');
|
||||
$buttonStates.on('click', () => $buttonStates.map((_, el) => $buttons.prop(el.value, el.checked)));
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
>
|
||||
{{svg "octicon-star"}} {{ctx.Locale.Tr "repo.projects.column.set_default"}}
|
||||
</a>
|
||||
<a class="item button link-action" data-url="{{$.Link}}/{{.ID}}" data-link-action-method="DELETE"
|
||||
<a class="item button link-action" data-url="{{$.Link}}/{{.ID}}" data-fetch-method="DELETE"
|
||||
data-modal-confirm-header="{{ctx.Locale.Tr "repo.projects.column.delete"}}"
|
||||
data-modal-confirm-content="{{ctx.Locale.Tr "repo.projects.column.deletion_desc"}}"
|
||||
>
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
</div>
|
||||
<div id="runWorkflowDispatchModal" class="ui tiny modal">
|
||||
<div class="content">
|
||||
<form id="runWorkflowDispatchForm" class="ui form" action="{{$.Link}}/run?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}" method="post">
|
||||
<form id="runWorkflowDispatchForm" class="ui form ignore-dirty" action="{{$.Link}}/run?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}" method="post">
|
||||
<div class="ui inline field required tw-flex tw-items-center">
|
||||
<span class="ui inline required field">
|
||||
<label>{{ctx.Locale.Tr "actions.workflow.from_ref"}}:</label>
|
||||
</span>
|
||||
<div class="ui inline field dropdown button select-branch branch-selector-dropdown ellipsis-text-items">
|
||||
<input type="hidden" name="ref" hx-sync="this:replace" hx-target="#runWorkflowDispatchModalInputs" hx-swap="innerHTML" hx-get="{{$.Link}}/workflow-dispatch-inputs?workflow={{$.CurWorkflow}}" hx-trigger="change" value="refs/heads/{{index .Branches 0}}">
|
||||
<input type="hidden" name="ref" value="refs/heads/{{index .Branches 0}}"
|
||||
data-fetch-trigger="change" data-fetch-sync="$body #runWorkflowDispatchModalInputs"
|
||||
data-fetch-url="{{$.Link}}/workflow-dispatch-inputs?workflow={{$.CurWorkflow}}"
|
||||
>
|
||||
{{svg "octicon-git-branch" 14}}
|
||||
<div class="default text">{{index .Branches 0}}</div>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
@@ -45,12 +48,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div id="runWorkflowDispatchModalInputs">
|
||||
{{template "repo/actions/workflow_dispatch_inputs" .}}
|
||||
</div>
|
||||
{{template "repo/actions/workflow_dispatch_inputs" .}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<div id="runWorkflowDispatchModalInputs">
|
||||
{{if not .WorkflowDispatchConfig}}
|
||||
<div class="ui error message tw-block">{{/* using "ui message" in "ui form" needs to force to display */}}
|
||||
{{if not .CurWorkflowExists}}
|
||||
@@ -44,3 +45,4 @@
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
{{end}}
|
||||
<button class="ui button ellipsis-button load-branches-and-tags tw-mt-2" aria-expanded="false"
|
||||
data-fetch-url="{{.RepoLink}}/commit/{{.CommitID}}/load-branches-and-tags"
|
||||
data-url="{{.RepoLink}}/commit/{{.CommitID}}/load-branches-and-tags"
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.commit.load_referencing_branches_and_tags"}}"
|
||||
>...</button>
|
||||
<div class="branch-and-tag-detail tw-hidden">
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
{{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" data-redirect="{{$.Issue.Link}}">
|
||||
<button class="ui button" data-do="{{$.Issue.Link}}/update">
|
||||
<span class="button-text">
|
||||
{{ctx.Locale.Tr "repo.pulls.update_branch"}}
|
||||
</span>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="ui right">
|
||||
<!-- the button is wrapped with a span because the tooltip doesn't show on hover if we put data-tooltip-content directly on the button -->
|
||||
<span data-tooltip-content="{{if or $isNew .Webhook.IsActive}}{{ctx.Locale.Tr "repo.settings.webhook.test_delivery_desc"}}{{else}}{{ctx.Locale.Tr "repo.settings.webhook.test_delivery_desc_disabled"}}{{end}}">
|
||||
<button class="ui tiny button{{if not (or $isNew .Webhook.IsActive)}} disabled{{end}}" id="test-delivery" data-link="{{.Link}}/test" data-redirect="{{.Link}}">
|
||||
<button class="ui tiny button{{if not (or $isNew .Webhook.IsActive)}} disabled{{end}}" id="test-delivery" data-link="{{.Link}}/test">
|
||||
<span class="text">{{ctx.Locale.Tr "repo.settings.webhook.test_delivery"}}</span>
|
||||
</button>
|
||||
</span>
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
<form class="flex-text-inline" hx-boost="true" hx-target="this" method="post" action="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}unstar{{else}}star{{end}}">
|
||||
<div class="ui labeled button" {{if not $.IsSigned}}data-tooltip-content="{{ctx.Locale.Tr "repo.star_guest_user"}}"{{end}}>
|
||||
{{$buttonText := ctx.Locale.Tr "repo.star"}}
|
||||
{{if $.IsStaringRepo}}{{$buttonText = ctx.Locale.Tr "repo.unstar"}}{{end}}
|
||||
<button type="submit" class="ui compact small basic button"{{if not $.IsSigned}} disabled{{end}} aria-label="{{$buttonText}}">
|
||||
{{svg (Iif $.IsStaringRepo "octicon-star-fill" "octicon-star")}}
|
||||
<span class="not-mobile" aria-hidden="true">{{$buttonText}}</span>
|
||||
</button>
|
||||
<a hx-boost="false" class="ui basic label" href="{{$.RepoLink}}/stars">
|
||||
{{CountFmt .Repository.NumStars}}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
<div class="ui labeled button" {{if not $.IsSigned}}data-tooltip-content="{{ctx.Locale.Tr "repo.star_guest_user"}}"{{end}}>
|
||||
{{$buttonText := ctx.Locale.Tr "repo.star"}}
|
||||
{{if $.IsStaringRepo}}{{$buttonText = ctx.Locale.Tr "repo.unstar"}}{{end}}
|
||||
<button type="button" class="ui compact small basic button" aria-label="{{$buttonText}}"
|
||||
{{if $.IsSigned}}
|
||||
data-fetch-method="post"
|
||||
data-fetch-url="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}unstar{{else}}star{{end}}"
|
||||
data-fetch-sync="$closest(.ui.labeled.button)"
|
||||
{{else}}
|
||||
disabled
|
||||
{{end}}
|
||||
>
|
||||
{{svg (Iif $.IsStaringRepo "octicon-star-fill" "octicon-star")}}
|
||||
<span class="not-mobile" aria-hidden="true">{{$buttonText}}</span>
|
||||
</button>
|
||||
<a class="ui basic label" href="{{$.RepoLink}}/stars">
|
||||
{{CountFmt .Repository.NumStars}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
<!-- Refresh the content if a htmx response contains "HX-Trigger" header.
|
||||
This usually happens when a user stays on the watchers/stargazers page
|
||||
when they watched/unwatched/starred/unstarred and the list should be refreshed.
|
||||
To test go to the watchers page and click the watch button. The user cards should reload.
|
||||
At the moment, no JS initialization would re-trigger (fortunately there is no JS for this page).
|
||||
-->
|
||||
<div class="no-loading-indicator tw-hidden"></div>
|
||||
<div class="user-cards"
|
||||
hx-trigger="refreshUserCards from:body" hx-indicator=".no-loading-indicator"
|
||||
hx-get="" hx-swap="outerHTML" hx-select=".user-cards"
|
||||
>
|
||||
{{/* need to reload after "watch/unwatch" or "star/unstar" fetch actions */}}
|
||||
<div class="user-cards" id="user-cards-container" data-fetch-trigger="fetch-reload">
|
||||
{{if .CardsTitle}}
|
||||
<h2 class="ui dividing header">
|
||||
{{.CardsTitle}}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
{{/* use grid layout, still use the old ID because there are many other CSS styles depending on this ID */}}
|
||||
<div id="repo-files-table" {{if .HasFilesWithoutLatestCommit}}hx-indicator="#repo-files-table .repo-file-cell.message" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
|
||||
<div id="repo-files-table"
|
||||
{{if .HasFilesWithoutLatestCommit}}
|
||||
data-fetch-url="{{.LastCommitLoaderURL}}"
|
||||
data-fetch-trigger="load" data-fetch-sync="$morph"
|
||||
data-fetch-indicator="#repo-files-table .repo-file-cell.notready.message"
|
||||
{{end}}
|
||||
>
|
||||
<div class="repo-file-line repo-file-last-commit">
|
||||
{{template "repo/latest_commit" .}}
|
||||
<div>{{if and .LatestCommit .LatestCommit.Committer}}{{DateUtils.TimeSince .LatestCommit.Committer.When}}{{end}}</div>
|
||||
@@ -15,7 +21,7 @@
|
||||
{{$entry := $item.Entry}}
|
||||
{{$commit := $item.Commit}}
|
||||
{{$submoduleFile := $item.SubmoduleFile}}
|
||||
<div class="repo-file-cell name muted-links {{if not $commit}}notready{{end}}">
|
||||
<div class="repo-file-cell name muted-links">
|
||||
{{index $.FileIcons $entry.Name}}
|
||||
{{if $entry.IsSubModule}}
|
||||
{{$submoduleLink := $submoduleFile.SubmoduleWebLinkTree ctx}}
|
||||
@@ -47,7 +53,7 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="repo-file-cell message commit-summary loading-icon-2px">
|
||||
<div class="repo-file-cell message commit-summary {{if not $commit}}notready{{end}}">
|
||||
{{if $commit}}
|
||||
{{$commitLink := printf "%s/commit/%s" $.RepoLink (PathEscape $commit.ID.String)}}
|
||||
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.Message $commitLink $.Repository}}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
<form class="flex-text-inline" hx-boost="true" hx-target="this" method="post" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}unwatch{{else}}watch{{end}}">
|
||||
<div class="ui labeled button" {{if not $.IsSigned}}data-tooltip-content="{{ctx.Locale.Tr "repo.watch_guest_user"}}"{{end}}>
|
||||
{{$buttonText := ctx.Locale.Tr "repo.watch"}}
|
||||
{{if $.IsWatchingRepo}}{{$buttonText = ctx.Locale.Tr "repo.unwatch"}}{{end}}
|
||||
<button type="submit" class="ui compact small basic button"{{if not $.IsSigned}} disabled{{end}} aria-label="{{$buttonText}}">
|
||||
{{svg "octicon-eye"}}
|
||||
<span class="not-mobile" aria-hidden="true">{{$buttonText}}</span>
|
||||
</button>
|
||||
<a hx-boost="false" class="ui basic label" href="{{.RepoLink}}/watchers">
|
||||
{{CountFmt .Repository.NumWatches}}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
<div class="ui labeled button" {{if not $.IsSigned}}data-tooltip-content="{{ctx.Locale.Tr "repo.watch_guest_user"}}"{{end}}>
|
||||
{{$buttonText := ctx.Locale.Tr "repo.watch"}}
|
||||
{{if $.IsWatchingRepo}}{{$buttonText = ctx.Locale.Tr "repo.unwatch"}}{{end}}
|
||||
<button type="button" class="ui compact small basic button" aria-label="{{$buttonText}}"
|
||||
{{if $.IsSigned}}
|
||||
data-fetch-method="post"
|
||||
data-fetch-url="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}unwatch{{else}}watch{{end}}"
|
||||
data-fetch-sync="$closest(.ui.labeled.button)"
|
||||
{{else}}
|
||||
disabled
|
||||
{{end}}
|
||||
>
|
||||
{{svg "octicon-eye"}}
|
||||
<span class="not-mobile" aria-hidden="true">{{$buttonText}}</span>
|
||||
</button>
|
||||
<a class="ui basic label" href="{{.RepoLink}}/watchers">
|
||||
{{CountFmt .Repository.NumWatches}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
<div class="divider tw-my-0"></div>
|
||||
<div role="main" class="page-content status-page-500">
|
||||
<div class="ui container" >
|
||||
<style> .ui.message.flash-message { text-align: left; } </style>
|
||||
{{template "base/alert" .}}
|
||||
<div class="status-page-error">
|
||||
<div class="status-page-error-title">500 Internal Server Error</div>
|
||||
|
||||
Reference in New Issue
Block a user