Refactor steps to be dependent on mode

This commit is contained in:
James Brunton 2025-09-08 16:54:54 +01:00
parent bb96522326
commit 3a20238335
8 changed files with 134 additions and 241 deletions

View File

@ -1,103 +0,0 @@
import { Stack, Divider, Text, NumberInput, Group, ColorInput } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters";
import WordsToRedactInput from "./WordsToRedactInput";
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();
return (
<Stack gap="md">
<Divider ml='-md' />
{/* Words to Redact */}
<WordsToRedactInput
wordsToRedact={parameters.wordsToRedact}
onWordsChange={(words) => onParameterChange('wordsToRedact', words)}
disabled={disabled}
/>
<Divider />
{/* Redaction Settings */}
<Stack gap="sm">
<Text size="sm" fw={500}>
{t('redact.auto.settings', 'Redaction Settings')}
</Text>
{/* Box Color */}
<Stack gap="sm">
<Text size="sm">{t('redact.auto.colorLabel', 'Box Colour')}</Text>
<ColorInput
value={parameters.redactColor}
onChange={(value) => onParameterChange('redactColor', value)}
disabled={disabled}
size="sm"
/>
</Stack>
{/* Box Padding */}
<Stack gap="sm">
<Text size="sm">{t('redact.auto.paddingLabel', 'Box 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}
size="sm"
placeholder="0.1"
/>
</Stack>
{/* Use Regex */}
<label
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
>
<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>
{/* Whole Word Search */}
<label
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
>
<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>
{/* Convert PDF to PDF-Image */}
<label
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
>
<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;

View File

@ -1,32 +1,33 @@
import { Stack, Text, NumberInput, ColorInput } from '@mantine/core'; import { Stack, Text, NumberInput, ColorInput } from "@mantine/core";
import { useTranslation } from 'react-i18next'; import { useTranslation } from "react-i18next";
import { RedactParameters } from '../../../hooks/tools/redact/useRedactParameters'; import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters";
interface RedactAdvancedStepProps { interface RedactAdvancedSettingsProps {
parameters: RedactParameters; parameters: RedactParameters;
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void; onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
disabled?: boolean; disabled?: boolean;
} }
export default function RedactAdvancedStep({ parameters, onParameterChange, disabled }: RedactAdvancedStepProps) { const RedactAdvancedSettings = ({ parameters, onParameterChange, disabled = false }: RedactAdvancedSettingsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Stack gap="md"> <Stack gap="md">
{/* Box Color */} {/* Box Color */}
<Stack gap="sm"> <Stack gap="sm">
<Text size="sm" fw={500}>{t('redact.advanced.colorLabel', 'Box Color')}</Text> <Text size="sm" fw={500}>{t('redact.auto.colorLabel', 'Box Colour')}</Text>
<ColorInput <ColorInput
value={parameters.redactColor} value={parameters.redactColor}
onChange={(value) => onParameterChange('redactColor', value)} onChange={(value) => onParameterChange('redactColor', value)}
disabled={disabled} disabled={disabled}
size="sm" size="sm"
format="hex"
/> />
</Stack> </Stack>
{/* Box Padding */} {/* Box Padding */}
<Stack gap="sm"> <Stack gap="sm">
<Text size="sm" fw={500}>{t('redact.advanced.paddingLabel', 'Box Padding')}</Text> <Text size="sm" fw={500}>{t('redact.auto.paddingLabel', 'Box Padding')}</Text>
<NumberInput <NumberInput
value={parameters.customPadding} value={parameters.customPadding}
onChange={(value) => onParameterChange('customPadding', typeof value === 'number' ? value : 0.1)} onChange={(value) => onParameterChange('customPadding', typeof value === 'number' ? value : 0.1)}
@ -47,7 +48,7 @@ export default function RedactAdvancedStep({ parameters, onParameterChange, disa
onChange={(e) => onParameterChange('useRegex', e.target.checked)} onChange={(e) => onParameterChange('useRegex', e.target.checked)}
disabled={disabled} disabled={disabled}
/> />
<Text size="sm">{t('redact.advanced.useRegexLabel', 'Use Regex')}</Text> <Text size="sm">{t('redact.auto.useRegexLabel', 'Use Regex')}</Text>
</label> </label>
{/* Whole Word Search */} {/* Whole Word Search */}
@ -58,7 +59,7 @@ export default function RedactAdvancedStep({ parameters, onParameterChange, disa
onChange={(e) => onParameterChange('wholeWordSearch', e.target.checked)} onChange={(e) => onParameterChange('wholeWordSearch', e.target.checked)}
disabled={disabled} disabled={disabled}
/> />
<Text size="sm">{t('redact.advanced.wholeWordSearchLabel', 'Whole Word Search')}</Text> <Text size="sm">{t('redact.auto.wholeWordSearchLabel', 'Whole Word Search')}</Text>
</label> </label>
{/* Convert PDF to PDF-Image */} {/* Convert PDF to PDF-Image */}
@ -69,8 +70,10 @@ export default function RedactAdvancedStep({ parameters, onParameterChange, disa
onChange={(e) => onParameterChange('convertPDFToImage', e.target.checked)} onChange={(e) => onParameterChange('convertPDFToImage', e.target.checked)}
disabled={disabled} disabled={disabled}
/> />
<Text size="sm">{t('redact.advanced.convertPDFToImageLabel', 'Convert PDF to PDF-Image (Used to remove text behind the box)')}</Text> <Text size="sm">{t('redact.auto.convertPDFToImageLabel', 'Convert PDF to PDF-Image (Used to remove text behind the box)')}</Text>
</label> </label>
</Stack> </Stack>
); );
} };
export default RedactAdvancedSettings;

View File

@ -1,21 +0,0 @@
import { Stack } from '@mantine/core';
import { RedactParameters } from '../../../hooks/tools/redact/useRedactParameters';
import RedactModeSelector from './RedactModeSelector';
interface RedactModeStepProps {
parameters: RedactParameters;
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
disabled?: boolean;
}
export default function RedactModeStep({ parameters, onParameterChange, disabled }: RedactModeStepProps) {
return (
<Stack gap="md">
<RedactModeSelector
mode={parameters.mode}
onModeChange={(mode) => onParameterChange('mode', mode)}
disabled={disabled}
/>
</Stack>
);
}

View File

@ -1,38 +0,0 @@
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;

View File

@ -0,0 +1,61 @@
import { Stack, Divider } from "@mantine/core";
import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters";
import RedactModeSelector from "./RedactModeSelector";
import WordsToRedactInput from "./WordsToRedactInput";
import RedactAdvancedSettings from "./RedactAdvancedSettings";
interface RedactSingleStepSettingsProps {
parameters: RedactParameters;
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
disabled?: boolean;
}
const RedactSingleStepSettings = ({ parameters, onParameterChange, disabled = false }: RedactSingleStepSettingsProps) => {
return (
<Stack gap="md">
{/* Mode Selection */}
<RedactModeSelector
mode={parameters.mode}
onModeChange={(mode) => onParameterChange('mode', mode)}
disabled={disabled}
/>
{/* Automatic Mode Settings */}
{parameters.mode === 'automatic' && (
<>
<Divider />
{/* Words to Redact */}
<WordsToRedactInput
wordsToRedact={parameters.wordsToRedact}
onWordsChange={(words) => onParameterChange('wordsToRedact', words)}
disabled={disabled}
/>
<Divider />
{/* Advanced Settings */}
<RedactAdvancedSettings
parameters={parameters}
onParameterChange={onParameterChange}
disabled={disabled}
/>
</>
)}
{/* Manual Mode Placeholder */}
{parameters.mode === 'manual' && (
<>
<Divider />
<Stack gap="md">
<div style={{ padding: '20px', textAlign: 'center', color: '#666' }}>
Manual redaction interface will be available here when implemented.
</div>
</Stack>
</>
)}
</Stack>
);
};
export default RedactSingleStepSettings;

View File

@ -1,21 +0,0 @@
import { Stack } from '@mantine/core';
import { RedactParameters } from '../../../hooks/tools/redact/useRedactParameters';
import WordsToRedactInput from './WordsToRedactInput';
interface RedactWordsStepProps {
parameters: RedactParameters;
onParameterChange: <K extends keyof RedactParameters>(key: K, value: RedactParameters[K]) => void;
disabled?: boolean;
}
export default function RedactWordsStep({ parameters, onParameterChange, disabled }: RedactWordsStepProps) {
return (
<Stack gap="md">
<WordsToRedactInput
wordsToRedact={parameters.wordsToRedact}
onWordsChange={(words) => onParameterChange('wordsToRedact', words)}
disabled={disabled}
/>
</Stack>
);
}

View File

@ -45,7 +45,7 @@ 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 RedactSingleStepSettings from "../components/tools/redact/RedactSingleStepSettings";
import Redact from "../tools/Redact"; import Redact from "../tools/Redact";
import { ToolId } from "../types/toolId"; import { ToolId } from "../types/toolId";
@ -711,7 +711,7 @@ export function useFlatToolRegistry(): ToolRegistry {
maxFiles: -1, maxFiles: -1,
endpoints: ["auto-redact"], endpoints: ["auto-redact"],
operationConfig: redactOperationConfig, operationConfig: redactOperationConfig,
settingsComponent: RedactSettings, settingsComponent: RedactSingleStepSettings,
}, },
}; };

View File

@ -1,14 +1,14 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useState } from "react"; import { useState } from "react";
import { createToolFlow } from "../components/tools/shared/createToolFlow"; import { createToolFlow } from "../components/tools/shared/createToolFlow";
import RedactModeStep from "../components/tools/redact/RedactModeStep"; import RedactModeSelector from "../components/tools/redact/RedactModeSelector";
import RedactWordsStep from "../components/tools/redact/RedactWordsStep";
import RedactAdvancedStep from "../components/tools/redact/RedactAdvancedStep";
import { useRedactParameters } from "../hooks/tools/redact/useRedactParameters"; import { useRedactParameters } from "../hooks/tools/redact/useRedactParameters";
import { useRedactOperation } from "../hooks/tools/redact/useRedactOperation"; import { useRedactOperation } from "../hooks/tools/redact/useRedactOperation";
import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
import { BaseToolProps, ToolComponent } from "../types/tool"; import { BaseToolProps, ToolComponent } from "../types/tool";
import { useRedactModeTips, useRedactWordsTips, useRedactAdvancedTips } from "../components/tooltips/useRedactTips"; import { useRedactModeTips, useRedactWordsTips, useRedactAdvancedTips } from "../components/tooltips/useRedactTips";
import RedactAdvancedSettings from "../components/tools/redact/RedactAdvancedSettings";
import WordsToRedactInput from "../components/tools/redact/WordsToRedactInput";
const Redact = (props: BaseToolProps) => { const Redact = (props: BaseToolProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -39,7 +39,59 @@ const Redact = (props: BaseToolProps) => {
// Compute actual collapsed state based on results and user state // Compute actual collapsed state based on results and user state
const getActualCollapsedState = (userCollapsed: boolean) => { const getActualCollapsedState = (userCollapsed: boolean) => {
return base.hasResults ? true : userCollapsed; // Force collapse when results are shown return (!base.hasFiles || base.hasResults) ? true : userCollapsed; // Force collapse when results are shown
};
// Build conditional steps based on redaction mode
const buildSteps = () => {
const steps = [
// Method selection step (always present)
{
title: t("redact.steps.method", "Method"),
isCollapsed: getActualCollapsedState(methodCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setMethodCollapsed(!methodCollapsed),
tooltip: modeTips,
content: (
<RedactModeSelector
mode={base.params.parameters.mode}
onModeChange={(mode) => base.params.updateParameter('mode', mode)}
disabled={base.endpointLoading}
/>
),
}
];
// Add mode-specific steps
if (base.params.parameters.mode === 'automatic') {
steps.push(
{
title: t("redact.steps.words", "Words to Redact"),
isCollapsed: getActualCollapsedState(wordsCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setWordsCollapsed(!wordsCollapsed),
tooltip: wordsTips,
content: <WordsToRedactInput
wordsToRedact={base.params.parameters.wordsToRedact}
onWordsChange={(words) => base.params.updateParameter('wordsToRedact', words)}
disabled={base.endpointLoading}
/>,
},
{
title: t("redact.steps.advanced", "Advanced Settings"),
isCollapsed: getActualCollapsedState(advancedCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setAdvancedCollapsed(!advancedCollapsed),
tooltip: advancedTips,
content: <RedactAdvancedSettings
parameters={base.params.parameters}
onParameterChange={base.params.updateParameter}
disabled={base.endpointLoading}
/>,
},
);
} else if (base.params.parameters.mode === 'manual') {
// Manual mode steps would go here when implemented
}
return steps;
}; };
return createToolFlow({ return createToolFlow({
@ -47,47 +99,7 @@ const Redact = (props: BaseToolProps) => {
selectedFiles: base.selectedFiles, selectedFiles: base.selectedFiles,
isCollapsed: base.hasResults, isCollapsed: base.hasResults,
}, },
steps: [ steps: buildSteps(),
{
title: t("redact.steps.method", "Method"),
isCollapsed: getActualCollapsedState(methodCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setMethodCollapsed(!methodCollapsed),
tooltip: modeTips,
content: (
<RedactModeStep
parameters={base.params.parameters}
onParameterChange={base.params.updateParameter}
disabled={base.endpointLoading}
/>
),
},
{
title: t("redact.steps.words", "Words to Redact"),
isCollapsed: getActualCollapsedState(wordsCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setWordsCollapsed(!wordsCollapsed),
tooltip: wordsTips,
content: (
<RedactWordsStep
parameters={base.params.parameters}
onParameterChange={base.params.updateParameter}
disabled={base.endpointLoading}
/>
),
},
{
title: t("redact.steps.advanced", "Advanced Settings"),
isCollapsed: getActualCollapsedState(advancedCollapsed),
onCollapsedClick: () => base.settingsCollapsed ? base.handleSettingsReset() : setAdvancedCollapsed(!advancedCollapsed),
tooltip: advancedTips,
content: (
<RedactAdvancedStep
parameters={base.params.parameters}
onParameterChange={base.params.updateParameter}
disabled={base.endpointLoading}
/>
),
},
],
executeButton: { executeButton: {
text: t("redact.submit", "Redact"), text: t("redact.submit", "Redact"),
isVisible: !base.hasResults, isVisible: !base.hasResults,