remove nginx

This commit is contained in:
2026-04-10 00:25:43 +02:00
parent 9223e4d35f
commit c170d20b65
15 changed files with 229 additions and 103 deletions
+103 -64
View File
@@ -2,6 +2,20 @@ import { useRef, useState } from 'react';
import { api } from '../../api';
import { useQueryClient } from '@tanstack/react-query';
interface UploadResult {
filename: string;
rms_total: number;
rms_ra: number;
rms_dec: number;
duration_min?: number;
camera_name?: string;
exposure_ms?: number;
mount_name?: string;
session_date?: string;
error?: string;
duplicate?: { id: number; message: string };
}
interface Props {
onUploaded?: (id: number) => void;
}
@@ -9,54 +23,64 @@ interface Props {
export default function PHD2UploadZone({ onUploaded }: Props) {
const inputRef = useRef<HTMLInputElement>(null);
const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [duplicate, setDuplicate] = useState<{ id: number; message: string } | null>(null);
const [result, setResult] = useState<{
rms_total: number;
rms_ra: number;
rms_dec: number;
duration_min?: number;
camera_name?: string;
exposure_ms?: number;
mount_name?: string;
session_date?: string;
} | null>(null);
const [results, setResults] = useState<UploadResult[]>([]);
const qc = useQueryClient();
const handleFile = async (file: File) => {
setUploading(true);
setError(null);
setDuplicate(null);
setResult(null);
const fd = new FormData();
fd.append('file', file);
const handleFiles = async (files: FileList | null) => {
if (!files || files.length === 0) return;
try {
const res = await api.phd2.upload(fd);
if (res.duplicate) {
setDuplicate({
id: res.duplicate_id || 0,
message: res.message || `Duplicate session detected (ID: ${res.duplicate_id})`
});
setResult(null);
} else {
const analysis = res.analysis as any;
setResult({
rms_total: analysis.rms_total_arcsec,
rms_ra: analysis.rms_ra_arcsec,
rms_dec: analysis.rms_dec_arcsec,
duration_min: analysis.duration_min,
camera_name: analysis.camera_name,
exposure_ms: analysis.exposure_ms,
mount_name: analysis.mount_name,
});
qc.invalidateQueries({ queryKey: ['phd2'] });
onUploaded?.(res.id);
setUploading(true);
setResults([]);
const uploadedIds: number[] = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const fd = new FormData();
fd.append('file', file);
try {
const res = await api.phd2.upload(fd);
if (res.duplicate) {
setResults(prev => [...prev, {
filename: file.name,
rms_total: 0,
rms_ra: 0,
rms_dec: 0,
duplicate: {
id: res.duplicate_id || 0,
message: res.message || `Duplicate session detected (ID: ${res.duplicate_id})`
}
}]);
} else {
const analysis = res.analysis as any;
setResults(prev => [...prev, {
filename: file.name,
rms_total: analysis.rms_total_arcsec,
rms_ra: analysis.rms_ra_arcsec,
rms_dec: analysis.rms_dec_arcsec,
duration_min: analysis.duration_min,
camera_name: analysis.camera_name,
exposure_ms: analysis.exposure_ms,
mount_name: analysis.mount_name,
session_date: analysis.session_date,
}]);
uploadedIds.push(res.id);
}
} catch (e) {
setResults(prev => [...prev, {
filename: file.name,
rms_total: 0,
rms_ra: 0,
rms_dec: 0,
error: `Parse failed: ${e instanceof Error ? e.message : 'Unknown error'}`
}]);
}
} catch (e) {
setError(`Parse failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
}
qc.invalidateQueries({ queryKey: ['phd2'] });
uploadedIds.forEach(id => onUploaded?.(id));
setUploading(false);
};
@@ -75,39 +99,54 @@ export default function PHD2UploadZone({ onUploaded }: Props) {
background: 'var(--bg-deep)',
}}
>
{uploading ? 'Parsing PHD2 log...' : '↑ Upload PHD2 log (.log)'}
{uploading ? 'Parsing PHD2 logs...' : '↑ Upload PHD2 log(s) (.log)'}
</div>
<input
ref={inputRef}
type="file"
accept=".log,.csv"
multiple
style={{ display: 'none' }}
onChange={e => e.target.files?.[0] && handleFile(e.target.files[0])}
onChange={e => handleFiles(e.target.files)}
/>
{error && <div style={{ color: 'var(--danger)', fontSize: 11, marginTop: 4 }}>{error}</div>}
{duplicate && (
<div style={{ color: 'var(--warn)', fontSize: 11, marginTop: 4, fontFamily: 'var(--font-mono)' }}>
{duplicate.message}
</div>
)}
{result && (
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--good)', marginTop: 4, lineHeight: '1.5' }}>
<div> RMS Total: {result.rms_total.toFixed(2)} (RA: {result.rms_ra.toFixed(2)} Dec: {result.rms_dec.toFixed(2)})</div>
{result.session_date && (
<div style={{ color: 'var(--text-mid)', marginTop: 4 }}>Date: {result.session_date}</div>
{results.map((result, idx) => (
<div key={idx} style={{ marginTop: 8, paddingTop: 8, borderTop: '1px solid var(--border)' }}>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-lo)', marginBottom: 4 }}>
{result.filename}
</div>
{result.error && (
<div style={{ color: 'var(--danger)', fontSize: 11 }}>
{result.error}
</div>
)}
{result.duration_min !== undefined && (
<div style={{ color: 'var(--text-mid)', marginTop: result.session_date ? 2 : 6 }}>Duration: {result.duration_min}m</div>
{result.duplicate && (
<div style={{ color: 'var(--warn)', fontSize: 11, fontFamily: 'var(--font-mono)' }}>
{result.duplicate.message}
</div>
)}
{(result.camera_name || result.mount_name) && (
<div style={{ color: 'var(--text-lo)', marginTop: 4 }}>
{result.camera_name && <div>Camera: {result.camera_name}</div>}
{result.mount_name && <div>Mount: {result.mount_name}</div>}
{result.exposure_ms && <div>Exposure: {result.exposure_ms}ms</div>}
{!result.error && !result.duplicate && (
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--good)', lineHeight: '1.5' }}>
<div> RMS: {result.rms_total.toFixed(2)} (RA: {result.rms_ra.toFixed(2)} Dec: {result.rms_dec.toFixed(2)})</div>
{result.session_date && (
<div style={{ color: 'var(--text-mid)', marginTop: 2 }}>Date: {result.session_date}</div>
)}
{result.duration_min !== undefined && (
<div style={{ color: 'var(--text-mid)', marginTop: 2 }}>Duration: {result.duration_min}m</div>
)}
{(result.camera_name || result.mount_name) && (
<div style={{ color: 'var(--text-lo)', marginTop: 2, fontSize: 10 }}>
{result.camera_name && <div>Camera: {result.camera_name}</div>}
{result.mount_name && <div>Mount: {result.mount_name}</div>}
{result.exposure_ms && <div>Exposure: {result.exposure_ms}ms</div>}
</div>
)}
</div>
)}
</div>
)}
))}
</div>
);
}