formatting

This commit is contained in:
Connor Yoh 2025-08-15 14:04:46 +01:00
parent 973e6704e8
commit bd86a58d9a
9 changed files with 323 additions and 349 deletions

View File

@ -37,30 +37,27 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleAddPassword = async () => { const handleAddPassword = async () => {
try { try {
await addPasswordOperation.executeOperation( await addPasswordOperation.executeOperation(addPasswordParams.fullParameters, selectedFiles);
addPasswordParams.fullParameters,
selectedFiles
);
if (addPasswordOperation.files && onComplete) { if (addPasswordOperation.files && onComplete) {
onComplete(addPasswordOperation.files); onComplete(addPasswordOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : t('addPassword.error.failed', 'Add password operation failed')); onError(error instanceof Error ? error.message : t("addPassword.error.failed", "Add password operation failed"));
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'addPassword'); sessionStorage.setItem("previousMode", "addPassword");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
addPasswordOperation.resetResults(); addPasswordOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('addPassword'); setCurrentMode("addPassword");
}; };
const hasFiles = selectedFiles.length > 0; const hasFiles = selectedFiles.length > 0;
@ -75,7 +72,7 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
}, },
steps: [ steps: [
{ {
title: t('addPassword.passwords.stepTitle', 'Passwords & Encryption'), title: t("addPassword.passwords.stepTitle", "Passwords & Encryption"),
isCollapsed: passwordsCollapsed, isCollapsed: passwordsCollapsed,
onCollapsedClick: hasResults ? handleSettingsReset : undefined, onCollapsedClick: hasResults ? handleSettingsReset : undefined,
tooltip: addPasswordTips, tooltip: addPasswordTips,
@ -85,10 +82,10 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
onParameterChange={addPasswordParams.updateParameter} onParameterChange={addPasswordParams.updateParameter}
disabled={endpointLoading} disabled={endpointLoading}
/> />
) ),
}, },
{ {
title: t('changePermissions.title', 'Document Permissions'), title: t("changePermissions.title", "Document Permissions"),
isCollapsed: permissionsCollapsed, isCollapsed: permissionsCollapsed,
onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedPermissions(!collapsedPermissions), onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedPermissions(!collapsedPermissions),
content: ( content: (
@ -97,23 +94,23 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
onParameterChange={addPasswordParams.permissions.updateParameter} onParameterChange={addPasswordParams.permissions.updateParameter}
disabled={endpointLoading} disabled={endpointLoading}
/> />
) ),
} },
], ],
executeButton: { executeButton: {
text: t('addPassword.submit', 'Encrypt'), text: t("addPassword.submit", "Encrypt"),
isVisible: !hasResults, isVisible: !hasResults,
loadingText: t('loading'), loadingText: t("loading"),
onClick: handleAddPassword, onClick: handleAddPassword,
disabled: !addPasswordParams.validateParameters() || !hasFiles || !endpointEnabled disabled: !addPasswordParams.validateParameters() || !hasFiles || !endpointEnabled,
}, },
review: { review: {
isVisible: hasResults, isVisible: hasResults,
operation: addPasswordOperation, operation: addPasswordOperation,
title: t('addPassword.results.title', 'Encrypted PDFs'), title: t("addPassword.results.title", "Encrypted PDFs"),
onFileClick: handleThumbnailClick onFileClick: handleThumbnailClick,
} },
}); });
} };
export default AddPassword; export default AddPassword;

View File

