new release script

This commit is contained in:
Mark Gregory
2026-10-18 14:49:36 +01:00
parent ebd0bd1e29
commit 4306211981
4 changed files with 161 additions and 32 deletions
+36
View File
@@ -2728,6 +2728,14 @@ struct WorkbenchAdministrationView: View {
.frame(width: 175)
}
Button {
exportAdministrationCSV()
} label: {
Label("Export CSV…", systemImage: "square.and.arrow.up")
}
.disabled(result.columns.isEmpty || result.rows.isEmpty)
.help("Export the currently filtered administration results as UTF-8 CSV")
Toggle("Auto-refresh", isOn: $autoRefresh)
.toggleStyle(.checkbox)
.help("Refresh every five seconds")
@@ -2748,6 +2756,34 @@ struct WorkbenchAdministrationView: View {
.padding(18)
}
// Phase 60: Export the currently displayed administration data without
// requiring an external MySQL client. RFC 4180 quoting protects commas,
// double quotes and multiline field values.
@MainActor
private func exportAdministrationCSV() {
guard !result.columns.isEmpty else { return }
let panel = NSSavePanel()
panel.allowedContentTypes = [.commaSeparatedText]
panel.canCreateDirectories = true
panel.nameFieldStringValue = "DBSyn-" + page.rawValue
.replacingOccurrences(of: " ", with: "-") + ".csv"
guard panel.runModal() == .OK, let url = panel.url else { return }
func record(_ values: [String]) -> String {
values.map { value in
let escaped = value.replacingOccurrences(of: "\"", with: "\"\"")
return "\"" + escaped + "\""
}.joined(separator: ",") + "\r\n"
}
do {
let rows = [result.columns] + filteredRows
let csv = rows.map(record).joined()
try csv.write(to: url, atomically: true, encoding: .utf8)
processActionStatus = "Exported \(filteredRows.count) rows to \(url.lastPathComponent)."
} catch {
errorMessage = "CSV export failed: \(error.localizedDescription)"
}
}
// The live charts occupy a fixed region ABOVE an independently scrolling
// counter table. They cannot disappear when the user scrolls the rows.
@ViewBuilder