package main import ( "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" ) type ProgressInfo struct { Percentage float64 CurrentFile string Paused bool } func handleRoot(w http.ResponseWriter, r *http.Request) { progressMutex.Lock() defer progressMutex.Unlock() jobsInfo := make(map[string]struct { Percentage float64 CurrentFile string Paused bool }) for filename, info := range progress { jobsInfo[filename] = struct { Percentage float64 CurrentFile string Paused bool }{ Percentage: info.Percentage, CurrentFile: info.CurrentFile, Paused: info.Paused, } } err := templates.ExecuteTemplate(w, "index", struct { Jobs map[string]struct { Percentage float64 CurrentFile string Paused bool } }{jobsInfo}) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func handleUpload(w http.ResponseWriter, r *http.Request) { file, header, err := r.FormFile("file") if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } defer file.Close() tempFile, err := os.CreateTemp(uploadDir, header.Filename) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer tempFile.Close() _, err = io.Copy(tempFile, file) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } tempFilename := filepath.Base(tempFile.Name()) _, err = parseInputFile(tempFile.Name()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } http.Redirect(w, r, "/select?filename="+tempFilename, http.StatusSeeOther) } func handleSelect(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") items, err := parseInputFile(filepath.Join(uploadDir, filename)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } groupedItems := groupItemsBySeason(items) err = templates.ExecuteTemplate(w, "select", struct { Filename string Items map[string][]Item }{ Filename: filename, Items: groupedItems, }) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func handleProcess(w http.ResponseWriter, r *http.Request) { filename := r.FormValue("filename") selectedItems := r.Form["items"] items, err := parseInputFile(filepath.Join(uploadDir, filename)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } filteredItems := filterSelectedItems(items, selectedItems) go func() { err := processItems(filename, filteredItems) if err != nil { fmt.Printf("Error processing file: %v\n", err) } os.Remove(filepath.Join(uploadDir, filename)) }() http.Redirect(w, r, "/progress?filename="+filename, http.StatusSeeOther) } func handleProgress(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") fmt.Printf("Handling progress request for filename: %s\n", filename) if r.Header.Get("Accept") == "application/json" { progressInfo := getProgress(filename) fmt.Printf("Progress info for %s: %+v\n", filename, progressInfo) if progressInfo == nil { w.WriteHeader(http.StatusNotFound) json.NewEncoder(w).Encode(map[string]string{"error": "No progress information found"}) return } w.Header().Set("Content-Type", "application/json") err := json.NewEncoder(w).Encode(progressInfo) if err != nil { fmt.Printf("Error encoding progress info: %v\n", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } return } err := templates.ExecuteTemplate(w, "progress", struct{ Filename string }{filename}) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func handlePause(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") if filename == "" { http.Error(w, "Filename is required", http.StatusBadRequest) return } jobsMutex.Lock() jobInfo, exists := jobs[filename] jobsMutex.Unlock() if !exists { http.Error(w, "Job not found", http.StatusNotFound) return } jobInfo.Paused = true if jobInfo.Cmd != nil && jobInfo.Cmd.Process != nil { jobInfo.Cmd.Process.Kill() } progressMutex.Lock() if progressInfo, ok := progress[filename]; ok { progressInfo.Paused = true } progressMutex.Unlock() fmt.Fprintf(w, "Pause signal sent for %s", filename) } func handleResume(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") if filename == "" { http.Error(w, "Filename is required", http.StatusBadRequest) return } jobsMutex.Lock() jobInfo, exists := jobs[filename] jobsMutex.Unlock() if !exists { http.Error(w, "Job not found", http.StatusNotFound) return } jobInfo.Paused = false jobInfo.ResumeChan <- struct{}{} // Update the progress information progressMutex.Lock() if progressInfo, ok := progress[filename]; ok { progressInfo.Paused = false } progressMutex.Unlock() fmt.Fprintf(w, "Resume signal sent for %s", filename) } func handleAbort(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") if filename == "" { http.Error(w, "Filename is required", http.StatusBadRequest) return } jobsMutex.Lock() jobInfo, exists := jobs[filename] jobsMutex.Unlock() if !exists { http.Error(w, "Job not found", http.StatusNotFound) return } close(jobInfo.AbortChan) if jobInfo.Cmd != nil && jobInfo.Cmd.Process != nil { jobInfo.Cmd.Process.Kill() } if jobInfo.TempDir != "" { os.RemoveAll(jobInfo.TempDir) } fmt.Fprintf(w, "Abort signal sent for %s", filename) } func handleClearCompleted(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } clearCompletedJobs() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]bool{"success": true}) } func clearCompletedJobs() { progressMutex.Lock() defer progressMutex.Unlock() for filename, info := range progress { if info.Percentage >= 100 { delete(progress, filename) } } } func updateProgress(filename string, value float64, currentFile string) { progressMutex.Lock() defer progressMutex.Unlock() jobsMutex.Lock() jobInfo, exists := jobs[filename] jobsMutex.Unlock() paused := false if exists { paused = jobInfo.Paused } if existingProgress, ok := progress[filename]; ok { existingProgress.Percentage = value existingProgress.CurrentFile = currentFile existingProgress.Paused = paused } else { progress[filename] = &ProgressInfo{ Percentage: value, CurrentFile: currentFile, Paused: paused, } } fmt.Printf("Progress updated for %s: %.2f%%, Current file: %s, Paused: %v\n", filename, value, currentFile, paused) }