mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-08-20 13:47:46 +02:00
V2 PDF to large page (#4236)
# Description of Changes <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
parent
857b2b5c53
commit
d1cb3f0b30
@ -1618,7 +1618,18 @@
|
|||||||
"pdfToSinglePage": {
|
"pdfToSinglePage": {
|
||||||
"title": "PDF To Single Page",
|
"title": "PDF To Single Page",
|
||||||
"header": "PDF To Single Page",
|
"header": "PDF To Single Page",
|
||||||
"submit": "Convert To Single Page"
|
"submit": "Convert To Single Page",
|
||||||
|
"description": "This tool will merge all pages of your PDF into one large single page. The width will remain the same as the original pages, but the height will be the sum of all page heights.",
|
||||||
|
"filenamePrefix": "single_page",
|
||||||
|
"files": {
|
||||||
|
"placeholder": "Select a PDF file in the main view to get started"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"failed": "An error occurred whilst converting to single page."
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"title": "Single Page Results"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"pageExtracter": {
|
"pageExtracter": {
|
||||||
"title": "Extract Pages",
|
"title": "Extract Pages",
|
||||||
|
@ -1345,7 +1345,18 @@
|
|||||||
"pdfToSinglePage": {
|
"pdfToSinglePage": {
|
||||||
"title": "PDF To Single Page",
|
"title": "PDF To Single Page",
|
||||||
"header": "PDF To Single Page",
|
"header": "PDF To Single Page",
|
||||||
"submit": "Convert To Single Page"
|
"submit": "Convert To Single Page",
|
||||||
|
"description": "This tool will merge all pages of your PDF into one large single page. The width will remain the same as the original pages, but the height will be the sum of all page heights.",
|
||||||
|
"filenamePrefix": "single_page",
|
||||||
|
"files": {
|
||||||
|
"placeholder": "Select a PDF file in the main view to get started"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"failed": "An error occurred while converting to single page."
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"title": "Single Page Results"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"pageExtracter": {
|
"pageExtracter": {
|
||||||
"title": "Extract Pages",
|
"title": "Extract Pages",
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { SingleLargePageParameters } from '../../../hooks/tools/singleLargePage/useSingleLargePageParameters';
|
||||||
|
|
||||||
|
interface SingleLargePageSettingsProps {
|
||||||
|
parameters: SingleLargePageParameters;
|
||||||
|
onParameterChange: <K extends keyof SingleLargePageParameters>(parameter: K, value: SingleLargePageParameters[K]) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SingleLargePageSettings: React.FC<SingleLargePageSettingsProps> = ({
|
||||||
|
parameters,
|
||||||
|
onParameterChange,
|
||||||
|
disabled = false
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="single-large-page-settings">
|
||||||
|
<p className="text-muted">
|
||||||
|
{t('pdfToSinglePage.description', 'This tool will merge all pages of your PDF into one large single page. The width will remain the same as the original pages, but the height will be the sum of all page heights.')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SingleLargePageSettings;
|
@ -11,10 +11,12 @@ import RemovePassword from '../tools/RemovePassword';
|
|||||||
import { SubcategoryId, ToolCategory, ToolRegistry } from './toolsTaxonomy';
|
import { SubcategoryId, ToolCategory, ToolRegistry } from './toolsTaxonomy';
|
||||||
import AddWatermark from '../tools/AddWatermark';
|
import AddWatermark from '../tools/AddWatermark';
|
||||||
import Repair from '../tools/Repair';
|
import Repair from '../tools/Repair';
|
||||||
|
import SingleLargePage from '../tools/SingleLargePage';
|
||||||
import UnlockPdfForms from '../tools/UnlockPdfForms';
|
import UnlockPdfForms from '../tools/UnlockPdfForms';
|
||||||
import RemoveCertificateSign from '../tools/RemoveCertificateSign';
|
import RemoveCertificateSign from '../tools/RemoveCertificateSign';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Hook to get the translated tool registry
|
// Hook to get the translated tool registry
|
||||||
export function useFlatToolRegistry(): ToolRegistry {
|
export function useFlatToolRegistry(): ToolRegistry {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -236,11 +238,13 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
"single-large-page": {
|
"single-large-page": {
|
||||||
icon: <span className="material-symbols-rounded">looks_one</span>,
|
icon: <span className="material-symbols-rounded">looks_one</span>,
|
||||||
name: t("home.PdfToSinglePage.title", "PDF to Single Large Page"),
|
name: t("home.PdfToSinglePage.title", "PDF to Single Large Page"),
|
||||||
component: null,
|
component: SingleLargePage,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.PdfToSinglePage.desc", "Merges all PDF pages into one large single page"),
|
description: t("home.PdfToSinglePage.desc", "Merges all PDF pages into one large single page"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
category: ToolCategory.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategory: SubcategoryId.PAGE_FORMATTING,
|
||||||
|
maxFiles: -1,
|
||||||
|
endpoints: ["pdf-to-single-page"]
|
||||||
},
|
},
|
||||||
"add-attachments": {
|
"add-attachments": {
|
||||||
icon: <span className="material-symbols-rounded">attachment</span>,
|
icon: <span className="material-symbols-rounded">attachment</span>,
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useToolOperation } from '../shared/useToolOperation';
|
||||||
|
import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
|
||||||
|
import { SingleLargePageParameters } from './useSingleLargePageParameters';
|
||||||
|
|
||||||
|
export const useSingleLargePageOperation = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const buildFormData = (parameters: SingleLargePageParameters, file: File): FormData => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("fileInput", file);
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
|
return useToolOperation<SingleLargePageParameters>({
|
||||||
|
operationType: 'singleLargePage',
|
||||||
|
endpoint: '/api/v1/general/pdf-to-single-page',
|
||||||
|
buildFormData,
|
||||||
|
filePrefix: t('pdfToSinglePage.filenamePrefix', 'single_page') + '_',
|
||||||
|
multiFileEndpoint: false,
|
||||||
|
getErrorMessage: createStandardErrorHandler(t('pdfToSinglePage.error.failed', 'An error occurred while converting to single page.'))
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,19 @@
|
|||||||
|
import { BaseParameters } from '../../../types/parameters';
|
||||||
|
import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters';
|
||||||
|
|
||||||
|
export interface SingleLargePageParameters extends BaseParameters {
|
||||||
|
// Extends BaseParameters - ready for future parameter additions if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultParameters: SingleLargePageParameters = {
|
||||||
|
// No parameters needed
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SingleLargePageParametersHook = BaseParametersHook<SingleLargePageParameters>;
|
||||||
|
|
||||||
|
export const useSingleLargePageParameters = (): SingleLargePageParametersHook => {
|
||||||
|
return useBaseParameters({
|
||||||
|
defaultParameters,
|
||||||
|
endpointName: 'pdf-to-single-page',
|
||||||
|
});
|
||||||
|
};
|
80
frontend/src/tools/SingleLargePage.tsx
Normal file
80
frontend/src/tools/SingleLargePage.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||||
|
import { useFileContext } from "../contexts/FileContext";
|
||||||
|
import { useToolFileSelection } from "../contexts/FileSelectionContext";
|
||||||
|
|
||||||
|
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||||
|
|
||||||
|
import { useSingleLargePageParameters } from "../hooks/tools/singleLargePage/useSingleLargePageParameters";
|
||||||
|
import { useSingleLargePageOperation } from "../hooks/tools/singleLargePage/useSingleLargePageOperation";
|
||||||
|
import { BaseToolProps } from "../types/tool";
|
||||||
|
|
||||||
|
const SingleLargePage = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { setCurrentMode } = useFileContext();
|
||||||
|
const { selectedFiles } = useToolFileSelection();
|
||||||
|
|
||||||
|
const singleLargePageParams = useSingleLargePageParameters();
|
||||||
|
const singleLargePageOperation = useSingleLargePageOperation();
|
||||||
|
|
||||||
|
// Endpoint validation
|
||||||
|
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(singleLargePageParams.getEndpointName());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
singleLargePageOperation.resetResults();
|
||||||
|
onPreviewFile?.(null);
|
||||||
|
}, [singleLargePageParams.parameters]);
|
||||||
|
|
||||||
|
const handleConvert = async () => {
|
||||||
|
try {
|
||||||
|
await singleLargePageOperation.executeOperation(singleLargePageParams.parameters, selectedFiles);
|
||||||
|
if (singleLargePageOperation.files && onComplete) {
|
||||||
|
onComplete(singleLargePageOperation.files);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (onError) {
|
||||||
|
onError(error instanceof Error ? error.message : t("pdfToSinglePage.error.failed", "Single large page operation failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleThumbnailClick = (file: File) => {
|
||||||
|
onPreviewFile?.(file);
|
||||||
|
sessionStorage.setItem("previousMode", "single-large-page");
|
||||||
|
setCurrentMode("viewer");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSettingsReset = () => {
|
||||||
|
singleLargePageOperation.resetResults();
|
||||||
|
onPreviewFile?.(null);
|
||||||
|
setCurrentMode("single-large-page");
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasFiles = selectedFiles.length > 0;
|
||||||
|
const hasResults = singleLargePageOperation.files.length > 0 || singleLargePageOperation.downloadUrl !== null;
|
||||||
|
|
||||||
|
return createToolFlow({
|
||||||
|
files: {
|
||||||
|
selectedFiles,
|
||||||
|
isCollapsed: hasFiles || hasResults,
|
||||||
|
placeholder: t("pdfToSinglePage.files.placeholder", "Select a PDF file in the main view to get started"),
|
||||||
|
},
|
||||||
|
steps: [],
|
||||||
|
executeButton: {
|
||||||
|
text: t("pdfToSinglePage.submit", "Convert To Single Page"),
|
||||||
|
isVisible: !hasResults,
|
||||||
|
loadingText: t("loading"),
|
||||||
|
onClick: handleConvert,
|
||||||
|
disabled: !singleLargePageParams.validateParameters() || !hasFiles || !endpointEnabled,
|
||||||
|
},
|
||||||
|
review: {
|
||||||
|
isVisible: hasResults,
|
||||||
|
operation: singleLargePageOperation,
|
||||||
|
title: t("pdfToSinglePage.results.title", "Single Page Results"),
|
||||||
|
onFileClick: handleThumbnailClick,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SingleLargePage;
|
@ -19,6 +19,7 @@ export type ModeType =
|
|||||||
| 'changePermissions'
|
| 'changePermissions'
|
||||||
| 'watermark'
|
| 'watermark'
|
||||||
| 'removePassword'
|
| 'removePassword'
|
||||||
|
| 'single-large-page'
|
||||||
| 'repair'
|
| 'repair'
|
||||||
| 'unlockPdfForms'
|
| 'unlockPdfForms'
|
||||||
| 'removeCertificateSign';
|
| 'removeCertificateSign';
|
||||||
|
Loading…
Reference in New Issue
Block a user