Compare commits
2 Commits
1e7c500f90
...
88b5591066
| Author | SHA1 | Date |
|---|---|---|
|
|
88b5591066 | |
|
|
a8ee946d02 |
|
|
@ -15,7 +15,6 @@ import {
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Paper,
|
Paper,
|
||||||
Select,
|
Select,
|
||||||
Snackbar,
|
|
||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
TextField,
|
TextField,
|
||||||
|
|
@ -153,12 +152,22 @@ function ReportHtmlFrame({ html }: { html: string }) {
|
||||||
const iframe = iframeRef.current;
|
const iframe = iframeRef.current;
|
||||||
if (!iframe) return;
|
if (!iframe) return;
|
||||||
|
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
|
||||||
const updateHeight = () => {
|
const updateHeight = () => {
|
||||||
try {
|
try {
|
||||||
const doc = iframe.contentDocument || iframe.contentWindow?.document;
|
const doc = iframe.contentDocument || iframe.contentWindow?.document;
|
||||||
if (doc?.body) {
|
if (doc?.body) {
|
||||||
const newHeight = doc.body.scrollHeight + 20;
|
const newHeight = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight) + 40;
|
||||||
if (newHeight > 50) setHeight(newHeight);
|
if (newHeight > 50) setHeight(newHeight);
|
||||||
|
|
||||||
|
if (!resizeObserver) {
|
||||||
|
resizeObserver = new ResizeObserver(() => {
|
||||||
|
const h = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight) + 40;
|
||||||
|
if (h > 50) setHeight(h);
|
||||||
|
});
|
||||||
|
resizeObserver.observe(doc.body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch { /* cross-origin safety */ }
|
} catch { /* cross-origin safety */ }
|
||||||
};
|
};
|
||||||
|
|
@ -169,6 +178,7 @@ function ReportHtmlFrame({ html }: { html: string }) {
|
||||||
return () => {
|
return () => {
|
||||||
iframe.removeEventListener('load', updateHeight);
|
iframe.removeEventListener('load', updateHeight);
|
||||||
timers.forEach(clearTimeout);
|
timers.forEach(clearTimeout);
|
||||||
|
resizeObserver?.disconnect();
|
||||||
};
|
};
|
||||||
}, [html]);
|
}, [html]);
|
||||||
|
|
||||||
|
|
@ -176,6 +186,7 @@ function ReportHtmlFrame({ html }: { html: string }) {
|
||||||
<iframe
|
<iframe
|
||||||
ref={iframeRef}
|
ref={iframeRef}
|
||||||
srcDoc={html}
|
srcDoc={html}
|
||||||
|
scrolling="no"
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height,
|
height,
|
||||||
|
|
@ -286,7 +297,7 @@ function WeeklyReport({ installationId, installationName, installationEmail }: W
|
||||||
const [autoSend, setAutoSend] = useState({ sendWeekly: false, sendMonthly: false, sendYearly: false });
|
const [autoSend, setAutoSend] = useState({ sendWeekly: false, sendMonthly: false, sendYearly: false });
|
||||||
const [autoSendDirty, setAutoSendDirty] = useState(false);
|
const [autoSendDirty, setAutoSendDirty] = useState(false);
|
||||||
const [savingAutoSend, setSavingAutoSend] = useState(false);
|
const [savingAutoSend, setSavingAutoSend] = useState(false);
|
||||||
const [autoSendSnackbar, setAutoSendSnackbar] = useState<string | null>(null);
|
const [autoSendStatus, setAutoSendStatus] = useState<{ message: string; severity: 'success' | 'error' } | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
axiosConfig.get('/GetEmailPreference', { params: { installationId } })
|
axiosConfig.get('/GetEmailPreference', { params: { installationId } })
|
||||||
|
|
@ -309,9 +320,11 @@ function WeeklyReport({ installationId, installationName, installationEmail }: W
|
||||||
params: { installationId, ...autoSend }
|
params: { installationId, ...autoSend }
|
||||||
});
|
});
|
||||||
setAutoSendDirty(false);
|
setAutoSendDirty(false);
|
||||||
setAutoSendSnackbar(intl.formatMessage({ id: 'autoSendSaved', defaultMessage: 'Auto-send preferences saved.' }));
|
setAutoSendStatus({ message: intl.formatMessage({ id: 'autoSendSaved', defaultMessage: 'Auto-send preferences saved.' }), severity: 'success' });
|
||||||
|
setTimeout(() => setAutoSendStatus(null), 4000);
|
||||||
} catch {
|
} catch {
|
||||||
setAutoSendSnackbar(intl.formatMessage({ id: 'autoSendSaveFailed', defaultMessage: 'Failed to save auto-send preferences.' }));
|
setAutoSendStatus({ message: intl.formatMessage({ id: 'autoSendSaveFailed', defaultMessage: 'Failed to save auto-send preferences.' }), severity: 'error' });
|
||||||
|
setTimeout(() => setAutoSendStatus(null), 4000);
|
||||||
} finally {
|
} finally {
|
||||||
setSavingAutoSend(false);
|
setSavingAutoSend(false);
|
||||||
}
|
}
|
||||||
|
|
@ -527,15 +540,13 @@ function WeeklyReport({ installationId, installationName, installationEmail }: W
|
||||||
<FormattedMessage id="autoSendNoEmail" defaultMessage="Set email address in Information tab to enable auto-send" />
|
<FormattedMessage id="autoSendNoEmail" defaultMessage="Set email address in Information tab to enable auto-send" />
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
{autoSendStatus && (
|
||||||
|
<Typography variant="caption" sx={{ color: autoSendStatus.severity === 'success' ? '#27ae60' : '#e74c3c', ml: 1, textTransform: 'uppercase', fontWeight: 600 }}>
|
||||||
|
{autoSendStatus.message}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Snackbar
|
|
||||||
open={!!autoSendSnackbar}
|
|
||||||
autoHideDuration={4000}
|
|
||||||
onClose={() => setAutoSendSnackbar(null)}
|
|
||||||
message={autoSendSnackbar}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Box sx={{ display: tabs[safeTab]?.key === 'daily' ? 'block' : 'none', minHeight: '50vh' }}>
|
<Box sx={{ display: tabs[safeTab]?.key === 'daily' ? 'block' : 'none', minHeight: '50vh' }}>
|
||||||
<DailySection installationId={installationId} onHasData={setDailyHasData} onPeriodChange={(date: string) => setReportPeriods(prev => ({ ...prev, daily: { start: date, end: date } }))} />
|
<DailySection installationId={installationId} onHasData={setDailyHasData} onPeriodChange={(date: string) => setReportPeriods(prev => ({ ...prev, daily: { start: date, end: date } }))} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue