diff --git a/cmd/backup_performer/main.go b/cmd/backup_performer/main.go index 7e5e9d9..57fb246 100644 --- a/cmd/backup_performer/main.go +++ b/cmd/backup_performer/main.go @@ -1,8 +1,8 @@ package main import ( - "backea/internal/backup/config" "backea/internal/backup/core" + "backea/internal/backup/models" "backea/internal/backup/strategy" "context" "flag" @@ -31,7 +31,7 @@ func main() { } } - cfg, err := config.LoadConfig(*configPath) + cfg, err := models.LoadConfig(*configPath) if err != nil { log.Fatalf("Failed to load configuration: %v", err) } diff --git a/cmd/list-backups/main.go b/cmd/list-backups/main.go index bb49583..5b1368d 100644 --- a/cmd/list-backups/main.go +++ b/cmd/list-backups/main.go @@ -20,13 +20,8 @@ func main() { log.Printf("Warning: Error loading .env file: %v", err) } - factoryBuilder := &strategy.DefaultFactoryBuilder{} - factory, err := factoryBuilder.BuildFactory(*configPath) - if err != nil { - log.Fatalf("Failed to create backup factory: %v", err) - } - - config := factory.Config + // cfg, _ := models.LoadConfig(configPath) + factory, _ := strategy.NewFactory(configPath) // Process each service group for groupName, serviceGroup := range factory.Config.Services { diff --git a/cmd/server/main.go b/cmd/server/main.go index 0735a35..885ccde 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,7 +1,7 @@ package main import ( - "backea/internal/backup" + "backea/internal/backup/strategy" "backea/internal/server" "log" "os" @@ -15,10 +15,12 @@ func main() { } // Create backup factory - backupFactory, _ := backup.NewBackupFactory("config.yml") + configPath := "config.yml" + // cfg, _ := models.LoadConfig(configPath) + backupFactory, _ := strategy.NewFactory(configPath) // Initialize and start the server - srv := server.New(backupFactory) + srv := server.New(*backupFactory) log.Printf("Starting server on port %s", port) if err := srv.Start(":" + port); err != nil { log.Fatalf("Failed to start server: %v", err) diff --git a/config.yml b/config.yml index 73a13fd..19313b6 100644 --- a/config.yml +++ b/config.yml @@ -11,7 +11,7 @@ services: backealocal: source: host: "local" - path: "/home/sirir/Images" + path: "/home/gevo/Images" hooks: before_hook: "ls" after_hook: "" @@ -21,18 +21,18 @@ services: type: "kopia" provider: "local" destination: - path: "/home/sirir/backup/image1" + path: "/home/gevo/backup/image1" 2: backup_strategy: type: "kopia" provider: "local" destination: - path: "/home/sirir/backup/images2" + path: "/home/gevo/backup/images2" imageslocal: source: host: "local" - path: "/home/sirir/Images/" + path: "/home/gevo/Images/" hooks: before_hook: "ls" after_hook: "" diff --git a/internal/backup/core/executor.go b/internal/backup/core/executor.go index 3ae0d43..ea5913c 100644 --- a/internal/backup/core/executor.go +++ b/internal/backup/core/executor.go @@ -1,7 +1,7 @@ package core import ( - "backea/internal/backup/config" + "backea/internal/backup/models" "backea/internal/backup/strategy" "backea/internal/mail" "context" @@ -12,14 +12,14 @@ import ( // Executor handles the execution of backups for multiple services type Executor struct { - Config *config.Configuration + Config *models.Configuration Factory strategy.Factory Mailer *mail.Mailer concurrency int } // NewExecutor creates a new backup executor -func NewExecutor(config *config.Configuration, factory strategy.Factory) *Executor { +func NewExecutor(config *models.Configuration, factory strategy.Factory) *Executor { return &Executor{ Config: config, Factory: factory, diff --git a/internal/backup/models/config.go b/internal/backup/models/config.go new file mode 100644 index 0000000..49a476c --- /dev/null +++ b/internal/backup/models/config.go @@ -0,0 +1,112 @@ +package models + +import ( + "log" + + "github.com/joho/godotenv" + "github.com/spf13/viper" +) + +// Configuration holds the complete application configuration +type Configuration struct { + Defaults DefaultsConfig `mapstructure:"defaults"` + Services map[string]ServiceGroup `mapstructure:"services"` +} + +// DefaultsConfig holds the default settings for all services +type DefaultsConfig struct { + Retention RetentionConfig `mapstructure:"retention"` +} + +// ServiceGroup represents a service group with a common directory and multiple backup configurations +type ServiceGroup struct { + Directory string `mapstructure:"directory,omitempty"` + Source SourceConfig `mapstructure:"source"` + Hooks HooksConfig `mapstructure:"hooks"` + BackupConfigs map[string]BackupConfig `mapstructure:"backup_configs"` +} + +// SourceConfig represents source configuration for backups +type SourceConfig struct { + Host string `mapstructure:"host"` + Path string `mapstructure:"path"` + SSHKey string `mapstructure:"ssh_key"` +} + +// HooksConfig contains the hooks to run before and after the backup +type HooksConfig struct { + BeforeHook string `mapstructure:"before_hook"` + AfterHook string `mapstructure:"after_hook"` +} + +// BackupConfig represents a specific backup configuration +type BackupConfig struct { + BackupStrategy StrategyConfig `mapstructure:"backup_strategy"` +} + +// StrategyConfig represents a backup strategy configuration +type StrategyConfig struct { + Type string `mapstructure:"type"` + Provider string `mapstructure:"provider"` + Options string `mapstructure:"options,omitempty"` + Retention RetentionConfig `mapstructure:"retention,omitempty"` + Destination DestConfig `mapstructure:"destination"` +} + +// RetentionConfig represents retention policy configuration +type RetentionConfig struct { + KeepLatest int `mapstructure:"keep_latest"` + KeepHourly int `mapstructure:"keep_hourly"` + KeepDaily int `mapstructure:"keep_daily"` + KeepWeekly int `mapstructure:"keep_weekly"` + KeepMonthly int `mapstructure:"keep_monthly"` + KeepYearly int `mapstructure:"keep_yearly"` +} + +// DestConfig represents destination configuration for remote backups +type DestConfig struct { + Host string `mapstructure:"host,omitempty"` + Path string `mapstructure:"path"` + SSHKey string `mapstructure:"ssh_key,omitempty"` +} + +// LoadConfig loads the application configuration from a file +func LoadConfig(configPath string) (*Configuration, error) { + if err := godotenv.Load(); err != nil { + log.Printf("Warning: Error loading .env file: %v", err) + } + + viper.SetConfigFile(configPath) + if err := viper.ReadInConfig(); err != nil { + return nil, err + } + + var config Configuration + if err := viper.Unmarshal(&config); err != nil { + return nil, err + } + + // Apply default retention settings where needed + for serviceName, service := range config.Services { + for configID, backupConfig := range service.BackupConfigs { + // If retention is not set, use defaults + if isRetentionEmpty(backupConfig.BackupStrategy.Retention) { + backupConfig.BackupStrategy.Retention = config.Defaults.Retention + service.BackupConfigs[configID] = backupConfig + } + } + config.Services[serviceName] = service + } + + return &config, nil +} + +// isRetentionEmpty checks if a retention config is empty (all zeros) +func isRetentionEmpty(retention RetentionConfig) bool { + return retention.KeepLatest == 0 && + retention.KeepHourly == 0 && + retention.KeepDaily == 0 && + retention.KeepWeekly == 0 && + retention.KeepMonthly == 0 && + retention.KeepYearly == 0 +} diff --git a/internal/backup/strategy/factory.go b/internal/backup/strategy/factory.go index 84d640a..c897bed 100644 --- a/internal/backup/strategy/factory.go +++ b/internal/backup/strategy/factory.go @@ -1,7 +1,7 @@ package strategy import ( - "backea/internal/backup/config" + "backea/internal/backup/models" "backea/internal/backup/strategy/kopia" "fmt" "os" @@ -12,13 +12,13 @@ import ( // Factory handles backup strategy creation type Factory struct { - Config *config.Configuration + Config *models.Configuration ConfigPath string } // NewFactory initializes and returns a Factory func NewFactory(configPath string) (*Factory, error) { - cfg, err := config.LoadConfig(configPath) + cfg, err := models.LoadConfig(configPath) if err != nil { return nil, fmt.Errorf("failed to load config: %w", err) } @@ -45,7 +45,7 @@ func (f *Factory) CreateBackupStrategyForService(groupName, serviceIndex string) } // createKopiaStrategy initializes a Kopia strategy -func (f *Factory) createKopiaStrategy(serviceConfig *config.BackupConfig, sourcePath string) (Strategy, error) { +func (f *Factory) createKopiaStrategy(serviceConfig *models.BackupConfig, sourcePath string) (Strategy, error) { provider, err := f.createKopiaProvider(serviceConfig.BackupStrategy) if err != nil { return nil, fmt.Errorf("failed to create kopia provider: %w", err) @@ -58,7 +58,7 @@ func (f *Factory) createKopiaStrategy(serviceConfig *config.BackupConfig, source } // createKopiaProvider returns a Kopia storage provider -func (f *Factory) createKopiaProvider(strategyConfig config.StrategyConfig) (kopia.Provider, error) { +func (f *Factory) createKopiaProvider(strategyConfig models.StrategyConfig) (kopia.Provider, error) { switch strategyConfig.Provider { case "local": return kopia.NewLocalProvider(getDefaultPath(strategyConfig.Destination.Path)), nil @@ -123,7 +123,7 @@ func (f *Factory) getServicePath(groupName string) (string, error) { } // getServiceConfig returns a service's config -func (f *Factory) getServiceConfig(groupName, serviceIndex string) (*config.BackupConfig, error) { +func (f *Factory) getServiceConfig(groupName, serviceIndex string) (*models.BackupConfig, error) { if serviceGroup, exists := f.Config.Services[groupName]; exists { if backupConfig, exists := serviceGroup.BackupConfigs[serviceIndex]; exists { return &backupConfig, nil @@ -134,7 +134,7 @@ func (f *Factory) getServiceConfig(groupName, serviceIndex string) (*config.Back // ReloadConfig reloads configuration func (f *Factory) ReloadConfig() error { - cfg, err := config.LoadConfig(f.ConfigPath) + cfg, err := models.LoadConfig(f.ConfigPath) if err != nil { return fmt.Errorf("could not reload config: %w", err) } diff --git a/internal/web/handlers/homepage_handler.go b/internal/web/handlers/homepage_handler.go index d07aff7..f29ead8 100644 --- a/internal/web/handlers/homepage_handler.go +++ b/internal/web/handlers/homepage_handler.go @@ -1,7 +1,7 @@ package handlers import ( - "backea/internal/backup/config" + "backea/internal/backup/models" "backea/internal/backup/strategy" "backea/templates" "context" @@ -29,20 +29,18 @@ func NewHomepageHandler(factory strategy.Factory) *HomepageHandler { // Home handles the homepage request and displays latest backups by service func (h *HomepageHandler) Home(c echo.Context) error { // Create the data structures - serviceBackups := make(map[string]map[string][]strategy.BackupInfo) + serviceBackups := make(map[string]map[string][]models.BackupInfo) serviceConfigs := make(map[string]map[string]templates.ServiceProviderInfo) groupDirectories := make(map[string]string) // Store directories by group name // Get the configuration from the factory - factoryConfig, err := h.getConfig() - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to get configuration: %v", err)) - } + + factoryConfig := h.getConfig() // Process each service group for groupName, serviceGroup := range factoryConfig.Services { // Initialize maps for this group - serviceBackups[groupName] = make(map[string][]strategy.BackupInfo) + serviceBackups[groupName] = make(map[string][]models.BackupInfo) serviceConfigs[groupName] = make(map[string]templates.ServiceProviderInfo) // Store the directory at the group level in a separate map @@ -76,10 +74,7 @@ func (h *HomepageHandler) ServiceGroupHeader(c echo.Context) error { groupName := c.Param("groupName") // Get the configuration - factoryConfig, err := h.getConfig() - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to get configuration: %v", err)) - } + factoryConfig := h.getConfig() // Check if the service group exists serviceGroup, exists := factoryConfig.Services[groupName] @@ -88,7 +83,7 @@ func (h *HomepageHandler) ServiceGroupHeader(c echo.Context) error { } // Create data structures - serviceBackups := make(map[string][]strategy.BackupInfo) + serviceBackups := make(map[string][]models.BackupInfo) serviceConfigs := make(map[string]templates.ServiceProviderInfo) // Setup synchronization @@ -153,10 +148,7 @@ func (h *HomepageHandler) ServiceGroupBackups(c echo.Context) error { groupName := c.Param("groupName") // Get the configuration - factoryConfig, err := h.getConfig() - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to get configuration: %v", err)) - } + factoryConfig := h.getConfig() // Check if the service group exists serviceGroup, exists := factoryConfig.Services[groupName] @@ -165,7 +157,7 @@ func (h *HomepageHandler) ServiceGroupBackups(c echo.Context) error { } // Create data structures - serviceBackups := make(map[string][]strategy.BackupInfo) + serviceBackups := make(map[string][]models.BackupInfo) serviceConfigs := make(map[string]templates.ServiceProviderInfo) // Setup synchronization @@ -216,7 +208,7 @@ func (h *HomepageHandler) ServiceGroupBackups(c echo.Context) error { wg.Wait() // Create a map with just the group for the template - groupServiceBackups := make(map[string]map[string][]strategy.BackupInfo) + groupServiceBackups := make(map[string]map[string][]models.BackupInfo) groupServiceBackups[groupName] = serviceBackups // Create a map with just the group configs for the template @@ -233,10 +225,7 @@ func (h *HomepageHandler) ServiceGroupAllBackups(c echo.Context) error { groupName := c.Param("groupName") // Get the configuration - factoryConfig, err := h.getConfig() - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to get configuration: %v", err)) - } + factoryConfig := h.getConfig() // Check if the service group exists serviceGroup, exists := factoryConfig.Services[groupName] @@ -245,7 +234,7 @@ func (h *HomepageHandler) ServiceGroupAllBackups(c echo.Context) error { } // Create data structures - serviceBackups := make(map[string][]strategy.BackupInfo) + serviceBackups := make(map[string][]models.BackupInfo) serviceConfigs := make(map[string]templates.ServiceProviderInfo) // Setup synchronization @@ -296,7 +285,7 @@ func (h *HomepageHandler) ServiceGroupAllBackups(c echo.Context) error { wg.Wait() // Create a map with just the group for the template - groupServiceBackups := make(map[string]map[string][]strategy.BackupInfo) + groupServiceBackups := make(map[string]map[string][]models.BackupInfo) groupServiceBackups[groupName] = serviceBackups // Create a map with just the group configs for the template @@ -341,13 +330,8 @@ func (h *HomepageHandler) ServiceGroupAllBackups(c echo.Context) error { } // Helper method to get configuration from factory -func (h *HomepageHandler) getConfig() (*config.Configuration, error) { +func (h *HomepageHandler) getConfig() *models.Configuration { // Type assert to get the concrete FactoryImpl type which has Config field - if factoryImpl, ok := h.backupFactory.(*strategy.FactoryImpl); ok { - return factoryImpl.Config, nil - } + return h.backupFactory.Config - // If we can't access the Config directly, get it through factory methods - // This is where we'd need to add methods to the Factory interface if not already there - return nil, fmt.Errorf("cannot access configuration from factory") } diff --git a/templates/home.templ b/templates/home.templ index a5bd9e0..8175464 100644 --- a/templates/home.templ +++ b/templates/home.templ @@ -1,10 +1,10 @@ package templates import ( - "backea/internal/backup" "backea/templates/layouts" "fmt" "sort" "time" + "backea/internal/backup/models" ) // FormatSize formats byte size to human-readable format @@ -59,7 +59,7 @@ func FormatServiceName(groupName, serviceIndex string) string { } // CalculateTotalSize calculates total size of all backups -func CalculateTotalSize(backups []backup.BackupInfo) int64 { +func CalculateTotalSize(backups []models.BackupInfo) int64 { var total int64 for _, b := range backups { total += b.Size @@ -68,7 +68,7 @@ func CalculateTotalSize(backups []backup.BackupInfo) int64 { } // CalculateGroupTotalSize calculates total size of all backups for a service group -func CalculateGroupTotalSize(serviceGroup map[string][]backup.BackupInfo) int64 { +func CalculateGroupTotalSize(serviceGroup map[string][]models.BackupInfo) int64 { var total int64 for _, backups := range serviceGroup { for _, b := range backups { @@ -79,7 +79,7 @@ func CalculateGroupTotalSize(serviceGroup map[string][]backup.BackupInfo) int64 } // GetGroupTotalBackupCount returns the total number of backups across all services in a group -func GetGroupTotalBackupCount(serviceGroup map[string][]backup.BackupInfo) int { +func GetGroupTotalBackupCount(serviceGroup map[string][]models.BackupInfo) int { count := 0 for _, backups := range serviceGroup { count += len(backups) @@ -88,7 +88,7 @@ func GetGroupTotalBackupCount(serviceGroup map[string][]backup.BackupInfo) int { } // GetLatestBackupTime returns the most recent backup time for a service group -func GetLatestBackupTime(serviceGroup map[string][]backup.BackupInfo) (time.Time, bool) { +func GetLatestBackupTime(serviceGroup map[string][]models.BackupInfo) (time.Time, bool) { var latestTime time.Time found := false @@ -103,7 +103,7 @@ func GetLatestBackupTime(serviceGroup map[string][]backup.BackupInfo) (time.Time } // GetGroupStatus returns the status of a service group based on the most recent backup -func GetGroupStatus(serviceGroup map[string][]backup.BackupInfo) string { +func GetGroupStatus(serviceGroup map[string][]models.BackupInfo) string { latestTime, found := GetLatestBackupTime(serviceGroup) if !found { return "No Backups" @@ -121,11 +121,11 @@ type ServiceProviderInfo struct { // BackupWithService represents a backup with its service identifier type BackupWithService struct { ServiceIndex string - Backup backup.BackupInfo + Backup models.BackupInfo } // GetSortedBackups collects all backups from a service group and sorts them by time -func GetSortedBackups(serviceGroup map[string][]backup.BackupInfo) []BackupWithService { +func GetSortedBackups(serviceGroup map[string][]models.BackupInfo) []BackupWithService { var allBackups []BackupWithService // Collect all backups with their service indices @@ -147,7 +147,7 @@ func GetSortedBackups(serviceGroup map[string][]backup.BackupInfo) []BackupWithS } // Home renders the homepage with lazy-loaded backup information -templ Home(serviceBackups map[string]map[string][]backup.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo, sortedGroupNames []string, groupDirectories map[string]string) { +templ Home(serviceBackups map[string]map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo, sortedGroupNames []string, groupDirectories map[string]string) { @layouts.Base("Backea - Backup Dashboard") {
@@ -276,7 +276,7 @@ templ Home(serviceBackups map[string]map[string][]backup.BackupInfo, serviceConf } // GroupHeaderComponent renders just the group header with up-to-date stats -templ GroupHeaderComponent(groupName string, serviceBackups map[string][]backup.BackupInfo, serviceConfigs map[string]ServiceProviderInfo, directory string) { +templ GroupHeaderComponent(groupName string, serviceBackups map[string][]models.BackupInfo, serviceConfigs map[string]ServiceProviderInfo, directory string) {

