Introduced ConnectionManager to support offline-first architecture:
- New internal/db/connection.go with thread-safe connection management
- Lazy connection establishment (5s timeout, 10s cooldown)
- Automatic ping caching (30s interval) to avoid excessive checks
- Updated middleware/offline.go to use ConnectionManager.IsOnline()
- Updated sync/worker.go to use ConnectionManager instead of direct DB
This enables the application to start without MariaDB and gracefully
handle offline/online transitions.
Part of Phase 2.5: Full Offline Mode
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed two critical issues preventing offline-first operation:
1. **Instant startup** - Removed blocking GetDB() call during server
initialization. Server now starts in <10ms instead of 1+ minute.
- Changed setupRouter() to use lazy DB connection via ConnectionManager
- mariaDB connection is now nil on startup, established only when needed
- Fixes timeout issues when MariaDB is unreachable
2. **Offline mode nil pointer panics** - Added graceful degradation
when database is offline:
- ComponentService.GetCategories() returns DefaultCategories if repo is nil
- ComponentService.List/GetByLotName checks for nil repo
- PricelistService methods return empty/error responses in offline mode
- All methods properly handle nil repositories
**Before**: Server startup took 1min+ and crashed with nil pointer panic
when trying to load /configurator page offline.
**After**: Server starts instantly and serves pages in offline mode using
DefaultCategories and SQLite data.
Related to Phase 2.5: Full Offline Mode (local-first architecture)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- 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>
Root cause: admin_pricing.html declared 'const showToast' while base.html
already defined 'function showToast', causing SyntaxError that prevented
all JavaScript from executing on the admin pricing page.
Changes:
- Removed duplicate showToast declaration from admin_pricing.html (lines 206-210)
- Removed debug logging added in previous commit
- Kept immediate function calls in base.html to ensure early initialization
This fixes the issue where username and "Администратор цен" link
disappeared when navigating to /admin/pricing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added immediate calls to checkDbStatus() and checkWritePermission() in base.html
- Calls happen right after function definitions, before DOMContentLoaded
- Added console.log statements to track function execution and API responses
- Removed duplicate calls from admin_pricing.html to avoid conflicts
- This will help diagnose why username and admin link disappear on admin pricing page
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Parse URLSearchParams to detect ?tab=pricelists on page load
- Load tab from URL or default to 'alerts'
- Fixes redirect from /pricelists to /admin/pricing?tab=pricelists
This resolves the critical UX issue where users redirected from
/pricelists would see the 'alerts' tab instead of 'pricelists'.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Pass originalHTML through syncAction function chain
- Simplify finally block by restoring original button innerHTML
- Remove hardcoded button HTML values (5 lines reduction)
- Improve maintainability: button text changes won't break code
- Preserve any custom classes, attributes, or nested elements
This fixes the issue where originalHTML was declared but never used.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- 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
- Replace text 'Online/Offline' with SVG icons in sync status
- Change sync button to circular arrow icon
- Add dropdown menu with push changes, full sync, and last sync status
- Add pricelist version badge to configuration page
- Load pricelist version via /api/pricelists/latest on DOMContentLoaded
This completes task 1 of Phase 2.5 (UI Improvements) as specified in CLAUDE.md
- Implement RefreshPrices for local-first mode
- Update prices from local_components.current_price cache
- Graceful degradation when component not found
- Add PriceUpdatedAt timestamp to LocalConfiguration model
- Support both authenticated and no-auth price refresh
- Fix sync duplicate entry bug
- pushConfigurationUpdate now ensures server_id exists before update
- Fetch from LocalConfiguration.ServerID or search on server if missing
- Update local config with server_id after finding
- Add application auto-restart after settings save
- Implement restartProcess() using syscall.Exec
- Setup handler signals restart via channel
- Setup page polls /health endpoint and redirects when ready
- Add "Back" button on setup page when settings exist
- Fix setup handler password handling
- Use PasswordEncrypted field consistently
- Support empty password by using saved value
- Improve sync status handling
- Add fallback for is_offline check in SyncStatusPartial
- Enhance background sync logging with prefixes
- Update CLAUDE.md documentation
- Mark Phase 2.5 tasks as complete
- Add UI Improvements section with future tasks
- Update SQLite tables documentation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create htmx-powered partial template for sync status display
- Show Online/Offline indicator with color coding (green/red)
- Display pending changes count badge when there are unsynced items
- Add Sync button to push pending changes (appears only when needed)
- Auto-refresh every 30 seconds via htmx polling
- Replace JavaScript-based sync indicator with server-rendered partial
- Integrate SyncStatusPartial handler with template rendering
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Consolidate UI TODO items into single sync status partial task
- Move conflict resolution to Phase 4
- Add LOCAL_FIRST_INTEGRATION.md with architecture guide
- Add unified repository interface for future use
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add development phases (pricelists, projects, local SQLite, price versioning)
- Add new table schemas (qt_pricelists, qt_projects, qt_specifications)
- Add local SQLite database structure for offline work
- Remove Docker files (distributing as binary only)
- Disable RBAC for initial phases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add price_updated_at field to qt_configurations table to track when prices were last updated
- Add RefreshPrices() method in configuration service to update all component prices with current values from database
- Add POST /api/configs/:uuid/refresh-prices API endpoint for price updates
- Add "Refresh Prices" button in configurator UI next to Save button
- Display last price update timestamp in human-readable format (e.g., "5 min ago", "2 hours ago")
- Create migration 004_add_price_updated_at.sql for database schema update
- Update CLAUDE.md documentation with new API endpoint and schema changes
- Add MIGRATION_PRICE_REFRESH.md with detailed migration instructions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add is_hidden field to hide components from configurator
- Add colored dot indicator showing component usage status:
- Green: available in configurator
- Cyan: used as source for meta-articles
- Gray: hidden from configurator
- Optimize price recalculation with caching and skip unchanged
- Show current lot name during price recalculation
- Add Dockerfile (Alpine-based multi-stage build)
- Add docker-compose.yml and .dockerignore
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Основные изменения:
1. CSV экспорт и веб-интерфейс:
- Компоненты теперь сортируются по иерархии категорий (display_order)
- Категории отображаются в правильном порядке: BB, CPU, MEM, GPU и т.д.
- Компоненты без категории отображаются в конце
2. Раздел PCI в конфигураторе:
- Разделен на секции: GPU/DPU, NIC/HCA, HBA
- Улучшена навигация и выбор компонентов
3. Сохранение "своей цены":
- Добавлено поле custom_price в модель Configuration
- Создана миграция 002_add_custom_price.sql
- "Своя цена" сохраняется при сохранении конфигурации
- При загрузке конфигурации восстанавливается сохраненная цена
4. Автосохранение:
- Конфигурация автоматически сохраняется через 1 секунду после изменений
- Debounce предотвращает избыточные запросы
- Автосохранение работает для всех изменений (компоненты, количество, цена)
5. Дополнительно:
- Добавлен cmd/importer для импорта метаданных из таблицы lot
- Создан скрипт apply_migration.sh для применения миграций
- Оптимизирована работа с категориями в ExportService
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Исправлен расчёт цен: теперь учитывается метод (медиана/среднее) и период для каждого компонента
- Добавлены функции calculateMedian и calculateAverage
- Исправлен PreviewPrice для корректного предпросмотра с учётом настроек
- Сортировка по умолчанию изменена на популярность (desc)
- Добавлен раздел "Своя цена" в конфигуратор:
- Ввод целевой цены с пропорциональным пересчётом всех позиций
- Отображение скидки в процентах
- Таблица скорректированных цен
- Экспорт CSV со скидкой
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Добавлено отображение последней полученной цены в окне настройки цены
- Добавлен функционал переименования конфигураций (PATCH /api/configs/:uuid/rename)
- Изменён формат имени файла при экспорте: "YYYY-MM-DD NAME SPEC.ext"
- Исправлена сортировка компонентов: перенесена на сервер для корректной работы с пагинацией
- Добавлен расчёт popularity_score на основе котировок из lot_log
- Исправлена потеря настроек (метод, период, коэффициент) при пересчёте цен
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add tab-based configurator (Base, Storage, PCI, Power, Accessories, Other)
- Base tab: single-select with autocomplete for MB, CPU, MEM
- Other tabs: multi-select with autocomplete and quantity input
- Table view with LOT, Description, Price, Quantity, Total columns
- Add configuration list page with create modal (opportunity number)
- Remove Excel export functionality and excelize dependency
- Increase component list limit from 100 to 5000
- Add web templates (base, index, configs, login, admin_pricing)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Go module with Gin, GORM, JWT, excelize dependencies
- Configuration loading from YAML with all settings
- GORM models for users, categories, components, configurations, alerts
- Repository layer for all entities
- Services: auth (JWT), pricing (median/average/weighted), components,
quotes, configurations, export (CSV/XLSX), alerts
- Middleware: JWT auth, role-based access, CORS
- HTTP handlers for all API endpoints
- Main server with dependency injection and graceful shutdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>