@ -32,30 +32,29 @@ const ChangePermissions = ({ onPreviewFile, onComplete, onError }: BaseToolProps
const handleChangePermissions = async () => { const handleChangePermissions = async () => {
try { try {
await changePermissionsOperation.executeOperation( await changePermissionsOperation.executeOperation(changePermissionsParams.parameters, selectedFiles);
changePermissionsParams.parameters,
selectedFiles
);
if (changePermissionsOperation.files && onComplete) { if (changePermissionsOperation.files && onComplete) {
onComplete(changePermissionsOperation.files); onComplete(changePermissionsOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : t('changePermissions.error.failed', 'Change permissions operation failed')); onError(
error instanceof Error ? error.message : t("changePermissions.error.failed", "Change permissions operation failed")
);
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'changePermissions'); sessionStorage.setItem("previousMode", "changePermissions");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
changePermissionsOperation.resetResults(); changePermissionsOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('changePermissions'); setCurrentMode("changePermissions");
}; };
const hasFiles = selectedFiles.length > 0; const hasFiles = selectedFiles.length > 0;
@ -67,33 +66,35 @@ const ChangePermissions = ({ onPreviewFile, onComplete, onError }: BaseToolProps
selectedFiles, selectedFiles,
isCollapsed: hasFiles || hasResults, isCollapsed: hasFiles || hasResults,
}, },
steps: [{ steps: [
title: t('changePermissions.title', 'Document Permissions'), {
isCollapsed: settingsCollapsed, title: t("changePermissions.title", "Document Permissions"),
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined, isCollapsed: settingsCollapsed,
tooltip: changePermissionsTips, onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
content: ( tooltip: changePermissionsTips,
<ChangePermissionsSettings content: (
parameters={changePermissionsParams.parameters} <ChangePermissionsSettings
onParameterChange={changePermissionsParams.updateParameter} parameters={changePermissionsParams.parameters}
disabled={endpointLoading} onParameterChange={changePermissionsParams.updateParameter}
/> disabled={endpointLoading}
) />
}], ),
},
],
executeButton: { executeButton: {
text: t('changePermissions.submit', 'Change Permissions'), text: t("changePermissions.submit", "Change Permissions"),
isVisible: !hasResults, isVisible: !hasResults,
loadingText: t('loading'), loadingText: t("loading"),
onClick: handleChangePermissions, onClick: handleChangePermissions,
disabled: !changePermissionsParams.validateParameters() || !hasFiles || !endpointEnabled disabled: !changePermissionsParams.validateParameters() || !hasFiles || !endpointEnabled,
}, },
review: { review: {
isVisible: hasResults, isVisible: hasResults,
operation: changePermissionsOperation, operation: changePermissionsOperation,
title: t('changePermissions.results.title', 'Modified PDFs'), title: t("changePermissions.results.title", "Modified PDFs"),
onFileClick: handleThumbnailClick onFileClick: handleThumbnailClick,
} },
}); });
} };
export default ChangePermissions; export default ChangePermissions;

View File

