0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-04-13 18:15:21 +02:00

fix(stopwatch): prevent page reload when starting/stopping from issue sidebar

Replace link-action buttons in the sidebar time-tracker with plain
buttons handled by a delegated click listener in stopwatch.ts. After a
successful POST the two button groups (.issue-start-buttons /
.issue-stop-cancel-buttons) are toggled immediately via show/hide,
so the page never reloads. The navbar icon continues to update via
the WebSocket push or periodic poller as before.
This commit is contained in:
Epid 2026-04-02 07:51:32 +03:00
parent 075af8eaf5
commit 111ca0cd4f
2 changed files with 36 additions and 10 deletions

View File

@ -8,27 +8,24 @@
{{svg "octicon-pencil"}}
</button>
</div>
<div class="ui buttons tw-mt-2 tw-w-full">
{{if $.IsStopwatchRunning}}
<button class="ui button tw-flex-1 issue-stop-time link-action" data-url="{{.Issue.Link}}/times/stopwatch/stop">
<div class="ui buttons tw-mt-2 tw-w-full issue-stop-cancel-buttons{{if not $.IsStopwatchRunning}} tw-hidden{{end}}">
<button class="ui button tw-flex-1 issue-stop-time" data-url="{{.Issue.Link}}/times/stopwatch/stop">
{{svg "octicon-stopwatch"}} {{ctx.Locale.Tr "repo.issues.timetracker_timer_stop"}}
</button>
<button class="ui icon button issue-cancel-time link-action" data-url="{{.Issue.Link}}/times/stopwatch/cancel" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.timetracker_timer_discard"}}">
<button class="ui icon button issue-cancel-time" data-url="{{.Issue.Link}}/times/stopwatch/cancel" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.timetracker_timer_discard"}}">
{{svg "octicon-trash"}}
</button>
{{else}}
<button class="ui button tw-flex-1 issue-start-time link-action" data-url="{{.Issue.Link}}/times/stopwatch/start">
</div>
<div class="ui buttons tw-mt-2 tw-w-full issue-start-buttons{{if $.IsStopwatchRunning}} tw-hidden{{end}}">
<button class="ui button tw-flex-1 issue-start-time" data-url="{{.Issue.Link}}/times/stopwatch/start">
{{svg "octicon-stopwatch"}} {{ctx.Locale.Tr "repo.issues.timetracker_timer_start"}}
</button>
<button class="ui icon button issue-add-time show-modal" data-modal="#issue-time-manually-add-modal" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.timetracker_timer_manually_add"}}">
{{svg "octicon-plus"}}
</button>
{{end}}
</div>
{{if and (not $.IsStopwatchRunning) .HasUserStopwatch}}
<div class="ui warning message">{{ctx.Locale.Tr "repo.issues.tracking_already_started" .OtherStopwatchURL}}</div>
{{end}}
<div class="ui warning message issue-tracking-already-started{{if or $.IsStopwatchRunning (not .HasUserStopwatch)}} tw-hidden{{end}}">{{ctx.Locale.Tr "repo.issues.tracking_already_started" .OtherStopwatchURL}}</div>
{{if .Issue.TimeEstimate}}
<div class="tw-my-2">{{ctx.Locale.Tr "repo.issues.time_estimate_display" (TimeEstimateString .Issue.TimeEstimate)}}</div>

View File

@ -52,6 +52,35 @@ export function initStopwatch() {
await POST(action, {data: new FormData(form)});
});
// Handle start/stop/cancel from the issue sidebar without a page reload.
// Buttons toggle between the two groups (.issue-start-buttons / .issue-stop-cancel-buttons)
// immediately; the navbar icon is updated by the WebSocket push or periodic poller.
addDelegatedEventListener(document, 'click', '.issue-start-time,.issue-stop-time,.issue-cancel-time', async (btn: HTMLElement, e: MouseEvent) => {
e.preventDefault();
const url = btn.getAttribute('data-url');
if (!url) return;
const startGroup = document.querySelector('.issue-start-buttons');
const stopGroup = document.querySelector('.issue-stop-cancel-buttons');
const isStart = btn.classList.contains('issue-start-time');
btn.classList.add('is-loading');
try {
const resp = await POST(url);
if (!resp.ok) return;
// Toggle sidebar button groups immediately, no reload needed.
if (isStart) {
hideElem(startGroup);
showElem(stopGroup);
} else {
hideElem(stopGroup);
showElem(startGroup);
}
} finally {
btn.classList.remove('is-loading');
}
});
let usingPeriodicPoller = false;
const startPeriodicPoller = (timeout: number) => {
if (timeout <= 0 || !Number.isFinite(timeout)) return;