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>
91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package repository
|
|
|
|
import (
|
|
"git.mchus.pro/mchus/quoteforge/internal/models"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type ConfigurationRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewConfigurationRepository(db *gorm.DB) *ConfigurationRepository {
|
|
return &ConfigurationRepository{db: db}
|
|
}
|
|
|
|
func (r *ConfigurationRepository) Create(config *models.Configuration) error {
|
|
return r.db.Create(config).Error
|
|
}
|
|
|
|
func (r *ConfigurationRepository) GetByID(id uint) (*models.Configuration, error) {
|
|
var config models.Configuration
|
|
err := r.db.Preload("User").First(&config, id).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &config, nil
|
|
}
|
|
|
|
func (r *ConfigurationRepository) GetByUUID(uuid string) (*models.Configuration, error) {
|
|
var config models.Configuration
|
|
err := r.db.Preload("User").Where("uuid = ?", uuid).First(&config).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &config, nil
|
|
}
|
|
|
|
func (r *ConfigurationRepository) Update(config *models.Configuration) error {
|
|
return r.db.Save(config).Error
|
|
}
|
|
|
|
func (r *ConfigurationRepository) Delete(id uint) error {
|
|
return r.db.Delete(&models.Configuration{}, id).Error
|
|
}
|
|
|
|
func (r *ConfigurationRepository) ListByUser(userID uint, offset, limit int) ([]models.Configuration, int64, error) {
|
|
var configs []models.Configuration
|
|
var total int64
|
|
|
|
r.db.Model(&models.Configuration{}).Where("user_id = ?", userID).Count(&total)
|
|
err := r.db.
|
|
Where("user_id = ?", userID).
|
|
Order("created_at DESC").
|
|
Offset(offset).
|
|
Limit(limit).
|
|
Find(&configs).Error
|
|
|
|
return configs, total, err
|
|
}
|
|
|
|
func (r *ConfigurationRepository) ListTemplates(offset, limit int) ([]models.Configuration, int64, error) {
|
|
var configs []models.Configuration
|
|
var total int64
|
|
|
|
r.db.Model(&models.Configuration{}).Where("is_template = ?", true).Count(&total)
|
|
err := r.db.
|
|
Preload("User").
|
|
Where("is_template = ?", true).
|
|
Order("created_at DESC").
|
|
Offset(offset).
|
|
Limit(limit).
|
|
Find(&configs).Error
|
|
|
|
return configs, total, err
|
|
}
|
|
|
|
// ListAll returns all configurations without user filter
|
|
func (r *ConfigurationRepository) ListAll(offset, limit int) ([]models.Configuration, int64, error) {
|
|
var configs []models.Configuration
|
|
var total int64
|
|
|
|
r.db.Model(&models.Configuration{}).Count(&total)
|
|
err := r.db.
|
|
Order("created_at DESC").
|
|
Offset(offset).
|
|
Limit(limit).
|
|
Find(&configs).Error
|
|
|
|
return configs, total, err
|
|
}
|