- Fix critical race condition in sync dropdown actions - Add loading states and spinners for sync operations - Implement proper event delegation to prevent memory leaks - Add accessibility attributes (aria-label, aria-haspopup, aria-expanded) - Add keyboard navigation (Escape to close dropdown) - Reduce code duplication in sync functions (70% reduction) - Improve error handling for pricelist badge - Fix z-index issues in dropdown menu - Maintain full backward compatibility Addresses all issues identified in the TODO list and bug reports
63 lines
3.7 KiB
HTML
63 lines
3.7 KiB
HTML
{{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">
|
|
<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">
|
|
<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>
|
|
</span>
|
|
{{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">
|
|
<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>
|
|
{{.PendingCount}}
|
|
</span>
|
|
{{end}}
|
|
|
|
<!-- Dropdown button for sync actions -->
|
|
<div class="relative">
|
|
<button id="sync-dropdown-button"
|
|
aria-label="Меню синхронизации"
|
|
aria-haspopup="true"
|
|
aria-expanded="false"
|
|
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}}
|