mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
Merge remote-tracking branch 'origin/V2' into feature/v2/automate
This commit is contained in:
commit
56b245271e
@ -1927,18 +1927,23 @@
|
|||||||
"noToolsFound": "No tools found",
|
"noToolsFound": "No tools found",
|
||||||
"allTools": "ALL TOOLS",
|
"allTools": "ALL TOOLS",
|
||||||
"quickAccess": "QUICK ACCESS",
|
"quickAccess": "QUICK ACCESS",
|
||||||
|
"categories": {
|
||||||
|
"standardTools": "Standard Tools",
|
||||||
|
"advancedTools": "Advanced Tools",
|
||||||
|
"recommendedTools": "Recommended Tools"
|
||||||
|
},
|
||||||
"subcategories": {
|
"subcategories": {
|
||||||
"Signing": "Signing",
|
"signing": "Signing",
|
||||||
"Document Security": "Document Security",
|
"documentSecurity": "Document Security",
|
||||||
"Verification": "Verification",
|
"verification": "Verification",
|
||||||
"Document Review": "Document Review",
|
"documentReview": "Document Review",
|
||||||
"Page Formatting": "Page Formatting",
|
"pageFormatting": "Page Formatting",
|
||||||
"Extraction": "Extraction",
|
"extraction": "Extraction",
|
||||||
"Removal": "Removal",
|
"removal": "Removal",
|
||||||
"Automation": "Automation",
|
"automation": "Automation",
|
||||||
"General": "General",
|
"general": "General",
|
||||||
"Advanced Formatting": "Advanced Formatting",
|
"advancedFormatting": "Advanced Formatting",
|
||||||
"Developer Tools": "Developer Tools"
|
"developerTools": "Developer Tools"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"quickAccess": {
|
"quickAccess": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Stack, Text } from '@mantine/core';
|
import { Box, Stack, Text } from '@mantine/core';
|
||||||
import { ToolRegistryEntry } from '../../data/toolsTaxonomy';
|
import { getSubcategoryLabel, ToolRegistryEntry } from '../../data/toolsTaxonomy';
|
||||||
import ToolButton from './toolPicker/ToolButton';
|
import ToolButton from './toolPicker/ToolButton';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useToolSections } from '../../hooks/useToolSections';
|
import { useToolSections } from '../../hooks/useToolSections';
|
||||||
@ -23,8 +23,8 @@ const SearchResults: React.FC<SearchResultsProps> = ({ filteredTools, onSelect }
|
|||||||
return (
|
return (
|
||||||
<Stack p="sm" gap="xs">
|
<Stack p="sm" gap="xs">
|
||||||
{searchGroups.map(group => (
|
{searchGroups.map(group => (
|
||||||
<Box key={group.subcategory} w="100%">
|
<Box key={group.subcategoryId} w="100%">
|
||||||
<SubcategoryHeader label={t(`toolPicker.subcategories.${group.subcategory}`, group.subcategory)} />
|
<SubcategoryHeader label={getSubcategoryLabel(t, group.subcategoryId)} />
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
{group.tools.map(({ id, tool }) => (
|
{group.tools.map(({ id, tool }) => (
|
||||||
<ToolButton
|
<ToolButton
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useMemo, useRef, useLayoutEffect, useState } from "react";
|
import React, { useMemo, useRef, useLayoutEffect, useState } from "react";
|
||||||
import { Box, Text, Stack } from "@mantine/core";
|
import { Box, Stack } from "@mantine/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ToolRegistryEntry } from "../../data/toolsTaxonomy";
|
import { ToolRegistryEntry } from "../../data/toolsTaxonomy";
|
||||||
import ToolButton from "./toolPicker/ToolButton";
|
|
||||||
import "./toolPicker/ToolPicker.css";
|
import "./toolPicker/ToolPicker.css";
|
||||||
import { useToolSections } from "../../hooks/useToolSections";
|
import { useToolSections } from "../../hooks/useToolSections";
|
||||||
import NoToolsFound from "./shared/NoToolsFound";
|
import NoToolsFound from "./shared/NoToolsFound";
|
||||||
@ -44,11 +43,11 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
|||||||
const { sections: visibleSections } = useToolSections(filteredTools);
|
const { sections: visibleSections } = useToolSections(filteredTools);
|
||||||
|
|
||||||
const quickSection = useMemo(
|
const quickSection = useMemo(
|
||||||
() => visibleSections.find(s => (s as any).key === 'quick'),
|
() => visibleSections.find(s => s.key === 'quick'),
|
||||||
[visibleSections]
|
[visibleSections]
|
||||||
);
|
);
|
||||||
const allSection = useMemo(
|
const allSection = useMemo(
|
||||||
() => visibleSections.find(s => (s as any).key === 'all'),
|
() => visibleSections.find(s => s.key === 'all'),
|
||||||
[visibleSections]
|
[visibleSections]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
|||||||
{searchGroups.length === 0 ? (
|
{searchGroups.length === 0 ? (
|
||||||
<NoToolsFound />
|
<NoToolsFound />
|
||||||
) : (
|
) : (
|
||||||
searchGroups.map(group => renderToolButtons(group, selectedToolKey, onSelect))
|
searchGroups.map(group => renderToolButtons(t, group, selectedToolKey, onSelect))
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
) : (
|
) : (
|
||||||
@ -140,7 +139,7 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
|||||||
<Box ref={quickAccessRef} w="100%">
|
<Box ref={quickAccessRef} w="100%">
|
||||||
<Stack p="sm" gap="xs">
|
<Stack p="sm" gap="xs">
|
||||||
{quickSection?.subcategories.map(sc =>
|
{quickSection?.subcategories.map(sc =>
|
||||||
renderToolButtons(sc, selectedToolKey, onSelect, false)
|
renderToolButtons(t, sc, selectedToolKey, onSelect, false)
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
@ -186,7 +185,7 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
|||||||
<Box ref={allToolsRef} w="100%">
|
<Box ref={allToolsRef} w="100%">
|
||||||
<Stack p="sm" gap="xs">
|
<Stack p="sm" gap="xs">
|
||||||
{allSection?.subcategories.map(sc =>
|
{allSection?.subcategories.map(sc =>
|
||||||
renderToolButtons(sc, selectedToolKey, onSelect, true)
|
renderToolButtons(t, sc, selectedToolKey, onSelect, true)
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -22,7 +22,7 @@ export function SuggestedToolsSection(): React.ReactElement {
|
|||||||
const IconComponent = tool.icon;
|
const IconComponent = tool.icon;
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={tool.name}
|
key={tool.id}
|
||||||
p="sm"
|
p="sm"
|
||||||
withBorder
|
withBorder
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
|
@ -3,19 +3,24 @@ import { Box, Stack } from '@mantine/core';
|
|||||||
import ToolButton from '../toolPicker/ToolButton';
|
import ToolButton from '../toolPicker/ToolButton';
|
||||||
import SubcategoryHeader from './SubcategoryHeader';
|
import SubcategoryHeader from './SubcategoryHeader';
|
||||||
|
|
||||||
|
import { getSubcategoryLabel } from "../../../data/toolsTaxonomy";
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
import { SubcategoryGroup } from '../../../hooks/useToolSections';
|
||||||
|
|
||||||
// Helper function to render tool buttons for a subcategory
|
// Helper function to render tool buttons for a subcategory
|
||||||
export const renderToolButtons = (
|
export const renderToolButtons = (
|
||||||
subcategory: any,
|
t: TFunction,
|
||||||
selectedToolKey: string | null,
|
subcategory: SubcategoryGroup,
|
||||||
onSelect: (id: string) => void,
|
selectedToolKey: String | null,
|
||||||
|
onSelect: (id: String) => void,
|
||||||
showSubcategoryHeader: boolean = true
|
showSubcategoryHeader: boolean = true
|
||||||
) => (
|
) => (
|
||||||
<Box key={subcategory.subcategory} w="100%">
|
<Box key={subcategory.subcategoryId} w="100%">
|
||||||
{showSubcategoryHeader && (
|
{showSubcategoryHeader && (
|
||||||
<SubcategoryHeader label={subcategory.subcategory} />
|
<SubcategoryHeader label={getSubcategoryLabel(t, subcategory.subcategoryId)} />
|
||||||
)}
|
)}
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
{subcategory.tools.map(({ id, tool }: { id: string; tool: any }) => (
|
{subcategory.tools.map(({ id, tool }) => (
|
||||||
<ToolButton
|
<ToolButton
|
||||||
key={id}
|
key={id}
|
||||||
id={id}
|
id={id}
|
||||||
|
@ -5,23 +5,23 @@ import { BaseToolProps } from '../types/tool';
|
|||||||
import { BaseParameters } from '../types/parameters';
|
import { BaseParameters } from '../types/parameters';
|
||||||
|
|
||||||
export enum SubcategoryId {
|
export enum SubcategoryId {
|
||||||
SIGNING = 'signing',
|
SIGNING = 'signing',
|
||||||
DOCUMENT_SECURITY = 'documentSecurity',
|
DOCUMENT_SECURITY = 'documentSecurity',
|
||||||
VERIFICATION = 'verification',
|
VERIFICATION = 'verification',
|
||||||
DOCUMENT_REVIEW = 'documentReview',
|
DOCUMENT_REVIEW = 'documentReview',
|
||||||
PAGE_FORMATTING = 'pageFormatting',
|
PAGE_FORMATTING = 'pageFormatting',
|
||||||
EXTRACTION = 'extraction',
|
EXTRACTION = 'extraction',
|
||||||
REMOVAL = 'removal',
|
REMOVAL = 'removal',
|
||||||
AUTOMATION = 'automation',
|
AUTOMATION = 'automation',
|
||||||
GENERAL = 'general',
|
GENERAL = 'general',
|
||||||
ADVANCED_FORMATTING = 'advancedFormatting',
|
ADVANCED_FORMATTING = 'advancedFormatting',
|
||||||
DEVELOPER_TOOLS = 'developerTools'
|
DEVELOPER_TOOLS = 'developerTools'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ToolCategory {
|
export enum ToolCategoryId {
|
||||||
STANDARD_TOOLS = 'Standard Tools',
|
STANDARD_TOOLS = 'standardTools',
|
||||||
ADVANCED_TOOLS = 'Advanced Tools',
|
ADVANCED_TOOLS = 'advancedTools',
|
||||||
RECOMMENDED_TOOLS = 'Recommended Tools'
|
RECOMMENDED_TOOLS = 'recommendedTools'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolRegistryEntry = {
|
export type ToolRegistryEntry = {
|
||||||
@ -30,8 +30,8 @@ export type ToolRegistryEntry = {
|
|||||||
component: React.ComponentType<BaseToolProps> | null;
|
component: React.ComponentType<BaseToolProps> | null;
|
||||||
view: 'sign' | 'security' | 'format' | 'extract' | 'view' | 'merge' | 'pageEditor' | 'convert' | 'redact' | 'split' | 'convert' | 'remove' | 'compress' | 'external';
|
view: 'sign' | 'security' | 'format' | 'extract' | 'view' | 'merge' | 'pageEditor' | 'convert' | 'redact' | 'split' | 'convert' | 'remove' | 'compress' | 'external';
|
||||||
description: string;
|
description: string;
|
||||||
category: ToolCategory;
|
categoryId: ToolCategoryId;
|
||||||
subcategory: SubcategoryId;
|
subcategoryId: SubcategoryId;
|
||||||
maxFiles?: number;
|
maxFiles?: number;
|
||||||
supportedFormats?: string[];
|
supportedFormats?: string[];
|
||||||
endpoints?: string[];
|
endpoints?: string[];
|
||||||
@ -43,67 +43,67 @@ export type ToolRegistryEntry = {
|
|||||||
settingsComponent?: React.ComponentType<any>;
|
settingsComponent?: React.ComponentType<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolRegistry = Record<string, ToolRegistryEntry>;
|
export type ToolRegistry = Record<string /* FIX ME: Should be ToolId */, ToolRegistryEntry>;
|
||||||
|
|
||||||
export const SUBCATEGORY_ORDER: SubcategoryId[] = [
|
export const SUBCATEGORY_ORDER: SubcategoryId[] = [
|
||||||
SubcategoryId.SIGNING,
|
SubcategoryId.SIGNING,
|
||||||
SubcategoryId.DOCUMENT_SECURITY,
|
SubcategoryId.DOCUMENT_SECURITY,
|
||||||
SubcategoryId.VERIFICATION,
|
SubcategoryId.VERIFICATION,
|
||||||
SubcategoryId.DOCUMENT_REVIEW,
|
SubcategoryId.DOCUMENT_REVIEW,
|
||||||
SubcategoryId.PAGE_FORMATTING,
|
SubcategoryId.PAGE_FORMATTING,
|
||||||
SubcategoryId.EXTRACTION,
|
SubcategoryId.EXTRACTION,
|
||||||
SubcategoryId.REMOVAL,
|
SubcategoryId.REMOVAL,
|
||||||
SubcategoryId.AUTOMATION,
|
SubcategoryId.AUTOMATION,
|
||||||
SubcategoryId.GENERAL,
|
SubcategoryId.GENERAL,
|
||||||
SubcategoryId.ADVANCED_FORMATTING,
|
SubcategoryId.ADVANCED_FORMATTING,
|
||||||
SubcategoryId.DEVELOPER_TOOLS,
|
SubcategoryId.DEVELOPER_TOOLS,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SUBCATEGORY_COLOR_MAP: Record<SubcategoryId, string> = {
|
export const SUBCATEGORY_COLOR_MAP: Record<SubcategoryId, string> = {
|
||||||
[SubcategoryId.SIGNING]: '#FF7892',
|
[SubcategoryId.SIGNING]: '#FF7892',
|
||||||
[SubcategoryId.DOCUMENT_SECURITY]: '#FF7892',
|
[SubcategoryId.DOCUMENT_SECURITY]: '#FF7892',
|
||||||
[SubcategoryId.VERIFICATION]: '#1BB1D4',
|
[SubcategoryId.VERIFICATION]: '#1BB1D4',
|
||||||
[SubcategoryId.DOCUMENT_REVIEW]: '#48BD54',
|
[SubcategoryId.DOCUMENT_REVIEW]: '#48BD54',
|
||||||
[SubcategoryId.PAGE_FORMATTING]: '#7882FF',
|
[SubcategoryId.PAGE_FORMATTING]: '#7882FF',
|
||||||
[SubcategoryId.EXTRACTION]: '#1BB1D4',
|
[SubcategoryId.EXTRACTION]: '#1BB1D4',
|
||||||
[SubcategoryId.REMOVAL]: '#7882FF',
|
[SubcategoryId.REMOVAL]: '#7882FF',
|
||||||
[SubcategoryId.AUTOMATION]: '#69DC95',
|
[SubcategoryId.AUTOMATION]: '#69DC95',
|
||||||
[SubcategoryId.GENERAL]: '#69DC95',
|
[SubcategoryId.GENERAL]: '#69DC95',
|
||||||
[SubcategoryId.ADVANCED_FORMATTING]: '#F55454',
|
[SubcategoryId.ADVANCED_FORMATTING]: '#F55454',
|
||||||
[SubcategoryId.DEVELOPER_TOOLS]: '#F55454',
|
[SubcategoryId.DEVELOPER_TOOLS]: '#F55454',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSubcategoryColor = (subcategory: SubcategoryId): string => SUBCATEGORY_COLOR_MAP[subcategory] || '#7882FF';
|
export const getCategoryLabel = (t: TFunction, id: ToolCategoryId): string => t(`toolPicker.categories.${id}`, id);
|
||||||
|
|
||||||
export const getSubcategoryLabel = (t: TFunction, id: SubcategoryId): string => t(`toolPicker.subcategories.${id}`, id);
|
export const getSubcategoryLabel = (t: TFunction, id: SubcategoryId): string => t(`toolPicker.subcategories.${id}`, id);
|
||||||
|
export const getSubcategoryColor = (subcategory: SubcategoryId): string => SUBCATEGORY_COLOR_MAP[subcategory] || '#7882FF';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getAllEndpoints = (registry: ToolRegistry): string[] => {
|
export const getAllEndpoints = (registry: ToolRegistry): string[] => {
|
||||||
const lists: string[][] = [];
|
const lists: string[][] = [];
|
||||||
Object.values(registry).forEach(entry => {
|
Object.values(registry).forEach(entry => {
|
||||||
if (entry.endpoints && entry.endpoints.length > 0) {
|
if (entry.endpoints && entry.endpoints.length > 0) {
|
||||||
lists.push(entry.endpoints);
|
lists.push(entry.endpoints);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Array.from(new Set(lists.flat()));
|
return Array.from(new Set(lists.flat()));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getConversionEndpoints = (extensionToEndpoint: Record<string, Record<string, string>>): string[] => {
|
export const getConversionEndpoints = (extensionToEndpoint: Record<string, Record<string, string>>): string[] => {
|
||||||
const endpoints = new Set<string>();
|
const endpoints = new Set<string>();
|
||||||
Object.values(extensionToEndpoint).forEach(toEndpoints => {
|
Object.values(extensionToEndpoint).forEach(toEndpoints => {
|
||||||
Object.values(toEndpoints).forEach(endpoint => {
|
Object.values(toEndpoints).forEach(endpoint => {
|
||||||
endpoints.add(endpoint);
|
endpoints.add(endpoint);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return Array.from(endpoints);
|
return Array.from(endpoints);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAllApplicationEndpoints = (
|
export const getAllApplicationEndpoints = (
|
||||||
registry: ToolRegistry,
|
registry: ToolRegistry,
|
||||||
extensionToEndpoint?: Record<string, Record<string, string>>
|
extensionToEndpoint?: Record<string, Record<string, string>>
|
||||||
): string[] => {
|
): string[] => {
|
||||||
const toolEp = getAllEndpoints(registry);
|
const toolEp = getAllEndpoints(registry);
|
||||||
const convEp = extensionToEndpoint ? getConversionEndpoints(extensionToEndpoint) : [];
|
const convEp = extensionToEndpoint ? getConversionEndpoints(extensionToEndpoint) : [];
|
||||||
return Array.from(new Set([...toolEp, ...convEp]));
|
return Array.from(new Set([...toolEp, ...convEp]));
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ import Sanitize from '../tools/Sanitize';
|
|||||||
import AddPassword from '../tools/AddPassword';
|
import AddPassword from '../tools/AddPassword';
|
||||||
import ChangePermissions from '../tools/ChangePermissions';
|
import ChangePermissions from '../tools/ChangePermissions';
|
||||||
import RemovePassword from '../tools/RemovePassword';
|
import RemovePassword from '../tools/RemovePassword';
|
||||||
import { SubcategoryId, ToolCategory, ToolRegistry } from './toolsTaxonomy';
|
import { SubcategoryId, ToolCategoryId, 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 SingleLargePage from '../tools/SingleLargePage';
|
||||||
@ -55,8 +55,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "sign",
|
view: "sign",
|
||||||
description: t("home.certSign.desc", "Signs a PDF with a Certificate/Key (PEM/P12)"),
|
description: t("home.certSign.desc", "Signs a PDF with a Certificate/Key (PEM/P12)"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.SIGNING
|
subcategoryId: SubcategoryId.SIGNING
|
||||||
},
|
},
|
||||||
"sign": {
|
"sign": {
|
||||||
icon: <span className="material-symbols-rounded">signature</span>,
|
icon: <span className="material-symbols-rounded">signature</span>,
|
||||||
@ -64,8 +64,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "sign",
|
view: "sign",
|
||||||
description: t("home.sign.desc", "Adds signature to PDF by drawing, text or image"),
|
description: t("home.sign.desc", "Adds signature to PDF by drawing, text or image"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.SIGNING
|
subcategoryId: SubcategoryId.SIGNING
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -77,8 +77,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: AddPassword,
|
component: AddPassword,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.addPassword.desc", "Add password protection and restrictions to PDF files"),
|
description: t("home.addPassword.desc", "Add password protection and restrictions to PDF files"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY,
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["add-password"],
|
endpoints: ["add-password"],
|
||||||
operationConfig: addPasswordOperationConfig,
|
operationConfig: addPasswordOperationConfig,
|
||||||
@ -91,8 +91,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
view: "format",
|
view: "format",
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
description: t("home.watermark.desc", "Add a custom watermark to your PDF document."),
|
description: t("home.watermark.desc", "Add a custom watermark to your PDF document."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY,
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
|
||||||
endpoints: ["add-watermark"],
|
endpoints: ["add-watermark"],
|
||||||
operationConfig: addWatermarkOperationConfig,
|
operationConfig: addWatermarkOperationConfig,
|
||||||
settingsComponent: AddWatermarkSingleStepSettings
|
settingsComponent: AddWatermarkSingleStepSettings
|
||||||
@ -103,8 +103,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.AddStampRequest.desc", "Add text or add image stamps at set locations"),
|
description: t("home.AddStampRequest.desc", "Add text or add image stamps at set locations"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY
|
||||||
},
|
},
|
||||||
"sanitize": {
|
"sanitize": {
|
||||||
icon: <span className="material-symbols-rounded">cleaning_services</span>,
|
icon: <span className="material-symbols-rounded">cleaning_services</span>,
|
||||||
@ -112,8 +112,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: Sanitize,
|
component: Sanitize,
|
||||||
view: "security",
|
view: "security",
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY,
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
|
||||||
description: t("home.sanitize.desc", "Remove potentially harmful elements from PDF files"),
|
description: t("home.sanitize.desc", "Remove potentially harmful elements from PDF files"),
|
||||||
endpoints: ["sanitize-pdf"],
|
endpoints: ["sanitize-pdf"],
|
||||||
operationConfig: sanitizeOperationConfig,
|
operationConfig: sanitizeOperationConfig,
|
||||||
@ -125,8 +125,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.flatten.desc", "Remove all interactive elements and forms from a PDF"),
|
description: t("home.flatten.desc", "Remove all interactive elements and forms from a PDF"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY
|
||||||
},
|
},
|
||||||
"unlock-pdf-forms": {
|
"unlock-pdf-forms": {
|
||||||
icon: <span className="material-symbols-rounded">preview_off</span>,
|
icon: <span className="material-symbols-rounded">preview_off</span>,
|
||||||
@ -134,8 +134,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: UnlockPdfForms,
|
component: UnlockPdfForms,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.unlockPDFForms.desc", "Remove read-only property of form fields in a PDF document."),
|
description: t("home.unlockPDFForms.desc", "Remove read-only property of form fields in a PDF document."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY,
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["unlock-pdf-forms"],
|
endpoints: ["unlock-pdf-forms"],
|
||||||
operationConfig: unlockPdfFormsOperationConfig,
|
operationConfig: unlockPdfFormsOperationConfig,
|
||||||
@ -147,8 +147,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.manageCertificates.desc", "Import, export, or delete digital certificate files used for signing PDFs."),
|
description: t("home.manageCertificates.desc", "Import, export, or delete digital certificate files used for signing PDFs."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY
|
||||||
},
|
},
|
||||||
"change-permissions": {
|
"change-permissions": {
|
||||||
icon: <span className="material-symbols-rounded">lock</span>,
|
icon: <span className="material-symbols-rounded">lock</span>,
|
||||||
@ -156,8 +156,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: ChangePermissions,
|
component: ChangePermissions,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.changePermissions.desc", "Change document restrictions and permissions"),
|
description: t("home.changePermissions.desc", "Change document restrictions and permissions"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_SECURITY,
|
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["add-password"],
|
endpoints: ["add-password"],
|
||||||
operationConfig: changePermissionsOperationConfig,
|
operationConfig: changePermissionsOperationConfig,
|
||||||
@ -171,8 +171,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "extract",
|
view: "extract",
|
||||||
description: t("home.getPdfInfo.desc", "Grabs any and all information possible on PDFs"),
|
description: t("home.getPdfInfo.desc", "Grabs any and all information possible on PDFs"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.VERIFICATION
|
subcategoryId: SubcategoryId.VERIFICATION
|
||||||
},
|
},
|
||||||
"validate-pdf-signature": {
|
"validate-pdf-signature": {
|
||||||
icon: <span className="material-symbols-rounded">verified</span>,
|
icon: <span className="material-symbols-rounded">verified</span>,
|
||||||
@ -180,8 +180,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.validateSignature.desc", "Verify digital signatures and certificates in PDF documents"),
|
description: t("home.validateSignature.desc", "Verify digital signatures and certificates in PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.VERIFICATION
|
subcategoryId: SubcategoryId.VERIFICATION
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -193,8 +193,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "view",
|
view: "view",
|
||||||
description: t("home.read.desc", "View and annotate PDFs. Highlight text, draw, or insert comments for review and collaboration."),
|
description: t("home.read.desc", "View and annotate PDFs. Highlight text, draw, or insert comments for review and collaboration."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_REVIEW
|
subcategoryId: SubcategoryId.DOCUMENT_REVIEW
|
||||||
},
|
},
|
||||||
"change-metadata": {
|
"change-metadata": {
|
||||||
icon: <span className="material-symbols-rounded">assignment</span>,
|
icon: <span className="material-symbols-rounded">assignment</span>,
|
||||||
@ -202,8 +202,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.changeMetadata.desc", "Change/Remove/Add metadata from a PDF document"),
|
description: t("home.changeMetadata.desc", "Change/Remove/Add metadata from a PDF document"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.DOCUMENT_REVIEW
|
subcategoryId: SubcategoryId.DOCUMENT_REVIEW
|
||||||
},
|
},
|
||||||
// Page Formatting
|
// Page Formatting
|
||||||
|
|
||||||
@ -213,8 +213,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.crop.desc", "Crop a PDF to reduce its size (maintains text!)"),
|
description: t("home.crop.desc", "Crop a PDF to reduce its size (maintains text!)"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"rotate": {
|
"rotate": {
|
||||||
icon: <span className="material-symbols-rounded">rotate_right</span>,
|
icon: <span className="material-symbols-rounded">rotate_right</span>,
|
||||||
@ -222,8 +222,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.rotate.desc", "Easily rotate your PDFs."),
|
description: t("home.rotate.desc", "Easily rotate your PDFs."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"splitPdf": {
|
"splitPdf": {
|
||||||
icon: <span className="material-symbols-rounded">content_cut</span>,
|
icon: <span className="material-symbols-rounded">content_cut</span>,
|
||||||
@ -231,8 +231,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: SplitPdfPanel,
|
component: SplitPdfPanel,
|
||||||
view: "split",
|
view: "split",
|
||||||
description: t("home.split.desc", "Split PDFs into multiple documents"),
|
description: t("home.split.desc", "Split PDFs into multiple documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING,
|
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||||
operationConfig: splitOperationConfig,
|
operationConfig: splitOperationConfig,
|
||||||
settingsComponent: SplitSettings
|
settingsComponent: SplitSettings
|
||||||
},
|
},
|
||||||
@ -242,8 +242,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "pageEditor",
|
view: "pageEditor",
|
||||||
description: t("home.reorganizePages.desc", "Rearrange, duplicate, or delete PDF pages with visual drag-and-drop control."),
|
description: t("home.reorganizePages.desc", "Rearrange, duplicate, or delete PDF pages with visual drag-and-drop control."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"adjust-page-size-scale": {
|
"adjust-page-size-scale": {
|
||||||
icon: <span className="material-symbols-rounded">crop_free</span>,
|
icon: <span className="material-symbols-rounded">crop_free</span>,
|
||||||
@ -251,8 +251,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.scalePages.desc", "Change the size/scale of a page and/or its contents."),
|
description: t("home.scalePages.desc", "Change the size/scale of a page and/or its contents."),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"addPageNumbers": {
|
"addPageNumbers": {
|
||||||
icon: <span className="material-symbols-rounded">123</span>,
|
icon: <span className="material-symbols-rounded">123</span>,
|
||||||
@ -260,8 +260,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.addPageNumbers.desc", "Add Page numbers throughout a document in a set location"),
|
description: t("home.addPageNumbers.desc", "Add Page numbers throughout a document in a set location"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"multi-page-layout": {
|
"multi-page-layout": {
|
||||||
icon: <span className="material-symbols-rounded">dashboard</span>,
|
icon: <span className="material-symbols-rounded">dashboard</span>,
|
||||||
@ -269,8 +269,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.pageLayout.desc", "Merge multiple pages of a PDF document into a single page"),
|
description: t("home.pageLayout.desc", "Merge multiple pages of a PDF document into a single page"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING
|
subcategoryId: SubcategoryId.PAGE_FORMATTING
|
||||||
},
|
},
|
||||||
"single-large-page": {
|
"single-large-page": {
|
||||||
icon: <span className="material-symbols-rounded">looks_one</span>,
|
icon: <span className="material-symbols-rounded">looks_one</span>,
|
||||||
@ -278,8 +278,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: SingleLargePage,
|
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,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING,
|
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["pdf-to-single-page"],
|
endpoints: ["pdf-to-single-page"],
|
||||||
operationConfig: singleLargePageOperationConfig
|
operationConfig: singleLargePageOperationConfig
|
||||||
@ -290,8 +290,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.attachments.desc", "Add or remove embedded files (attachments) to/from a PDF"),
|
description: t("home.attachments.desc", "Add or remove embedded files (attachments) to/from a PDF"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.PAGE_FORMATTING,
|
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -303,8 +303,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "extract",
|
view: "extract",
|
||||||
description: t("home.extractPages.desc", "Extract specific pages from a PDF document"),
|
description: t("home.extractPages.desc", "Extract specific pages from a PDF document"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.EXTRACTION
|
subcategoryId: SubcategoryId.EXTRACTION
|
||||||
},
|
},
|
||||||
"extract-images": {
|
"extract-images": {
|
||||||
icon: <span className="material-symbols-rounded">filter</span>,
|
icon: <span className="material-symbols-rounded">filter</span>,
|
||||||
@ -312,8 +312,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "extract",
|
view: "extract",
|
||||||
description: t("home.extractImages.desc", "Extract images from PDF documents"),
|
description: t("home.extractImages.desc", "Extract images from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.EXTRACTION
|
subcategoryId: SubcategoryId.EXTRACTION
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -325,8 +325,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "remove",
|
view: "remove",
|
||||||
description: t("home.removePages.desc", "Remove specific pages from a PDF document"),
|
description: t("home.removePages.desc", "Remove specific pages from a PDF document"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL
|
subcategoryId: SubcategoryId.REMOVAL
|
||||||
},
|
},
|
||||||
"remove-blank-pages": {
|
"remove-blank-pages": {
|
||||||
icon: <span className="material-symbols-rounded">scan_delete</span>,
|
icon: <span className="material-symbols-rounded">scan_delete</span>,
|
||||||
@ -334,8 +334,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "remove",
|
view: "remove",
|
||||||
description: t("home.removeBlanks.desc", "Remove blank pages from PDF documents"),
|
description: t("home.removeBlanks.desc", "Remove blank pages from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL
|
subcategoryId: SubcategoryId.REMOVAL
|
||||||
},
|
},
|
||||||
"remove-annotations": {
|
"remove-annotations": {
|
||||||
icon: <span className="material-symbols-rounded">thread_unread</span>,
|
icon: <span className="material-symbols-rounded">thread_unread</span>,
|
||||||
@ -343,8 +343,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "remove",
|
view: "remove",
|
||||||
description: t("home.removeAnnotations.desc", "Remove annotations and comments from PDF documents"),
|
description: t("home.removeAnnotations.desc", "Remove annotations and comments from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL
|
subcategoryId: SubcategoryId.REMOVAL
|
||||||
},
|
},
|
||||||
"remove-image": {
|
"remove-image": {
|
||||||
icon: <span className="material-symbols-rounded">remove_selection</span>,
|
icon: <span className="material-symbols-rounded">remove_selection</span>,
|
||||||
@ -352,8 +352,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.removeImagePdf.desc", "Remove images from PDF documents"),
|
description: t("home.removeImagePdf.desc", "Remove images from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL
|
subcategoryId: SubcategoryId.REMOVAL
|
||||||
},
|
},
|
||||||
"remove-password": {
|
"remove-password": {
|
||||||
icon: <span className="material-symbols-rounded">lock_open_right</span>,
|
icon: <span className="material-symbols-rounded">lock_open_right</span>,
|
||||||
@ -361,8 +361,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: RemovePassword,
|
component: RemovePassword,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.removePassword.desc", "Remove password protection from PDF documents"),
|
description: t("home.removePassword.desc", "Remove password protection from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL,
|
subcategoryId: SubcategoryId.REMOVAL,
|
||||||
endpoints: ["remove-password"],
|
endpoints: ["remove-password"],
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
operationConfig: removePasswordOperationConfig,
|
operationConfig: removePasswordOperationConfig,
|
||||||
@ -374,8 +374,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: RemoveCertificateSign,
|
component: RemoveCertificateSign,
|
||||||
view: "security",
|
view: "security",
|
||||||
description: t("home.removeCertSign.desc", "Remove digital signature from PDF documents"),
|
description: t("home.removeCertSign.desc", "Remove digital signature from PDF documents"),
|
||||||
category: ToolCategory.STANDARD_TOOLS,
|
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||||
subcategory: SubcategoryId.REMOVAL,
|
subcategoryId: SubcategoryId.REMOVAL,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["remove-certificate-sign"],
|
endpoints: ["remove-certificate-sign"],
|
||||||
operationConfig: removeCertificateSignOperationConfig
|
operationConfig: removeCertificateSignOperationConfig
|
||||||
@ -390,8 +390,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: React.lazy(() => import('../tools/Automate')),
|
component: React.lazy(() => import('../tools/Automate')),
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.automate.desc", "Build multi-step workflows by chaining together PDF actions. Ideal for recurring tasks."),
|
description: t("home.automate.desc", "Build multi-step workflows by chaining together PDF actions. Ideal for recurring tasks."),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.AUTOMATION,
|
subcategoryId: SubcategoryId.AUTOMATION,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["handleData"]
|
endpoints: ["handleData"]
|
||||||
},
|
},
|
||||||
@ -401,8 +401,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.auto-rename.desc", "Automatically rename PDF files based on their content"),
|
description: t("home.auto-rename.desc", "Automatically rename PDF files based on their content"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.AUTOMATION
|
subcategoryId: SubcategoryId.AUTOMATION
|
||||||
},
|
},
|
||||||
"auto-split-pages": {
|
"auto-split-pages": {
|
||||||
icon: <span className="material-symbols-rounded">split_scene_right</span>,
|
icon: <span className="material-symbols-rounded">split_scene_right</span>,
|
||||||
@ -410,8 +410,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.autoSplitPDF.desc", "Automatically split PDF pages based on content detection"),
|
description: t("home.autoSplitPDF.desc", "Automatically split PDF pages based on content detection"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.AUTOMATION
|
subcategoryId: SubcategoryId.AUTOMATION
|
||||||
},
|
},
|
||||||
"auto-split-by-size-count": {
|
"auto-split-by-size-count": {
|
||||||
icon: <span className="material-symbols-rounded">content_cut</span>,
|
icon: <span className="material-symbols-rounded">content_cut</span>,
|
||||||
@ -419,8 +419,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.autoSizeSplitPDF.desc", "Automatically split PDFs by file size or page count"),
|
description: t("home.autoSizeSplitPDF.desc", "Automatically split PDFs by file size or page count"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.AUTOMATION
|
subcategoryId: SubcategoryId.AUTOMATION
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -432,8 +432,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.adjustContrast.desc", "Adjust colors and contrast of PDF documents"),
|
description: t("home.adjustContrast.desc", "Adjust colors and contrast of PDF documents"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"repair": {
|
"repair": {
|
||||||
icon: <span className="material-symbols-rounded">build</span>,
|
icon: <span className="material-symbols-rounded">build</span>,
|
||||||
@ -441,8 +441,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: Repair,
|
component: Repair,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.repair.desc", "Repair corrupted or damaged PDF files"),
|
description: t("home.repair.desc", "Repair corrupted or damaged PDF files"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING,
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: ["repair"],
|
endpoints: ["repair"],
|
||||||
operationConfig: repairOperationConfig,
|
operationConfig: repairOperationConfig,
|
||||||
@ -454,8 +454,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.ScannerImageSplit.desc", "Detect and split scanned photos into separate pages"),
|
description: t("home.ScannerImageSplit.desc", "Detect and split scanned photos into separate pages"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"overlay-pdfs": {
|
"overlay-pdfs": {
|
||||||
icon: <span className="material-symbols-rounded">layers</span>,
|
icon: <span className="material-symbols-rounded">layers</span>,
|
||||||
@ -463,8 +463,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.overlay-pdfs.desc", "Overlay one PDF on top of another"),
|
description: t("home.overlay-pdfs.desc", "Overlay one PDF on top of another"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"replace-and-invert-color": {
|
"replace-and-invert-color": {
|
||||||
icon: <span className="material-symbols-rounded">format_color_fill</span>,
|
icon: <span className="material-symbols-rounded">format_color_fill</span>,
|
||||||
@ -472,8 +472,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.replaceColorPdf.desc", "Replace or invert colors in PDF documents"),
|
description: t("home.replaceColorPdf.desc", "Replace or invert colors in PDF documents"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"add-image": {
|
"add-image": {
|
||||||
icon: <span className="material-symbols-rounded">image</span>,
|
icon: <span className="material-symbols-rounded">image</span>,
|
||||||
@ -481,8 +481,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.addImage.desc", "Add images to PDF documents"),
|
description: t("home.addImage.desc", "Add images to PDF documents"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"edit-table-of-contents": {
|
"edit-table-of-contents": {
|
||||||
icon: <span className="material-symbols-rounded">bookmark_add</span>,
|
icon: <span className="material-symbols-rounded">bookmark_add</span>,
|
||||||
@ -490,8 +490,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.editTableOfContents.desc", "Add or edit bookmarks and table of contents in PDF documents"),
|
description: t("home.editTableOfContents.desc", "Add or edit bookmarks and table of contents in PDF documents"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
"scanner-effect": {
|
"scanner-effect": {
|
||||||
icon: <span className="material-symbols-rounded">scanner</span>,
|
icon: <span className="material-symbols-rounded">scanner</span>,
|
||||||
@ -499,8 +499,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.fakeScan.desc", "Create a PDF that looks like it was scanned"),
|
description: t("home.fakeScan.desc", "Create a PDF that looks like it was scanned"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.ADVANCED_FORMATTING
|
subcategoryId: SubcategoryId.ADVANCED_FORMATTING
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -512,8 +512,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "extract",
|
view: "extract",
|
||||||
description: t("home.showJS.desc", "Extract and display JavaScript code from PDF documents"),
|
description: t("home.showJS.desc", "Extract and display JavaScript code from PDF documents"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.DEVELOPER_TOOLS
|
subcategoryId: SubcategoryId.DEVELOPER_TOOLS
|
||||||
},
|
},
|
||||||
"dev-api": {
|
"dev-api": {
|
||||||
icon: <span className="material-symbols-rounded" style={{ color: '#2F7BF6' }}>open_in_new</span>,
|
icon: <span className="material-symbols-rounded" style={{ color: '#2F7BF6' }}>open_in_new</span>,
|
||||||
@ -521,8 +521,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "external",
|
view: "external",
|
||||||
description: t("home.devApi.desc", "Link to API documentation"),
|
description: t("home.devApi.desc", "Link to API documentation"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.DEVELOPER_TOOLS,
|
subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
|
||||||
link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html"
|
link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html"
|
||||||
},
|
},
|
||||||
"dev-folder-scanning": {
|
"dev-folder-scanning": {
|
||||||
@ -531,8 +531,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "external",
|
view: "external",
|
||||||
description: t("home.devFolderScanning.desc", "Link to automated folder scanning guide"),
|
description: t("home.devFolderScanning.desc", "Link to automated folder scanning guide"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.DEVELOPER_TOOLS,
|
subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
|
||||||
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/"
|
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/"
|
||||||
},
|
},
|
||||||
"dev-sso-guide": {
|
"dev-sso-guide": {
|
||||||
@ -541,8 +541,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "external",
|
view: "external",
|
||||||
description: t("home.devSsoGuide.desc", "Link to SSO guide"),
|
description: t("home.devSsoGuide.desc", "Link to SSO guide"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.DEVELOPER_TOOLS,
|
subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
|
||||||
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration",
|
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration",
|
||||||
},
|
},
|
||||||
"dev-airgapped": {
|
"dev-airgapped": {
|
||||||
@ -551,8 +551,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "external",
|
view: "external",
|
||||||
description: t("home.devAirgapped.desc", "Link to air-gapped setup guide"),
|
description: t("home.devAirgapped.desc", "Link to air-gapped setup guide"),
|
||||||
category: ToolCategory.ADVANCED_TOOLS,
|
categoryId: ToolCategoryId.ADVANCED_TOOLS,
|
||||||
subcategory: SubcategoryId.DEVELOPER_TOOLS,
|
subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
|
||||||
link: "https://docs.stirlingpdf.com/Pro/#activation"
|
link: "https://docs.stirlingpdf.com/Pro/#activation"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -564,8 +564,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "format",
|
view: "format",
|
||||||
description: t("home.compare.desc", "Compare two PDF documents and highlight differences"),
|
description: t("home.compare.desc", "Compare two PDF documents and highlight differences"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL
|
subcategoryId: SubcategoryId.GENERAL
|
||||||
},
|
},
|
||||||
"compress": {
|
"compress": {
|
||||||
icon: <span className="material-symbols-rounded">zoom_in_map</span>,
|
icon: <span className="material-symbols-rounded">zoom_in_map</span>,
|
||||||
@ -573,8 +573,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: CompressPdfPanel,
|
component: CompressPdfPanel,
|
||||||
view: "compress",
|
view: "compress",
|
||||||
description: t("home.compress.desc", "Compress PDFs to reduce their file size."),
|
description: t("home.compress.desc", "Compress PDFs to reduce their file size."),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
operationConfig: compressOperationConfig,
|
operationConfig: compressOperationConfig,
|
||||||
settingsComponent: CompressSettings
|
settingsComponent: CompressSettings
|
||||||
@ -585,8 +585,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: ConvertPanel,
|
component: ConvertPanel,
|
||||||
view: "convert",
|
view: "convert",
|
||||||
description: t("home.convert.desc", "Convert files to and from PDF format"),
|
description: t("home.convert.desc", "Convert files to and from PDF format"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
endpoints: [
|
endpoints: [
|
||||||
"pdf-to-img",
|
"pdf-to-img",
|
||||||
@ -631,8 +631,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "merge",
|
view: "merge",
|
||||||
description: t("home.merge.desc", "Merge multiple PDFs into a single document"),
|
description: t("home.merge.desc", "Merge multiple PDFs into a single document"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
maxFiles: -1
|
maxFiles: -1
|
||||||
},
|
},
|
||||||
"multi-tool": {
|
"multi-tool": {
|
||||||
@ -641,8 +641,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "pageEditor",
|
view: "pageEditor",
|
||||||
description: t("home.multiTool.desc", "Use multiple tools on a single PDF document"),
|
description: t("home.multiTool.desc", "Use multiple tools on a single PDF document"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
maxFiles: -1
|
maxFiles: -1
|
||||||
},
|
},
|
||||||
"ocr": {
|
"ocr": {
|
||||||
@ -651,8 +651,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: OCRPanel,
|
component: OCRPanel,
|
||||||
view: "convert",
|
view: "convert",
|
||||||
description: t("home.ocr.desc", "Extract text from scanned PDFs using Optical Character Recognition"),
|
description: t("home.ocr.desc", "Extract text from scanned PDFs using Optical Character Recognition"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL,
|
subcategoryId: SubcategoryId.GENERAL,
|
||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
operationConfig: ocrOperationConfig,
|
operationConfig: ocrOperationConfig,
|
||||||
settingsComponent: OCRSettings
|
settingsComponent: OCRSettings
|
||||||
@ -663,8 +663,8 @@ export function useFlatToolRegistry(): ToolRegistry {
|
|||||||
component: null,
|
component: null,
|
||||||
view: "redact",
|
view: "redact",
|
||||||
description: t("home.redact.desc", "Permanently remove sensitive information from PDF documents"),
|
description: t("home.redact.desc", "Permanently remove sensitive information from PDF documents"),
|
||||||
category: ToolCategory.RECOMMENDED_TOOLS,
|
categoryId: ToolCategoryId.RECOMMENDED_TOOLS,
|
||||||
subcategory: SubcategoryId.GENERAL
|
subcategoryId: SubcategoryId.GENERAL
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import CropIcon from '@mui/icons-material/Crop';
|
|||||||
import TextFieldsIcon from '@mui/icons-material/TextFields';
|
import TextFieldsIcon from '@mui/icons-material/TextFields';
|
||||||
|
|
||||||
export interface SuggestedTool {
|
export interface SuggestedTool {
|
||||||
name: string;
|
id: string /* FIX ME: Should be ToolId */;
|
||||||
title: string;
|
title: string;
|
||||||
icon: React.ComponentType<any>;
|
icon: React.ComponentType<any>;
|
||||||
navigate: () => void;
|
navigate: () => void;
|
||||||
@ -17,27 +17,27 @@ export interface SuggestedTool {
|
|||||||
|
|
||||||
const ALL_SUGGESTED_TOOLS: Omit<SuggestedTool, 'navigate'>[] = [
|
const ALL_SUGGESTED_TOOLS: Omit<SuggestedTool, 'navigate'>[] = [
|
||||||
{
|
{
|
||||||
name: 'compress',
|
id: 'compress',
|
||||||
title: 'Compress',
|
title: 'Compress',
|
||||||
icon: CompressIcon
|
icon: CompressIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'convert',
|
id: 'convert',
|
||||||
title: 'Convert',
|
title: 'Convert',
|
||||||
icon: SwapHorizIcon
|
icon: SwapHorizIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'sanitize',
|
id: 'sanitize',
|
||||||
title: 'Sanitize',
|
title: 'Sanitize',
|
||||||
icon: CleaningServicesIcon
|
icon: CleaningServicesIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'split',
|
id: 'split',
|
||||||
title: 'Split',
|
title: 'Split',
|
||||||
icon: CropIcon
|
icon: CropIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ocr',
|
id: 'ocr',
|
||||||
title: 'OCR',
|
title: 'OCR',
|
||||||
icon: TextFieldsIcon
|
icon: TextFieldsIcon
|
||||||
}
|
}
|
||||||
@ -49,12 +49,12 @@ export function useSuggestedTools(): SuggestedTool[] {
|
|||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
// Filter out the current tool
|
// Filter out the current tool
|
||||||
const filteredTools = ALL_SUGGESTED_TOOLS.filter(tool => tool.name !== selectedToolKey);
|
const filteredTools = ALL_SUGGESTED_TOOLS.filter(tool => tool.id !== selectedToolKey);
|
||||||
|
|
||||||
// Add navigation function to each tool
|
// Add navigation function to each tool
|
||||||
return filteredTools.map(tool => ({
|
return filteredTools.map(tool => ({
|
||||||
...tool,
|
...tool,
|
||||||
navigate: () => actions.handleToolSelect(tool.name)
|
navigate: () => actions.handleToolSelect(tool.id)
|
||||||
}));
|
}));
|
||||||
}, [selectedToolKey, actions]);
|
}, [selectedToolKey, actions]);
|
||||||
}
|
}
|
||||||
|
@ -1,65 +1,87 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { SUBCATEGORY_ORDER, ToolCategory, ToolRegistryEntry } from '../data/toolsTaxonomy';
|
import { SUBCATEGORY_ORDER, SubcategoryId, ToolCategoryId, ToolRegistryEntry } from '../data/toolsTaxonomy';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
type SubcategoryIdMap = {
|
||||||
|
[subcategoryId in SubcategoryId]: Array<{ id: string /* FIX ME: Should be ToolId */; tool: ToolRegistryEntry }>;
|
||||||
|
}
|
||||||
|
|
||||||
type GroupedTools = {
|
type GroupedTools = {
|
||||||
[category: string]: {
|
[categoryId in ToolCategoryId]: SubcategoryIdMap;
|
||||||
[subcategory: string]: Array<{ id: string; tool: ToolRegistryEntry }>;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useToolSections(filteredTools: [string, ToolRegistryEntry][]) {
|
export interface SubcategoryGroup {
|
||||||
|
subcategoryId: SubcategoryId;
|
||||||
|
tools: {
|
||||||
|
id: string /* FIX ME: Should be ToolId */;
|
||||||
|
tool: ToolRegistryEntry;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ToolSectionKey = 'quick' | 'all';
|
||||||
|
|
||||||
|
export interface ToolSection {
|
||||||
|
key: ToolSectionKey;
|
||||||
|
title: string;
|
||||||
|
subcategories: SubcategoryGroup[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useToolSections(filteredTools: [string /* FIX ME: Should be ToolId */, ToolRegistryEntry][]) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const groupedTools = useMemo(() => {
|
const groupedTools = useMemo(() => {
|
||||||
const grouped: GroupedTools = {};
|
const grouped = {} as GroupedTools;
|
||||||
filteredTools.forEach(([id, tool]) => {
|
filteredTools.forEach(([id, tool]) => {
|
||||||
const category = tool.category;
|
const categoryId = tool.categoryId;
|
||||||
const subcategory = tool.subcategory;
|
const subcategoryId = tool.subcategoryId;
|
||||||
if (!grouped[category]) grouped[category] = {};
|
if (!grouped[categoryId]) grouped[categoryId] = {} as SubcategoryIdMap;
|
||||||
if (!grouped[category][subcategory]) grouped[category][subcategory] = [];
|
if (!grouped[categoryId][subcategoryId]) grouped[categoryId][subcategoryId] = [];
|
||||||
grouped[category][subcategory].push({ id, tool });
|
grouped[categoryId][subcategoryId].push({ id, tool });
|
||||||
});
|
});
|
||||||
return grouped;
|
return grouped;
|
||||||
}, [filteredTools]);
|
}, [filteredTools]);
|
||||||
|
|
||||||
const sections = useMemo(() => {
|
const sections: ToolSection[] = useMemo(() => {
|
||||||
const getOrderIndex = (name: string) => {
|
const getOrderIndex = (id: SubcategoryId) => {
|
||||||
const idx = SUBCATEGORY_ORDER.indexOf(name as any);
|
const idx = SUBCATEGORY_ORDER.indexOf(id);
|
||||||
return idx === -1 ? Number.MAX_SAFE_INTEGER : idx;
|
return idx === -1 ? Number.MAX_SAFE_INTEGER : idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
const quick: Record<string, Array<{ id: string; tool: ToolRegistryEntry }>> = {};
|
const quick = {} as SubcategoryIdMap;
|
||||||
const all: Record<string, Array<{ id: string; tool: ToolRegistryEntry }>> = {};
|
const all = {} as SubcategoryIdMap;
|
||||||
|
|
||||||
Object.entries(groupedTools).forEach(([origCat, subs]) => {
|
Object.entries(groupedTools).forEach(([c, subs]) => {
|
||||||
const upperCat = origCat.toUpperCase();
|
const categoryId = c as ToolCategoryId;
|
||||||
|
|
||||||
Object.entries(subs).forEach(([sub, tools]) => {
|
Object.entries(subs).forEach(([s, tools]) => {
|
||||||
if (!all[sub]) all[sub] = [];
|
const subcategoryId = s as SubcategoryId;
|
||||||
all[sub].push(...tools);
|
if (!all[subcategoryId]) all[subcategoryId] = [];
|
||||||
|
all[subcategoryId].push(...tools);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (upperCat === ToolCategory.RECOMMENDED_TOOLS.toUpperCase()) {
|
if (categoryId === ToolCategoryId.RECOMMENDED_TOOLS) {
|
||||||
Object.entries(subs).forEach(([sub, tools]) => {
|
Object.entries(subs).forEach(([s, tools]) => {
|
||||||
if (!quick[sub]) quick[sub] = [];
|
const subcategoryId = s as SubcategoryId;
|
||||||
quick[sub].push(...tools);
|
if (!quick[subcategoryId]) quick[subcategoryId] = [];
|
||||||
|
quick[subcategoryId].push(...tools);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const sortSubs = (obj: Record<string, Array<{ id: string; tool: ToolRegistryEntry }>>) =>
|
const sortSubs = (obj: SubcategoryIdMap) =>
|
||||||
Object.entries(obj)
|
Object.entries(obj)
|
||||||
.sort(([a], [b]) => {
|
.sort(([a], [b]) => {
|
||||||
const ai = getOrderIndex(a);
|
const aId = a as SubcategoryId;
|
||||||
const bi = getOrderIndex(b);
|
const bId = b as SubcategoryId;
|
||||||
|
const ai = getOrderIndex(aId);
|
||||||
|
const bi = getOrderIndex(bId);
|
||||||
if (ai !== bi) return ai - bi;
|
if (ai !== bi) return ai - bi;
|
||||||
return a.localeCompare(b);
|
return aId.localeCompare(bId);
|
||||||
})
|
})
|
||||||
.map(([subcategory, tools]) => ({ subcategory, tools }));
|
.map(([subcategoryId, tools]) => ({ subcategoryId, tools } as SubcategoryGroup));
|
||||||
|
|
||||||
const built = [
|
const built: ToolSection[] = [
|
||||||
{ key: 'quick', title: t('toolPicker.quickAccess', 'QUICK ACCESS'), subcategories: sortSubs(quick) },
|
{ key: 'quick', title: t('toolPicker.quickAccess', 'QUICK ACCESS'), subcategories: sortSubs(quick) },
|
||||||
{ key: 'all', title: t('toolPicker.allTools', 'ALL TOOLS'), subcategories: sortSubs(all) }
|
{ key: 'all', title: t('toolPicker.allTools', 'ALL TOOLS'), subcategories: sortSubs(all) }
|
||||||
];
|
];
|
||||||
@ -67,19 +89,20 @@ export function useToolSections(filteredTools: [string, ToolRegistryEntry][]) {
|
|||||||
return built.filter(section => section.subcategories.some(sc => sc.tools.length > 0));
|
return built.filter(section => section.subcategories.some(sc => sc.tools.length > 0));
|
||||||
}, [groupedTools]);
|
}, [groupedTools]);
|
||||||
|
|
||||||
const searchGroups = useMemo(() => {
|
const searchGroups: SubcategoryGroup[] = useMemo(() => {
|
||||||
const subMap: Record<string, Array<{ id: string; tool: ToolRegistryEntry }>> = {};
|
const subMap = {} as SubcategoryIdMap;
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string /* FIX ME: Should be ToolId */>();
|
||||||
filteredTools.forEach(([id, tool]) => {
|
filteredTools.forEach(([id, tool]) => {
|
||||||
if (seen.has(id)) return;
|
const toolId = id as string /* FIX ME: Should be ToolId */;
|
||||||
seen.add(id);
|
if (seen.has(toolId)) return;
|
||||||
const sub = tool.subcategory;
|
seen.add(toolId);
|
||||||
|
const sub = tool.subcategoryId;
|
||||||
if (!subMap[sub]) subMap[sub] = [];
|
if (!subMap[sub]) subMap[sub] = [];
|
||||||
subMap[sub].push({ id, tool });
|
subMap[sub].push({ id: toolId, tool });
|
||||||
});
|
});
|
||||||
return Object.entries(subMap)
|
return Object.entries(subMap)
|
||||||
.sort(([a], [b]) => a.localeCompare(b))
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
.map(([subcategory, tools]) => ({ subcategory, tools }));
|
.map(([subcategoryId, tools]) => ({ subcategoryId, tools } as SubcategoryGroup));
|
||||||
}, [filteredTools]);
|
}, [filteredTools]);
|
||||||
|
|
||||||
return { sections, searchGroups };
|
return { sections, searchGroups };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user