diff --git a/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index bce6e1272..83e67b49d 100644 --- a/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/app/common/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -303,22 +303,23 @@ public class EndpointConfiguration { // Adding endpoints to "PageOps" group addEndpointToGroup("PageOps", "remove-pages"); addEndpointToGroup("PageOps", "merge-pdfs"); - addEndpointToGroup("PageOps", "split-pdfs"); - addEndpointToGroup("PageOps", "pdf-organizer"); + addEndpointToGroup("PageOps", "split-pages"); + addEndpointToGroup("PageOps", "rearrange-pages"); addEndpointToGroup("PageOps", "rotate-pdf"); addEndpointToGroup("PageOps", "multi-page-layout"); addEndpointToGroup("PageOps", "booklet-imposition"); addEndpointToGroup("PageOps", "scale-pages"); addEndpointToGroup("PageOps", "crop"); - addEndpointToGroup("PageOps", "extract-page"); addEndpointToGroup("PageOps", "pdf-to-single-page"); addEndpointToGroup("PageOps", "auto-split-pdf"); addEndpointToGroup("PageOps", "split-by-size-or-count"); addEndpointToGroup("PageOps", "overlay-pdf"); addEndpointToGroup("PageOps", "split-pdf-by-sections"); addEndpointToGroup("PageOps", "split-pdf-by-chapters"); + addEndpointToGroup("PageOps", "add-page-numbers"); + addEndpointToGroup("PageOps", "extract-pages"); - // Adding endpoints to "Convert" group + // Adding endpoints to "Convert" group (Frontend has 15 convert endpoints) addEndpointToGroup("Convert", "pdf-to-img"); addEndpointToGroup("Convert", "img-to-pdf"); addEndpointToGroup("Convert", "pdf-to-pdfa"); @@ -334,6 +335,8 @@ public class EndpointConfiguration { addEndpointToGroup("Convert", "pdf-to-csv"); addEndpointToGroup("Convert", "pdf-to-markdown"); addEndpointToGroup("Convert", "eml-to-pdf"); + addEndpointToGroup("Convert", "pdf-to-epub"); + // Backend-only endpoints (not in frontend tool registry) addEndpointToGroup("Convert", "pdf-to-vector"); addEndpointToGroup("Convert", "vector-to-pdf"); addEndpointToGroup("Convert", "pdf-to-video"); @@ -341,6 +344,7 @@ public class EndpointConfiguration { addEndpointToGroup("Convert", "pdf-to-cbz"); addEndpointToGroup("Convert", "pdf-to-json"); addEndpointToGroup("Convert", "json-to-pdf"); + addEndpointToGroup("Convert", "pdf-to-rtf"); // Adding endpoints to "Security" group addEndpointToGroup("Security", "add-password"); @@ -351,51 +355,49 @@ public class EndpointConfiguration { addEndpointToGroup("Security", "remove-cert-sign"); addEndpointToGroup("Security", "sanitize-pdf"); addEndpointToGroup("Security", "auto-redact"); - addEndpointToGroup("Security", "redact"); addEndpointToGroup("Security", "validate-signature"); + addEndpointToGroup("Security", "add-stamp"); + addEndpointToGroup("Security", "unlock-pdf-forms"); + // Backend-only endpoints (not in frontend tool registry endpoints) + addEndpointToGroup("Security", "redact"); addEndpointToGroup("Security", "verify-pdf"); - addEndpointToGroup("Security", "stamp"); addEndpointToGroup("Security", "sign"); // Adding endpoints to "Other" group addEndpointToGroup("Other", "ocr-pdf"); - addEndpointToGroup("Other", "add-image"); addEndpointToGroup("Other", "extract-images"); - addEndpointToGroup("Other", "change-metadata"); + addEndpointToGroup("Other", "update-metadata"); addEndpointToGroup("Other", "flatten"); - addEndpointToGroup("Other", "unlock-pdf-forms"); addEndpointToGroup("Other", REMOVE_BLANKS); addEndpointToGroup("Other", "remove-annotations"); - addEndpointToGroup("Other", "compare"); - addEndpointToGroup("Other", "add-page-numbers"); addEndpointToGroup("Other", "get-info-on-pdf"); addEndpointToGroup("Other", "remove-image-pdf"); addEndpointToGroup("Other", "add-attachments"); + addEndpointToGroup("Other", "replace-invert-pdf"); + addEndpointToGroup("Other", "edit-table-of-contents"); + addEndpointToGroup("Other", "text-editor-pdf"); + // Backend-only endpoints (not in frontend tool registry endpoints) + addEndpointToGroup("Other", "add-image"); + addEndpointToGroup("Other", "compare"); addEndpointToGroup("Other", "view-pdf"); - addEndpointToGroup("Other", "replace-and-invert-color-pdf"); addEndpointToGroup("Other", "multi-tool"); - - // Adding form-related endpoints to "Other" group addEndpointToGroup("Other", "fields"); addEndpointToGroup("Other", "modify-fields"); addEndpointToGroup("Other", "delete-fields"); addEndpointToGroup("Other", "fill"); // Adding endpoints to "Advance" group - addEndpointToGroup("Advance", "adjust-contrast"); addEndpointToGroup("Advance", "compress-pdf"); addEndpointToGroup("Advance", "extract-image-scans"); addEndpointToGroup("Advance", "repair"); addEndpointToGroup("Advance", "auto-rename"); - addEndpointToGroup("Advance", "pipeline"); + addEndpointToGroup("Advance", "handleData"); addEndpointToGroup("Advance", "scanner-effect"); - addEndpointToGroup("Advance", "auto-split-pdf"); addEndpointToGroup("Advance", "show-javascript"); - addEndpointToGroup("Advance", "split-by-size-or-count"); addEndpointToGroup("Advance", "overlay-pdf"); - addEndpointToGroup("Advance", "split-pdf-by-sections"); - addEndpointToGroup("Advance", "edit-table-of-contents"); - addEndpointToGroup("Advance", "split-pdf-by-chapters"); + // Backend-only endpoints + addEndpointToGroup("Advance", "adjust-contrast"); + addEndpointToGroup("Advance", "pipeline"); // CLI addEndpointToGroup("CLI", "compress-pdf"); @@ -436,8 +438,8 @@ public class EndpointConfiguration { // Java addEndpointToGroup("Java", "merge-pdfs"); addEndpointToGroup("Java", "remove-pages"); - addEndpointToGroup("Java", "split-pdfs"); - addEndpointToGroup("Java", "pdf-organizer"); + addEndpointToGroup("Java", "split-pages"); + addEndpointToGroup("Java", "rearrange-pages"); addEndpointToGroup("Java", "rotate-pdf"); addEndpointToGroup("Java", "pdf-to-img"); addEndpointToGroup("Java", "img-to-pdf"); @@ -445,9 +447,10 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "remove-password"); addEndpointToGroup("Java", "change-permissions"); addEndpointToGroup("Java", "add-watermark"); + addEndpointToGroup("Java", "add-stamp"); addEndpointToGroup("Java", "add-image"); addEndpointToGroup("Java", "extract-images"); - addEndpointToGroup("Java", "change-metadata"); + addEndpointToGroup("Java", "update-metadata"); addEndpointToGroup("Java", "cert-sign"); addEndpointToGroup("Java", "remove-cert-sign"); addEndpointToGroup("Java", "multi-page-layout"); @@ -459,7 +462,6 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "sanitize-pdf"); addEndpointToGroup("Java", "crop"); addEndpointToGroup("Java", "get-info-on-pdf"); - addEndpointToGroup("Java", "extract-page"); addEndpointToGroup("Java", "pdf-to-single-page"); addEndpointToGroup("Java", "markdown-to-pdf"); addEndpointToGroup("Java", "show-javascript"); @@ -469,7 +471,9 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "split-by-size-or-count"); addEndpointToGroup("Java", "overlay-pdf"); addEndpointToGroup("Java", "split-pdf-by-sections"); + addEndpointToGroup("Java", "split-pdf-by-chapters"); addEndpointToGroup("Java", REMOVE_BLANKS); + addEndpointToGroup("Java", "remove-annotations"); addEndpointToGroup("Java", "pdf-to-text"); addEndpointToGroup("Java", "remove-image-pdf"); addEndpointToGroup("Java", "pdf-to-markdown"); @@ -479,15 +483,24 @@ public class EndpointConfiguration { addEndpointToGroup("Java", "pdf-to-cbz"); addEndpointToGroup("Java", "pdf-to-json"); addEndpointToGroup("Java", "json-to-pdf"); - addEndpointToGroup("rar", "pdf-to-cbr"); addEndpointToGroup("Java", "pdf-to-video"); addEndpointToGroup("Java", "verify-pdf"); + addEndpointToGroup("Java", "flatten"); + addEndpointToGroup("Java", "unlock-pdf-forms"); + addEndpointToGroup("Java", "validate-signature"); + addEndpointToGroup("Java", "text-editor-pdf"); + addEndpointToGroup("Java", "edit-table-of-contents"); + addEndpointToGroup("Java", "pdf-to-epub"); + addEndpointToGroup("Java", "eml-to-pdf"); + addEndpointToGroup("Java", "handleData"); + addEndpointToGroup("rar", "pdf-to-cbr"); // Javascript - addEndpointToGroup("Javascript", "pdf-organizer"); + addEndpointToGroup("Javascript", "rearrange-pages"); addEndpointToGroup("Javascript", "sign"); addEndpointToGroup("Javascript", "compare"); addEndpointToGroup("Javascript", "adjust-contrast"); + addEndpointToGroup("Javascript", "text-editor-pdf"); /* qpdf */ addEndpointToGroup("qpdf", "repair"); @@ -498,6 +511,7 @@ public class EndpointConfiguration { addEndpointToGroup("Ghostscript", "compress-pdf"); addEndpointToGroup("Ghostscript", "crop"); addEndpointToGroup("Ghostscript", "replace-invert-pdf"); + addEndpointToGroup("Ghostscript", "scanner-effect"); addEndpointToGroup("Ghostscript", "pdf-to-vector"); addEndpointToGroup("Ghostscript", "vector-to-pdf"); @@ -546,6 +560,9 @@ public class EndpointConfiguration { // Pdftohtml dependent endpoints addEndpointToGroup("Pdftohtml", "pdf-to-html"); addEndpointToGroup("Pdftohtml", "pdf-to-markdown"); + + // Calibre dependent endpoints + addEndpointToGroup("Calibre", "pdf-to-epub"); } private void processEnvironmentConfigs() { diff --git a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java index 3203daa93..041439232 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java @@ -118,7 +118,8 @@ public class ExternalAppDepConfig { for (String group : affectedGroups) { List affectedFeatures = getAffectedFeatures(group); - endpointConfiguration.disableGroup(group); + endpointConfiguration.disableGroup( + group, EndpointConfiguration.DisableReason.DEPENDENCY); log.warn( "Missing dependency: {} - Disabling group: {} (Affected features: {})", command, @@ -143,7 +144,8 @@ public class ExternalAppDepConfig { commandToGroupMapping.getOrDefault( command, List.of("Weasyprint")); for (String group : affectedGroups) { - endpointConfiguration.disableGroup(group); + endpointConfiguration.disableGroup( + group, EndpointConfiguration.DisableReason.DEPENDENCY); } log.warn( "WeasyPrint version {} is below required {} - disabling" @@ -172,7 +174,8 @@ public class ExternalAppDepConfig { List affectedGroups = commandToGroupMapping.getOrDefault(command, List.of("qpdf")); for (String group : affectedGroups) { - endpointConfiguration.disableGroup(group); + endpointConfiguration.disableGroup( + group, EndpointConfiguration.DisableReason.DEPENDENCY); } log.warn( "qpdf version {} is below required {} - disabling group(s): {}", @@ -226,7 +229,8 @@ public class ExternalAppDepConfig { int ec = runAndWait(List.of(python, "-c", "import cv2"), DEFAULT_TIMEOUT).exitCode(); if (ec != 0) { List openCVFeatures = getAffectedFeatures("OpenCV"); - endpointConfiguration.disableGroup("OpenCV"); + endpointConfiguration.disableGroup( + "OpenCV", EndpointConfiguration.DisableReason.DEPENDENCY); log.warn( "OpenCV not available in Python - Disabling OpenCV features: {}", String.join(", ", openCVFeatures)); @@ -236,8 +240,10 @@ public class ExternalAppDepConfig { private void disablePythonAndOpenCV(String reason) { List pythonFeatures = getAffectedFeatures("Python"); List openCVFeatures = getAffectedFeatures("OpenCV"); - endpointConfiguration.disableGroup("Python"); - endpointConfiguration.disableGroup("OpenCV"); + endpointConfiguration.disableGroup( + "Python", EndpointConfiguration.DisableReason.DEPENDENCY); + endpointConfiguration.disableGroup( + "OpenCV", EndpointConfiguration.DisableReason.DEPENDENCY); log.warn( "Missing dependency: Python (reason: {}) - Disabling Python features: {} and OpenCV" + " features: {}", diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx index 4a5b2466e..7b5b30a40 100644 --- a/frontend/src/core/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -180,6 +180,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { categoryId: ToolCategoryId.RECOMMENDED_TOOLS, subcategoryId: SubcategoryId.GENERAL, maxFiles: -1, + endpoints: ["multi-tool"], synonyms: getSynonyms(t, "multiTool"), supportsAutomate: false, automationSettings: null @@ -218,6 +219,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { description: t("home.sign.desc", "Adds signature to PDF by drawing, text or image"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.SIGNING, + endpoints: ["sign"], operationConfig: signOperationConfig, automationSettings: SignSettings, // TODO:: not all settings shown, suggested next tools shown synonyms: getSynonyms(t, "sign"), @@ -230,6 +232,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { description: t('home.addText.desc', 'Add custom text anywhere in your PDF'), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.GENERAL, + endpoints: ["sign"], operationConfig: signOperationConfig, automationSettings: null, synonyms: getSynonyms(t, 'addText'), @@ -242,6 +245,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { description: t('home.addImage.desc', 'Add images anywhere in your PDF'), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.GENERAL, + endpoints: ["add-image"], operationConfig: signOperationConfig, automationSettings: null, synonyms: getSynonyms(t, 'addImage'), @@ -255,6 +259,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.GENERAL, workbench: 'viewer', + endpoints: ["view-pdf"], operationConfig: signOperationConfig, automationSettings: null, synonyms: getSynonyms(t, 'annotate'), @@ -393,6 +398,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { ), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_REVIEW, + endpoints: ["view-pdf"], synonyms: getSynonyms(t, "read"), supportsAutomate: false, automationSettings: null @@ -710,6 +716,8 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { description: t("home.adjustContrast.desc", "Adjust colors and contrast of PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + maxFiles: -1, + endpoints: ["adjust-contrast"], operationConfig: adjustContrastOperationConfig, automationSettings: AdjustContrastSingleStepSettings, synonyms: getSynonyms(t, "adjustContrast"), @@ -850,6 +858,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { categoryId: ToolCategoryId.RECOMMENDED_TOOLS, subcategoryId: SubcategoryId.GENERAL, maxFiles: 2, + endpoints: ["compare"], operationConfig: undefined, automationSettings: null, synonyms: getSynonyms(t, "compare"), diff --git a/frontend/src/core/tools/Split.tsx b/frontend/src/core/tools/Split.tsx index 3b311a5cf..c7f8b0c46 100644 --- a/frontend/src/core/tools/Split.tsx +++ b/frontend/src/core/tools/Split.tsx @@ -1,4 +1,5 @@ import { useTranslation } from "react-i18next"; +import { useMemo } from "react"; import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; import CardSelector from "@app/components/shared/CardSelector"; import SplitSettings from "@app/components/tools/split/SplitSettings"; @@ -8,7 +9,8 @@ import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; import { useSplitMethodTips } from "@app/components/tooltips/useSplitMethodTips"; import { useSplitSettingsTips } from "@app/components/tooltips/useSplitSettingsTips"; import { BaseToolProps, ToolComponent } from "@app/types/tool"; -import { type SplitMethod, METHOD_OPTIONS, type MethodOption } from "@app/constants/splitConstants"; +import { type SplitMethod, METHOD_OPTIONS, type MethodOption, ENDPOINTS } from "@app/constants/splitConstants"; +import { useMultipleEndpointsEnabled } from "@app/hooks/useEndpointConfig"; const Split = (props: BaseToolProps) => { const { t } = useTranslation(); @@ -20,15 +22,23 @@ const Split = (props: BaseToolProps) => { props ); + // Check which split endpoints are available + const allSplitEndpoints = useMemo(() => Object.values(ENDPOINTS), []); + const { endpointStatus } = useMultipleEndpointsEnabled(allSplitEndpoints); + + // Filter METHOD_OPTIONS to only show methods with enabled endpoints + const availableMethodOptions = useMemo(() => { + return METHOD_OPTIONS.filter(option => { + const endpoint = ENDPOINTS[option.value]; + // If endpoint status is not loaded yet, show all options (optimistic) + // If endpoint is explicitly disabled (false), hide the option + return endpointStatus[endpoint] !== false; + }); + }, [endpointStatus]); + const methodTips = useSplitMethodTips(); const settingsTips = useSplitSettingsTips(base.params.parameters.method); - // Get tooltip content for a specific method - const getMethodTooltip = (option: MethodOption) => { - const tooltipContent = useSplitSettingsTips(option.value); - return tooltipContent?.tips || []; - }; - // Get the method name for the settings step title const getSettingsTitle = () => { if (!base.params.parameters.method) return t("split.steps.settings", "Settings"); @@ -54,10 +64,9 @@ const Split = (props: BaseToolProps) => { tooltip: methodTips, content: ( - options={METHOD_OPTIONS} + options={availableMethodOptions} onSelect={(method) => base.params.updateParameter('method', method)} disabled={base.endpointLoading} - getTooltipContent={getMethodTooltip} /> ), }, diff --git a/frontend/src/proprietary/components/shared/config/configSections/AdminEndpointsSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AdminEndpointsSection.tsx index 8bcf305bb..7c030e1d6 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/AdminEndpointsSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/AdminEndpointsSection.tsx @@ -65,51 +65,103 @@ export default function AdminEndpointsSection() { ); } - // Common endpoint examples + // Complete list of all endpoints from frontend tool registry (alphabetical) const commonEndpoints = [ - 'img-to-pdf', - 'pdf-to-img', - 'merge-pdfs', - 'split-pdf', - 'rotate-pdf', - 'compress-pdf', - 'extract-images', - 'extract-image-scans', - 'add-watermark', - 'remove-watermark', - 'add-password', - 'remove-password', - 'change-permissions', - 'ocr-pdf', - 'pdf-to-pdfa', - 'html-to-pdf', - 'url-to-pdf', - 'markdown-to-pdf', - 'get-info-on-pdf', - 'extract-pdf-metadata', - 'pdf-to-single-page', - 'crop', - 'auto-split-pdf', - 'sanitize-pdf', + 'add-attachments', + 'add-image', 'add-page-numbers', + 'add-password', + 'add-stamp', + 'add-watermark', + 'adjust-contrast', + 'auto-redact', 'auto-rename', - 'scale-pages', - 'repair', + 'auto-split-pdf', + 'booklet-imposition', + 'cert-sign', + 'compare', + 'compress-pdf', + 'crop', + 'edit-table-of-contents', + 'eml-to-pdf', + 'extract-image-scans', + 'extract-images', + 'file-to-pdf', 'flatten', + 'get-info-on-pdf', + 'handleData', + 'html-to-pdf', + 'img-to-pdf', + 'markdown-to-pdf', + 'merge-pdfs', + 'multi-page-layout', + 'multi-tool', + 'ocr-pdf', + 'overlay-pdf', + 'pdf-to-csv', + 'pdf-to-epub', + 'pdf-to-html', + 'pdf-to-img', + 'pdf-to-markdown', + 'pdf-to-pdfa', + 'pdf-to-presentation', + 'pdf-to-single-page', + 'pdf-to-text', + 'pdf-to-word', + 'pdf-to-xml', + 'rearrange-pages', + 'remove-annotations', 'remove-blanks', - 'compare-pdfs' + 'remove-cert-sign', + 'remove-image-pdf', + 'remove-pages', + 'remove-password', + 'repair', + 'replace-invert-pdf', + 'rotate-pdf', + 'sanitize-pdf', + 'scale-pages', + 'scanner-effect', + 'show-javascript', + 'sign', + 'split-by-size-or-count', + 'split-pages', + 'split-pdf-by-chapters', + 'split-pdf-by-sections', + 'text-editor-pdf', + 'unlock-pdf-forms', + 'update-metadata', + 'validate-signature', + 'view-pdf', ]; - // Common endpoint groups + // Complete list of functional and tool groups from EndpointConfiguration.java const commonGroups = [ - 'Conversion', + // Functional Groups + 'PageOps', + 'Convert', 'Security', 'Other', - 'Organize', - 'LibreOffice', + 'Advance', + // Tool Groups 'CLI', 'Python', - 'OpenCV' + 'OpenCV', + 'LibreOffice', + 'Unoconvert', + 'Java', + 'Javascript', + 'qpdf', + 'Ghostscript', + 'ImageMagick', + 'tesseract', + 'OCRmyPDF', + 'Weasyprint', + 'Pdftohtml', + 'Calibre', + 'FFmpeg', + 'veraPDF', + 'rar', ]; return (