Commit Graph

86 Commits

Author SHA1 Message Date
Mikhail Chusavitin
80ec7bc6b8 Apply remaining pricelist and local-first updates 2026-02-06 13:01:40 +03:00
Mikhail Chusavitin
726dccb07c feat: add projects flow and consolidate default project handling 2026-02-06 11:39:12 +03:00
Mikhail Chusavitin
41c0a47f54 Implement local DB migrations and archived configuration lifecycle 2026-02-04 18:52:56 +03:00
Mikhail Chusavitin
f4f92dea66 Store configuration owner by MariaDB username 2026-02-04 12:20:41 +03:00
Mikhail Chusavitin
d094d39427 Add server-to-local configuration import in web UI 2026-02-04 11:31:23 +03:00
Mikhail Chusavitin
7c606af2bb Fix missing config handling and auto-restart after setup 2026-02-04 10:19:35 +03:00
Mikhail Chusavitin
8d84484412 fix: fix online mode after offline-first architecture changes
- Fix nil pointer dereference in PricingHandler alert methods
- Add automatic MariaDB connection on startup if settings exist
- Update setupRouter to accept mariaDB as parameter
- Fix offline mode checks: use h.db instead of h.alertService
- Update setup handler to show restart required message
- Add warning status support in setup.html UI

This ensures that after saving connection settings, the application
works correctly in online mode after restart. All repositories are
properly initialized with MariaDB connection on startup.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 10:50:07 +03:00
4735e2b9bb feat: always show admin menu with online checks for operations
**Changes:**

1. **Admin menu always visible** (base.html)
   - Removed 'hidden' class from "Администратор цен" link
   - Menu no longer depends on write permission check
   - Users can access pricing/pricelists pages in offline mode

2. **Online status checks for mutations** (admin_pricing.html)
   - Added checkOnlineStatus() helper function
   - createPricelist() checks online before creating
   - deletePricelist() checks online before deleting
   - Clear user feedback when operations blocked offline

**User Impact:**
- Admin menu accessible in both online and offline modes
- View-only access to pricelists when offline
- Clear error messages when attempting mutations offline
- Better offline-first UX

Part of Phase 2.5: Full Offline Mode

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 07:12:18 +03:00
cdf5cef2cf perf: eliminate connection timeouts in offline mode
Fixed application freezing in offline mode by preventing unnecessary
reconnection attempts:

**Changes:**

1. **DSN timeouts** (localdb.go)
   - Added timeout=3s, readTimeout=3s, writeTimeout=3s to MySQL DSN
   - Reduces connection timeout from 75s to 3s when MariaDB unreachable

2. **Fast /api/db-status** (main.go)
   - Check connection status before attempting GetDB()
   - Avoid reconnection attempts on every status request
   - Returns cached offline status instantly

3. **Optimized sync service** (sync/service.go)
   - GetStatus() checks connection status before GetDB()
   - NeedSync() skips server check if already offline
   - Prevents repeated 3s timeouts on every sync info request

4. **Local pricelist fallback** (pricelist.go)
   - GetLatest() returns local pricelists when server offline
   - UI can now display pricelist version in offline mode

5. **Better UI error messages** (configs.html)
   - 404 shows "Не загружен" instead of "Ошибка загрузки"
   - Network errors show "Не доступен" in gray
   - Distinguishes between missing data and real errors

**Performance:**
- Before: 75s timeout on every offline request
- After: <5ms response time in offline mode
- Cached error state prevents repeated connection attempts

**User Impact:**
- UI no longer freezes when loading pages offline
- Instant page loads and API responses
- Pricelist version displays correctly in offline mode
- Clear visual feedback for offline state

