package components import ( "context" "fmt" "time" ) type BackupFile struct { Name string Size string ModTime time.Time } type LogFile struct { Name string Size string ModTime time.Time Path string } type AdminToolsData struct { JobHistoryCount int DatabaseSize string LastBackupTime *time.Time BackupCount int SystemUptime string ActiveJobs int TotalConfigs int TotalJobs int TotalUsers int DatabasePath string BackupPath string MaintenanceMessage string BackupFiles []BackupFile LogFiles []LogFile LogContent string CurrentLogFile string EmailTestSuccess *bool EmailTestMessage string SmtpServer string } // Dialog component for confirmation dialogs templ Dialog(id string, title string, message string, confirmClass string, confirmText string, formId string, targetAction string) { } script hideDialog(id string) { document.getElementById(id).classList.add("hidden"); } script submitFormAndHideDialog(formId string, dialogId string) { // Use HTMX's API to trigger the request instead of bypassing it htmx.trigger(document.getElementById(formId), 'submit'); document.getElementById(dialogId).classList.add("hidden"); } script showDialog(id string) { document.getElementById(id).classList.remove("hidden"); } // Backup dialog component specifically for restore and delete actions templ BackupActionDialog(id string, title string, message string, confirmClass string, confirmText string, action string, backupName string) { } templ AdminTools(ctx context.Context, data AdminToolsData) { @LayoutWithContext("Admin Tools", ctx) {

Admin Tools

if data.MaintenanceMessage != "" {

{ data.MaintenanceMessage }

}

System Overview

Database Size
{ data.DatabaseSize }
Job History Records
{ fmt.Sprint(data.JobHistoryCount) }
System Uptime
{ data.SystemUptime }
Active Jobs
{ fmt.Sprint(data.ActiveJobs) }

Backup & Restore

if data.LastBackupTime != nil { Last backup: { data.LastBackupTime.Format("Jan 02, 2006 15:04:05") } } else { Last backup: Never }

Restore Database

Warning: This will replace your current database. Make sure to backup first!

Maintenance Tools

@Dialog("clear-job-dialog", "Clear Job History", "Are you sure you want to clear all job history? This cannot be undone.", "btn-danger", "Clear History", "purge-form", "")

Runs VACUUM to optimize the database and reclaim unused space.

Email Testing

Test your email configuration by sending a test email to verify the server can send emails properly.

Email Configuration

if data.SmtpServer != "" {

Current SMTP server: { data.SmtpServer }

} else {

Email settings are configured in your application configuration file. Make sure SMTP settings are properly configured before testing.

}
@BackupsList(data)

System Information

Database Path
{ data.DatabasePath }
Backup Directory
{ data.BackupPath }
Total Users
{ fmt.Sprint(data.TotalUsers) }
Total Configurations
{ fmt.Sprint(data.TotalConfigs) }
Total Jobs
{ fmt.Sprint(data.TotalJobs) }
Application Version
{ AppVersion } if AppVersion == "dev" { } else if AppVersion == "1.0.0" { } else if AppVersion == "1.1.0" { } else { }

Build Information

Version
{ AppVersion }
Build Time
{ getBuildTime() }
Commit
{ getCommit() }
@AdminLogViewer(data)

Webhook Notifications

GoMFT can send webhook notifications when jobs run. You can configure webhooks for individual jobs in the job edit form. Below is the format of the webhook payload:

{
  "event_type": "job_execution",
  "job_id": 123,
  "job_name": "Daily Backup",
  "config_id": 456,
  "config_name": "Backup Config",
  "status": "completed",
  "start_time": "2023-06-18T15:30:45Z",
  "end_time": "2023-06-18T15:35:12Z",
  "duration_seconds": 267,
  "history_id": 789,
  "bytes_transferred": 1048576,
  "files_transferred": 5,
  "source": {
    "type": "local",
    "path": "/path/to/source"
  },
  "destination": {
    "type": "s3",
    "path": "bucket/path"
  }
}

Authentication

When configuring a webhook, you can optionally provide a secret key. This will be used to sign the webhook payload with HMAC-SHA256. The signature is provided in the X-Hub-Signature-256 header.

HTTP Request Details

Property Value
Method POST
Content-Type application/json
User-Agent GoMFT-Webhook/1.0
X-Hub-Signature-256 HMAC SHA256 signature (if secret configured)
Custom Headers Any additional headers specified in the job configuration
} } // BackupsList is a separate component for the backups list that can be refreshed via HTMX templ BackupsList(data AdminToolsData) { if len(data.BackupFiles) > 0 {

Available Backups

for _, backup := range data.BackupFiles { }
Name Size Date Action
{ backup.Name } { backup.Size } { backup.ModTime.Format("Jan 02, 2006 15:04:05") } @BackupActionDialog( fmt.Sprintf("restore-dialog-%s", backup.Name), "RESTORE BACKUP", fmt.Sprintf("Are you sure you want to restore the backup '%s'? This will replace your current database.", backup.Name), "btn-warning", "Restore", "restore", backup.Name, ) @BackupActionDialog( fmt.Sprintf("delete-dialog-%s", backup.Name), "DELETE BACKUP", fmt.Sprintf("Are you sure you want to delete the backup '%s'? This cannot be undone.", backup.Name), "btn-danger", "Delete", "delete", backup.Name, )
} else {

Available Backups

No Backups Available

Create a backup using the "Backup Database" button.

} } // Add this new template after other admin tool templates templ AdminLogViewer(data AdminToolsData) {

Log Files

Available Logs

if len(data.LogFiles) == 0 {
No log files found
} else {
for _, logFile := range data.LogFiles { }
}

if data.CurrentLogFile != "" { Log: { data.CurrentLogFile } } else { Select a log file }

if data.CurrentLogFile != "" {
}
@AdminLogContent(data)
} // AdminLogContent template for log view templ AdminLogContent(data AdminToolsData) {
if data.CurrentLogFile == "" {

Select a log file to view its contents

} else {
{ data.LogContent }
}
} // getBuildTime returns the build time of the application // This can be set using ldflags during build // Example: go build -ldflags "-X github.com/starfleetcptn/gomft/components.BuildTime=2023-01-01T00:00:00Z" var BuildTime = "unknown" func getBuildTime() string { return BuildTime } // getCommit returns the commit hash of the application // This can be set using ldflags during build // Example: go build -ldflags "-X github.com/starfleetcptn/gomft/components.Commit=abcdef123456" var Commit = "unknown" func getCommit() string { return Commit } // EmailTestToast is a component for showing email test results templ EmailTestToast(success bool, message string) {
if success { } else { }

if success { Email Sent Successfully } else { Email Sending Failed }

{ message }
} // Add a style for the animate-fade-in animation script fadeInAnimation() { // Add CSS animation if it doesn't exist if (!document.getElementById('fade-in-animation')) { const style = document.createElement('style'); style.id = 'fade-in-animation'; style.textContent = ` @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-in { animation: fadeIn 0.3s ease-out forwards; } `; document.head.appendChild(style); } }