Fix settings toggles layout and add processing-log retention controls
This commit is contained in:
@@ -12,6 +12,7 @@ import type {
|
||||
DisplaySettings,
|
||||
HandwritingStyleClusteringSettings,
|
||||
OcrTaskSettings,
|
||||
ProcessingLogRetentionSettings,
|
||||
PredefinedPathEntry,
|
||||
PredefinedTagEntry,
|
||||
ProviderSettings,
|
||||
@@ -47,6 +48,24 @@ function parseCardsPerPageInput(input: string, fallback: number): number {
|
||||
return clampCardsPerPage(parsed);
|
||||
}
|
||||
|
||||
const DEFAULT_PROCESSING_LOG_RETENTION: ProcessingLogRetentionSettings = {
|
||||
keep_document_sessions: 2,
|
||||
keep_unbound_entries: 80,
|
||||
};
|
||||
|
||||
const PROCESSING_LOG_SESSION_MIN = 0;
|
||||
const PROCESSING_LOG_SESSION_MAX = 20;
|
||||
const PROCESSING_LOG_UNBOUND_MIN = 0;
|
||||
const PROCESSING_LOG_UNBOUND_MAX = 400;
|
||||
|
||||
function clampProcessingLogDocumentSessions(value: number): number {
|
||||
return Math.max(PROCESSING_LOG_SESSION_MIN, Math.min(PROCESSING_LOG_SESSION_MAX, value));
|
||||
}
|
||||
|
||||
function clampProcessingLogUnboundEntries(value: number): number {
|
||||
return Math.max(PROCESSING_LOG_UNBOUND_MIN, Math.min(PROCESSING_LOG_UNBOUND_MAX, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders compact human-oriented settings controls.
|
||||
*/
|
||||
@@ -69,6 +88,7 @@ export default function SettingsScreen({
|
||||
const [newPredefinedTag, setNewPredefinedTag] = useState<string>('');
|
||||
const [uploadDefaults, setUploadDefaults] = useState<UploadDefaultsSettings | null>(null);
|
||||
const [displaySettings, setDisplaySettings] = useState<DisplaySettings | null>(null);
|
||||
const [processingLogRetention, setProcessingLogRetention] = useState<ProcessingLogRetentionSettings | null>(null);
|
||||
const [cardsPerPageInput, setCardsPerPageInput] = useState<string>('12');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -92,6 +112,15 @@ export default function SettingsScreen({
|
||||
setPredefinedTags(settings.predefined_tags);
|
||||
setUploadDefaults(settings.upload_defaults);
|
||||
setDisplaySettings(settings.display);
|
||||
setProcessingLogRetention({
|
||||
keep_document_sessions: clampProcessingLogDocumentSessions(
|
||||
settings.processing_log_retention?.keep_document_sessions ??
|
||||
DEFAULT_PROCESSING_LOG_RETENTION.keep_document_sessions,
|
||||
),
|
||||
keep_unbound_entries: clampProcessingLogUnboundEntries(
|
||||
settings.processing_log_retention?.keep_unbound_entries ?? DEFAULT_PROCESSING_LOG_RETENTION.keep_unbound_entries,
|
||||
),
|
||||
});
|
||||
setCardsPerPageInput(String(settings.display.cards_per_page));
|
||||
setError(null);
|
||||
}, [settings]);
|
||||
@@ -163,7 +192,15 @@ export default function SettingsScreen({
|
||||
};
|
||||
|
||||
const handleSave = useCallback(async (): Promise<void> => {
|
||||
if (!ocrTask || !summaryTask || !routingTask || !handwritingStyle || !uploadDefaults || !displaySettings) {
|
||||
if (
|
||||
!ocrTask ||
|
||||
!summaryTask ||
|
||||
!routingTask ||
|
||||
!handwritingStyle ||
|
||||
!uploadDefaults ||
|
||||
!displaySettings ||
|
||||
!processingLogRetention
|
||||
) {
|
||||
setError('Settings are not fully loaded yet');
|
||||
return;
|
||||
}
|
||||
@@ -175,7 +212,12 @@ export default function SettingsScreen({
|
||||
setError(null);
|
||||
try {
|
||||
const resolvedCardsPerPage = parseCardsPerPageInput(cardsPerPageInput, displaySettings.cards_per_page);
|
||||
const resolvedProcessingLogRetention: ProcessingLogRetentionSettings = {
|
||||
keep_document_sessions: clampProcessingLogDocumentSessions(processingLogRetention.keep_document_sessions),
|
||||
keep_unbound_entries: clampProcessingLogUnboundEntries(processingLogRetention.keep_unbound_entries),
|
||||
};
|
||||
setDisplaySettings({ ...displaySettings, cards_per_page: resolvedCardsPerPage });
|
||||
setProcessingLogRetention(resolvedProcessingLogRetention);
|
||||
setCardsPerPageInput(String(resolvedCardsPerPage));
|
||||
|
||||
await onSave({
|
||||
@@ -187,6 +229,7 @@ export default function SettingsScreen({
|
||||
cards_per_page: resolvedCardsPerPage,
|
||||
log_typing_animation_enabled: displaySettings.log_typing_animation_enabled,
|
||||
},
|
||||
processing_log_retention: resolvedProcessingLogRetention,
|
||||
predefined_paths: predefinedPaths,
|
||||
predefined_tags: predefinedTags,
|
||||
handwriting_style_clustering: {
|
||||
@@ -252,21 +295,51 @@ export default function SettingsScreen({
|
||||
routingTask,
|
||||
summaryTask,
|
||||
uploadDefaults,
|
||||
processingLogRetention,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!onRegisterSaveAction) {
|
||||
return;
|
||||
}
|
||||
if (!settings || !ocrTask || !summaryTask || !routingTask || !handwritingStyle || !uploadDefaults || !displaySettings) {
|
||||
if (
|
||||
!settings ||
|
||||
!ocrTask ||
|
||||
!summaryTask ||
|
||||
!routingTask ||
|
||||
!handwritingStyle ||
|
||||
!uploadDefaults ||
|
||||
!displaySettings ||
|
||||
!processingLogRetention
|
||||
) {
|
||||
onRegisterSaveAction(null);
|
||||
return;
|
||||
}
|
||||
onRegisterSaveAction(() => handleSave());
|
||||
return () => onRegisterSaveAction(null);
|
||||
}, [displaySettings, handleSave, handwritingStyle, ocrTask, onRegisterSaveAction, routingTask, settings, summaryTask, uploadDefaults]);
|
||||
}, [
|
||||
displaySettings,
|
||||
handleSave,
|
||||
handwritingStyle,
|
||||
ocrTask,
|
||||
onRegisterSaveAction,
|
||||
processingLogRetention,
|
||||
routingTask,
|
||||
settings,
|
||||
summaryTask,
|
||||
uploadDefaults,
|
||||
]);
|
||||
|
||||
if (!settings || !ocrTask || !summaryTask || !routingTask || !handwritingStyle || !uploadDefaults || !displaySettings) {
|
||||
if (
|
||||
!settings ||
|
||||
!ocrTask ||
|
||||
!summaryTask ||
|
||||
!routingTask ||
|
||||
!handwritingStyle ||
|
||||
!uploadDefaults ||
|
||||
!displaySettings ||
|
||||
!processingLogRetention
|
||||
) {
|
||||
return (
|
||||
<section className="settings-layout">
|
||||
<div className="settings-card">
|
||||
@@ -313,6 +386,42 @@ export default function SettingsScreen({
|
||||
onChange={(event) => setCardsPerPageInput(event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label className="settings-field">
|
||||
Keep document sessions
|
||||
<input
|
||||
type="number"
|
||||
min={PROCESSING_LOG_SESSION_MIN}
|
||||
max={PROCESSING_LOG_SESSION_MAX}
|
||||
value={processingLogRetention.keep_document_sessions}
|
||||
onChange={(event) => {
|
||||
const nextValue = Number.parseInt(event.target.value, 10);
|
||||
if (!Number.isNaN(nextValue)) {
|
||||
setProcessingLogRetention({
|
||||
...processingLogRetention,
|
||||
keep_document_sessions: clampProcessingLogDocumentSessions(nextValue),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
<label className="settings-field">
|
||||
Keep unbound entries
|
||||
<input
|
||||
type="number"
|
||||
min={PROCESSING_LOG_UNBOUND_MIN}
|
||||
max={PROCESSING_LOG_UNBOUND_MAX}
|
||||
value={processingLogRetention.keep_unbound_entries}
|
||||
onChange={(event) => {
|
||||
const nextValue = Number.parseInt(event.target.value, 10);
|
||||
if (!Number.isNaN(nextValue)) {
|
||||
setProcessingLogRetention({
|
||||
...processingLogRetention,
|
||||
keep_unbound_entries: clampProcessingLogUnboundEntries(nextValue),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
<label className="inline-checkbox settings-checkbox-field">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -323,6 +432,9 @@ export default function SettingsScreen({
|
||||
/>
|
||||
Processing log typing animation enabled
|
||||
</label>
|
||||
<p className="small settings-helper-text">
|
||||
Processing-log retention values are used by backend trim routines when pruning historical entries.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user