diff --git a/frontend/src/tools/AddPassword.tsx b/frontend/src/tools/AddPassword.tsx
index 773fb4d1c..667252680 100644
--- a/frontend/src/tools/AddPassword.tsx
+++ b/frontend/src/tools/AddPassword.tsx
@@ -1,16 +1,10 @@
-import { useEffect, useMemo, useState } from "react";
-import { Box, Button, Stack, Text } from "@mantine/core";
+import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
-import DownloadIcon from "@mui/icons-material/Download";
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
import { useFileContext } from "../contexts/FileContext";
import { useToolFileSelection } from "../contexts/FileSelectionContext";
-import ToolStep, { ToolStepContainer } from "../components/tools/shared/ToolStep";
-import OperationButton from "../components/tools/shared/OperationButton";
-import ErrorNotification from "../components/tools/shared/ErrorNotification";
-import FileStatusIndicator from "../components/tools/shared/FileStatusIndicator";
-import ResultsPreview from "../components/tools/shared/ResultsPreview";
+import { createToolFlow } from "../components/tools/shared/createToolFlow";
import AddPasswordSettings from "../components/tools/addPassword/AddPasswordSettings";
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
@@ -37,7 +31,7 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
useEffect(() => {
addPasswordOperation.resetResults();
onPreviewFile?.(null);
- }, [addPasswordParams.parameters, selectedFiles]);
+ }, [addPasswordParams.parameters]);
const handleAddPassword = async () => {
try {
@@ -69,121 +63,57 @@ const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const hasFiles = selectedFiles.length > 0;
const hasResults = addPasswordOperation.files.length > 0 || addPasswordOperation.downloadUrl !== null;
- const filesCollapsed = hasFiles;
- const passwordsCollapsed = hasResults;
+ const passwordsCollapsed = !hasFiles || hasResults;
const permissionsCollapsed = collapsedPermissions || hasResults;
- const previewResults = useMemo(() =>
- addPasswordOperation.files?.map((file, index) => ({
- file,
- thumbnail: addPasswordOperation.thumbnails[index]
- })) || [],
- [addPasswordOperation.files, addPasswordOperation.thumbnails]
- );
-
- return (
-
-
- {/* Files Step */}
-
-
-
-
- {/* Passwords & Encryption Step */}
-
+ return createToolFlow({
+ files: {
+ selectedFiles,
+ isCollapsed: hasFiles && !hasResults,
+ },
+ steps: [
+ {
+ title: t('addPassword.passwords.stepTitle', 'Passwords & Encryption'),
+ isVisible: hasFiles,
+ isCollapsed: passwordsCollapsed,
+ onCollapsedClick: hasResults ? handleSettingsReset : undefined,
+ tooltip: addPasswordTips,
+ content: (
-
-
- {/* Permissions Step */}
- setCollapsedPermissions(!collapsedPermissions)}
- >
+ )
+ },
+ {
+ title: t('addPassword.permissions.stepTitle', 'Document Permissions'),
+ isVisible: hasFiles,
+ isCollapsed: permissionsCollapsed,
+ onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedPermissions(!collapsedPermissions),
+ content: (
-
-
-
-
-
-
- {/* Results Step */}
-
-
- {addPasswordOperation.status && (
- {addPasswordOperation.status}
- )}
-
-
-
- {addPasswordOperation.downloadUrl && (
- }
- color="green"
- fullWidth
- mb="md"
- >
- {t("download", "Download")}
-
- )}
-
-
-
-
-
-
- );
+ )
+ }
+ ],
+ executeButton: {
+ text: t('addPassword.submit', 'Encrypt'),
+ isVisible: !hasResults,
+ loadingText: t('loading'),
+ onClick: handleAddPassword,
+ disabled: !addPasswordParams.validateParameters() || !hasFiles || !endpointEnabled
+ },
+ review: {
+ isVisible: hasResults,
+ operation: addPasswordOperation,
+ title: t('addPassword.results.title', 'Encrypted PDFs'),
+ onFileClick: handleThumbnailClick
+ }
+ });
}
export default AddPassword;
diff --git a/frontend/src/tools/ChangePermissions.tsx b/frontend/src/tools/ChangePermissions.tsx
index 58cb32474..19e3d859f 100644
--- a/frontend/src/tools/ChangePermissions.tsx
+++ b/frontend/src/tools/ChangePermissions.tsx
@@ -1,16 +1,10 @@
-import { useEffect, useMemo } from "react";
-import { Button, Stack, Text } from "@mantine/core";
+import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
-import DownloadIcon from "@mui/icons-material/Download";
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
import { useFileContext } from "../contexts/FileContext";
import { useToolFileSelection } from "../contexts/FileSelectionContext";
-import ToolStep, { ToolStepContainer } from "../components/tools/shared/ToolStep";
-import OperationButton from "../components/tools/shared/OperationButton";
-import ErrorNotification from "../components/tools/shared/ErrorNotification";
-import FileStatusIndicator from "../components/tools/shared/FileStatusIndicator";
-import ResultsPreview from "../components/tools/shared/ResultsPreview";
+import { createToolFlow } from "../components/tools/shared/createToolFlow";
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
@@ -34,7 +28,7 @@ const ChangePermissions = ({ onPreviewFile, onComplete, onError }: BaseToolProps
useEffect(() => {
changePermissionsOperation.resetResults();
onPreviewFile?.(null);
- }, [changePermissionsParams.parameters, selectedFiles]);
+ }, [changePermissionsParams.parameters]);
const handleChangePermissions = async () => {
try {
@@ -66,105 +60,40 @@ const ChangePermissions = ({ onPreviewFile, onComplete, onError }: BaseToolProps
const hasFiles = selectedFiles.length > 0;
const hasResults = changePermissionsOperation.files.length > 0 || changePermissionsOperation.downloadUrl !== null;
- const filesCollapsed = hasFiles;
- const settingsCollapsed = hasResults;
+ const settingsCollapsed = !hasFiles || hasResults;
- const previewResults = useMemo(() =>
- changePermissionsOperation.files?.map((file, index) => ({
- file,
- thumbnail: changePermissionsOperation.thumbnails[index]
- })) || [],
- [changePermissionsOperation.files, changePermissionsOperation.thumbnails]
- );
-
- return (
-
-
- {/* Files Step */}
-
-
-
-
- {/* Settings Step */}
-
-
-
-
-
-
-
-
- {/* Results Step */}
-
-
- {changePermissionsOperation.status && (
- {changePermissionsOperation.status}
- )}
-
-
-
- {changePermissionsOperation.downloadUrl && (
- }
- color="green"
- fullWidth
- mb="md"
- >
- {t("download", "Download")}
-
- )}
-
-
-
-
-
-
- );
+ return createToolFlow({
+ files: {
+ selectedFiles,
+ isCollapsed: hasFiles && !hasResults,
+ },
+ steps: [{
+ title: t('settings.title', 'Settings'),
+ isCollapsed: settingsCollapsed,
+ onCollapsedClick: settingsCollapsed ? handleSettingsReset : undefined,
+ tooltip: changePermissionsTips,
+ content: (
+
+ )
+ }],
+ executeButton: {
+ text: t('changePermissions.submit', 'Change Permissions'),
+ isVisible: !hasResults,
+ loadingText: t('loading'),
+ onClick: handleChangePermissions,
+ disabled: !changePermissionsParams.validateParameters() || !hasFiles || !endpointEnabled
+ },
+ review: {
+ isVisible: hasResults,
+ operation: changePermissionsOperation,
+ title: t('changePermissions.results.title', 'Modified PDFs'),
+ onFileClick: handleThumbnailClick
+ }
+ });
}
export default ChangePermissions;