mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
suggested tool structure
This commit is contained in:
parent
ee6f7a2939
commit
fa4098504a
@ -1,25 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Text, Box, Flex, ActionIcon, Tooltip } from '@mantine/core';
|
||||
import PushPinIcon from '@mui/icons-material/PushPin';
|
||||
import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
|
||||
import { useFileContext } from '../../../contexts/FileContext';
|
||||
import { Text } from '@mantine/core';
|
||||
|
||||
export interface FileStatusIndicatorProps {
|
||||
selectedFiles?: File[];
|
||||
isCompleted?: boolean;
|
||||
placeholder?: string;
|
||||
showFileName?: boolean;
|
||||
showPinControls?: boolean;
|
||||
}
|
||||
|
||||
const FileStatusIndicator = ({
|
||||
selectedFiles = [],
|
||||
isCompleted = false,
|
||||
placeholder = "Select a PDF file in the main view to get started",
|
||||
showFileName = true,
|
||||
showPinControls = true
|
||||
placeholder = "Select a PDF file in the main view to get started"
|
||||
}: FileStatusIndicatorProps) => {
|
||||
const { pinFile, unpinFile, isFilePinned } = useFileContext();
|
||||
|
||||
// Only show content when no files are selected
|
||||
if (selectedFiles.length === 0) {
|
||||
return (
|
||||
<Text size="sm" c="dimmed">
|
||||
@ -28,19 +20,8 @@ const FileStatusIndicator = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isCompleted) {
|
||||
return (
|
||||
<Text size="sm" c="green">
|
||||
✓ Selected: {showFileName ? selectedFiles[0]?.name : `${selectedFiles.length} file${selectedFiles.length > 1 ? 's' : ''}`}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Text size="sm" c="blue">
|
||||
Selected: {showFileName ? selectedFiles[0]?.name : `${selectedFiles.length} file${selectedFiles.length > 1 ? 's' : ''}`}
|
||||
</Text>
|
||||
);
|
||||
// Return nothing when files are selected
|
||||
return null;
|
||||
}
|
||||
|
||||
export default FileStatusIndicator;
|
@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text, Divider, SimpleGrid, Card, Group } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSuggestedTools } from '../../../hooks/useSuggestedTools';
|
||||
export interface SuggestedToolsSectionProps {}
|
||||
|
||||
export function SuggestedToolsSection(): React.ReactElement {
|
||||
const { t } = useTranslation();
|
||||
const suggestedTools = useSuggestedTools();
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Divider />
|
||||
|
||||
<Text size="lg" fw={600}>
|
||||
{t('editYourNewFiles', 'Edit your new File(s)')}
|
||||
</Text>
|
||||
|
||||
<SimpleGrid cols={2} spacing="sm">
|
||||
{suggestedTools.map((tool) => {
|
||||
const IconComponent = tool.icon;
|
||||
return (
|
||||
<Card
|
||||
key={tool.name}
|
||||
p="sm"
|
||||
withBorder
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={tool.navigate}
|
||||
>
|
||||
<Group gap="xs">
|
||||
<IconComponent fontSize="small" />
|
||||
<Text size="sm" fw={500}>
|
||||
{tool.title}
|
||||
</Text>
|
||||
</Group>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
);
|
||||
}
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import ErrorNotification from './ErrorNotification';
|
||||
import ReviewPanel from './ReviewPanel';
|
||||
import { SuggestedToolsSection } from './SuggestedToolsSection';
|
||||
import { ToolOperationHook } from '../../../hooks/tools/shared/useToolOperation';
|
||||
|
||||
export interface ReviewToolStepProps<TParams = any> {
|
||||
@ -31,10 +32,6 @@ export function createReviewToolStep<TParams = any>(
|
||||
_noPadding: true
|
||||
}, (
|
||||
<Stack gap="sm" >
|
||||
{operation.status && (
|
||||
<Text size="sm" c="dimmed">{operation.status}</Text>
|
||||
)}
|
||||
|
||||
<ErrorNotification
|
||||
error={operation.errorMessage}
|
||||
onClose={operation.clearError}
|
||||
@ -62,6 +59,8 @@ export function createReviewToolStep<TParams = any>(
|
||||
{t("download", "Download")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<SuggestedToolsSection />
|
||||
</Stack>
|
||||
));
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Stack } from '@mantine/core';
|
||||
import { createToolSteps, ToolStepProvider } from './ToolStep';
|
||||
import OperationButton from './OperationButton';
|
||||
import { ToolOperationHook } from '../../../hooks/tools/shared/useToolOperation';
|
||||
@ -58,6 +59,7 @@ export function createToolFlow(config: ToolFlowConfig) {
|
||||
const steps = createToolSteps();
|
||||
|
||||
return (
|
||||
<Stack gap="sm" p="sm" style={{ height: '100vh', overflow: 'auto' }}>
|
||||
<ToolStepProvider>
|
||||
{/* Files Step */}
|
||||
{steps.createFilesStep({
|
||||
@ -97,5 +99,6 @@ export function createToolFlow(config: ToolFlowConfig) {
|
||||
onFileClick: config.review.onFileClick
|
||||
})}
|
||||
</ToolStepProvider>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
59
frontend/src/hooks/useSuggestedTools.ts
Normal file
59
frontend/src/hooks/useSuggestedTools.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useToolWorkflow } from '../contexts/ToolWorkflowContext';
|
||||
|
||||
// Material UI Icons
|
||||
import CompressIcon from '@mui/icons-material/Compress';
|
||||
import SwapHorizIcon from '@mui/icons-material/SwapHoriz';
|
||||
import CleaningServicesIcon from '@mui/icons-material/CleaningServices';
|
||||
import CropIcon from '@mui/icons-material/Crop';
|
||||
import TextFieldsIcon from '@mui/icons-material/TextFields';
|
||||
|
||||
export interface SuggestedTool {
|
||||
name: string;
|
||||
title: string;
|
||||
icon: React.ComponentType<any>;
|
||||
navigate: () => void;
|
||||
}
|
||||
|
||||
const ALL_SUGGESTED_TOOLS: Omit<SuggestedTool, 'navigate'>[] = [
|
||||
{
|
||||
name: 'compress',
|
||||
title: 'Compress',
|
||||
icon: CompressIcon
|
||||
},
|
||||
{
|
||||
name: 'convert',
|
||||
title: 'Convert',
|
||||
icon: SwapHorizIcon
|
||||
},
|
||||
{
|
||||
name: 'sanitize',
|
||||
title: 'Sanitize',
|
||||
icon: CleaningServicesIcon
|
||||
},
|
||||
{
|
||||
name: 'split',
|
||||
title: 'Split',
|
||||
icon: CropIcon
|
||||
},
|
||||
{
|
||||
name: 'ocr',
|
||||
title: 'OCR',
|
||||
icon: TextFieldsIcon
|
||||
}
|
||||
];
|
||||
|
||||
export function useSuggestedTools(): SuggestedTool[] {
|
||||
const { handleToolSelect, selectedToolKey } = useToolWorkflow();
|
||||
|
||||
return useMemo(() => {
|
||||
// Filter out the current tool
|
||||
const filteredTools = ALL_SUGGESTED_TOOLS.filter(tool => tool.name !== selectedToolKey);
|
||||
|
||||
// Add navigation function to each tool
|
||||
return filteredTools.map(tool => ({
|
||||
...tool,
|
||||
navigate: () => handleToolSelect(tool.name)
|
||||
}));
|
||||
}, [selectedToolKey, handleToolSelect]);
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
@ -63,9 +62,7 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const hasResults = compressOperation.files.length > 0 || compressOperation.downloadUrl !== null;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
|
||||
return (
|
||||
<Stack gap="sm" p="sm" style={{ height: '100vh', overflow: 'auto' }}>
|
||||
{createToolFlow({
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasFiles && !hasResults,
|
||||
@ -96,9 +93,7 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
title: t("compress.title", "Compression Results"),
|
||||
onFileClick: handleThumbnailClick
|
||||
}
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
@ -100,9 +99,7 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
setCurrentMode('convert');
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack gap="sm" p="sm" style={{ height: '100vh', overflow: 'auto' }}>
|
||||
{createToolFlow({
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: filesCollapsed,
|
||||
@ -137,9 +134,7 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
onFileClick: handleThumbnailClick,
|
||||
testId: "conversion-results"
|
||||
}
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default Convert;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
@ -80,15 +79,12 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
};
|
||||
|
||||
|
||||
const filesCollapsed = expandedStep !== 'files';
|
||||
const settingsCollapsed = expandedStep !== 'settings';
|
||||
|
||||
return (
|
||||
<Stack gap="sm" p="sm" style={{ height: '100vh', overflow: 'auto' }}>
|
||||
{createToolFlow({
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: hasFiles && !hasResults && filesCollapsed,
|
||||
isCollapsed: hasFiles || hasResults,
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
@ -137,9 +133,7 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
title: t("ocr.results.title", "OCR Results"),
|
||||
onFileClick: handleThumbnailClick
|
||||
}
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default OCR;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useEffect } from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useToolFileSelection } from "../contexts/FileSelectionContext";
|
||||
@ -64,9 +63,7 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const filesCollapsed = hasFiles || hasResults;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
|
||||
return (
|
||||
<Stack gap="sm" p="sm" style={{ height: '100vh', overflow: 'auto' }}>
|
||||
{createToolFlow({
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: filesCollapsed,
|
||||
@ -97,9 +94,7 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
title: t("sanitize.sanitizationResults", "Sanitization Results"),
|
||||
onFileClick: handleThumbnailClick
|
||||
}
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default Sanitize;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileContext } from "../contexts/FileContext";
|
||||
@ -63,9 +62,7 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const filesCollapsed = hasFiles;
|
||||
const settingsCollapsed = !hasFiles || hasResults;
|
||||
|
||||
return (
|
||||
<Stack gap="sm" h="100%" p="sm" style={{ overflow: 'auto' }}>
|
||||
{createToolFlow({
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles,
|
||||
isCollapsed: filesCollapsed,
|
||||
@ -96,9 +93,7 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
title: "Split Results",
|
||||
onFileClick: handleThumbnailClick
|
||||
}
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default Split;
|
||||
|
Loading…
x
Reference in New Issue
Block a user