Fix QC scroll, show error toasts, enable Apache WS module

- ProofDetailView: remove h-full from root div so content can scroll
  naturally (h-full was capping height at viewport, blocking scroll)
- App.tsx: wire up error state to a top toast banner so users see
  failures (campaign load, proof upload, etc.) instead of silent drops;
  auto-dismiss after 8s, same pattern as notification toast
- Apache: enabled mod_proxy_wstunnel (was missing — proxy_http was
  handling WebSocket connections and dropping them due to HTTP-level
  timeouts; wstunnel provides a proper bidirectional tunnel)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-03-18 12:52:30 +00:00
parent 5c338c31fb
commit 416c9dce0e
2 changed files with 23 additions and 2 deletions

View file

@ -83,7 +83,13 @@ const AppContent: React.FC<{ msalInstance: any }> = ({ msalInstance }) => {
const [selectedCampaign, setSelectedCampaign] = useState<string | null>(initialUrlState.campaignName);
const [selectedProof, setSelectedProof] = useState<any | null>(null);
const [pendingProofId, setPendingProofId] = useState<string | null>(initialUrlState.proofId);
const [error, setError] = useState<string | null>(null);
const [error, setErrorState] = useState<string | null>(null);
const errorTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const setError = (msg: string | null) => {
setErrorState(msg);
if (errorTimerRef.current) clearTimeout(errorTimerRef.current);
if (msg) errorTimerRef.current = setTimeout(() => setErrorState(null), 8000);
};
const [isLoadingData, setIsLoadingData] = useState(true);
const [notification, setNotification] = useState<string | null>(null);
const notificationTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
@ -981,6 +987,21 @@ const AppContent: React.FC<{ msalInstance: any }> = ({ msalInstance }) => {
</main>
</div>
{/* Error toast */}
{error && (
<div className="fixed top-6 left-1/2 -translate-x-1/2 z-50 flex items-start gap-3 bg-error text-white text-sm px-5 py-3.5 rounded-xl shadow-2xl max-w-md w-full mx-4 animate-fade-in">
<svg className="w-5 h-5 shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg>
<p className="flex-1 leading-snug">{error}</p>
<button onClick={() => setErrorState(null)} className="text-white/70 hover:text-white shrink-0">
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
)}
{/* Model fallback notification toast */}
{notification && (
<div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 flex items-start gap-3 bg-oliver-orange text-oliver-black text-sm px-5 py-3.5 rounded-xl shadow-2xl max-w-md w-full mx-4 animate-fade-in">

View file

@ -1673,7 +1673,7 @@ const ProofDetailView: React.FC<{
}
return (
<div className="p-4 sm:p-6 lg:p-8 h-full bg-white">
<div className="p-4 sm:p-6 lg:p-8 bg-white">
<header className="mb-8">
<div className="flex items-center gap-4">
<button