Fixes Phase 2.5 offline mode performance issues.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 07:10:53 +03:00
2c75a7ccb8 feat: improve admin pricing modal quote count display to show period and total counts 2026-02-02 21:34:51 +03:00
Mikhail Chusavitin
0bde12a39d 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>
2026-02-02 17:19:52 +03:00
Mikhail Chusavitin
e0404186ad fix: remove duplicate showToast declaration causing JavaScript error
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>
2026-02-02 14:54:13 +03:00
Mikhail Chusavitin
eda0e7cb47 debug: add logging to diagnose admin pricing page issue
- 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>
2026-02-02 14:51:38 +03:00
Mikhail Chusavitin
693c1d05d7 fix: ensure write permission check on admin pricing page load\n\n- Added explicit checkWritePermission() call when admin pricing page loads\n- Ensures 'Администратор цен' link and username are properly displayed\n- Fixes issue where these elements disappeared when navigating to admin pricing 2026-02-02 14:30:28 +03:00
Mikhail Chusavitin
7fb9dd0267 fix: cache database username to avoid redundant API calls\n\n- Added cachedDbUsername variable to store username after first API call\n- Modified loadPricelistsDbUsername to check cache before making API request\n- Reduces unnecessary API calls when opening pricelists modal multiple times\n- Improves performance and reduces server load 2026-02-02 14:19:23 +03:00
Mikhail Chusavitin
61646bea46 fix: hide pagination when pricelists loading fails\n\n- Added pagination hiding when pricelists load error occurs\n- Prevents display of empty pagination controls when there's an error\n- Maintains consistent UI behavior 2026-02-02 14:15:23 +03:00
Mikhail Chusavitin
9495f929aa fix: add double-submit protection for pricelist creation\n\n- Added isCreatingPricelist flag to prevent duplicate submissions\n- Disable submit button during creation process\n- Show loading text during submission\n- Re-enable button and restore text in finally block\n- Prevents accidental creation of duplicate pricelists 2026-02-02 14:03:39 +03:00
Mikhail Chusavitin
b80bde7dac fix: add showToast fallback for robustness\n\n- Added fallback showToast function to prevent undefined errors\n- If showToast is not available from base.html, use simple alert fallback\n- Maintains same functionality while improving robustness\n- Addresses potential undefined showToast issue in pricelists functions 2026-02-02 13:50:32 +03:00
Mikhail Chusavitin
e307a2765d fix: rename global canWrite variable to avoid naming conflicts\n\n- Renamed global 'canWrite' variable to 'pricelistsCanWrite' to avoid potential conflicts\n- Updated all references to the renamed variable in pricelists functions\n- Maintains same functionality while improving code quality 2026-02-02 13:00:05 +03:00
Mikhail Chusavitin
6f1feb942a fix: handle URL tab parameter in admin pricing page
- 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>
2026-02-02 12:56:14 +03:00
Mikhail Chusavitin
236e37376e fix: properly hide main tab content when pricelists tab is active\n\n- Fixed tab switching logic to properly hide main tab-content when pricelists tab is selected\n- Ensures no 'Загрузка...' text appears in pricelists tab\n- Maintains proper tab visibility for all other tabs 2026-02-02 12:45:33 +03:00
Mikhail Chusavitin
ded6e09b5e feat: move pricelists to admin pricing tab\n\n- Removed separate 'Прайслисты' link from navigation\n- Added 4th tab 'Прайслисты' to admin_pricing.html\n- Moved pricelists table, create modal, and CRUD functionality to admin pricing\n- Updated /pricelists route to redirect to /admin/pricing?tab=pricelists\n\nFixes task 2: Прайслисты → вкладка в "Администратор цен" 2026-02-02 12:42:05 +03:00
Mikhail Chusavitin
96bbe0a510 fix: use originalHTML to restore button state after sync
- 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>
2026-02-02 12:32:44 +03:00
Mikhail Chusavitin
b672cbf27d feat: implement comprehensive sync UI improvements and bug fixes
- 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
2026-02-02 12:17:17 +03:00
Mikhail Chusavitin
e206531364 feat: implement sync icon + pricelist badge UI improvements
- 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
2026-02-02 11:18:24 +03:00
Mikhail Chusavitin
9bd2acd4f7 Add offline RefreshPrices, fix sync bugs, implement auto-restart
- 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>
2026-02-02 11:03:41 +03:00
ec3c16f3fc Add UI sync status indicator with pending badge
- 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>
2026-02-02 06:38:23 +03:00
143d217397 Add Phase 2: Local SQLite database with sync functionality
Implements complete offline-first architecture with SQLite caching and MariaDB synchronization.

Key features:
- Local SQLite database for offline operation (data/quoteforge.db)
- Connection settings with encrypted credentials
- Component and pricelist caching with auto-sync
- Sync API endpoints (/api/sync/status, /components, /pricelists, /all)
- Real-time sync status indicator in UI with auto-refresh
- Offline mode detection middleware
- Migration tool for database initialization
- Setup wizard for initial configuration

New components:
- internal/localdb: SQLite repository layer (components, pricelists, sync)
- internal/services/sync: Synchronization service
- internal/handlers/sync: Sync API handlers
- internal/handlers/setup: Setup wizard handlers
- internal/middleware/offline: Offline detection
- cmd/migrate: Database migration tool

UI improvements:
- Setup page for database configuration
- Sync status indicator with online/offline detection
- Warning icons for pending synchronization
- Auto-refresh every 30 seconds

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 11:00:32 +03:00
f31ae69233 Add price refresh functionality to configurator
- 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>
2026-01-31 10:31:00 +03:00
8309a5dc0e Add hide component feature, usage indicators, and Docker support
- 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>
2026-01-30 22:49:11 +03:00
Mikhail Chusavitin
48921c699d Add meta component pricing functionality and admin UI enhancements 2026-01-30 20:49:59 +03:00
Mikhail Chusavitin
d32b1c5d0c Добавлены сортировка по категориям, секции PCI и автосохранение
Основные изменения:

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>
2026-01-30 17:48:44 +03:00
Mikhail Chusavitin
db37040399 Исправления расчёта цен и добавление функционала своей цены
- Исправлен расчёт цен: теперь учитывается метод (медиана/среднее) и период для каждого компонента
- Добавлены функции calculateMedian и calculateAverage
- Исправлен PreviewPrice для корректного предпросмотра с учётом настроек
- Сортировка по умолчанию изменена на популярность (desc)
- Добавлен раздел "Своя цена" в конфигуратор:
  - Ввод целевой цены с пропорциональным пересчётом всех позиций
  - Отображение скидки в процентах
  - Таблица скорректированных цен
  - Экспорт CSV со скидкой

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 11:53:39 +03:00
Mikhail Chusavitin
7ded78f2c3 Улучшения управления ценами и конфигурациями
- Добавлено отображение последней полученной цены в окне настройки цены
- Добавлен функционал переименования конфигураций (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>
2026-01-27 11:39:12 +03:00
Mikhail Chusavitin
d7d6e9d62c New Quotator and some major changes to pricing admin 2026-01-26 18:30:45 +03:00
Mikhail Chusavitin
a93644131c Redesign configurator UI with tabs and remove Excel export
- 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>
2026-01-26 15:57:15 +03:00