Browse Source

rendering pending tasks

worker-execute-ec-tasks
chrislu 4 months ago
parent
commit
960acc031e
  1. 18
      docker/admin_integration/Makefile
  2. 55
      weed/admin/handlers/maintenance_handlers.go
  3. 42
      weed/admin/maintenance/maintenance_queue.go
  4. 35
      weed/admin/view/app/maintenance_queue.templ
  5. 56
      weed/admin/view/app/maintenance_queue_templ.go

18
docker/admin_integration/Makefile

@ -1,7 +1,7 @@
# SeaweedFS Admin Integration Test Makefile # SeaweedFS Admin Integration Test Makefile
# Tests the admin server and worker functionality using official weed commands # Tests the admin server and worker functionality using official weed commands
.PHONY: help build build-and-restart start stop restart logs clean status test admin-ui worker-logs master-logs admin-logs
.PHONY: help build build-and-restart restart-workers start stop restart logs clean status test admin-ui worker-logs master-logs admin-logs
.DEFAULT_GOAL := help .DEFAULT_GOAL := help
COMPOSE_FILE := docker-compose-ec-test.yml COMPOSE_FILE := docker-compose-ec-test.yml
@ -19,10 +19,20 @@ build: ## Build SeaweedFS with latest changes and create Docker image
@echo "💡 Run 'make restart' to apply changes to running services" @echo "💡 Run 'make restart' to apply changes to running services"
build-and-restart: build ## Build with latest changes and restart services build-and-restart: build ## Build with latest changes and restart services
@echo "🔄 Restarting services to apply changes..."
@docker-compose -f $(COMPOSE_FILE) restart admin
@echo "✅ Services restarted with latest changes!"
@echo "🔄 Recreating services with new image..."
@echo "1️⃣ Recreating admin server with new image..."
@docker-compose -f $(COMPOSE_FILE) up -d admin
@sleep 5
@echo "2️⃣ Recreating workers to reconnect..."
@docker-compose -f $(COMPOSE_FILE) up -d worker1 worker2 worker3
@echo "✅ All services recreated with latest changes!"
@echo "🌐 Admin UI: http://localhost:23646/" @echo "🌐 Admin UI: http://localhost:23646/"
@echo "💡 Workers will reconnect to the new admin server"
restart-workers: ## Restart all workers to reconnect to admin server
@echo "🔄 Restarting workers to reconnect to admin server..."
@docker-compose -f $(COMPOSE_FILE) restart worker1 worker2 worker3
@echo "✅ Workers restarted and will reconnect to admin server"
help: ## Show this help message help: ## Show this help message
@echo "SeaweedFS Admin Integration Test" @echo "SeaweedFS Admin Integration Test"

55
weed/admin/handlers/maintenance_handlers.go

