Add landscape page size options (#6248)

# Description of Changes

Adds orientation (portrait/landscape) to the Adjust Page Scale tool.

- Orientation as a separate parameter (per review), sent through to the
backend
- ScalePagesController simplified; PDFWithPageSize gains the orientation
field
- Regenerated tool_models.py; frontend + backend tests added

---

## 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/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)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### 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 run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: ConnorYoh <[email protected]>
This commit is contained in:
Anthony Stirling
2026-05-28 14:16:15 +00:00
committed by GitHub
co-authored by ConnorYoh
parent b3c4b8b463
commit 8bd78d2624
12 changed files with 142 additions and 57 deletions
@@ -494,6 +494,11 @@ title = "Adjust Page Scale"
[adjustPageScale.error]
failed = "An error occurred while adjusting the page scale."
[adjustPageScale.orientation]
label = "Page orientation"
landscape = "Landscape"
portrait = "Portrait"
[adjustPageScale.pageSize]
keep = "Keep Original Size"
label = "Target Page Size"
@@ -24,6 +24,7 @@ describe("AdjustPageScaleSettings", () => {
const defaultParameters: AdjustPageScaleParameters = {
scaleFactor: 1.0,
pageSize: PageSize.KEEP,
orientation: "PORTRAIT",
};
const mockOnParameterChange = vi.fn();
@@ -51,6 +52,7 @@ describe("AdjustPageScaleSettings", () => {
const customParameters: AdjustPageScaleParameters = {
scaleFactor: 2.5,
pageSize: PageSize.A4,
orientation: "LANDSCAPE",
};
render(
@@ -1,7 +1,8 @@
import { Stack, NumberInput, Select } from "@mantine/core";
import { Stack, NumberInput, Select, SegmentedControl } from "@mantine/core";
import { useTranslation } from "react-i18next";
import {
AdjustPageScaleParameters,
Orientation,
PageSize,
} from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters";
import { Z_INDEX_AUTOMATE_DROPDOWN } from "@app/styles/zIndex";
@@ -22,6 +23,8 @@ const AdjustPageScaleSettings = ({
}: AdjustPageScaleSettingsProps) => {
const { t } = useTranslation();
const isKeepSelected = parameters.pageSize === PageSize.KEEP;
const pageSizeOptions = [
{
value: PageSize.KEEP,
@@ -44,6 +47,17 @@ const AdjustPageScaleSettings = ({
},
];
const orientationOptions = [
{
value: "PORTRAIT",
label: t("adjustPageScale.orientation.portrait", "Portrait"),
},
{
value: "LANDSCAPE",
label: t("adjustPageScale.orientation.landscape", "Landscape"),
},
];
return (
<Stack gap="md">
<NumberInput
@@ -66,9 +80,10 @@ const AdjustPageScaleSettings = ({
label={t("adjustPageScale.pageSize.label", "Target Page Size")}
value={parameters.pageSize}
onChange={(value) => {
if (value && Object.values(PageSize).includes(value as PageSize)) {
onParameterChange("pageSize", value as PageSize);
}
if (!value) return;
const next = value as PageSize;
if (!Object.values(PageSize).includes(next)) return;
onParameterChange("pageSize", next);
}}
data={pageSizeOptions}
disabled={disabled}
@@ -77,6 +92,17 @@ const AdjustPageScaleSettings = ({
zIndex: Z_INDEX_AUTOMATE_DROPDOWN,
}}
/>
<SegmentedControl
aria-label={t("adjustPageScale.orientation.label", "Page orientation")}
value={parameters.orientation}
onChange={(value) =>
onParameterChange("orientation", value as Orientation)
}
data={orientationOptions}
disabled={disabled || isKeepSelected}
fullWidth
/>
</Stack>
);
};
@@ -0,0 +1,13 @@
import { AdjustPageScaleParameters } from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters";
export const buildAdjustPageScaleFormData = (
parameters: AdjustPageScaleParameters,
file: File,
): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
formData.append("scaleFactor", parameters.scaleFactor.toString());
formData.append("pageSize", parameters.pageSize);
formData.append("orientation", parameters.orientation);
return formData;
};
@@ -0,0 +1,51 @@
import { describe, expect, it } from "vitest";
import { buildAdjustPageScaleFormData } from "@app/hooks/tools/adjustPageScale/adjustPageScaleFormData";
import {
defaultParameters,
PageSize,
} from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters";
const stubFile = () =>
new File(["data"], "doc.pdf", { type: "application/pdf" });
describe("buildAdjustPageScaleFormData", () => {
it("includes scaleFactor, pageSize, and orientation by default", () => {
const formData = buildAdjustPageScaleFormData(
defaultParameters,
stubFile(),
);
expect(formData.get("scaleFactor")).toBe(
defaultParameters.scaleFactor.toString(),
);
expect(formData.get("pageSize")).toBe(defaultParameters.pageSize);
expect(formData.get("orientation")).toBe(defaultParameters.orientation);
});
it("forwards orientation=LANDSCAPE to the backend", () => {
const formData = buildAdjustPageScaleFormData(
{ ...defaultParameters, pageSize: PageSize.A4, orientation: "LANDSCAPE" },
stubFile(),
);
expect(formData.get("orientation")).toBe("LANDSCAPE");
expect(formData.get("pageSize")).toBe("A4");
});
it("forwards orientation=PORTRAIT to the backend", () => {
const formData = buildAdjustPageScaleFormData(
{
...defaultParameters,
pageSize: PageSize.LEGAL,
orientation: "PORTRAIT",
},
stubFile(),
);
expect(formData.get("orientation")).toBe("PORTRAIT");
expect(formData.get("pageSize")).toBe("LEGAL");
});
it("attaches the uploaded file under fileInput", () => {
const file = stubFile();
const formData = buildAdjustPageScaleFormData(defaultParameters, file);
expect(formData.get("fileInput")).toBe(file);
});
});
@@ -8,17 +8,9 @@ import {
AdjustPageScaleParameters,
defaultParameters,
} from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters";
import { buildAdjustPageScaleFormData } from "@app/hooks/tools/adjustPageScale/adjustPageScaleFormData";
export const buildAdjustPageScaleFormData = (
parameters: AdjustPageScaleParameters,
file: File,
): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
formData.append("scaleFactor", parameters.scaleFactor.toString());
formData.append("pageSize", parameters.pageSize);
return formData;
};
export { buildAdjustPageScaleFormData };
export const adjustPageScaleOperationConfig = {
toolType: ToolType.singleFile,
@@ -23,6 +23,8 @@ describe("useAdjustPageScaleParameters", () => {
{ paramName: "pageSize" as const, value: PageSize.A4 },
{ paramName: "pageSize" as const, value: PageSize.LETTER },
{ paramName: "pageSize" as const, value: PageSize.LEGAL },
{ paramName: "orientation" as const, value: "LANDSCAPE" as const },
{ paramName: "orientation" as const, value: "PORTRAIT" as const },
])("should update parameter $paramName to $value", ({ paramName, value }) => {
const { result } = renderHook(() => useAdjustPageScaleParameters());
@@ -17,14 +17,18 @@ export enum PageSize {
LEGAL = "LEGAL",
}
export type Orientation = "PORTRAIT" | "LANDSCAPE";
export interface AdjustPageScaleParameters extends BaseParameters {
scaleFactor: number;
pageSize: PageSize;
orientation: Orientation;
}
export const defaultParameters: AdjustPageScaleParameters = {
scaleFactor: 1.0,
pageSize: PageSize.KEEP,
orientation: "PORTRAIT",
};
export type AdjustPageScaleParametersHook =