@ -32,30 +32,27 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleCompress = async () => { const handleCompress = async () => {
try { try {
await compressOperation.executeOperation( await compressOperation.executeOperation(compressParams.parameters, selectedFiles);
compressParams.parameters,
selectedFiles
);
if (compressOperation.files && onComplete) { if (compressOperation.files && onComplete) {
onComplete(compressOperation.files); onComplete(compressOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : 'Compress operation failed'); onError(error instanceof Error ? error.message : "Compress operation failed");
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'compress'); sessionStorage.setItem("previousMode", "compress");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
compressOperation.resetResults(); compressOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('compress'); setCurrentMode("compress");
}; };
const hasFiles = selectedFiles.length > 0; const hasFiles = selectedFiles.length > 0;
@ -63,38 +60,39 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const settingsCollapsed = !hasFiles || hasResults; const settingsCollapsed = !hasFiles || hasResults;
return createToolFlow({ return createToolFlow({
files: { files: {
selectedFiles, selectedFiles,
isCollapsed: hasFiles && !hasResults, isCollapsed: hasFiles && !hasResults,
}, },
steps: [{ steps: [
title: "Settings", {
isCollapsed: settingsCollapsed, title: "Settings",
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined, isCollapsed: settingsCollapsed,
tooltip: compressTips, onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
content: ( tooltip: compressTips,
<CompressSettings content: (
parameters={compressParams.parameters} <CompressSettings
onParameterChange={compressParams.updateParameter} parameters={compressParams.parameters}
disabled={endpointLoading} onParameterChange={compressParams.updateParameter}
/> disabled={endpointLoading}
) />
}], ),
executeButton: { },
text: t("compress.submit", "Compress"), ],
isVisible: !hasResults, executeButton: {
loadingText: t("loading"), text: t("compress.submit", "Compress"),
onClick: handleCompress, isVisible: !hasResults,
disabled: !compressParams.validateParameters() || !hasFiles || !endpointEnabled loadingText: t("loading"),
}, onClick: handleCompress,
review: { disabled: !compressParams.validateParameters() || !hasFiles || !endpointEnabled,
isVisible: hasResults, },
operation: compressOperation, review: {
title: t("compress.title", "Compression Results"), isVisible: hasResults,
onFileClick: handleThumbnailClick operation: compressOperation,
} title: t("compress.title", "Compression Results"),
}); onFileClick: handleThumbnailClick,
} },
});
};
export default Compress; export default Compress;

View File

@ -21,15 +21,13 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const convertParams = useConvertParameters(); const convertParams = useConvertParameters();
const convertOperation = useConvertOperation(); const convertOperation = useConvertOperation();
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled( const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(convertParams.getEndpointName());
convertParams.getEndpointName()
);
const scrollToBottom = () => { const scrollToBottom = () => {
if (scrollContainerRef.current) { if (scrollContainerRef.current) {
scrollContainerRef.current.scrollTo({ scrollContainerRef.current.scrollTo({
top: scrollContainerRef.current.scrollHeight, top: scrollContainerRef.current.scrollHeight,
behavior: 'smooth' behavior: "smooth",
}); });
} }
}; };
@ -73,68 +71,67 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleConvert = async () => { const handleConvert = async () => {
try { try {
await convertOperation.executeOperation( await convertOperation.executeOperation(convertParams.parameters, selectedFiles);
convertParams.parameters,
selectedFiles
);
if (convertOperation.files && onComplete) { if (convertOperation.files && onComplete) {
onComplete(convertOperation.files); onComplete(convertOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : 'Convert operation failed'); onError(error instanceof Error ? error.message : "Convert operation failed");
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'convert'); sessionStorage.setItem("previousMode", "convert");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
convertOperation.resetResults(); convertOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('convert'); setCurrentMode("convert");
}; };
return createToolFlow({ return createToolFlow({
files: { files: {
selectedFiles, selectedFiles,
isCollapsed: filesCollapsed, isCollapsed: filesCollapsed,
placeholder: t("convert.selectFilesPlaceholder", "Select files in the main view to get started") placeholder: t("convert.selectFilesPlaceholder", "Select files in the main view to get started"),
}, },
steps: [{ steps: [
title: t("convert.settings", "Settings"), {
isCollapsed: settingsCollapsed, title: t("convert.settings", "Settings"),
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined, isCollapsed: settingsCollapsed,
content: ( onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
<ConvertSettings content: (
parameters={convertParams.parameters} <ConvertSettings
onParameterChange={convertParams.updateParameter} parameters={convertParams.parameters}
getAvailableToExtensions={convertParams.getAvailableToExtensions} onParameterChange={convertParams.updateParameter}
selectedFiles={selectedFiles} getAvailableToExtensions={convertParams.getAvailableToExtensions}
disabled={endpointLoading} selectedFiles={selectedFiles}
/> disabled={endpointLoading}
) />
}], ),
executeButton: { },
text: t("convert.convertFiles", "Convert Files"), ],
loadingText: t("convert.converting", "Converting..."), executeButton: {
onClick: handleConvert, text: t("convert.convertFiles", "Convert Files"),
isVisible: !hasResults, loadingText: t("convert.converting", "Converting..."),
disabled: !convertParams.validateParameters() || !hasFiles || !endpointEnabled, onClick: handleConvert,
testId: "convert-button" isVisible: !hasResults,
}, disabled: !convertParams.validateParameters() || !hasFiles || !endpointEnabled,
review: { testId: "convert-button",
isVisible: hasResults, },
operation: convertOperation, review: {
title: t("convert.conversionResults", "Conversion Results"), isVisible: hasResults,
onFileClick: handleThumbnailClick, operation: convertOperation,
testId: "conversion-results" title: t("convert.conversionResults", "Conversion Results"),
} onFileClick: handleThumbnailClick,
}); testId: "conversion-results",
},
});
}; };
export default Convert; export default Convert;

View File

@ -15,12 +15,7 @@ export interface MergePdfPanelProps {
updateParams: (newParams: Partial<MergePdfPanelProps["params"]>) => void; updateParams: (newParams: Partial<MergePdfPanelProps["params"]>) => void;
} }
const MergePdfPanel: React.FC<MergePdfPanelProps> = ({ const MergePdfPanel: React.FC<MergePdfPanelProps> = ({ files, setDownloadUrl, params, updateParams }) => {
files,
setDownloadUrl,
params,
updateParams,
}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedFiles, setSelectedFiles] = useState<boolean[]>([]); const [selectedFiles, setSelectedFiles] = useState<boolean[]>([]);
const [downloadUrl, setLocalDownloadUrl] = useState<string | null>(null); const [downloadUrl, setLocalDownloadUrl] = useState<string | null>(null);
@ -51,7 +46,7 @@ const MergePdfPanel: React.FC<MergePdfPanelProps> = ({
const blob = new Blob([storedFile.data], { type: storedFile.type }); const blob = new Blob([storedFile.data], { type: storedFile.type });
const actualFile = new File([blob], storedFile.name, { const actualFile = new File([blob], storedFile.name, {
type: storedFile.type, type: storedFile.type,
lastModified: storedFile.lastModified lastModified: storedFile.lastModified,
}); });
formData.append("fileInput", actualFile); formData.append("fileInput", actualFile);
} }
@ -83,9 +78,7 @@ const MergePdfPanel: React.FC<MergePdfPanelProps> = ({
}; };
const handleCheckboxChange = (index: number) => { const handleCheckboxChange = (index: number) => {
setSelectedFiles((prev) => setSelectedFiles((prev) => prev.map((selected, i) => (i === index ? !selected : selected)));
prev.map((selected, i) => (i === index ? !selected : selected))
);
}; };
const selectedCount = selectedFiles.filter(Boolean).length; const selectedCount = selectedFiles.filter(Boolean).length;
@ -96,7 +89,9 @@ const MergePdfPanel: React.FC<MergePdfPanelProps> = ({
return ( return (
<Stack align="center" justify="center" h={200}> <Stack align="center" justify="center" h={200}>
<Loader size="md" /> <Loader size="md" />
<Text size="sm" c="dimmed">{t("loading", "Loading...")}</Text> <Text size="sm" c="dimmed">
{t("loading", "Loading...")}
</Text>
</Stack> </Stack>
); );
} }
@ -112,55 +107,42 @@ const MergePdfPanel: React.FC<MergePdfPanelProps> = ({
} }
return ( return (
<Stack> <Stack>
<Text fw={500} size="lg">{t("merge.header")}</Text> <Text fw={500} size="lg">
<Stack gap={4}> {t("merge.header")}
{files.map((file, index) => ( </Text>
<Group key={index} gap="xs"> <Stack gap={4}>
<Checkbox {files.map((file, index) => (
checked={selectedFiles[index] || false} <Group key={index} gap="xs">
onChange={() => handleCheckboxChange(index)} <Checkbox checked={selectedFiles[index] || false} onChange={() => handleCheckboxChange(index)} />
/> <Text size="sm">{file.name}</Text>
<Text size="sm">{file.name}</Text> </Group>
</Group> ))}
))}
</Stack>
{selectedCount < 2 && (
<Text size="sm" c="red">
{t("multiPdfPrompt")}
</Text>
)}
<Button
onClick={handleMerge}
loading={isLoading}
disabled={selectedCount < 2 || isLoading}
mt="md"
>
{t("merge.submit")}
</Button>
{errorMessage && (
<Alert color="red" mt="sm">
{errorMessage}
</Alert>
)}
{downloadUrl && (
<Button
component="a"
href={downloadUrl}
download="merged.pdf"
color="green"
variant="light"
mt="md"
>
{t("downloadPdf")}
</Button>
)}
<Checkbox
label={t("merge.removeCertSign")}
checked={removeDuplicates}
onChange={() => updateParams({ removeDuplicates: !removeDuplicates })}
/>
</Stack> </Stack>
{selectedCount < 2 && (
<Text size="sm" c="red">
{t("multiPdfPrompt")}
</Text>
)}
<Button onClick={handleMerge} loading={isLoading} disabled={selectedCount < 2 || isLoading} mt="md">
{t("merge.submit")}
</Button>
{errorMessage && (
<Alert color="red" mt="sm">
{errorMessage}
</Alert>
)}
{downloadUrl && (
<Button component="a" href={downloadUrl} download="merged.pdf" color="green" variant="light" mt="md">
{t("downloadPdf")}
</Button>
)}
<Checkbox
label={t("merge.removeCertSign")}
checked={removeDuplicates}
onChange={() => updateParams({ removeDuplicates: !removeDuplicates })}
/>
</Stack>
); );
}; };

