mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
feat: Implement logging filter for successful HTTP access logs and enhance modal styling for better usability
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import atexit
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
@@ -13,6 +14,23 @@ from .conversion_runner import run_conversion_job
|
||||
from .service import build_service
|
||||
|
||||
|
||||
class _SuppressSuccessfulAccessFilter(logging.Filter):
|
||||
"""Filter out successful (HTTP 200) werkzeug access logs."""
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool: # pragma: no cover - small utility
|
||||
try:
|
||||
message = record.getMessage()
|
||||
except Exception: # pragma: no cover - defensive
|
||||
return True
|
||||
# Werkzeug access logs include the status code near the end, e.g.
|
||||
# "GET /path HTTP/1.1" 200 -
|
||||
# Treat any 2xx response as success to suppress.
|
||||
return " 200 " not in message and " 201 " not in message and " 204 " not in message
|
||||
|
||||
|
||||
_access_log_filter_attached = False
|
||||
|
||||
|
||||
def _default_dirs() -> tuple[Path, Path]:
|
||||
uploads_override = os.environ.get("ABOGEN_UPLOAD_ROOT")
|
||||
outputs_override = os.environ.get("ABOGEN_OUTPUT_ROOT")
|
||||
@@ -64,6 +82,11 @@ def create_app(config: Optional[dict[str, Any]] = None) -> Flask:
|
||||
|
||||
atexit.register(service.shutdown)
|
||||
|
||||
global _access_log_filter_attached
|
||||
if not _access_log_filter_attached:
|
||||
logging.getLogger("werkzeug").addFilter(_SuppressSuccessfulAccessFilter())
|
||||
_access_log_filter_attached = True
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,6 @@ const initDashboard = () => {
|
||||
const formulaInput = scope.querySelector('[data-role="voice-formula"]');
|
||||
const languageSelect = uploadModal?.querySelector("#language") || document.getElementById("language");
|
||||
|
||||
const sourceText = scope.querySelector('[data-role="source-text"]');
|
||||
const previewEl = scope.querySelector('[data-role="text-preview"]');
|
||||
const previewBody = scope.querySelector('[data-role="preview-body"]');
|
||||
const charCountEl = scope.querySelector('[data-role="char-count"]');
|
||||
const wordCountEl = scope.querySelector('[data-role="word-count"]');
|
||||
|
||||
let lastTrigger = null;
|
||||
|
||||
const openUploadModal = (trigger) => {
|
||||
@@ -156,36 +150,6 @@ const initDashboard = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const updatePreview = () => {
|
||||
if (!sourceText || !previewBody || !charCountEl || !wordCountEl) {
|
||||
return;
|
||||
}
|
||||
const raw = sourceText.value || "";
|
||||
const trimmed = raw.trim();
|
||||
const charCount = raw.length;
|
||||
const wordCount = trimmed ? trimmed.split(/\s+/).length : 0;
|
||||
|
||||
const charLabel = `${charCount.toLocaleString()} ${charCount === 1 ? "character" : "characters"}`;
|
||||
const wordLabel = `${wordCount.toLocaleString()} ${wordCount === 1 ? "word" : "words"}`;
|
||||
|
||||
charCountEl.textContent = charLabel;
|
||||
wordCountEl.textContent = wordLabel;
|
||||
|
||||
if (!trimmed) {
|
||||
previewBody.textContent = "Paste text to see a live preview and character count.";
|
||||
if (previewEl) {
|
||||
previewEl.setAttribute("data-state", "empty");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const snippet = trimmed.length > 1200 ? `${trimmed.slice(0, 1200)}…` : trimmed;
|
||||
previewBody.textContent = snippet;
|
||||
if (previewEl) {
|
||||
previewEl.setAttribute("data-state", "ready");
|
||||
}
|
||||
};
|
||||
|
||||
if (profileSelect) {
|
||||
const hasSaved = selectFirstProfileIfAvailable();
|
||||
profileSelect.addEventListener("change", updateVoiceControls);
|
||||
@@ -196,11 +160,6 @@ const initDashboard = () => {
|
||||
} else {
|
||||
hydrateDefaultVoice();
|
||||
}
|
||||
|
||||
if (sourceText) {
|
||||
sourceText.addEventListener("input", updatePreview);
|
||||
updatePreview();
|
||||
}
|
||||
};
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
|
||||
@@ -150,6 +150,7 @@ body {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 300;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal[data-open="true"] {
|
||||
@@ -211,6 +212,7 @@ body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.modal__footer {
|
||||
@@ -246,6 +248,7 @@ body {
|
||||
padding: 1.5rem 1.75rem 1.75rem;
|
||||
overflow-y: auto;
|
||||
max-height: calc(90vh - 150px);
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.voice-browser__filters,
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<form action="{{ url_for('web.enqueue_job') }}" method="post" enctype="multipart/form-data" class="upload-form">
|
||||
<div class="modal__body">
|
||||
<div class="grid grid--two form-grid">
|
||||
<div class="grid">
|
||||
<div class="field field--file">
|
||||
<label for="source_file">Source File</label>
|
||||
<input type="file" id="source_file" name="source_file" accept=".txt,.pdf,.epub,.md,.markdown">
|
||||
@@ -129,24 +128,6 @@
|
||||
<p class="hint">Creates a synchronized EPUB alongside audio output.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div class="field field--full">
|
||||
<label for="source_text">Or Paste Text Directly</label>
|
||||
<textarea id="source_text" name="source_text" rows="12" placeholder="Drop some text here if you don't have a file handy..." data-role="source-text"></textarea>
|
||||
</div>
|
||||
<div class="text-preview" data-role="text-preview" aria-live="polite">
|
||||
<div class="text-preview__header">
|
||||
<h2>Preview</h2>
|
||||
<div class="text-preview__meta">
|
||||
<span data-role="char-count">0 characters</span>
|
||||
<span>·</span>
|
||||
<span data-role="word-count">0 words</span>
|
||||
</div>
|
||||
</div>
|
||||
<pre class="text-preview__body" data-role="preview-body">Paste text to see a live preview and character count.</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="modal__footer">
|
||||
<button type="button" class="button button--ghost" data-role="upload-modal-close">Cancel</button>
|
||||
|
||||
Reference in New Issue
Block a user