@ -10,6 +10,7 @@ import (
"github.com/seaweedfs/seaweedfs/weed/admin/view/app" "github.com/seaweedfs/seaweedfs/weed/admin/view/app"
"github.com/seaweedfs/seaweedfs/weed/admin/view/components" "github.com/seaweedfs/seaweedfs/weed/admin/view/components"
"github.com/seaweedfs/seaweedfs/weed/admin/view/layout" "github.com/seaweedfs/seaweedfs/weed/admin/view/layout"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/worker/tasks" "github.com/seaweedfs/seaweedfs/weed/worker/tasks"
"github.com/seaweedfs/seaweedfs/weed/worker/types" "github.com/seaweedfs/seaweedfs/weed/worker/types"
) )
@ -30,19 +31,31 @@ func NewMaintenanceHandlers(adminServer *dash.AdminServer) *MaintenanceHandlers
func (h *MaintenanceHandlers) ShowMaintenanceQueue(c *gin.Context) { func (h *MaintenanceHandlers) ShowMaintenanceQueue(c *gin.Context) {
data, err := h.getMaintenanceQueueData() data, err := h.getMaintenanceQueueData()
if err != nil { if err != nil {
glog.Infof("DEBUG ShowMaintenanceQueue: error getting data: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
} }
glog.Infof("DEBUG ShowMaintenanceQueue: got data with %d tasks", len(data.Tasks))
if data.Stats != nil {
glog.Infof("DEBUG ShowMaintenanceQueue: stats = {pending: %d, running: %d, completed: %d}",
data.Stats.PendingTasks, data.Stats.RunningTasks, data.Stats.CompletedToday)
} else {
glog.Infof("DEBUG ShowMaintenanceQueue: stats is nil")
}
// Render HTML template // Render HTML template
c.Header("Content-Type", "text/html") c.Header("Content-Type", "text/html")
maintenanceComponent := app.MaintenanceQueue(data) maintenanceComponent := app.MaintenanceQueue(data)
layoutComponent := layout.Layout(c, maintenanceComponent) layoutComponent := layout.Layout(c, maintenanceComponent)
err = layoutComponent.Render(c.Request.Context(), c.Writer) err = layoutComponent.Render(c.Request.Context(), c.Writer)
if err != nil { if err != nil {
glog.Infof("DEBUG ShowMaintenanceQueue: render error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render template: " + err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render template: " + err.Error()})
return return
} }
glog.Infof("DEBUG ShowMaintenanceQueue: template rendered successfully")
} }
// ShowMaintenanceWorkers displays the maintenance workers page // ShowMaintenanceWorkers displays the maintenance workers page
@ -287,27 +300,42 @@ func (h *MaintenanceHandlers) UpdateMaintenanceConfig(c *gin.Context) {
// Helper methods that delegate to AdminServer // Helper methods that delegate to AdminServer
func (h *MaintenanceHandlers) getMaintenanceQueueData() (*maintenance.MaintenanceQueueData, error) { func (h *MaintenanceHandlers) getMaintenanceQueueData() (*maintenance.MaintenanceQueueData, error) {
glog.Infof("DEBUG getMaintenanceQueueData: starting data assembly")
tasks, err := h.getMaintenanceTasks() tasks, err := h.getMaintenanceTasks()
if err != nil { if err != nil {
glog.Infof("DEBUG getMaintenanceQueueData: error getting tasks: %v", err)
return nil, err return nil, err
} }
glog.Infof("DEBUG getMaintenanceQueueData: got %d tasks", len(tasks))
workers, err := h.getMaintenanceWorkers() workers, err := h.getMaintenanceWorkers()
if err != nil { if err != nil {
glog.Infof("DEBUG getMaintenanceQueueData: error getting workers: %v", err)
return nil, err return nil, err
} }
glog.Infof("DEBUG getMaintenanceQueueData: got %d workers", len(workers))
stats, err := h.getMaintenanceQueueStats() stats, err := h.getMaintenanceQueueStats()
if err != nil { if err != nil {
glog.Infof("DEBUG getMaintenanceQueueData: error getting stats: %v", err)
return nil, err return nil, err
} }
if stats != nil {
glog.Infof("DEBUG getMaintenanceQueueData: got stats {pending: %d, running: %d}", stats.PendingTasks, stats.RunningTasks)
} else {
glog.Infof("DEBUG getMaintenanceQueueData: stats is nil")
}
return &maintenance.MaintenanceQueueData{
data := &maintenance.MaintenanceQueueData{
Tasks: tasks, Tasks: tasks,
Workers: workers, Workers: workers,
Stats: stats, Stats: stats,
LastUpdated: time.Now(), LastUpdated: time.Now(),
}, nil
}
glog.Infof("DEBUG getMaintenanceQueueData: assembled data with %d tasks, %d workers", len(data.Tasks), len(data.Workers))
return data, nil
} }
func (h *MaintenanceHandlers) getMaintenanceQueueStats() (*maintenance.QueueStats, error) { func (h *MaintenanceHandlers) getMaintenanceQueueStats() (*maintenance.QueueStats, error) {
@ -316,16 +344,33 @@ func (h *MaintenanceHandlers) getMaintenanceQueueStats() (*maintenance.QueueStat
} }
func (h *MaintenanceHandlers) getMaintenanceTasks() ([]*maintenance.MaintenanceTask, error) { func (h *MaintenanceHandlers) getMaintenanceTasks() ([]*maintenance.MaintenanceTask, error) {
// Call the private method logic directly since the public GetMaintenanceTasks is for HTTP handlers
// Call the maintenance manager directly to get all tasks
if h.adminServer == nil { if h.adminServer == nil {
glog.Infof("DEBUG getMaintenanceTasks: adminServer is nil")
return []*maintenance.MaintenanceTask{}, nil return []*maintenance.MaintenanceTask{}, nil
} }
// We need to access the maintenance manager through reflection or add a proper accessor
// For now, return empty tasks until proper accessor is added
if h.adminServer.GetMaintenanceManager() == nil {
glog.Infof("DEBUG getMaintenanceTasks: maintenance manager is nil")
return []*maintenance.MaintenanceTask{}, nil return []*maintenance.MaintenanceTask{}, nil
} }
// Get ALL tasks using empty parameters - this should match what the API returns
allTasks := h.adminServer.GetMaintenanceManager().GetTasks("", "", 0)
glog.Infof("DEBUG getMaintenanceTasks: retrieved %d tasks from maintenance manager", len(allTasks))
for i, task := range allTasks {
if task != nil {
glog.Infof("DEBUG getMaintenanceTasks: task[%d] = {id: %s, type: %s, status: %s, volume: %d}",
i, task.ID, task.Type, task.Status, task.VolumeID)
} else {
glog.Infof("DEBUG getMaintenanceTasks: task[%d] is nil", i)
}
}
return allTasks, nil
}
func (h *MaintenanceHandlers) getMaintenanceWorkers() ([]*maintenance.MaintenanceWorker, error) { func (h *MaintenanceHandlers) getMaintenanceWorkers() ([]*maintenance.MaintenanceWorker, error) {
// This would integrate with the maintenance system to get real workers // This would integrate with the maintenance system to get real workers
// For now, return mock data // For now, return mock data

42
weed/admin/maintenance/maintenance_queue.go

@ -1,6 +1,8 @@
package maintenance package maintenance
import ( import (
"crypto/rand"
"fmt"
"sort" "sort"
"time" "time"
@ -24,11 +26,17 @@ func (mq *MaintenanceQueue) SetIntegration(integration *MaintenanceIntegration)
glog.V(1).Infof("Maintenance queue configured with integration") glog.V(1).Infof("Maintenance queue configured with integration")
} }
// AddTask adds a new maintenance task to the queue
// AddTask adds a new maintenance task to the queue with deduplication
func (mq *MaintenanceQueue) AddTask(task *MaintenanceTask) { func (mq *MaintenanceQueue) AddTask(task *MaintenanceTask) {
mq.mutex.Lock() mq.mutex.Lock()
defer mq.mutex.Unlock() defer mq.mutex.Unlock()
// Check for duplicate tasks (same type + volume + not completed)
if mq.hasDuplicateTask(task) {
glog.V(2).Infof("Skipping duplicate task: %s for volume %d (already exists)", task.Type, task.VolumeID)
return
}
task.ID = generateTaskID() task.ID = generateTaskID()
task.Status = TaskStatusPending task.Status = TaskStatusPending
task.CreatedAt = time.Now() task.CreatedAt = time.Now()
@ -48,6 +56,21 @@ func (mq *MaintenanceQueue) AddTask(task *MaintenanceTask) {
glog.V(2).Infof("Added maintenance task %s: %s for volume %d", task.ID, task.Type, task.VolumeID) glog.V(2).Infof("Added maintenance task %s: %s for volume %d", task.ID, task.Type, task.VolumeID)
} }
// hasDuplicateTask checks if a similar task already exists (same type, volume, and not completed)
func (mq *MaintenanceQueue) hasDuplicateTask(newTask *MaintenanceTask) bool {
for _, existingTask := range mq.tasks {
if existingTask.Type == newTask.Type &&
existingTask.VolumeID == newTask.VolumeID &&
existingTask.Server == newTask.Server &&
(existingTask.Status == TaskStatusPending ||
existingTask.Status == TaskStatusAssigned ||
existingTask.Status == TaskStatusInProgress) {
return true
}
}
return false
}
// AddTasksFromResults converts detection results to tasks and adds them to the queue // AddTasksFromResults converts detection results to tasks and adds them to the queue
func (mq *MaintenanceQueue) AddTasksFromResults(results []*TaskDetectionResult) { func (mq *MaintenanceQueue) AddTasksFromResults(results []*TaskDetectionResult) {
for _, result := range results { for _, result := range results {
@ -311,10 +334,23 @@ func (mq *MaintenanceQueue) GetWorkers() []*MaintenanceWorker {
func generateTaskID() string { func generateTaskID() string {
const charset = "abcdefghijklmnopqrstuvwxyz0123456789" const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
b := make([]byte, 8) b := make([]byte, 8)
randBytes := make([]byte, 8)
// Generate random bytes
if _, err := rand.Read(randBytes); err != nil {
// Fallback to timestamp-based ID if crypto/rand fails
timestamp := time.Now().UnixNano()
return fmt.Sprintf("task-%d", timestamp)
}
// Convert random bytes to charset
for i := range b { for i := range b {
b[i] = charset[i%len(charset)]
b[i] = charset[int(randBytes[i])%len(charset)]
} }
return string(b)
// Add timestamp suffix to ensure uniqueness
timestamp := time.Now().Unix() % 10000 // last 4 digits of timestamp
return fmt.Sprintf("%s-%04d", string(b), timestamp)
} }
// CleanupOldTasks removes old completed and failed tasks // CleanupOldTasks removes old completed and failed tasks

35
weed/admin/view/app/maintenance_queue.templ

@ -103,9 +103,9 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
</thead> </thead>
<tbody> <tbody>
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusPending {
if string(task.Status) == "pending" {
<tr> <tr>
<td><code>{task.ID[:8]}...</code></td>
<td><code>{task.ID}</code></td>
<td> <td>
@TaskTypeIcon(task.Type) @TaskTypeIcon(task.Type)
{string(task.Type)} {string(task.Type)}
@ -160,9 +160,9 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
</thead> </thead>
<tbody> <tbody>
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusAssigned || task.Status == maintenance.TaskStatusInProgress {
if string(task.Status) == "assigned" || string(task.Status) == "in_progress" {
<tr> <tr>
<td><code>{task.ID[:8]}...</code></td>
<td><code>{task.ID}</code></td>
<td> <td>
@TaskTypeIcon(task.Type) @TaskTypeIcon(task.Type)
{string(task.Type)} {string(task.Type)}
@ -172,7 +172,7 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
<td>{fmt.Sprintf("%d", task.VolumeID)}</td> <td>{fmt.Sprintf("%d", task.VolumeID)}</td>
<td> <td>
if task.WorkerID != "" { if task.WorkerID != "" {
<small>{task.WorkerID[:8]}...</small>
<small>{task.WorkerID}</small>
} else { } else {
<span class="text-muted">-</span> <span class="text-muted">-</span>
} }
@ -229,10 +229,10 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
</thead> </thead>
<tbody> <tbody>
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusCompleted || task.Status == maintenance.TaskStatusFailed || task.Status == maintenance.TaskStatusCancelled {
if task.Status == maintenance.TaskStatusFailed {
if string(task.Status) == "completed" || string(task.Status) == "failed" || string(task.Status) == "cancelled" {
if string(task.Status) == "failed" {
<tr class="table-danger"> <tr class="table-danger">
<td><code>{task.ID[:8]}...</code></td>
<td><code>{task.ID}</code></td>
<td> <td>
@TaskTypeIcon(task.Type) @TaskTypeIcon(task.Type)
{string(task.Type)} {string(task.Type)}
@ -241,7 +241,7 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
<td>{fmt.Sprintf("%d", task.VolumeID)}</td> <td>{fmt.Sprintf("%d", task.VolumeID)}</td>
<td> <td>
if task.WorkerID != "" { if task.WorkerID != "" {
<small>{task.WorkerID[:8]}...</small>
<small>{task.WorkerID}</small>
} else { } else {
<span class="text-muted">-</span> <span class="text-muted">-</span>
} }
@ -263,7 +263,7 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
</tr> </tr>
} else { } else {
<tr> <tr>
<td><code>{task.ID[:8]}...</code></td>
<td><code>{task.ID}</code></td>
<td> <td>
@TaskTypeIcon(task.Type) @TaskTypeIcon(task.Type)
{string(task.Type)} {string(task.Type)}
@ -272,7 +272,7 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
<td>{fmt.Sprintf("%d", task.VolumeID)}</td> <td>{fmt.Sprintf("%d", task.VolumeID)}</td>
<td> <td>
if task.WorkerID != "" { if task.WorkerID != "" {
<small>{task.WorkerID[:8]}...</small>
<small>{task.WorkerID}</small>
} else { } else {
<span class="text-muted">-</span> <span class="text-muted">-</span>
} }
@ -306,6 +306,9 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
</div> </div>
<script> <script>
// Debug output to browser console
console.log("DEBUG: Maintenance Queue Template loaded");
// Auto-refresh every 10 seconds // Auto-refresh every 10 seconds
setInterval(function() { setInterval(function() {
if (!document.hidden) { if (!document.hidden) {
@ -313,7 +316,8 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
} }
}, 10000); }, 10000);
function triggerScan() {
window.triggerScan = function() {
console.log("triggerScan called");
fetch('/api/maintenance/scan', { fetch('/api/maintenance/scan', {
method: 'POST', method: 'POST',
headers: { headers: {
@ -332,7 +336,12 @@ templ MaintenanceQueue(data *maintenance.MaintenanceQueueData) {
.catch(error => { .catch(error => {
alert('Error: ' + error.message); alert('Error: ' + error.message);
}); });
}
};
window.refreshPage = function() {
console.log("refreshPage called");
window.location.reload();
};
</script> </script>
} }

56
weed/admin/view/app/maintenance_queue_templ.go

@ -102,21 +102,21 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusPending {
if string(task.Status) == "pending" {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<tr><td><code>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<tr><td><code>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var6 string var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID[:8])
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 108, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 108, Col: 70}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "...</code></td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</code></td><td>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -219,21 +219,21 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusAssigned || task.Status == maintenance.TaskStatusInProgress {
if string(task.Status) == "assigned" || string(task.Status) == "in_progress" {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<tr><td><code>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<tr><td><code>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var12 string var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID[:8])
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 165, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 165, Col: 70}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "...</code></td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</code></td><td>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -289,15 +289,15 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var15 string var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID[:8])
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 175, Col: 85}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 175, Col: 81}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "...</small>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</small>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -353,22 +353,22 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, task := range data.Tasks { for _, task := range data.Tasks {
if task.Status == maintenance.TaskStatusCompleted || task.Status == maintenance.TaskStatusFailed || task.Status == maintenance.TaskStatusCancelled {
if task.Status == maintenance.TaskStatusFailed {
if string(task.Status) == "completed" || string(task.Status) == "failed" || string(task.Status) == "cancelled" {
if string(task.Status) == "failed" {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<tr class=\"table-danger\"><td><code>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<tr class=\"table-danger\"><td><code>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var17 string var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID[:8])
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 235, Col: 78}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 235, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "...</code></td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</code></td><td>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -416,15 +416,15 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var20 string var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID[:8])
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 244, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 244, Col: 85}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "...</small>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</small>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -484,15 +484,15 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var23 string var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID[:8])
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(task.ID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 266, Col: 78}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 266, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "...</code></td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</code></td><td>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -540,15 +540,15 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var26 string var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID[:8])
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(task.WorkerID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 275, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 275, Col: 85}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "...</small>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</small>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -610,7 +610,7 @@ func MaintenanceQueue(data *maintenance.MaintenanceQueueData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "</div></div></div></div></div><script>\n // Auto-refresh every 10 seconds\n setInterval(function() {\n if (!document.hidden) {\n window.location.reload();\n }\n }, 10000);\n\n function triggerScan() {\n fetch('/api/maintenance/scan', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n }\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n alert('Maintenance scan triggered successfully');\n setTimeout(() => window.location.reload(), 2000);\n } else {\n alert('Failed to trigger scan: ' + (data.error || 'Unknown error'));\n }\n })\n .catch(error => {\n alert('Error: ' + error.message);\n });\n }\n </script>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "</div></div></div></div></div><script>\n // Debug output to browser console\n console.log(\"DEBUG: Maintenance Queue Template loaded\");\n \n // Auto-refresh every 10 seconds\n setInterval(function() {\n if (!document.hidden) {\n window.location.reload();\n }\n }, 10000);\n\n window.triggerScan = function() {\n console.log(\"triggerScan called\");\n fetch('/api/maintenance/scan', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n }\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n alert('Maintenance scan triggered successfully');\n setTimeout(() => window.location.reload(), 2000);\n } else {\n alert('Failed to trigger scan: ' + (data.error || 'Unknown error'));\n }\n })\n .catch(error => {\n alert('Error: ' + error.message);\n });\n };\n\n window.refreshPage = function() {\n console.log(\"refreshPage called\");\n window.location.reload();\n };\n </script>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -809,7 +809,7 @@ func ProgressBar(progress float64, status maintenance.MaintenanceTaskStatus) tem
var templ_7745c5c3_Var35 string var templ_7745c5c3_Var35 string
templ_7745c5c3_Var35, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %.1f%%", progress)) templ_7745c5c3_Var35, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %.1f%%", progress))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 381, Col: 102}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 390, Col: 102}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -822,7 +822,7 @@ func ProgressBar(progress float64, status maintenance.MaintenanceTaskStatus) tem
var templ_7745c5c3_Var36 string var templ_7745c5c3_Var36 string
templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%%", progress)) templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%%", progress))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 384, Col: 66}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_queue.templ`, Line: 393, Col: 66}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

Loading…
Cancel
Save