@@ -347,7 +347,7 @@ templ GroupHeaderComponent(groupName string, serviceBackups map[string][]backup. } // Updated table templates with action column -templ ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]backup.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) { +templ ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) {
if GetGroupTotalBackupCount(serviceGroup) > 0 {
@@ -395,7 +395,7 @@ templ ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]backu } // ServiceGroupAllBackupsTable template for showing all backups -templ ServiceGroupAllBackupsTable(groupName string, serviceGroup map[string][]backup.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) { +templ ServiceGroupAllBackupsTable(groupName string, serviceGroup map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) { if GetGroupTotalBackupCount(serviceGroup) > 0 {
@@ -499,7 +499,7 @@ templ renderSortedBackups(groupName string, sortedBackups []BackupWithService, l // backupsTableRowsSorted renders backup rows sorted by creation time across all services -templ backupsTableRowsSorted(groupName string, serviceGroup map[string][]backup.BackupInfo, limit int, serviceConfigs map[string]map[string]ServiceProviderInfo) { +templ backupsTableRowsSorted(groupName string, serviceGroup map[string][]models.BackupInfo, limit int, serviceConfigs map[string]map[string]ServiceProviderInfo) { @renderSortedBackups(groupName, GetSortedBackups(serviceGroup), limit, serviceConfigs) } diff --git a/templates/home_templ.go b/templates/home_templ.go index 9bf0663..2f67fb1 100644 --- a/templates/home_templ.go +++ b/templates/home_templ.go @@ -5,16 +5,15 @@ package templates //lint:file-ignore SA4006 This context is only used if a nested component is present. +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + import ( - "backea/internal/backup" - "backea/internal/backup/strategy" + "backea/internal/backup/models" "backea/templates/layouts" "fmt" "sort" "time" - - "github.com/a-h/templ" - templruntime "github.com/a-h/templ/runtime" ) // FormatSize formats byte size to human-readable format @@ -69,7 +68,7 @@ func FormatServiceName(groupName, serviceIndex string) string { } // CalculateTotalSize calculates total size of all backups -func CalculateTotalSize(backups []backup.BackupInfo) int64 { +func CalculateTotalSize(backups []models.BackupInfo) int64 { var total int64 for _, b := range backups { total += b.Size @@ -78,7 +77,7 @@ func CalculateTotalSize(backups []backup.BackupInfo) int64 { } // CalculateGroupTotalSize calculates total size of all backups for a service group -func CalculateGroupTotalSize(serviceGroup map[string][]backup.BackupInfo) int64 { +func CalculateGroupTotalSize(serviceGroup map[string][]models.BackupInfo) int64 { var total int64 for _, backups := range serviceGroup { for _, b := range backups { @@ -89,7 +88,7 @@ func CalculateGroupTotalSize(serviceGroup map[string][]backup.BackupInfo) int64 } // GetGroupTotalBackupCount returns the total number of backups across all services in a group -func GetGroupTotalBackupCount(serviceGroup map[string][]backup.BackupInfo) int { +func GetGroupTotalBackupCount(serviceGroup map[string][]models.BackupInfo) int { count := 0 for _, backups := range serviceGroup { count += len(backups) @@ -98,7 +97,7 @@ func GetGroupTotalBackupCount(serviceGroup map[string][]backup.BackupInfo) int { } // GetLatestBackupTime returns the most recent backup time for a service group -func GetLatestBackupTime(serviceGroup map[string][]backup.BackupInfo) (time.Time, bool) { +func GetLatestBackupTime(serviceGroup map[string][]models.BackupInfo) (time.Time, bool) { var latestTime time.Time found := false @@ -113,7 +112,7 @@ func GetLatestBackupTime(serviceGroup map[string][]backup.BackupInfo) (time.Time } // GetGroupStatus returns the status of a service group based on the most recent backup -func GetGroupStatus(serviceGroup map[string][]backup.BackupInfo) string { +func GetGroupStatus(serviceGroup map[string][]models.BackupInfo) string { latestTime, found := GetLatestBackupTime(serviceGroup) if !found { return "No Backups" @@ -131,11 +130,11 @@ type ServiceProviderInfo struct { // BackupWithService represents a backup with its service identifier type BackupWithService struct { ServiceIndex string - Backup backup.BackupInfo + Backup models.BackupInfo } // GetSortedBackups collects all backups from a service group and sorts them by time -func GetSortedBackups(serviceGroup map[string][]backup.BackupInfo) []BackupWithService { +func GetSortedBackups(serviceGroup map[string][]models.BackupInfo) []BackupWithService { var allBackups []BackupWithService // Collect all backups with their service indices @@ -157,7 +156,7 @@ func GetSortedBackups(serviceGroup map[string][]backup.BackupInfo) []BackupWithS } // Home renders the homepage with lazy-loaded backup information -func Home(serviceBackups map[string]map[string][]strategy.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo, sortedGroupNames []string, groupDirectories map[string]string) templ.Component { +func Home(serviceBackups map[string]map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo, sortedGroupNames []string, groupDirectories map[string]string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -433,7 +432,7 @@ func Home(serviceBackups map[string]map[string][]strategy.BackupInfo, serviceCon } // GroupHeaderComponent renders just the group header with up-to-date stats -func GroupHeaderComponent(groupName string, serviceBackups map[string][]backup.BackupInfo, serviceConfigs map[string]ServiceProviderInfo, directory string) templ.Component { +func GroupHeaderComponent(groupName string, serviceBackups map[string][]models.BackupInfo, serviceConfigs map[string]ServiceProviderInfo, directory string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -667,7 +666,7 @@ func GroupHeaderComponent(groupName string, serviceBackups map[string][]backup.B } // Updated table templates with action column -func ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]backup.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { +func ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -808,7 +807,7 @@ func ServiceGroupBackupsTable(groupName string, serviceGroup map[string][]backup } // ServiceGroupAllBackupsTable template for showing all backups -func ServiceGroupAllBackupsTable(groupName string, serviceGroup map[string][]backup.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { +func ServiceGroupAllBackupsTable(groupName string, serviceGroup map[string][]models.BackupInfo, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -1200,7 +1199,7 @@ func renderSortedBackups(groupName string, sortedBackups []BackupWithService, li } // backupsTableRowsSorted renders backup rows sorted by creation time across all services -func backupsTableRowsSorted(groupName string, serviceGroup map[string][]backup.BackupInfo, limit int, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { +func backupsTableRowsSorted(groupName string, serviceGroup map[string][]models.BackupInfo, limit int, serviceConfigs map[string]map[string]ServiceProviderInfo) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {