mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-29 07:39:23 +00:00
V2 reduce tool boilerplate (#4313)
# Description of Changes Reduce boilerplate in tool frontends by creating a base frontend hook for the simple tools to use. I've done all the simple tools here. It'd be nice to add in some of the more complex tools as well in the future if we can figure out how.
This commit is contained in:
parent
e142af2863
commit
442b373ff4
118
frontend/src/hooks/tools/shared/useBaseTool.ts
Normal file
118
frontend/src/hooks/tools/shared/useBaseTool.ts
Normal file
@ -0,0 +1,118 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useFileSelection } from '../../../contexts/FileContext';
|
||||
import { useEndpointEnabled } from '../../useEndpointConfig';
|
||||
import { BaseToolProps } from '../../../types/tool';
|
||||
import { ToolOperationHook } from './useToolOperation';
|
||||
import { BaseParametersHook } from './useBaseParameters';
|
||||
|
||||
interface BaseToolReturn<TParams> {
|
||||
// File management
|
||||
selectedFiles: File[];
|
||||
|
||||
// Tool-specific hooks
|
||||
params: BaseParametersHook<TParams>;
|
||||
operation: ToolOperationHook<TParams>;
|
||||
|
||||
// Endpoint validation
|
||||
endpointEnabled: boolean | null;
|
||||
endpointLoading: boolean;
|
||||
|
||||
// Standard handlers
|
||||
handleExecute: () => Promise<void>;
|
||||
handleThumbnailClick: (file: File) => void;
|
||||
handleSettingsReset: () => void;
|
||||
|
||||
// Standard computed state
|
||||
hasFiles: boolean;
|
||||
hasResults: boolean;
|
||||
settingsCollapsed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base tool hook for tool components. Manages standard behaviour for tools.
|
||||
*/
|
||||
export function useBaseTool<TParams>(
|
||||
toolName: string,
|
||||
useParams: () => BaseParametersHook<TParams>,
|
||||
useOperation: () => ToolOperationHook<TParams>,
|
||||
props: BaseToolProps,
|
||||
): BaseToolReturn<TParams> {
|
||||
const { onPreviewFile, onComplete, onError } = props;
|
||||
|
||||
// File selection
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
// Tool-specific hooks
|
||||
const params = useParams();
|
||||
const operation = useOperation();
|
||||
|
||||
// Endpoint validation using parameters hook
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(params.getEndpointName());
|
||||
|
||||
// Reset results when parameters change
|
||||
useEffect(() => {
|
||||
operation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [params.parameters]);
|
||||
|
||||
// Reset results when selected files change
|
||||
useEffect(() => {
|
||||
if (selectedFiles.length > 0) {
|
||||
operation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}
|
||||
}, [selectedFiles.length]);
|
||||
|
||||
// Standard handlers
|
||||
const handleExecute = useCallback(async () => {
|
||||
try {
|
||||
await operation.executeOperation(params.parameters, selectedFiles);
|
||||
if (operation.files && onComplete) {
|
||||
onComplete(operation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
const message = error instanceof Error ? error.message : `${toolName} operation failed`;
|
||||
onError(message);
|
||||
}
|
||||
}
|
||||
}, [operation, params.parameters, selectedFiles, onComplete, onError, toolName]);
|
||||
|
||||
const handleThumbnailClick = useCallback((file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem('previousMode', toolName);
|
||||
}, [onPreviewFile, toolName]);
|
||||
|
||||
const handleSettingsReset = useCallback(() => {
|
||||
operation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [operation, onPreviewFile]);
|
||||
|
||||
// Standard computed state
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = operation.files.length > 0 || operation.downloadUrl !== null;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
|
||||
return {
|
||||
// File management
|
||||
selectedFiles,
|
||||
|
||||
// Tool-specific hooks
|
||||
params,
|
||||
operation,
|
||||
|
||||
// Endpoint validation
|
||||
endpointEnabled,
|
||||
endpointLoading,
|
||||
|
||||
// Handlers
|
||||
handleExecute,
|
||||
handleThumbnailClick,
|
||||
handleSettingsReset,
|
||||
|
||||
// State
|
||||
hasFiles,
|
||||
hasResults,
|
||||
settingsCollapsed
|
||||
};
|
||||
}
|
@ -1,96 +1,55 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
|
||||
|
||||
import { useChangePermissionsParameters } from "../hooks/tools/changePermissions/useChangePermissionsParameters";
|
||||
import { useChangePermissionsOperation } from "../hooks/tools/changePermissions/useChangePermissionsOperation";
|
||||
import { useChangePermissionsTips } from "../components/tooltips/useChangePermissionsTips";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const ChangePermissions = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const ChangePermissions = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const changePermissionsParams = useChangePermissionsParameters();
|
||||
const changePermissionsOperation = useChangePermissionsOperation();
|
||||
const changePermissionsTips = useChangePermissionsTips();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(changePermissionsParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
changePermissionsOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [changePermissionsParams.parameters]);
|
||||
|
||||
const handleChangePermissions = async () => {
|
||||
try {
|
||||
await changePermissionsOperation.executeOperation(changePermissionsParams.parameters, selectedFiles);
|
||||
if (changePermissionsOperation.files && onComplete) {
|
||||
onComplete(changePermissionsOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(
|
||||
error instanceof Error ? error.message : t("changePermissions.error.failed", "Change permissions operation failed")
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "changePermissions");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
changePermissionsOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = changePermissionsOperation.files.length > 0 || changePermissionsOperation.downloadUrl !== null;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
const base = useBaseTool(
|
||||
'changePermissions',
|
||||
useChangePermissionsParameters,
|
||||
useChangePermissionsOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
title: t("changePermissions.title", "Document Permissions"),
|
||||
isCollapsed: settingsCollapsed,
|
||||
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
|
||||
isCollapsed: base.settingsCollapsed,
|
||||
onCollapsedClick: base.settingsCollapsed ? base.handleSettingsReset : undefined,
|
||||
tooltip: changePermissionsTips,
|
||||
content: (
|
||||
<ChangePermissionsSettings
|
||||
parameters={changePermissionsParams.parameters}
|
||||
onParameterChange={changePermissionsParams.updateParameter}
|
||||
disabled={endpointLoading}
|
||||
parameters={base.params.parameters}
|
||||
onParameterChange={base.params.updateParameter}
|
||||
disabled={base.endpointLoading}
|
||||
/>
|
||||
),
|
||||
},
|
||||
],
|
||||
executeButton: {
|
||||
text: t("changePermissions.submit", "Change Permissions"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleChangePermissions,
|
||||
disabled: !changePermissionsParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: changePermissionsOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("changePermissions.results.title", "Modified PDFs"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,95 +1,55 @@
|
||||
import React, { use, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import CompressSettings from "../components/tools/compress/CompressSettings";
|
||||
|
||||
import { useCompressParameters } from "../hooks/tools/compress/useCompressParameters";
|
||||
import { useCompressOperation } from "../hooks/tools/compress/useCompressOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
import { useCompressTips } from "../components/tooltips/useCompressTips";
|
||||
|
||||
const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const Compress = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const compressParams = useCompressParameters();
|
||||
const compressOperation = useCompressOperation();
|
||||
const compressTips = useCompressTips();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled("compress-pdf");
|
||||
|
||||
useEffect(() => {
|
||||
compressOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [compressParams.parameters]);
|
||||
|
||||
const handleCompress = async () => {
|
||||
try {
|
||||
await compressOperation.executeOperation(compressParams.parameters, selectedFiles);
|
||||
if (compressOperation.files && onComplete) {
|
||||
onComplete(compressOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : "Compress operation failed");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "compress");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
compressOperation.resetResults();
|
||||
onPreviewFile?.(null); };
|
||||
|
||||
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = compressOperation.files.length > 0 || compressOperation.downloadUrl !== null;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
const base = useBaseTool(
|
||||
'compress',
|
||||
useCompressParameters,
|
||||
useCompressOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
title: "Settings",
|
||||
isCollapsed: settingsCollapsed,
|
||||
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
|
||||
isCollapsed: base.settingsCollapsed,
|
||||
onCollapsedClick: base.settingsCollapsed ? base.handleSettingsReset : undefined,
|
||||
tooltip: compressTips,
|
||||
content: (
|
||||
<CompressSettings
|
||||
parameters={compressParams.parameters}
|
||||
onParameterChange={compressParams.updateParameter}
|
||||
disabled={endpointLoading}
|
||||
parameters={base.params.parameters}
|
||||
onParameterChange={base.params.updateParameter}
|
||||
disabled={base.endpointLoading}
|
||||
/>
|
||||
),
|
||||
},
|
||||
],
|
||||
executeButton: {
|
||||
text: t("compress.submit", "Compress"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleCompress,
|
||||
disabled: !compressParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: compressOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("compress.title", "Compression Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,78 +1,39 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
import { useFileSelection } from "../contexts/file/fileHooks";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import { useRemoveCertificateSignParameters } from "../hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters";
|
||||
import { useRemoveCertificateSignOperation } from "../hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const RemoveCertificateSign = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const RemoveCertificateSign = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const removeCertificateSignParams = useRemoveCertificateSignParameters();
|
||||
const removeCertificateSignOperation = useRemoveCertificateSignOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(removeCertificateSignParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
removeCertificateSignOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [removeCertificateSignParams.parameters]);
|
||||
|
||||
const handleRemoveSignature = async () => {
|
||||
try {
|
||||
await removeCertificateSignOperation.executeOperation(removeCertificateSignParams.parameters, selectedFiles);
|
||||
if (removeCertificateSignOperation.files && onComplete) {
|
||||
onComplete(removeCertificateSignOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("removeCertSign.error.failed", "Remove certificate signature operation failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "removeCertificateSign");
|
||||
actions.setMode("viewer");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
removeCertificateSignOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = removeCertificateSignOperation.files.length > 0 || removeCertificateSignOperation.downloadUrl !== null;
|
||||
const base = useBaseTool(
|
||||
'removeCertificateSign',
|
||||
useRemoveCertificateSignParameters,
|
||||
useRemoveCertificateSignOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasFiles || hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
placeholder: t("removeCertSign.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||
},
|
||||
steps: [],
|
||||
executeButton: {
|
||||
text: t("removeCertSign.submit", "Remove Signature"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleRemoveSignature,
|
||||
disabled: !removeCertificateSignParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: removeCertificateSignOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("removeCertSign.results.title", "Certificate Removal Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -80,4 +41,4 @@ const RemoveCertificateSign = ({ onPreviewFile, onComplete, onError }: BaseToolP
|
||||
// Static method to get the operation hook for automation
|
||||
RemoveCertificateSign.tool = () => useRemoveCertificateSignOperation;
|
||||
|
||||
export default RemoveCertificateSign as ToolComponent;
|
||||
export default RemoveCertificateSign as ToolComponent;
|
||||
|
@ -1,95 +1,55 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import RemovePasswordSettings from "../components/tools/removePassword/RemovePasswordSettings";
|
||||
|
||||
import { useRemovePasswordParameters } from "../hooks/tools/removePassword/useRemovePasswordParameters";
|
||||
import { useRemovePasswordOperation } from "../hooks/tools/removePassword/useRemovePasswordOperation";
|
||||
import { useRemovePasswordTips } from "../components/tooltips/useRemovePasswordTips";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const RemovePassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const RemovePassword = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const removePasswordParams = useRemovePasswordParameters();
|
||||
const removePasswordOperation = useRemovePasswordOperation();
|
||||
const removePasswordTips = useRemovePasswordTips();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(removePasswordParams.getEndpointName());
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
removePasswordOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [removePasswordParams.parameters]);
|
||||
|
||||
const handleRemovePassword = async () => {
|
||||
try {
|
||||
await removePasswordOperation.executeOperation(removePasswordParams.parameters, selectedFiles);
|
||||
if (removePasswordOperation.files && onComplete) {
|
||||
onComplete(removePasswordOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("removePassword.error.failed", "Remove password operation failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "removePassword");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
removePasswordOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = removePasswordOperation.files.length > 0 || removePasswordOperation.downloadUrl !== null;
|
||||
const passwordCollapsed = !hasFiles || hasResults;
|
||||
const base = useBaseTool(
|
||||
'removePassword',
|
||||
useRemovePasswordParameters,
|
||||
useRemovePasswordOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
title: t("removePassword.password.stepTitle", "Remove Password"),
|
||||
isCollapsed: passwordCollapsed,
|
||||
onCollapsedClick: hasResults ? handleSettingsReset : undefined,
|
||||
isCollapsed: base.settingsCollapsed,
|
||||
onCollapsedClick: base.hasResults ? base.handleSettingsReset : undefined,
|
||||
tooltip: removePasswordTips,
|
||||
content: (
|
||||
<RemovePasswordSettings
|
||||
parameters={removePasswordParams.parameters}
|
||||
onParameterChange={removePasswordParams.updateParameter}
|
||||
disabled={endpointLoading}
|
||||
parameters={base.params.parameters}
|
||||
onParameterChange={base.params.updateParameter}
|
||||
disabled={base.endpointLoading}
|
||||
/>
|
||||
),
|
||||
},
|
||||
],
|
||||
executeButton: {
|
||||
text: t("removePassword.submit", "Remove Password"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleRemovePassword,
|
||||
disabled: !removePasswordParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: removePasswordOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("removePassword.results.title", "Decrypted PDFs"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,78 +1,39 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
import { useFileSelection } from "../contexts/file/fileHooks";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import { useRepairParameters } from "../hooks/tools/repair/useRepairParameters";
|
||||
import { useRepairOperation } from "../hooks/tools/repair/useRepairOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const Repair = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const Repair = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const repairParams = useRepairParameters();
|
||||
const repairOperation = useRepairOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(repairParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
repairOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [repairParams.parameters]);
|
||||
|
||||
const handleRepair = async () => {
|
||||
try {
|
||||
await repairOperation.executeOperation(repairParams.parameters, selectedFiles);
|
||||
if (repairOperation.files && onComplete) {
|
||||
onComplete(repairOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("repair.error.failed", "Repair operation failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "repair");
|
||||
actions.setMode("viewer");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
repairOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = repairOperation.files.length > 0 || repairOperation.downloadUrl !== null;
|
||||
const base = useBaseTool(
|
||||
'repair',
|
||||
useRepairParameters,
|
||||
useRepairOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
placeholder: t("repair.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||
},
|
||||
steps: [],
|
||||
executeButton: {
|
||||
text: t("repair.submit", "Repair PDF"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleRepair,
|
||||
disabled: !repairParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: repairOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("repair.results.title", "Repair Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,90 +1,53 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
import SanitizeSettings from "../components/tools/sanitize/SanitizeSettings";
|
||||
|
||||
import { useSanitizeParameters } from "../hooks/tools/sanitize/useSanitizeParameters";
|
||||
import { useSanitizeOperation } from "../hooks/tools/sanitize/useSanitizeOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const Sanitize = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const sanitizeParams = useSanitizeParameters();
|
||||
const sanitizeOperation = useSanitizeOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(sanitizeParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
sanitizeOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [sanitizeParams.parameters]);
|
||||
|
||||
const handleSanitize = async () => {
|
||||
try {
|
||||
await sanitizeOperation.executeOperation(sanitizeParams.parameters, selectedFiles);
|
||||
if (sanitizeOperation.files && onComplete) {
|
||||
onComplete(sanitizeOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("sanitize.error.generic", "Sanitization failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
sanitizeOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "sanitize");
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = sanitizeOperation.files.length > 0;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
const base = useBaseTool(
|
||||
'sanitize',
|
||||
useSanitizeParameters,
|
||||
useSanitizeOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
placeholder: t("sanitize.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
title: t("sanitize.steps.settings", "Settings"),
|
||||
isCollapsed: settingsCollapsed,
|
||||
onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
|
||||
isCollapsed: base.settingsCollapsed,
|
||||
onCollapsedClick: base.settingsCollapsed ? base.handleSettingsReset : undefined,
|
||||
content: (
|
||||
<SanitizeSettings
|
||||
parameters={sanitizeParams.parameters}
|
||||
onParameterChange={sanitizeParams.updateParameter}
|
||||
disabled={endpointLoading}
|
||||
parameters={base.params.parameters}
|
||||
onParameterChange={base.params.updateParameter}
|
||||
disabled={base.endpointLoading}
|
||||
/>
|
||||
),
|
||||
},
|
||||
],
|
||||
executeButton: {
|
||||
text: t("sanitize.submit", "Sanitize PDF"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleSanitize,
|
||||
disabled: !sanitizeParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: sanitizeOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("sanitize.sanitizationResults", "Sanitization Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,78 +1,39 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
import { useFileSelection } from "../contexts/file/fileHooks";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import { useSingleLargePageParameters } from "../hooks/tools/singleLargePage/useSingleLargePageParameters";
|
||||
import { useSingleLargePageOperation } from "../hooks/tools/singleLargePage/useSingleLargePageOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const SingleLargePage = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const SingleLargePage = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const singleLargePageParams = useSingleLargePageParameters();
|
||||
const singleLargePageOperation = useSingleLargePageOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(singleLargePageParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
singleLargePageOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [singleLargePageParams.parameters]);
|
||||
|
||||
const handleConvert = async () => {
|
||||
try {
|
||||
await singleLargePageOperation.executeOperation(singleLargePageParams.parameters, selectedFiles);
|
||||
if (singleLargePageOperation.files && onComplete) {
|
||||
onComplete(singleLargePageOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("pdfToSinglePage.error.failed", "Single large page operation failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "single-large-page");
|
||||
actions.setMode("viewer");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
singleLargePageOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = singleLargePageOperation.files.length > 0 || singleLargePageOperation.downloadUrl !== null;
|
||||
const base = useBaseTool(
|
||||
'singleLargePage',
|
||||
useSingleLargePageParameters,
|
||||
useSingleLargePageOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasFiles || hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
placeholder: t("pdfToSinglePage.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||
},
|
||||
steps: [],
|
||||
executeButton: {
|
||||
text: t("pdfToSinglePage.submit", "Convert To Single Page"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleConvert,
|
||||
disabled: !singleLargePageParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: singleLargePageOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("pdfToSinglePage.results.title", "Single Page Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -80,4 +41,4 @@ const SingleLargePage = ({ onPreviewFile, onComplete, onError }: BaseToolProps)
|
||||
// Static method to get the operation hook for automation
|
||||
SingleLargePage.tool = () => useSingleLargePageOperation;
|
||||
|
||||
export default SingleLargePage as ToolComponent;
|
||||
export default SingleLargePage as ToolComponent;
|
||||
|
@ -1,84 +1,37 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
import SplitSettings from "../components/tools/split/SplitSettings";
|
||||
|
||||
import { useSplitParameters } from "../hooks/tools/split/useSplitParameters";
|
||||
import { useSplitOperation } from "../hooks/tools/split/useSplitOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const Split = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const splitParams = useSplitParameters();
|
||||
const splitOperation = useSplitOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(splitParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
// Only reset results when parameters change, not when files change
|
||||
splitOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [splitParams.parameters]);
|
||||
|
||||
useEffect(() => {
|
||||
// Reset results when selected files change (user selected different files)
|
||||
if (selectedFiles.length > 0) {
|
||||
splitOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}
|
||||
}, [selectedFiles]);
|
||||
|
||||
const handleSplit = async () => {
|
||||
try {
|
||||
await splitOperation.executeOperation(splitParams.parameters, selectedFiles);
|
||||
if (splitOperation.files && onComplete) {
|
||||
onComplete(splitOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : "Split operation failed");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "split");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
splitOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = splitOperation.files.length > 0 || splitOperation.downloadUrl !== null;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
const base = useBaseTool(
|
||||
'split',
|
||||
useSplitParameters,
|
||||
useSplitOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasResults,
|
||||
placeholder: "Select a PDF file in the main view to get started",
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasResults,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
title: "Settings",
|
||||
isCollapsed: settingsCollapsed,
|
||||
onCollapsedClick: hasResults ? handleSettingsReset : undefined,
|
||||
isCollapsed: base.settingsCollapsed,
|
||||
onCollapsedClick: base.hasResults ? base.handleSettingsReset : undefined,
|
||||
content: (
|
||||
<SplitSettings
|
||||
parameters={splitParams.parameters}
|
||||
onParameterChange={splitParams.updateParameter}
|
||||
disabled={endpointLoading}
|
||||
parameters={base.params.parameters}
|
||||
onParameterChange={base.params.updateParameter}
|
||||
disabled={base.endpointLoading}
|
||||
/>
|
||||
),
|
||||
},
|
||||
@ -86,15 +39,15 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
executeButton: {
|
||||
text: t("split.submit", "Split PDF"),
|
||||
loadingText: t("loading"),
|
||||
onClick: handleSplit,
|
||||
isVisible: !hasResults,
|
||||
disabled: !splitParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
isVisible: !base.hasResults,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: splitOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: "Split Results",
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,78 +1,39 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
import { useNavigationActions } from "../contexts/NavigationContext";
|
||||
import { useFileSelection } from "../contexts/file/fileHooks";
|
||||
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
|
||||
import { useUnlockPdfFormsParameters } from "../hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters";
|
||||
import { useUnlockPdfFormsOperation } from "../hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation";
|
||||
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
const UnlockPdfForms = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const UnlockPdfForms = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions } = useNavigationActions();
|
||||
const { selectedFiles } = useFileSelection();
|
||||
|
||||
const unlockPdfFormsParams = useUnlockPdfFormsParameters();
|
||||
const unlockPdfFormsOperation = useUnlockPdfFormsOperation();
|
||||
|
||||
// Endpoint validation
|
||||
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(unlockPdfFormsParams.getEndpointName());
|
||||
|
||||
useEffect(() => {
|
||||
unlockPdfFormsOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
}, [unlockPdfFormsParams.parameters]);
|
||||
|
||||
const handleUnlock = async () => {
|
||||
try {
|
||||
await unlockPdfFormsOperation.executeOperation(unlockPdfFormsParams.parameters, selectedFiles);
|
||||
if (unlockPdfFormsOperation.files && onComplete) {
|
||||
onComplete(unlockPdfFormsOperation.files);
|
||||
}
|
||||
} catch (error) {
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error.message : t("unlockPDFForms.error.failed", "Unlock PDF forms operation failed"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleThumbnailClick = (file: File) => {
|
||||
onPreviewFile?.(file);
|
||||
sessionStorage.setItem("previousMode", "unlockPdfForms");
|
||||
actions.setMode("viewer");
|
||||
};
|
||||
|
||||
const handleSettingsReset = () => {
|
||||
unlockPdfFormsOperation.resetResults();
|
||||
onPreviewFile?.(null);
|
||||
};
|
||||
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
const hasResults = unlockPdfFormsOperation.files.length > 0 || unlockPdfFormsOperation.downloadUrl !== null;
|
||||
const base = useBaseTool(
|
||||
'unlockPdfForms',
|
||||
useUnlockPdfFormsParameters,
|
||||
useUnlockPdfFormsOperation,
|
||||
props
|
||||
);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasFiles || hasResults,
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: base.hasFiles || base.hasResults,
|
||||
placeholder: t("unlockPDFForms.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||
},
|
||||
steps: [],
|
||||
executeButton: {
|
||||
text: t("unlockPDFForms.submit", "Unlock Forms"),
|
||||
isVisible: !hasResults,
|
||||
isVisible: !base.hasResults,
|
||||
loadingText: t("loading"),
|
||||
onClick: handleUnlock,
|
||||
disabled: !unlockPdfFormsParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||
onClick: base.handleExecute,
|
||||
disabled: !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: unlockPdfFormsOperation,
|
||||
isVisible: base.hasResults,
|
||||
operation: base.operation,
|
||||
title: t("unlockPDFForms.results.title", "Unlocked Forms Results"),
|
||||
onFileClick: handleThumbnailClick,
|
||||
onFileClick: base.handleThumbnailClick,
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -80,4 +41,4 @@ const UnlockPdfForms = ({ onPreviewFile, onComplete, onError }: BaseToolProps) =
|
||||
// Static method to get the operation hook for automation
|
||||
UnlockPdfForms.tool = () => useUnlockPdfFormsOperation;
|
||||
|
||||
export default UnlockPdfForms as ToolComponent;
|
||||
export default UnlockPdfForms as ToolComponent;
|
||||
|
Loading…
x
Reference in New Issue
Block a user