View File

@ -24,7 +24,7 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const ocrTips = useOCRTips(); const ocrTips = useOCRTips();
// Step expansion state management // Step expansion state management
const [expandedStep, setExpandedStep] = useState<'files' | 'settings' | 'advanced' | null>('files'); const [expandedStep, setExpandedStep] = useState<"files" | "settings" | "advanced" | null>("files");
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled("ocr-pdf"); const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled("ocr-pdf");
@ -38,8 +38,8 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
}, [ocrParams.parameters]); }, [ocrParams.parameters]);
useEffect(() => { useEffect(() => {
if (selectedFiles.length > 0 && expandedStep === 'files') { if (selectedFiles.length > 0 && expandedStep === "files") {
setExpandedStep('settings'); setExpandedStep("settings");
} }
}, [selectedFiles.length, expandedStep]); }, [selectedFiles.length, expandedStep]);
@ -52,88 +52,88 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleOCR = async () => { const handleOCR = async () => {
try { try {
await ocrOperation.executeOperation( await ocrOperation.executeOperation(ocrParams.parameters, selectedFiles);
ocrParams.parameters,
selectedFiles
);
if (ocrOperation.files && onComplete) { if (ocrOperation.files && onComplete) {
onComplete(ocrOperation.files); onComplete(ocrOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : 'OCR operation failed'); onError(error instanceof Error ? error.message : "OCR operation failed");
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'ocr'); sessionStorage.setItem("previousMode", "ocr");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
ocrOperation.resetResults(); ocrOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('ocr'); setCurrentMode("ocr");
}; };
const settingsCollapsed = expandedStep !== "settings";
const settingsCollapsed = expandedStep !== 'settings';
return createToolFlow({ return createToolFlow({
files: { files: {
selectedFiles, selectedFiles,
isCollapsed: hasFiles || hasResults, isCollapsed: hasFiles || hasResults,
}, },
steps: [ steps: [
{ {
title: "Settings", title: "Settings",
isCollapsed: !hasFiles || settingsCollapsed, isCollapsed: !hasFiles || settingsCollapsed,
onCollapsedClick: hasResults ? handleSettingsReset : () => { onCollapsedClick: hasResults
? handleSettingsReset
: () => {
if (!hasFiles) return; // Only allow if files are selected if (!hasFiles) return; // Only allow if files are selected
setExpandedStep(expandedStep === 'settings' ? null : 'settings'); setExpandedStep(expandedStep === "settings" ? null : "settings");
}, },
tooltip: ocrTips, tooltip: ocrTips,
content: ( content: (
<OCRSettings <OCRSettings
parameters={ocrParams.parameters} parameters={ocrParams.parameters}
onParameterChange={ocrParams.updateParameter} onParameterChange={ocrParams.updateParameter}
disabled={endpointLoading} disabled={endpointLoading}
/> />
) ),
}, },
{ {
title: "Advanced", title: "Advanced",
isCollapsed: expandedStep !== 'advanced', isCollapsed: expandedStep !== "advanced",
onCollapsedClick: hasResults ? handleSettingsReset : () => { onCollapsedClick: hasResults
? handleSettingsReset
: () => {
if (!hasFiles) return; // Only allow if files are selected if (!hasFiles) return; // Only allow if files are selected
setExpandedStep(expandedStep === 'advanced' ? null : 'advanced'); setExpandedStep(expandedStep === "advanced" ? null : "advanced");
}, },
content: ( content: (
<AdvancedOCRSettings <AdvancedOCRSettings
advancedOptions={ocrParams.parameters.additionalOptions} advancedOptions={ocrParams.parameters.additionalOptions}
ocrRenderType={ocrParams.parameters.ocrRenderType} ocrRenderType={ocrParams.parameters.ocrRenderType}
onParameterChange={ocrParams.updateParameter} onParameterChange={ocrParams.updateParameter}
disabled={endpointLoading} disabled={endpointLoading}
/> />
) ),
} },
], ],
executeButton: { executeButton: {
text: t("ocr.operation.submit", "Process OCR and Review"), text: t("ocr.operation.submit", "Process OCR and Review"),
loadingText: t("loading"), loadingText: t("loading"),
onClick: handleOCR, onClick: handleOCR,
isVisible: hasValidSettings && !hasResults, isVisible: hasValidSettings && !hasResults,
disabled: !ocrParams.validateParameters() || !hasFiles || !endpointEnabled disabled: !ocrParams.validateParameters() || !hasFiles || !endpointEnabled,
}, },
review: { review: {
isVisible: hasResults, isVisible: hasResults,
operation: ocrOperation, operation: ocrOperation,
title: t("ocr.results.title", "OCR Results"), title: t("ocr.results.title", "OCR Results"),
onFileClick: handleThumbnailClick onFileClick: handleThumbnailClick,
} },
}); });
} };
export default OCR; export default OCR;

View File

@ -21,9 +21,7 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const sanitizeOperation = useSanitizeOperation(); const sanitizeOperation = useSanitizeOperation();
// Endpoint validation // Endpoint validation
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled( const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(sanitizeParams.getEndpointName());
sanitizeParams.getEndpointName()
);
useEffect(() => { useEffect(() => {
sanitizeOperation.resetResults(); sanitizeOperation.resetResults();
@ -32,16 +30,13 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleSanitize = async () => { const handleSanitize = async () => {
try { try {
await sanitizeOperation.executeOperation( await sanitizeOperation.executeOperation(sanitizeParams.parameters, selectedFiles);
sanitizeParams.parameters,
selectedFiles,
);
if (sanitizeOperation.files && onComplete) { if (sanitizeOperation.files && onComplete) {
onComplete(sanitizeOperation.files); onComplete(sanitizeOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : t('sanitize.error.generic', 'Sanitization failed')); onError(error instanceof Error ? error.message : t("sanitize.error.generic", "Sanitization failed"));
} }
} }
}; };
@ -49,13 +44,13 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleSettingsReset = () => { const handleSettingsReset = () => {
sanitizeOperation.resetResults(); sanitizeOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('sanitize'); setCurrentMode("sanitize");
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'sanitize'); sessionStorage.setItem("previousMode", "sanitize");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const hasFiles = selectedFiles.length > 0; const hasFiles = selectedFiles.length > 0;
@ -64,37 +59,39 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const settingsCollapsed = !hasFiles || hasResults; const settingsCollapsed = !hasFiles || hasResults;
return createToolFlow({ return createToolFlow({
files: { files: {
selectedFiles, selectedFiles,
isCollapsed: filesCollapsed, isCollapsed: filesCollapsed,
placeholder: t('sanitize.files.placeholder', 'Select a PDF file in the main view to get started') placeholder: t("sanitize.files.placeholder", "Select a PDF file in the main view to get started"),
}, },
steps: [{ steps: [
title: t('sanitize.steps.settings', 'Settings'), {
isCollapsed: settingsCollapsed, title: t("sanitize.steps.settings", "Settings"),
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined, isCollapsed: settingsCollapsed,
content: ( onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
<SanitizeSettings content: (
parameters={sanitizeParams.parameters} <SanitizeSettings
onParameterChange={sanitizeParams.updateParameter} parameters={sanitizeParams.parameters}
disabled={endpointLoading} onParameterChange={sanitizeParams.updateParameter}
/> disabled={endpointLoading}
) />
}], ),
executeButton: { },
text: t("sanitize.submit", "Sanitize PDF"), ],
isVisible: !hasResults, executeButton: {
loadingText: t("loading"), text: t("sanitize.submit", "Sanitize PDF"),
onClick: handleSanitize, isVisible: !hasResults,
disabled: !sanitizeParams.validateParameters() || !hasFiles || !endpointEnabled loadingText: t("loading"),
}, onClick: handleSanitize,
review: { disabled: !sanitizeParams.validateParameters() || !hasFiles || !endpointEnabled,
isVisible: hasResults, },
operation: sanitizeOperation, review: {
title: t("sanitize.sanitizationResults", "Sanitization Results"), isVisible: hasResults,
onFileClick: handleThumbnailClick operation: sanitizeOperation,
} title: t("sanitize.sanitizationResults", "Sanitization Results"),
}); onFileClick: handleThumbnailClick,
} },
});
};
export default Sanitize; export default Sanitize;

View File

@ -20,9 +20,7 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const splitOperation = useSplitOperation(); const splitOperation = useSplitOperation();
// Endpoint validation // Endpoint validation
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled( const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(splitParams.getEndpointName());
splitParams.getEndpointName()
);
useEffect(() => { useEffect(() => {
splitOperation.resetResults(); splitOperation.resetResults();
@ -31,30 +29,27 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const handleSplit = async () => { const handleSplit = async () => {
try { try {
await splitOperation.executeOperation( await splitOperation.executeOperation(splitParams.parameters, selectedFiles);
splitParams.parameters,
selectedFiles
);
if (splitOperation.files && onComplete) { if (splitOperation.files && onComplete) {
onComplete(splitOperation.files); onComplete(splitOperation.files);
} }
} catch (error) { } catch (error) {
if (onError) { if (onError) {
onError(error instanceof Error ? error.message : 'Split operation failed'); onError(error instanceof Error ? error.message : "Split operation failed");
} }
} }
}; };
const handleThumbnailClick = (file: File) => { const handleThumbnailClick = (file: File) => {
onPreviewFile?.(file); onPreviewFile?.(file);
sessionStorage.setItem('previousMode', 'split'); sessionStorage.setItem("previousMode", "split");
setCurrentMode('viewer'); setCurrentMode("viewer");
}; };
const handleSettingsReset = () => { const handleSettingsReset = () => {
splitOperation.resetResults(); splitOperation.resetResults();
onPreviewFile?.(null); onPreviewFile?.(null);
setCurrentMode('split'); setCurrentMode("split");
}; };
const hasFiles = selectedFiles.length > 0; const hasFiles = selectedFiles.length > 0;
@ -63,37 +58,39 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const settingsCollapsed = !hasFiles || hasResults; const settingsCollapsed = !hasFiles || hasResults;
return createToolFlow({ return createToolFlow({
files: { files: {
selectedFiles, selectedFiles,
isCollapsed: filesCollapsed, isCollapsed: filesCollapsed,
placeholder: "Select a PDF file in the main view to get started" placeholder: "Select a PDF file in the main view to get started",
}, },
steps: [{ steps: [
title: "Settings", {
isCollapsed: settingsCollapsed, title: "Settings",
onCollapsedClick: hasResults ? handleSettingsReset : undefined, isCollapsed: settingsCollapsed,
content: ( onCollapsedClick: hasResults ? handleSettingsReset : undefined,
<SplitSettings content: (
parameters={splitParams.parameters} <SplitSettings
onParameterChange={splitParams.updateParameter} parameters={splitParams.parameters}
disabled={endpointLoading} onParameterChange={splitParams.updateParameter}
/> disabled={endpointLoading}
) />
}], ),
executeButton: { },
text: t("split.submit", "Split PDF"), ],
loadingText: t("loading"), executeButton: {
onClick: handleSplit, text: t("split.submit", "Split PDF"),
isVisible: !hasResults, loadingText: t("loading"),
disabled: !splitParams.validateParameters() || !hasFiles || !endpointEnabled onClick: handleSplit,
}, isVisible: !hasResults,
review: { disabled: !splitParams.validateParameters() || !hasFiles || !endpointEnabled,
isVisible: hasResults, },
operation: splitOperation, review: {
title: "Split Results", isVisible: hasResults,
onFileClick: handleThumbnailClick operation: splitOperation,
} title: "Split Results",
}); onFileClick: handleThumbnailClick,
} },
});
};
export default Split; export default Split;

View File

@ -1,16 +1,21 @@
import React, { useEffect } from 'react'; import React, { useEffect } from "react";
import { BaseToolProps } from '../types/tool'; import { BaseToolProps } from "../types/tool";
const SwaggerUI: React.FC<BaseToolProps> = () => { const SwaggerUI: React.FC<BaseToolProps> = () => {
useEffect(() => { useEffect(() => {
// Redirect to Swagger UI // Redirect to Swagger UI
window.open('/swagger-ui/5.21.0/index.html', '_blank'); window.open("/swagger-ui/5.21.0/index.html", "_blank");
}, []); }, []);
return ( return (
<div style={{ textAlign: 'center', padding: '2rem' }}> <div style={{ textAlign: "center", padding: "2rem" }}>
<p>Opening Swagger UI in a new tab...</p> <p>Opening Swagger UI in a new tab...</p>
<p>If it didn't open automatically, <a href="/swagger-ui/5.21.0/index.html" target="_blank" rel="noopener noreferrer">click here</a></p> <p>
If it didn't open automatically,{" "}
<a href="/swagger-ui/5.21.0/index.html" target="_blank" rel="noopener noreferrer">
click here
</a>
</p>
</div> </div>
); );
}; };