mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-24 12:36:13 +00:00
Initial working version of Auto Redact
This commit is contained in:
parent
11d23a2d43
commit
1991cdbe07
@ -498,13 +498,9 @@
|
|||||||
"title": "Show Javascript",
|
"title": "Show Javascript",
|
||||||
"desc": "Searches and displays any JS injected into a PDF"
|
"desc": "Searches and displays any JS injected into a PDF"
|
||||||
},
|
},
|
||||||
"autoRedact": {
|
|
||||||
"title": "Auto Redact",
|
|
||||||
"desc": "Auto Redacts(Blacks out) text in a PDF based on input text"
|
|
||||||
},
|
|
||||||
"redact": {
|
"redact": {
|
||||||
"title": "Manual Redaction",
|
"title": "Redact",
|
||||||
"desc": "Redacts a PDF based on selected text, drawn shapes and/or selected page(s)"
|
"desc": "Redacts (blacks out) a PDF based on selected text, drawn shapes and/or selected page(s)"
|
||||||
},
|
},
|
||||||
"overlay-pdfs": {
|
"overlay-pdfs": {
|
||||||
"title": "Overlay PDFs",
|
"title": "Overlay PDFs",
|
||||||
@ -1583,50 +1579,60 @@
|
|||||||
"downloadJS": "Download Javascript",
|
"downloadJS": "Download Javascript",
|
||||||
"submit": "Show"
|
"submit": "Show"
|
||||||
},
|
},
|
||||||
"autoRedact": {
|
|
||||||
"tags": "Redact,Hide,black out,black,marker,hidden",
|
|
||||||
"title": "Auto Redact",
|
|
||||||
"header": "Auto Redact",
|
|
||||||
"colorLabel": "Colour",
|
|
||||||
"textsToRedactLabel": "Text to Redact (line-separated)",
|
|
||||||
"textsToRedactPlaceholder": "e.g. \\nConfidential \\nTop-Secret",
|
|
||||||
"useRegexLabel": "Use Regex",
|
|
||||||
"wholeWordSearchLabel": "Whole Word Search",
|
|
||||||
"customPaddingLabel": "Custom Extra Padding",
|
|
||||||
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)",
|
|
||||||
"submitButton": "Submit"
|
|
||||||
},
|
|
||||||
"redact": {
|
"redact": {
|
||||||
"tags": "Redact,Hide,black out,black,marker,hidden,manual",
|
"tags": "Redact,Hide,black out,black,marker,hidden,auto redact,manual redact",
|
||||||
"title": "Manual Redaction",
|
"title": "Redact",
|
||||||
"header": "Manual Redaction",
|
|
||||||
"submit": "Redact",
|
"submit": "Redact",
|
||||||
"textBasedRedaction": "Text based Redaction",
|
"error": {
|
||||||
"pageBasedRedaction": "Page-based Redaction",
|
"failed": "An error occurred while redacting the PDF."
|
||||||
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)",
|
|
||||||
"pageRedactionNumbers": {
|
|
||||||
"title": "Pages",
|
|
||||||
"placeholder": "(e.g. 1,2,8 or 4,7,12-16 or 2n-1)"
|
|
||||||
},
|
},
|
||||||
"redactionColor": {
|
"modeSelector": {
|
||||||
"title": "Redaction Color"
|
"title": "Redaction Mode",
|
||||||
|
"automatic": "Automatic",
|
||||||
|
"automaticDesc": "Redact text based on search terms",
|
||||||
|
"manual": "Manual",
|
||||||
|
"manualDesc": "Click and drag to redact specific areas",
|
||||||
|
"manualComingSoon": "Manual redaction coming soon"
|
||||||
},
|
},
|
||||||
"export": "Export",
|
"auto": {
|
||||||
"upload": "Upload",
|
"header": "Auto Redact",
|
||||||
"boxRedaction": "Box draw redaction",
|
"colorLabel": "Colour",
|
||||||
"zoom": "Zoom",
|
"textsToRedactLabel": "Text to Redact (line-separated)",
|
||||||
"zoomIn": "Zoom in",
|
"textsToRedactPlaceholder": "e.g. \nConfidential \nTop-Secret",
|
||||||
"zoomOut": "Zoom out",
|
"useRegexLabel": "Use Regex",
|
||||||
"nextPage": "Next Page",
|
"wholeWordSearchLabel": "Whole Word Search",
|
||||||
"previousPage": "Previous Page",
|
"customPaddingLabel": "Custom Extra Padding",
|
||||||
"toggleSidebar": "Toggle Sidebar",
|
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)"
|
||||||
"showThumbnails": "Show Thumbnails",
|
},
|
||||||
"showDocumentOutline": "Show Document Outline (double-click to expand/collapse all items)",
|
"manual": {
|
||||||
"showAttatchments": "Show Attachments",
|
"header": "Manual Redaction",
|
||||||
"showLayers": "Show Layers (double-click to reset all layers to the default state)",
|
"textBasedRedaction": "Text based Redaction",
|
||||||
"colourPicker": "Colour Picker",
|
"pageBasedRedaction": "Page-based Redaction",
|
||||||
"findCurrentOutlineItem": "Find current outline item",
|
"convertPDFToImageLabel": "Convert PDF to PDF-Image (Used to remove text behind the box)",
|
||||||
"applyChanges": "Apply Changes"
|
"pageRedactionNumbers": {
|
||||||
|
"title": "Pages",
|
||||||
|
"placeholder": "(e.g. 1,2,8 or 4,7,12-16 or 2n-1)"
|
||||||
|
},
|
||||||
|
"redactionColor": {
|
||||||
|
"title": "Redaction Color"
|
||||||
|
},
|
||||||
|
"export": "Export",
|
||||||
|
"upload": "Upload",
|
||||||
|
"boxRedaction": "Box draw redaction",
|
||||||
|
"zoom": "Zoom",
|
||||||
|
"zoomIn": "Zoom in",
|
||||||
|
"zoomOut": "Zoom out",
|
||||||
|
"nextPage": "Next Page",
|
||||||
|
"previousPage": "Previous Page",
|
||||||
|
"toggleSidebar": "Toggle Sidebar",
|
||||||
|
"showThumbnails": "Show Thumbnails",
|
||||||
|
"showDocumentOutline": "Show Document Outline (double-click to expand/collapse all items)",
|
||||||
|
"showAttatchments": "Show Attachments",
|
||||||
|
"showLayers": "Show Layers (double-click to reset all layers to the default state)",
|
||||||
|
"colourPicker": "Colour Picker",
|
||||||
|
"findCurrentOutlineItem": "Find current outline item",
|
||||||
|
"applyChanges": "Apply Changes"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"tableExtraxt": {
|
"tableExtraxt": {
|
||||||
"tags": "CSV,Table Extraction,extract,convert"
|
"tags": "CSV,Table Extraction,extract,convert"
|
||||||
|
129
frontend/src/components/tools/redact/AutomaticRedactSettings.tsx
Normal file
129
frontend/src/components/tools/redact/AutomaticRedactSettings.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { Stack, Text, Textarea, Select, NumberInput, Divider } from "@mantine/core";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters";
|
||||||
|
|
||||||
|
interface AutomaticRedactSettingsProps {
|
||||||
|
parameters: RedactParameters;
|
||||||
|
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AutomaticRedactSettings = ({ parameters, onParameterChange, disabled = false }: AutomaticRedactSettingsProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const colorOptions = [
|
||||||
|
{ value: '#000000', label: t('black', 'Black') },
|
||||||
|
{ value: '#FFFFFF', label: t('white', 'White') },
|
||||||
|
{ value: '#FF0000', label: t('red', 'Red') },
|
||||||
|
{ value: '#00FF00', label: t('green', 'Green') },
|
||||||
|
{ value: '#0000FF', label: t('blue', 'Blue') },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack gap="md">
|
||||||
|
<Divider ml='-md' />
|
||||||
|
|
||||||
|
{/* Text to Redact */}
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm" fw={500}>
|
||||||
|
{t('redact.auto.textsToRedactLabel', 'Text to Redact (line-separated)')}
|
||||||
|
</Text>
|
||||||
|
<Textarea
|
||||||
|
placeholder={t('redact.auto.textsToRedactPlaceholder', 'e.g. \nConfidential \nTop-Secret')}
|
||||||
|
value={parameters.listOfText}
|
||||||
|
onChange={(e) => onParameterChange('listOfText', e.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
|
rows={4}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{/* Redaction Color */}
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm" fw={500}>
|
||||||
|
{t('redact.auto.colorLabel', 'Color')}
|
||||||
|
</Text>
|
||||||
|
<Select
|
||||||
|
value={parameters.redactColor}
|
||||||
|
onChange={(value) => {
|
||||||
|
if (value) {
|
||||||
|
onParameterChange('redactColor', value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={disabled}
|
||||||
|
data={colorOptions}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{/* Search Options */}
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm" fw={500}>Search Options</Text>
|
||||||
|
|
||||||
|
<label
|
||||||
|
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
|
||||||
|
title="Use regular expressions for pattern matching"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={parameters.useRegex}
|
||||||
|
onChange={(e) => onParameterChange('useRegex', e.target.checked)}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<Text size="sm">{t('redact.auto.useRegexLabel', 'Use Regex')}</Text>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label
|
||||||
|
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
|
||||||
|
title="Match whole words only, not partial matches within words"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={parameters.wholeWordSearch}
|
||||||
|
onChange={(e) => onParameterChange('wholeWordSearch', e.target.checked)}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<Text size="sm">{t('redact.auto.wholeWordSearchLabel', 'Whole Word Search')}</Text>
|
||||||
|
</label>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{/* Advanced Options */}
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm" fw={500}>Advanced Options</Text>
|
||||||
|
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm">{t('redact.auto.customPaddingLabel', 'Custom Extra Padding')}</Text>
|
||||||
|
<NumberInput
|
||||||
|
value={parameters.customPadding}
|
||||||
|
onChange={(value) => onParameterChange('customPadding', typeof value === 'number' ? value : 0.1)}
|
||||||
|
min={0}
|
||||||
|
max={10}
|
||||||
|
step={0.1}
|
||||||
|
disabled={disabled}
|
||||||
|
placeholder="0.1"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<label
|
||||||
|
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
|
||||||
|
title="Convert PDF to PDF-Image to remove text behind the redaction box"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={parameters.convertPDFToImage}
|
||||||
|
onChange={(e) => onParameterChange('convertPDFToImage', e.target.checked)}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<Text size="sm">{t('redact.auto.convertPDFToImageLabel', 'Convert PDF to PDF-Image (Used to remove text behind the box)')}</Text>
|
||||||
|
</label>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AutomaticRedactSettings;
|
50
frontend/src/components/tools/redact/RedactModeSelector.tsx
Normal file
50
frontend/src/components/tools/redact/RedactModeSelector.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Radio, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
|
import { RedactMode } from '../../../hooks/tools/redact/useRedactParameters';
|
||||||
|
|
||||||
|
interface RedactModeSelectorProps {
|
||||||
|
mode: RedactMode;
|
||||||
|
onModeChange: (mode: RedactMode) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RedactModeSelector({ mode, onModeChange, disabled }: RedactModeSelectorProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text size="sm" fw={600}>
|
||||||
|
{t('redact.modeSelector.title', 'Redaction Mode')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Radio.Group
|
||||||
|
value={mode}
|
||||||
|
onChange={(value) => onModeChange(value as RedactMode)}
|
||||||
|
>
|
||||||
|
<Stack gap="xs">
|
||||||
|
<Radio
|
||||||
|
value="automatic"
|
||||||
|
label={t('redact.modeSelector.automatic', 'Automatic')}
|
||||||
|
description={t('redact.modeSelector.automaticDesc', 'Redact text based on search terms')}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tooltip
|
||||||
|
label={t('redact.modeSelector.manualComingSoon', 'Manual redaction coming soon')}
|
||||||
|
position="right"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<Radio
|
||||||
|
value="manual"
|
||||||
|
label={t('redact.modeSelector.manual', 'Manual')}
|
||||||
|
description={t('redact.modeSelector.manualDesc', 'Click and drag to redact specific areas')}
|
||||||
|
disabled={true}
|
||||||
|
style={{ opacity: 0.5 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Radio.Group>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
38
frontend/src/components/tools/redact/RedactSettings.tsx
Normal file
38
frontend/src/components/tools/redact/RedactSettings.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { Stack } from "@mantine/core";
|
||||||
|
import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters";
|
||||||
|
import RedactModeSelector from "./RedactModeSelector";
|
||||||
|
import AutomaticRedactSettings from "./AutomaticRedactSettings";
|
||||||
|
|
||||||
|
interface RedactSettingsProps {
|
||||||
|
parameters: RedactParameters;
|
||||||
|
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RedactSettings = ({ parameters, onParameterChange, disabled = false }: RedactSettingsProps) => {
|
||||||
|
return (
|
||||||
|
<Stack gap="md">
|
||||||
|
<RedactModeSelector
|
||||||
|
mode={parameters.mode}
|
||||||
|
onModeChange={(mode) => onParameterChange('mode', mode)}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{parameters.mode === 'automatic' && (
|
||||||
|
<AutomaticRedactSettings
|
||||||
|
parameters={parameters}
|
||||||
|
onParameterChange={onParameterChange}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{parameters.mode === 'manual' && (
|
||||||
|
<div style={{ padding: '20px', textAlign: 'center', color: '#666' }}>
|
||||||
|
Manual redaction interface will be available here when implemented.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RedactSettings;
|
@ -32,6 +32,7 @@ import { removeCertificateSignOperationConfig } from "../hooks/tools/removeCerti
|
|||||||
import { changePermissionsOperationConfig } from "../hooks/tools/changePermissions/useChangePermissionsOperation";
|
import { changePermissionsOperationConfig } from "../hooks/tools/changePermissions/useChangePermissionsOperation";
|
||||||
import { autoRenameOperationConfig } from "../hooks/tools/autoRename/useAutoRenameOperation";
|
import { autoRenameOperationConfig } from "../hooks/tools/autoRename/useAutoRenameOperation";
|
||||||
import { flattenOperationConfig } from "../hooks/tools/flatten/useFlattenOperation";
|
import { flattenOperationConfig } from "../hooks/tools/flatten/useFlattenOperation";
|
||||||
|
import { redactOperationConfig } from "../hooks/tools/redact/useRedactOperation";
|
||||||
import CompressSettings from "../components/tools/compress/CompressSettings";
|
import CompressSettings from "../components/tools/compress/CompressSettings";
|
||||||
import SplitSettings from "../components/tools/split/SplitSettings";
|
import SplitSettings from "../components/tools/split/SplitSettings";
|
||||||
import AddPasswordSettings from "../components/tools/addPassword/AddPasswordSettings";
|
import AddPasswordSettings from "../components/tools/addPassword/AddPasswordSettings";
|
||||||
@ -44,6 +45,8 @@ import OCRSettings from "../components/tools/ocr/OCRSettings";
|
|||||||
import ConvertSettings from "../components/tools/convert/ConvertSettings";
|
import ConvertSettings from "../components/tools/convert/ConvertSettings";
|
||||||
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
|
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
|
||||||
import FlattenSettings from "../components/tools/flatten/FlattenSettings";
|
import FlattenSettings from "../components/tools/flatten/FlattenSettings";
|
||||||
|
import RedactSettings from "../components/tools/redact/RedactSettings";
|
||||||
|
import Redact from "../tools/Redact";
|
||||||
import { ToolId } from "../types/toolId";
|
import { ToolId } from "../types/toolId";
|
||||||
|
|
||||||
const showPlaceholderTools = true; // Show all tools; grey out unavailable ones in UI
|
const showPlaceholderTools = true; // Show all tools; grey out unavailable ones in UI
|
||||||
@ -701,10 +704,14 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
redact: {
|
redact: {
|
||||||
icon: <LocalIcon icon="visibility-off-rounded" width="1.5rem" height="1.5rem" />,
|
icon: <LocalIcon icon="visibility-off-rounded" width="1.5rem" height="1.5rem" />,
|
||||||
name: t("home.redact.title", "Redact"),
|
name: t("home.redact.title", "Redact"),
|
||||||
component: null,
|
component: Redact,
|
||||||
description: t("home.redact.desc", "Permanently remove sensitive information from PDF documents"),
|
description: t("home.redact.desc", "Permanently remove sensitive information from PDF documents"),
|
||||||
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategoryId: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
|
maxFiles: -1,
|
||||||
|
endpoints: ["auto-redact"],
|
||||||
|
operationConfig: redactOperationConfig,
|
||||||
|
settingsComponent: RedactSettings,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
50
frontend/src/hooks/tools/redact/useRedactOperation.ts
Normal file
50
frontend/src/hooks/tools/redact/useRedactOperation.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useToolOperation, ToolType } from '../shared/useToolOperation';
|
||||||
|
import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
|
||||||
|
import { RedactParameters, defaultParameters } from './useRedactParameters';
|
||||||
|
|
||||||
|
// Static configuration that can be used by both the hook and automation executor
|
||||||
|
export const buildRedactFormData = (parameters: RedactParameters, file: File): FormData => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("fileInput", file);
|
||||||
|
|
||||||
|
if (parameters.mode === 'automatic') {
|
||||||
|
formData.append("listOfText", parameters.listOfText);
|
||||||
|
formData.append("useRegex", parameters.useRegex.toString());
|
||||||
|
formData.append("wholeWordSearch", parameters.wholeWordSearch.toString());
|
||||||
|
formData.append("redactColor", parameters.redactColor.replace('#', ''));
|
||||||
|
formData.append("customPadding", parameters.customPadding.toString());
|
||||||
|
formData.append("convertPDFToImage", parameters.convertPDFToImage.toString());
|
||||||
|
} else {
|
||||||
|
// Manual mode parameters would go here when implemented
|
||||||
|
throw new Error('Manual redaction not yet implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static configuration object
|
||||||
|
export const redactOperationConfig = {
|
||||||
|
toolType: ToolType.singleFile,
|
||||||
|
buildFormData: buildRedactFormData,
|
||||||
|
operationType: 'redact',
|
||||||
|
endpoint: (parameters: RedactParameters) => {
|
||||||
|
if (parameters.mode === 'automatic') {
|
||||||
|
return '/api/v1/security/auto-redact';
|
||||||
|
} else {
|
||||||
|
// Manual redaction endpoint would go here when implemented
|
||||||
|
throw new Error('Manual redaction not yet implemented');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filePrefix: 'redacted_',
|
||||||
|
defaultParameters,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const useRedactOperation = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return useToolOperation<RedactParameters>({
|
||||||
|
...redactOperationConfig,
|
||||||
|
getErrorMessage: createStandardErrorHandler(t('redact.error.failed', 'An error occurred while redacting the PDF.'))
|
||||||
|
});
|
||||||
|
};
|
45
frontend/src/hooks/tools/redact/useRedactParameters.ts
Normal file
45
frontend/src/hooks/tools/redact/useRedactParameters.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters';
|
||||||
|
|
||||||
|
export type RedactMode = 'automatic' | 'manual';
|
||||||
|
|
||||||
|
export interface RedactParameters {
|
||||||
|
mode: RedactMode;
|
||||||
|
|
||||||
|
// Automatic redaction parameters
|
||||||
|
listOfText: string;
|
||||||
|
useRegex: boolean;
|
||||||
|
wholeWordSearch: boolean;
|
||||||
|
redactColor: string;
|
||||||
|
customPadding: number;
|
||||||
|
convertPDFToImage: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultParameters: RedactParameters = {
|
||||||
|
mode: 'automatic',
|
||||||
|
listOfText: '',
|
||||||
|
useRegex: false,
|
||||||
|
wholeWordSearch: false,
|
||||||
|
redactColor: '#000000',
|
||||||
|
customPadding: 0.1,
|
||||||
|
convertPDFToImage: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRedactParameters = (): BaseParametersHook<RedactParameters> => {
|
||||||
|
return useBaseParameters<RedactParameters>({
|
||||||
|
defaultParameters,
|
||||||
|
endpointName: (params) => {
|
||||||
|
if (params.mode === 'automatic') {
|
||||||
|
return '/api/v1/security/auto-redact';
|
||||||
|
}
|
||||||
|
// Manual redaction endpoint would go here when implemented
|
||||||
|
throw new Error('Manual redaction not yet implemented');
|
||||||
|
},
|
||||||
|
validateFn: (params) => {
|
||||||
|
if (params.mode === 'automatic') {
|
||||||
|
return params.listOfText.trim().length > 0;
|
||||||
|
}
|
||||||
|
// Manual mode validation would go here when implemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
62
frontend/src/tools/Redact.tsx
Normal file
62
frontend/src/tools/Redact.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||||
|
import RedactSettings from "../components/tools/redact/RedactSettings";
|
||||||
|
import { useRedactParameters } from "../hooks/tools/redact/useRedactParameters";
|
||||||
|
import { useRedactOperation } from "../hooks/tools/redact/useRedactOperation";
|
||||||
|
import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
|
||||||
|
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||||
|
|
||||||
|
const Redact = (props: BaseToolProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const base = useBaseTool(
|
||||||
|
'redact',
|
||||||
|
useRedactParameters,
|
||||||
|
useRedactOperation,
|
||||||
|
props
|
||||||
|
);
|
||||||
|
|
||||||
|
const isExecuteDisabled = () => {
|
||||||
|
if (base.params.parameters.mode === 'manual') {
|
||||||
|
return true; // Manual mode not implemented yet
|
||||||
|
}
|
||||||
|
return !base.params.validateParameters() || !base.hasFiles || !base.endpointEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
return createToolFlow({
|
||||||
|
files: {
|
||||||
|
selectedFiles: base.selectedFiles,
|
||||||
|
isCollapsed: base.hasResults,
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
title: "Settings",
|
||||||
|
isCollapsed: base.settingsCollapsed,
|
||||||
|
onCollapsedClick: base.settingsCollapsed ? base.handleSettingsReset : undefined,
|
||||||
|
content: (
|
||||||
|
<RedactSettings
|
||||||
|
parameters={base.params.parameters}
|
||||||
|
onParameterChange={base.params.updateParameter}
|
||||||
|
disabled={base.endpointLoading}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
executeButton: {
|
||||||
|
text: t("redact.submit", "Redact"),
|
||||||
|
isVisible: !base.hasResults,
|
||||||
|
loadingText: t("loading"),
|
||||||
|
onClick: base.handleExecute,
|
||||||
|
disabled: isExecuteDisabled(),
|
||||||
|
},
|
||||||
|
review: {
|
||||||
|
isVisible: base.hasResults,
|
||||||
|
operation: base.operation,
|
||||||
|
title: t("redact.title", "Redaction Results"),
|
||||||
|
onFileClick: base.handleThumbnailClick,
|
||||||
|
onUndo: base.handleUndo,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Redact as ToolComponent;
|
Loading…
x
Reference in New Issue
Block a user