diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 6f993ba30..8d2456fb3 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -1081,13 +1081,6 @@ "changeMetadata": { "tags": "Title,author,date,creation,time,publisher,producer,stats", "header": "Change Metadata", - "selectText": { - "1": "Please edit the variables you wish to change", - "2": "Delete all metadata", - "3": "Show Custom Metadata:", - "4": "Other Metadata:", - "5": "Add Custom Metadata Entry" - }, "submit": "Change", "filenamePrefix": "metadata", "settings": { @@ -1125,16 +1118,15 @@ "placeholder": "Document producer" }, "dates": { - "title": "Document Dates", - "format": "Format: yyyy/MM/dd HH:mm:ss" + "title": "Document Dates" }, "creationDate": { "label": "Creation Date", - "placeholder": "e.g. 2025/01/17 14:30:00" + "placeholder": "Creation date" }, "modificationDate": { "label": "Modification Date", - "placeholder": "e.g. 2025/01/17 14:30:00" + "placeholder": "Modification date" }, "trapped": { "label": "Trapped Status", @@ -1179,8 +1171,7 @@ "title": "Date Fields", "text": "When the document was created and modified.", "bullet1": "Creation Date: When original document was made", - "bullet2": "Modification Date: When last changed", - "bullet3": "Format: yyyy/MM/dd HH:mm:ss (e.g., 2025/01/17 14:30:00)" + "bullet2": "Modification Date: When last changed" }, "options": { "title": "Additional Options", diff --git a/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx b/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx index 1cbd1e31c..e46e7799d 100644 --- a/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx +++ b/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx @@ -1,4 +1,4 @@ -import { Stack, Text } from "@mantine/core"; +import { Stack } from "@mantine/core"; import { DateTimePicker } from "@mantine/dates"; import { useTranslation } from "react-i18next"; import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; @@ -16,43 +16,22 @@ const DocumentDatesStep = ({ }: DocumentDatesStepProps) => { const { t } = useTranslation(); - const parseDate = (dateString: string): Date | null => { - if (!dateString) return null; - const date = new Date(dateString.replace(/(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2})/, '$1-$2-$3T$4:$5:$6')); - return isNaN(date.getTime()) ? null : date; - }; - - const formatDate = (date: Date | null): string => { - if (!date) return ''; - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; - }; - return ( - - {t('changeMetadata.dates.format', 'Format: yyyy/MM/dd HH:mm:ss')} - - onParameterChange('creationDate', formatDate(parseDate(date)))} + placeholder={t('changeMetadata.creationDate.placeholder', 'Creation date')} + value={parameters.creationDate} + onChange={(date) => onParameterChange('creationDate', date ? new Date(date) : null)} disabled={disabled} clearable /> onParameterChange('modificationDate', formatDate(parseDate(date)))} + placeholder={t('changeMetadata.modificationDate.placeholder', 'Modification date')} + value={parameters.modificationDate} + onChange={(date) => onParameterChange('modificationDate', date ? new Date(date) : null)} disabled={disabled} clearable /> diff --git a/frontend/src/components/tooltips/useChangeMetadataTips.ts b/frontend/src/components/tooltips/useChangeMetadataTips.ts index c5366063e..b7357e0ae 100644 --- a/frontend/src/components/tooltips/useChangeMetadataTips.ts +++ b/frontend/src/components/tooltips/useChangeMetadataTips.ts @@ -54,7 +54,6 @@ export const useDocumentDatesTips = (): TooltipContent => { bullets: [ t("changeMetadata.tooltip.dates.bullet1", "Creation Date: When original document was made"), t("changeMetadata.tooltip.dates.bullet2", "Modification Date: When last changed"), - t("changeMetadata.tooltip.dates.bullet3", "Format: yyyy/MM/dd HH:mm:ss (e.g., 2025/01/17 14:30:00)") ] } ] diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts index ed883f94a..8836189ac 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts +++ b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts @@ -13,8 +13,8 @@ describe('buildChangeMetadataFormData', () => { keywords: '', creator: '', producer: '', - creationDate: '', - modificationDate: '', + creationDate: null, + modificationDate: null, trapped: TrappedStatus.UNKNOWN, customMetadata: [], deleteAll: false, @@ -62,8 +62,8 @@ describe('buildChangeMetadataFormData', () => { keywords: 'test, keywords', creator: 'Test Creator', producer: 'Test Producer', - creationDate: '2025/01/17 14:30:00', - modificationDate: '2025/01/17 15:30:00', + creationDate: new Date('2025/01/17 14:30:00'), + modificationDate: new Date('2025/01/17 15:30:00'), trapped: TrappedStatus.TRUE, }, expectedFormData: { diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts index b0032f671..61c7d2228 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts +++ b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts @@ -3,6 +3,18 @@ import { useToolOperation, ToolType } from '../shared/useToolOperation'; import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; import { ChangeMetadataParameters, defaultParameters } from './useChangeMetadataParameters'; +// Helper function to format Date object to string +const formatDateForBackend = (date: Date | null): string => { + if (!date) return ''; + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; +}; + // Static function that can be used by both the hook and automation executor export const buildChangeMetadataFormData = (parameters: ChangeMetadataParameters, file: File): FormData => { const formData = new FormData(); @@ -16,9 +28,9 @@ export const buildChangeMetadataFormData = (parameters: ChangeMetadataParameters formData.append("creator", parameters.creator || ""); formData.append("producer", parameters.producer || ""); - // Date fields - formData.append("creationDate", parameters.creationDate || ""); - formData.append("modificationDate", parameters.modificationDate || ""); + // Date fields - convert Date objects to strings + formData.append("creationDate", formatDateForBackend(parameters.creationDate)); + formData.append("modificationDate", formatDateForBackend(parameters.modificationDate)); // Trapped status formData.append("trapped", parameters.trapped || ""); diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts index 4b95b3256..fb27ef7a5 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts +++ b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts @@ -1,5 +1,5 @@ import { renderHook, act } from '@testing-library/react'; -import { useChangeMetadataParameters } from './useChangeMetadataParameters'; +import { defaultParameters, useChangeMetadataParameters } from './useChangeMetadataParameters'; import { TrappedStatus } from '../../../types/metadata'; import { describe, expect, test } from 'vitest'; @@ -7,19 +7,7 @@ describe('useChangeMetadataParameters', () => { test('should initialize with default parameters', () => { const { result } = renderHook(() => useChangeMetadataParameters()); - expect(result.current.parameters).toEqual({ - title: '', - author: '', - subject: '', - keywords: '', - creator: '', - producer: '', - creationDate: '', - modificationDate: '', - trapped: TrappedStatus.UNKNOWN, - customMetadata: [], - deleteAll: false, - }); + expect(result.current.parameters).toStrictEqual(defaultParameters); }); describe('parameter updates', () => { @@ -30,8 +18,8 @@ describe('useChangeMetadataParameters', () => { { paramName: 'keywords', value: 'test, metadata' }, { paramName: 'creator', value: 'Test Creator' }, { paramName: 'producer', value: 'Test Producer' }, - { paramName: 'creationDate', value: '2025/01/17 14:30:00' }, - { paramName: 'modificationDate', value: '2025/01/17 15:30:00' }, + { paramName: 'creationDate', value: new Date('2025/01/17 14:30:00') }, + { paramName: 'modificationDate', value: new Date('2025/01/17 15:30:00') }, { paramName: 'trapped', value: TrappedStatus.TRUE }, { paramName: 'deleteAll', value: true }, ] as const)('should update $paramName parameter', ({ paramName, value }) => { @@ -54,8 +42,8 @@ describe('useChangeMetadataParameters', () => { { description: 'has keywords', updates: { keywords: 'test' }, expected: true }, { description: 'has creator', updates: { creator: 'Test Creator' }, expected: true }, { description: 'has producer', updates: { producer: 'Test Producer' }, expected: true }, - { description: 'has creation date', updates: { creationDate: '2025/01/17 14:30:00' }, expected: true }, - { description: 'has modification date', updates: { modificationDate: '2025/01/17 14:30:00' }, expected: true }, + { description: 'has creation date', updates: { creationDate: new Date('2025/01/17 14:30:00') }, expected: true }, + { description: 'has modification date', updates: { modificationDate: new Date('2025/01/17 14:30:00') }, expected: true }, { description: 'has trapped status', updates: { trapped: TrappedStatus.TRUE }, expected: true }, { description: 'no meaningful content', updates: {}, expected: false }, { description: 'whitespace only', updates: { title: ' ', author: ' ' }, expected: false }, @@ -72,11 +60,9 @@ describe('useChangeMetadataParameters', () => { }); test.each([ - { description: 'invalid creation date', updates: { title: 'Test', creationDate: 'invalid-date' }, expected: false }, - { description: 'invalid modification date', updates: { title: 'Test', modificationDate: 'not-a-date' }, expected: false }, - { description: 'valid creation date', updates: { title: 'Test', creationDate: '2025/01/17 14:30:00' }, expected: true }, - { description: 'valid modification date', updates: { title: 'Test', modificationDate: '2025/01/17 14:30:00' }, expected: true }, - { description: 'empty dates are valid', updates: { title: 'Test', creationDate: '', modificationDate: '' }, expected: true }, + { description: 'valid creation date', updates: { title: 'Test', creationDate: new Date('2025/01/17 14:30:00') }, expected: true }, + { description: 'valid modification date', updates: { title: 'Test', modificationDate: new Date('2025/01/17 14:30:00') }, expected: true }, + { description: 'empty dates are valid', updates: { title: 'Test', creationDate: null, modificationDate: null }, expected: true }, ])('should validate dates correctly with $description', ({ updates, expected }) => { const { result } = renderHook(() => useChangeMetadataParameters()); diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts index c7b1a2f10..c5a892d90 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts +++ b/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts @@ -11,9 +11,9 @@ export interface ChangeMetadataParameters extends BaseParameters { creator: string; producer: string; - // Date fields (format: yyyy/MM/dd HH:mm:ss) - creationDate: string; - modificationDate: string; + // Date fields + creationDate: Date | null; + modificationDate: Date | null; // Trapped status trapped: TrappedStatus; @@ -32,8 +32,8 @@ export const defaultParameters: ChangeMetadataParameters = { keywords: '', creator: '', producer: '', - creationDate: '', - modificationDate: '', + creationDate: null, + modificationDate: null, trapped: TrappedStatus.UNKNOWN, customMetadata: [], deleteAll: false, @@ -57,8 +57,8 @@ const validateParameters = (params: ChangeMetadataParameters): boolean => { || params.keywords.trim() || params.creator.trim() || params.producer.trim() - || params.creationDate.trim() - || params.modificationDate.trim() + || params.creationDate + || params.modificationDate || params.trapped !== TrappedStatus.UNKNOWN ); @@ -66,12 +66,7 @@ const validateParameters = (params: ChangeMetadataParameters): boolean => { entry => entry.key.trim() && entry.value.trim() ); - // Date validation if provided - const datePattern = /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}$/; - const isValidCreationDate = !params.creationDate.trim() || datePattern.test(params.creationDate); - const isValidModificationDate = !params.modificationDate.trim() || datePattern.test(params.modificationDate); - - return (hasStandardMetadata || hasCustomMetadata) && isValidCreationDate && isValidModificationDate; + return hasStandardMetadata || hasCustomMetadata; }; export type ChangeMetadataParametersHook = BaseParametersHook & { diff --git a/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts b/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts index 67c8745c9..423e19d7e 100644 --- a/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts +++ b/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts @@ -47,8 +47,8 @@ export const useMetadataExtraction = (params: MetadataExtractionParams) => { params.updateParameter('keywords', metadata.keywords); params.updateParameter('creator', metadata.creator); params.updateParameter('producer', metadata.producer); - params.updateParameter('creationDate', metadata.creationDate); - params.updateParameter('modificationDate', metadata.modificationDate); + params.updateParameter('creationDate', metadata.creationDate ? new Date(metadata.creationDate) : null); + params.updateParameter('modificationDate', metadata.modificationDate ? new Date(metadata.modificationDate) : null); params.updateParameter('trapped', metadata.trapped); params.updateParameter('customMetadata', metadata.customMetadata);