Add status progress for batch tool operations
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -131,6 +132,24 @@ function addPaths(paths) {
|
||||
selectedPage = Math.max(0, Math.ceil(pickedFiles.length / PAGE_SIZE) - 1);
|
||||
renderSelection();
|
||||
}
|
||||
async function readJSONStream(response, handle) {
|
||||
if (!response.ok || !response.body) throw new Error('Request failed.');
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
let newline;
|
||||
while ((newline = buffer.indexOf('\n')) >= 0) {
|
||||
const line = buffer.slice(0, newline);
|
||||
buffer = buffer.slice(newline + 1);
|
||||
if (line.trim()) handle(JSON.parse(line));
|
||||
}
|
||||
}
|
||||
if (buffer.trim()) handle(JSON.parse(buffer));
|
||||
}
|
||||
renderSelection();
|
||||
setupDropZone('dropZone', statusEl, (j) => {
|
||||
addPaths(j.paths || []);
|
||||
@@ -161,8 +180,25 @@ document.getElementById('scan').addEventListener('click', async () => {
|
||||
resultsEl.innerHTML = '';
|
||||
if (!pickedFiles.length) { statusEl.classList.remove('is-busy'); statusEl.textContent = 'Pick files first.'; return; }
|
||||
const payload = { files: pickedFiles };
|
||||
const r = await fetch('/api/mraid/scan', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload) });
|
||||
const j = await r.json();
|
||||
let j = null;
|
||||
try {
|
||||
const r = await fetch('/api/mraid/scan', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload) });
|
||||
await readJSONStream(r, (msg) => {
|
||||
if (msg.type === 'status') {
|
||||
statusEl.textContent = msg.message;
|
||||
statusEl.classList.add('is-busy');
|
||||
} else if (msg.type === 'done') {
|
||||
j = msg;
|
||||
} else if (msg.type === 'error') {
|
||||
j = { error: msg.message, results: msg.results || [], skipped: msg.skipped, skippedReason: msg.skippedReason };
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
statusEl.classList.remove('is-busy');
|
||||
statusEl.textContent = 'Error: ' + (e.message || e);
|
||||
return;
|
||||
}
|
||||
if (!j) { statusEl.classList.remove('is-busy'); statusEl.textContent = 'Error: No response.'; return; }
|
||||
if (j.error) { statusEl.classList.remove('is-busy'); statusEl.textContent = 'Error: ' + j.error; return; }
|
||||
const total = j.results.length;
|
||||
const withIssues = j.results.filter(r => !r.ok).length;
|
||||
@@ -228,12 +264,13 @@ func MraidPickFiles(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func MraidScan(w http.ResponseWriter, r *http.Request) {
|
||||
send := newJSONStream(w)
|
||||
var req struct {
|
||||
Folder string `json:"folder"`
|
||||
Files []string `json:"files"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeJSON(w, map[string]any{"results": []mraidResult{}, "error": err.Error()})
|
||||
send(map[string]any{"type": "error", "message": err.Error(), "results": []mraidResult{}})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -268,16 +305,17 @@ func MraidScan(w http.ResponseWriter, r *http.Request) {
|
||||
noTargetsError = "No AppLovin, ironSource, or Unity folder HTML files were found."
|
||||
baseDir = req.Folder
|
||||
} else {
|
||||
writeJSON(w, map[string]any{"results": []mraidResult{}, "error": "Pick a folder or files first"})
|
||||
send(map[string]any{"type": "error", "message": "Pick a folder or files first", "results": []mraidResult{}})
|
||||
return
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
writeJSON(w, map[string]any{"results": []mraidResult{}, "skipped": skipped, "skippedReason": skippedReason, "error": noTargetsError})
|
||||
send(map[string]any{"type": "error", "message": noTargetsError, "results": []mraidResult{}, "skipped": skipped, "skippedReason": skippedReason})
|
||||
return
|
||||
}
|
||||
|
||||
results := []mraidResult{}
|
||||
for _, file := range targets {
|
||||
for i, file := range targets {
|
||||
send(map[string]any{"type": "status", "message": fmt.Sprintf("Scanning %d/%d %s", i+1, len(targets), filepath.Base(file))})
|
||||
data, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
continue
|
||||
@@ -293,7 +331,7 @@ func MraidScan(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
results = append(results, mraidResult{File: display, OK: len(issues) == 0, Issues: issues})
|
||||
}
|
||||
writeJSON(w, map[string]any{"results": results, "skipped": skipped, "skippedReason": skippedReason})
|
||||
send(map[string]any{"type": "done", "results": results, "skipped": skipped, "skippedReason": skippedReason})
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
Reference in New Issue
Block a user