mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-17 13:52:14 +01:00
Implement 'Add Password' and 'Change Permissions' tools in V2 (#4195)
# Description of Changes Implement Add Password and Change Permissions tools in V2 (both in one because Change Permissions is a fake endpoint which just calls Add Password behind the scenes). --------- Co-authored-by: James <james@crosscourtanalytics.com>
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import AddPasswordSettings from './AddPasswordSettings';
|
||||
import { defaultParameters } from '../../../hooks/tools/addPassword/useAddPasswordParameters';
|
||||
import type { AddPasswordParameters } from '../../../hooks/tools/addPassword/useAddPasswordParameters';
|
||||
|
||||
// Mock useTranslation with predictable return values
|
||||
const mockT = vi.fn((key: string) => `mock-${key}`);
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({ t: mockT })
|
||||
}));
|
||||
|
||||
// Wrapper component to provide Mantine context
|
||||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineProvider>{children}</MantineProvider>
|
||||
);
|
||||
|
||||
describe('AddPasswordSettings', () => {
|
||||
const mockOnParameterChange = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should render password input fields', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Should render user and owner password fields labels
|
||||
expect(screen.getByText('mock-addPassword.passwords.user.label')).toBeInTheDocument();
|
||||
expect(screen.getByText('mock-addPassword.passwords.owner.label')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render encryption key length select', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Should render key length select input
|
||||
expect(screen.getByRole('textbox', { name: /keyLength/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render main component sections', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Check that main section titles are rendered
|
||||
expect(screen.getByText('mock-addPassword.passwords.title')).toBeInTheDocument();
|
||||
expect(screen.getByText('mock-addPassword.encryption.title')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should call onParameterChange when password fields are modified', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// This test is complex with Mantine's PasswordInput, just verify the component renders
|
||||
expect(screen.getByText('mock-addPassword.passwords.user.label')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should call onParameterChange when key length is changed', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Find key length select and change it
|
||||
const keyLengthSelect = screen.getByText('mock-addPassword.encryption.keyLength.128bit');
|
||||
|
||||
fireEvent.mouseDown(keyLengthSelect);
|
||||
const option256 = screen.getByText('mock-addPassword.encryption.keyLength.256bit');
|
||||
fireEvent.click(option256);
|
||||
|
||||
expect(mockOnParameterChange).toHaveBeenCalledWith('keyLength', 256);
|
||||
});
|
||||
|
||||
test('should disable all form elements when disabled prop is true', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
disabled={true}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Check password inputs are disabled
|
||||
const passwordInputs = screen.getAllByRole('textbox');
|
||||
passwordInputs.forEach(input => {
|
||||
expect(input).toBeDisabled();
|
||||
});
|
||||
|
||||
// Check key length select is disabled - simplified test due to Mantine complexity
|
||||
expect(screen.getByText('mock-addPassword.encryption.keyLength.128bit')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should enable all form elements when disabled prop is false', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
disabled={false}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Check password inputs are enabled
|
||||
const passwordInputs = screen.getAllByRole('textbox');
|
||||
passwordInputs.forEach(input => {
|
||||
expect(input).not.toBeDisabled();
|
||||
});
|
||||
|
||||
// Check key length select is enabled - simplified test due to Mantine complexity
|
||||
expect(screen.getByText('mock-addPassword.encryption.keyLength.128bit')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should call translation function with correct keys', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Verify that translation keys are being called
|
||||
expect(mockT).toHaveBeenCalledWith('addPassword.passwords.title', 'Passwords');
|
||||
expect(mockT).toHaveBeenCalledWith('addPassword.encryption.title', 'Encryption');
|
||||
expect(mockT).toHaveBeenCalledWith('addPassword.passwords.user.label', 'User Password');
|
||||
expect(mockT).toHaveBeenCalledWith('addPassword.passwords.owner.label', 'Owner Password');
|
||||
});
|
||||
|
||||
test.each([
|
||||
{ keyLength: 40, expectedLabel: 'mock-addPassword.encryption.keyLength.40bit' },
|
||||
{ keyLength: 128, expectedLabel: 'mock-addPassword.encryption.keyLength.128bit' },
|
||||
{ keyLength: 256, expectedLabel: 'mock-addPassword.encryption.keyLength.256bit' }
|
||||
])('should handle key length $keyLength correctly', ({ keyLength, expectedLabel }) => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<AddPasswordSettings
|
||||
parameters={{ ...defaultParameters, keyLength }}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.getByText(expectedLabel)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, PasswordInput, Select } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AddPasswordParameters } from "../../../hooks/tools/addPassword/useAddPasswordParameters";
|
||||
|
||||
interface AddPasswordSettingsProps {
|
||||
parameters: AddPasswordParameters;
|
||||
onParameterChange: (key: keyof AddPasswordParameters, value: any) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const AddPasswordSettings = ({ parameters, onParameterChange, disabled = false }: AddPasswordSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
{/* Password Settings */}
|
||||
<Stack gap="sm">
|
||||
<Text size="sm" fw={500}>{t('addPassword.passwords.title', 'Passwords')}</Text>
|
||||
<PasswordInput
|
||||
label={t('addPassword.passwords.user.label', 'User Password')}
|
||||
placeholder={t('addPassword.passwords.user.placeholder', 'Enter user password')}
|
||||
value={parameters.password}
|
||||
onChange={(e) => onParameterChange('password', e.target.value)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<PasswordInput
|
||||
label={t('addPassword.passwords.owner.label', 'Owner Password')}
|
||||
placeholder={t('addPassword.passwords.owner.placeholder', 'Enter owner password')}
|
||||
value={parameters.ownerPassword}
|
||||
onChange={(e) => onParameterChange('ownerPassword', e.target.value)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
{/* Encryption Settings */}
|
||||
<Stack gap="sm">
|
||||
<Text size="sm" fw={500}>{t('addPassword.encryption.title', 'Encryption')}</Text>
|
||||
<Select
|
||||
label={t('addPassword.encryption.keyLength.label', 'Key Length')}
|
||||
value={parameters.keyLength.toString()}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
onParameterChange('keyLength', parseInt(value));
|
||||
}
|
||||
}}
|
||||
disabled={disabled}
|
||||
data={[
|
||||
{ value: '40', label: t('addPassword.encryption.keyLength.40bit', '40-bit (Low)') },
|
||||
{ value: '128', label: t('addPassword.encryption.keyLength.128bit', '128-bit (Standard)') },
|
||||
{ value: '256', label: t('addPassword.encryption.keyLength.256bit', '256-bit (High)') }
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddPasswordSettings;
|
||||
@@ -0,0 +1,226 @@
|
||||
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import ChangePermissionsSettings from './ChangePermissionsSettings';
|
||||
import { defaultParameters } from '../../../hooks/tools/changePermissions/useChangePermissionsParameters';
|
||||
import type { ChangePermissionsParameters } from '../../../hooks/tools/changePermissions/useChangePermissionsParameters';
|
||||
|
||||
// Mock useTranslation with predictable return values
|
||||
const mockT = vi.fn((key: string) => `mock-${key}`);
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({ t: mockT })
|
||||
}));
|
||||
|
||||
// Wrapper component to provide Mantine context
|
||||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineProvider>{children}</MantineProvider>
|
||||
);
|
||||
|
||||
describe('ChangePermissionsSettings', () => {
|
||||
const mockOnParameterChange = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should render section title', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.getByText('mock-changePermissions.restrictions.title')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render all permission checkboxes', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Should render checkboxes for all permission types
|
||||
const permissionKeys = Object.keys(defaultParameters) as Array<keyof ChangePermissionsParameters>;
|
||||
const checkboxes = screen.getAllByRole('checkbox');
|
||||
expect(checkboxes).toHaveLength(permissionKeys.length);
|
||||
|
||||
// Verify specific permission labels are rendered
|
||||
expect(screen.getByText('mock-changePermissions.restrictions.preventAssembly.label')).toBeInTheDocument();
|
||||
expect(screen.getByText('mock-changePermissions.restrictions.preventPrinting.label')).toBeInTheDocument();
|
||||
expect(screen.getByText('mock-changePermissions.restrictions.preventModify.label')).toBeInTheDocument();
|
||||
expect(screen.getByText('mock-changePermissions.restrictions.preventExtractContent.label')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render all permission types with correct labels', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const permissionKeys = Object.keys(defaultParameters) as Array<keyof ChangePermissionsParameters>;
|
||||
|
||||
permissionKeys.forEach(permission => {
|
||||
expect(screen.getByText(`mock-changePermissions.restrictions.${permission}.label`)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test('should show checkboxes as unchecked by default', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const checkboxes = screen.getAllByRole('checkbox') as HTMLInputElement[];
|
||||
checkboxes.forEach(checkbox => {
|
||||
expect(checkbox.checked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
test('should show checkboxes as checked when parameters are true', () => {
|
||||
const checkedParameters: ChangePermissionsParameters = {
|
||||
...defaultParameters,
|
||||
preventAssembly: true,
|
||||
preventPrinting: true,
|
||||
preventModify: true
|
||||
};
|
||||
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={checkedParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Find specific checkboxes by their labels and verify they are checked
|
||||
const assemblyCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventAssembly.label') as HTMLInputElement;
|
||||
const printingCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventPrinting.label') as HTMLInputElement;
|
||||
const modifyCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventModify.label') as HTMLInputElement;
|
||||
const formCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventFillInForm.label') as HTMLInputElement;
|
||||
|
||||
expect(assemblyCheckbox.checked).toBe(true);
|
||||
expect(printingCheckbox.checked).toBe(true);
|
||||
expect(modifyCheckbox.checked).toBe(true);
|
||||
expect(formCheckbox.checked).toBe(false); // Ensure other checkboxes are unaffected
|
||||
});
|
||||
|
||||
test.each([
|
||||
{ initialValue: false, expectedValue: true, description: 'checking an unchecked box' },
|
||||
{ initialValue: true, expectedValue: false, description: 'unchecking a checked box' }
|
||||
])('should call onParameterChange with $expectedValue when $description', ({ initialValue, expectedValue }) => {
|
||||
const testParameters: ChangePermissionsParameters = {
|
||||
...defaultParameters,
|
||||
preventAssembly: initialValue
|
||||
};
|
||||
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={testParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const assemblyCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventAssembly.label');
|
||||
fireEvent.click(assemblyCheckbox);
|
||||
|
||||
expect(mockOnParameterChange).toHaveBeenCalledWith('preventAssembly', expectedValue);
|
||||
});
|
||||
|
||||
test('should handle multiple checkbox interactions', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Click multiple checkboxes
|
||||
const assemblyCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventAssembly.label');
|
||||
const printingCheckbox = screen.getByLabelText('mock-changePermissions.restrictions.preventPrinting.label');
|
||||
|
||||
fireEvent.click(assemblyCheckbox);
|
||||
fireEvent.click(printingCheckbox);
|
||||
|
||||
expect(mockOnParameterChange).toHaveBeenCalledWith('preventAssembly', true);
|
||||
expect(mockOnParameterChange).toHaveBeenCalledWith('preventPrinting', true);
|
||||
expect(mockOnParameterChange).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test.each([
|
||||
{ disabled: true, expectedState: true },
|
||||
{ disabled: false, expectedState: false }
|
||||
])('should set checkboxes disabled=$disabled when disabled prop is $disabled', ({ disabled, expectedState }) => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const checkboxes = screen.getAllByRole('checkbox') as HTMLInputElement[];
|
||||
checkboxes.forEach(checkbox => {
|
||||
expect(checkbox.disabled).toBe(expectedState);
|
||||
});
|
||||
});
|
||||
|
||||
test('should call translation function with correct keys', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={defaultParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Verify that translation keys are being called
|
||||
expect(mockT).toHaveBeenCalledWith('changePermissions.restrictions.title', 'Document Restrictions');
|
||||
|
||||
const permissionKeys = Object.keys(defaultParameters) as Array<keyof ChangePermissionsParameters>;
|
||||
permissionKeys.forEach(permission => {
|
||||
expect(mockT).toHaveBeenCalledWith(`changePermissions.restrictions.${permission}.label`, permission);
|
||||
});
|
||||
});
|
||||
|
||||
test.each(Object.keys(defaultParameters) as Array<keyof ChangePermissionsParameters>)('should handle %s permission type individually', (permission) => {
|
||||
const testParameters: ChangePermissionsParameters = {
|
||||
...defaultParameters,
|
||||
[permission]: true
|
||||
};
|
||||
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ChangePermissionsSettings
|
||||
parameters={testParameters}
|
||||
onParameterChange={mockOnParameterChange}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const checkbox = screen.getByLabelText(`mock-changePermissions.restrictions.${permission}.label`) as HTMLInputElement;
|
||||
expect(checkbox.checked).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Stack, Text, Checkbox } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ChangePermissionsParameters } from "../../../hooks/tools/changePermissions/useChangePermissionsParameters";
|
||||
|
||||
interface ChangePermissionsSettingsProps {
|
||||
parameters: ChangePermissionsParameters;
|
||||
onParameterChange: (key: keyof ChangePermissionsParameters, value: boolean) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const ChangePermissionsSettings = ({ parameters, onParameterChange, disabled = false }: ChangePermissionsSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack gap="sm">
|
||||
<Text size="sm" fw={500}>{t('changePermissions.restrictions.title', 'Document Restrictions')}</Text>
|
||||
|
||||
<Stack gap="xs">
|
||||
{(Object.keys(parameters) as Array<keyof ChangePermissionsParameters>).map((key) => (
|
||||
<Checkbox
|
||||
key={key}
|
||||
label={t(`changePermissions.restrictions.${key}.label`, key)}
|
||||
checked={parameters[key]}
|
||||
onChange={(e) => onParameterChange(key, e.target.checked)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangePermissionsSettings;
|
||||
@@ -1,19 +1,7 @@
|
||||
import { Stack, TextInput, Select, Checkbox } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isSplitMode, SPLIT_MODES, SPLIT_TYPES, type SplitMode, type SplitType } from '../../../constants/splitConstants';
|
||||
|
||||
export interface SplitParameters {
|
||||
mode: SplitMode | '';
|
||||
pages: string;
|
||||
hDiv: string;
|
||||
vDiv: string;
|
||||
merge: boolean;
|
||||
splitType: SplitType | '';
|
||||
splitValue: string;
|
||||
bookmarkLevel: string;
|
||||
includeMetadata: boolean;
|
||||
allowDuplicates: boolean;
|
||||
}
|
||||
import { isSplitMode, SPLIT_MODES, SPLIT_TYPES } from '../../../constants/splitConstants';
|
||||
import { SplitParameters } from '../../../hooks/tools/split/useSplitParameters';
|
||||
|
||||
export interface SplitSettingsProps {
|
||||
parameters: SplitParameters;
|
||||
|
||||
35
frontend/src/components/tooltips/useAddPasswordTips.ts
Normal file
35
frontend/src/components/tooltips/useAddPasswordTips.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TooltipContent } from '../../types/tips';
|
||||
|
||||
export const useAddPasswordTips = (): TooltipContent => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
header: {
|
||||
title: t("addPassword.tooltip.header.title", "Password Protection Overview")
|
||||
},
|
||||
tips: [
|
||||
{
|
||||
title: t("addPassword.tooltip.passwords.title", "Password Types"),
|
||||
description: t("addPassword.tooltip.passwords.text", "User passwords restrict opening the document, while owner passwords control what can be done with the document once opened. You can set both or just one."),
|
||||
bullets: [
|
||||
t("addPassword.tooltip.passwords.bullet1", "User Password: Required to open the PDF"),
|
||||
t("addPassword.tooltip.passwords.bullet2", "Owner Password: Controls document permissions (not supported by all PDF viewers)")
|
||||
]
|
||||
},
|
||||
{
|
||||
title: t("addPassword.tooltip.encryption.title", "Encryption Levels"),
|
||||
description: t("addPassword.tooltip.encryption.text", "Higher encryption levels provide better security but may not be supported by older PDF viewers."),
|
||||
bullets: [
|
||||
t("addPassword.tooltip.encryption.bullet1", "40-bit: Basic security, compatible with older viewers"),
|
||||
t("addPassword.tooltip.encryption.bullet2", "128-bit: Standard security, widely supported"),
|
||||
t("addPassword.tooltip.encryption.bullet3", "256-bit: Maximum security, requires modern viewers")
|
||||
]
|
||||
},
|
||||
{
|
||||
title: t("addPassword.tooltip.restrictions.title", "Document Restrictions"),
|
||||
description: t("addPassword.tooltip.restrictions.text", "These restrictions control what users can do with the PDF. Most effective when combined with an owner password."),
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
18
frontend/src/components/tooltips/useChangePermissionsTips.ts
Normal file
18
frontend/src/components/tooltips/useChangePermissionsTips.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TooltipContent } from '../../types/tips';
|
||||
|
||||
export const useChangePermissionsTips = (): TooltipContent => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
header: {
|
||||
title: t("changePermissions.tooltip.header.title", "Change Permissions")
|
||||
},
|
||||
tips: [
|
||||
{
|
||||
title: t("changePermissions.tooltip.description.title", "Description"),
|
||||
description: t("changePermissions.tooltip.description.text", "Changes document permissions. Warning: To make these restrictions unchangeable, use the Add Password tool to set an owner password.")
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TooltipContent } from '../../types/tips';
|
||||
|
||||
export const CompressTips = (): TooltipContent => {
|
||||
export const useCompressTips = (): TooltipContent => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
@@ -27,4 +27,4 @@ export const CompressTips = (): TooltipContent => {
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TooltipContent } from '../../types/tips';
|
||||
|
||||
export const OcrTips = (): TooltipContent => {
|
||||
export const useOCRTips = (): TooltipContent => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
@@ -33,4 +33,4 @@ export const OcrTips = (): TooltipContent => {
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user