fix: display only real sync errors in error count and list

- Added CountErroredChanges() method to count only pending changes with LastError
- Previously, error count included all pending changes, not just failed ones
- Added /api/sync/info endpoint with proper error count and error list
- Added sync info modal to display sync status, error count, and error details
- Made sync status indicators clickable to open the modal
- Fixed disconnect between "Error count: 4" and "No errors" in the list

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-02-02 17:19:52 +03:00
parent e0404186ad
commit 0bde12a39d
5 changed files with 202 additions and 99 deletions

View File

@@ -1,13 +1,13 @@
{{define "sync_status"}}
<div class="flex items-center gap-2 relative">
{{if .IsOffline}}
<span class="flex items-center gap-1 text-red-600" title="Offline">
<span class="flex items-center gap-1 text-red-600 cursor-pointer" title="Offline" onclick="openSyncModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
</span>
{{else}}
<span class="flex items-center gap-1 text-green-600" title="Online">
<span class="flex items-center gap-1 text-green-600 cursor-pointer" title="Online" onclick="openSyncModal()">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
@@ -15,7 +15,7 @@
{{end}}
{{if gt .PendingCount 0}}
<span class="bg-yellow-100 text-yellow-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1">
<span class="bg-yellow-100 text-yellow-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1 cursor-pointer" onclick="openSyncModal()">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
@@ -23,40 +23,15 @@
</span>
{{end}}
<!-- Dropdown button for sync actions -->
<!-- Sync button (full sync only) -->
<div class="relative">
<button id="sync-dropdown-button"
aria-label="Меню синхронизации"
aria-haspopup="true"
aria-expanded="false"
<button id="sync-button"
aria-label="Синхронизация"
class="text-gray-600 hover:text-gray-800 text-xs flex items-center gap-1">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
</button>
<!-- Dropdown menu -->
<div id="sync-dropdown-menu" class="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 hidden z-50">
<button data-action="push-changes" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">
<svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
Push changes
</button>
<button data-action="full-sync" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">
<svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
Full sync
</button>
<div class="border-t border-gray-100 my-1"></div>
<div class="px-4 py-2 text-xs text-gray-500">
<svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
Последняя синхронизация: <span id="last-sync-time">-</span>
</div>
</div>
</div>
</div>
{{end}}