From 80d0900757f10c0c99299b067ed169502823ef34 Mon Sep 17 00:00:00 2001 From: EthanHealy01 Date: Fri, 26 Sep 2025 01:20:47 +0100 Subject: [PATCH] add the reorganize pages tool --- .../public/locales/en-GB/translation.json | 15 ++- .../public/locales/en-US/translation.json | 19 +++- .../ReorganizePagesSettings.tsx | 65 +++++++++++ .../tools/reorganizePages/constants.ts | 59 ++++++++++ .../src/data/useTranslatedToolRegistry.tsx | 7 +- .../useReorganizePagesOperation.ts | 36 ++++++ .../useReorganizePagesParameters.ts | 39 +++++++ frontend/src/tools/ReorganizePages.tsx | 104 ++++++++++++++++++ 8 files changed, 338 insertions(+), 6 deletions(-) create mode 100644 frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx create mode 100644 frontend/src/components/tools/reorganizePages/constants.ts create mode 100644 frontend/src/hooks/tools/reorganizePages/useReorganizePagesOperation.ts create mode 100644 frontend/src/hooks/tools/reorganizePages/useReorganizePagesParameters.ts create mode 100644 frontend/src/tools/ReorganizePages.tsx diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index c30bc7c55..9a4f8bdf1 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -959,7 +959,7 @@ "header": "PDF Page Organiser", "submit": "Rearrange Pages", "mode": { - "_value": "Mode", + "_value": "Organization mode", "1": "Custom Page Order", "2": "Reverse Order", "3": "Duplex Sort", @@ -972,6 +972,19 @@ "10": "Odd-Even Merge", "11": "Duplicate all pages" }, + "desc": { + "CUSTOM": "Use a custom sequence of page numbers or expressions to define a new order.", + "REVERSE_ORDER": "Flip the document so the last page becomes first and so on.", + "DUPLEX_SORT": "Interleave fronts then backs as if a duplex scanner scanned all fronts, then all backs (1, n, 2, n-1, …).", + "BOOKLET_SORT": "Arrange pages for booklet printing (last, first, second, second last, …).", + "SIDE_STITCH_BOOKLET_SORT": "Arrange pages for side‑stitch booklet printing (optimised for binding on the side).", + "ODD_EVEN_SPLIT": "Split the document into two outputs: all odd pages and all even pages.", + "ODD_EVEN_MERGE": "Merge two PDFs by alternating pages: odd from the first, even from the second.", + "DUPLICATE": "Duplicate each page according to the custom order count (e.g., 4 duplicates each page 4×).", + "REMOVE_FIRST": "Remove the first page from the document.", + "REMOVE_LAST": "Remove the last page from the document.", + "REMOVE_FIRST_AND_LAST": "Remove both the first and last pages from the document." + }, "placeholder": "(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)" }, "addImage": { diff --git a/frontend/public/locales/en-US/translation.json b/frontend/public/locales/en-US/translation.json index ae23ddd73..5f80a389f 100644 --- a/frontend/public/locales/en-US/translation.json +++ b/frontend/public/locales/en-US/translation.json @@ -769,7 +769,7 @@ "header": "PDF Page Organizer", "submit": "Rearrange Pages", "mode": { - "_value": "Mode", + "_value": "Organization mode", "1": "Custom Page Order", "2": "Reverse Order", "3": "Duplex Sort", @@ -782,6 +782,19 @@ "10": "Odd-Even Merge", "11": "Duplicate all pages" }, + "desc": { + "CUSTOM": "Use a custom sequence of page numbers or expressions to define a new order.", + "REVERSE_ORDER": "Flip the document so the last page becomes first and so on.", + "DUPLEX_SORT": "Interleave fronts then backs as if a duplex scanner scanned all fronts, then all backs (1, n, 2, n-1, …).", + "BOOKLET_SORT": "Arrange pages for booklet printing (last, first, second, second last, …).", + "SIDE_STITCH_BOOKLET_SORT": "Arrange pages for side‑stitch booklet printing (optimized for binding on the side).", + "ODD_EVEN_SPLIT": "Split the document into two outputs: all odd pages and all even pages.", + "ODD_EVEN_MERGE": "Merge two PDFs by alternating pages: odd from the first, even from the second.", + "DUPLICATE": "Duplicate each page according to the custom order count (e.g., 4 duplicates each page 4×).", + "REMOVE_FIRST": "Remove the first page from the document.", + "REMOVE_LAST": "Remove the last page from the document.", + "REMOVE_FIRST_AND_LAST": "Remove both the first and last pages from the document." + }, "placeholder": "(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)" }, "addImage": { @@ -1852,7 +1865,7 @@ "title": "How we use Cookies", "description": { "1": "We use cookies and other technologies to make Stirling PDF work better for you—helping us improve our tools and keep building features you'll love.", - "2": "If you’d rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly." + "2": "If you'd rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly." }, "acceptAllBtn": "Okay", "acceptNecessaryBtn": "No Thanks", @@ -1876,7 +1889,7 @@ "1": "Strictly Necessary Cookies", "2": "Always Enabled" }, - "description": "These cookies are essential for the website to function properly. They enable core features like setting your privacy preferences, logging in, and filling out forms—which is why they can’t be turned off." + "description": "These cookies are essential for the website to function properly. They enable core features like setting your privacy preferences, logging in, and filling out forms—which is why they can't be turned off." }, "analytics": { "title": "Analytics", diff --git a/frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx b/frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx new file mode 100644 index 000000000..910d13f15 --- /dev/null +++ b/frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Divider, Select, Stack, TextInput } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import { ReorganizePagesParameters } from '../../../hooks/tools/reorganizePages/useReorganizePagesParameters'; +import { getReorganizePagesModeData } from './constants'; + +export default function ReorganizePagesSettings({ + parameters, + onParameterChange, + disabled, +}: { + parameters: ReorganizePagesParameters; + onParameterChange: ( + key: K, + value: ReorganizePagesParameters[K] + ) => void; + disabled?: boolean; +}) { + const { t } = useTranslation(); + const modeData = getReorganizePagesModeData(t); + + const requiresOrder = parameters.customMode === '' || parameters.customMode === 'DUPLICATE'; + const selectedMode = modeData.find(mode => mode.value === parameters.customMode) || modeData[0]; + return ( + +