mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-23 12:49:24 +00:00
Added optional title for tool workflow (#4256)
- Added optional title for tool workflow - Not added to any tool. Just there for when we need it - Added add files button to files step - renamed Local files button in filemanager to Upload Files - --------- Co-authored-by: Connor Yoh <connor@stirlingpdf.com> Co-authored-by: James Brunton <jbrunton96@gmail.com>
This commit is contained in:
parent
23d86deae7
commit
888bac9408
@ -1970,6 +1970,7 @@
|
||||
"dropFilesHere": "Drop files here or click to upload",
|
||||
"pdfFilesOnly": "PDF files only",
|
||||
"supportedFileTypes": "Supported file types",
|
||||
"upload": "Upload",
|
||||
"uploadFile": "Upload File",
|
||||
"uploadFiles": "Upload Files",
|
||||
"noFilesInStorage": "No files available in storage. Upload some files first.",
|
||||
|
@ -17,7 +17,7 @@ const FileInfoCard: React.FC<FileInfoCardProps> = ({
|
||||
|
||||
return (
|
||||
<Card withBorder p={0} h={`calc(${modalHeight} * 0.32 - 1rem)`} style={{ flex: 1, overflow: 'hidden' }}>
|
||||
<Box bg="blue.6" p="sm" style={{ borderTopLeftRadius: 'var(--mantine-radius-md)', borderTopRightRadius: 'var(--mantine-radius-md)' }}>
|
||||
<Box bg="gray.4" p="sm" style={{ borderTopLeftRadius: 'var(--mantine-radius-md)', borderTopRightRadius: 'var(--mantine-radius-md)' }}>
|
||||
<Text size="sm" fw={500} ta="center" c="white">
|
||||
{t('fileManager.details', 'File Details')}
|
||||
</Text>
|
||||
@ -31,7 +31,7 @@ const FileInfoCard: React.FC<FileInfoCardProps> = ({
|
||||
</Text>
|
||||
</Group>
|
||||
<Divider />
|
||||
|
||||
|
||||
<Group justify="space-between" py="xs">
|
||||
<Text size="sm" c="dimmed">{t('fileManager.fileFormat', 'Format')}</Text>
|
||||
{currentFile ? (
|
||||
@ -43,7 +43,7 @@ const FileInfoCard: React.FC<FileInfoCardProps> = ({
|
||||
)}
|
||||
</Group>
|
||||
<Divider />
|
||||
|
||||
|
||||
<Group justify="space-between" py="xs">
|
||||
<Text size="sm" c="dimmed">{t('fileManager.fileSize', 'Size')}</Text>
|
||||
<Text size="sm" fw={500}>
|
||||
@ -51,7 +51,7 @@ const FileInfoCard: React.FC<FileInfoCardProps> = ({
|
||||
</Text>
|
||||
</Group>
|
||||
<Divider />
|
||||
|
||||
|
||||
<Group justify="space-between" py="xs">
|
||||
<Text size="sm" c="dimmed">{t('fileManager.fileVersion', 'Version')}</Text>
|
||||
<Text size="sm" fw={500}>
|
||||
@ -64,4 +64,4 @@ const FileInfoCard: React.FC<FileInfoCardProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default FileInfoCard;
|
||||
export default FileInfoCard;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text, Button, Group } from '@mantine/core';
|
||||
import HistoryIcon from '@mui/icons-material/History';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import UploadIcon from '@mui/icons-material/Upload';
|
||||
import CloudIcon from '@mui/icons-material/Cloud';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useFileManagerContext } from '../../contexts/FileManagerContext';
|
||||
@ -10,7 +10,7 @@ interface FileSourceButtonsProps {
|
||||
horizontal?: boolean;
|
||||
}
|
||||
|
||||
const FileSourceButtons: React.FC<FileSourceButtonsProps> = ({
|
||||
const FileSourceButtons: React.FC<FileSourceButtonsProps> = ({
|
||||
horizontal = false
|
||||
}) => {
|
||||
const { activeSource, onSourceChange, onLocalFileClick } = useFileManagerContext();
|
||||
@ -44,11 +44,11 @@ const FileSourceButtons: React.FC<FileSourceButtonsProps> = ({
|
||||
>
|
||||
{horizontal ? t('fileManager.recent', 'Recent') : t('fileManager.recent', 'Recent')}
|
||||
</Button>
|
||||
|
||||
|
||||
<Button
|
||||
variant="subtle"
|
||||
color='var(--mantine-color-gray-6)'
|
||||
leftSection={<FolderIcon />}
|
||||
leftSection={<UploadIcon />}
|
||||
justify={horizontal ? "center" : "flex-start"}
|
||||
onClick={onLocalFileClick}
|
||||
fullWidth={!horizontal}
|
||||
@ -63,9 +63,9 @@ const FileSourceButtons: React.FC<FileSourceButtonsProps> = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
{horizontal ? t('fileManager.localFiles', 'Local') : t('fileManager.localFiles', 'Local Files')}
|
||||
{horizontal ? t('fileUpload.uploadFiles', 'Upload') : t('fileUpload.uploadFiles', 'Upload Files')}
|
||||
</Button>
|
||||
|
||||
|
||||
<Button
|
||||
variant={buttonProps.variant('drive')}
|
||||
leftSection={<CloudIcon />}
|
||||
@ -100,4 +100,4 @@ const FileSourceButtons: React.FC<FileSourceButtonsProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default FileSourceButtons;
|
||||
export default FileSourceButtons;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@mantine/core';
|
||||
import { Box, Center } from '@mantine/core';
|
||||
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
||||
import { FileMetadata } from '../../types/file';
|
||||
import DocumentThumbnail from './filePreview/DocumentThumbnail';
|
||||
import DocumentStack from './filePreview/DocumentStack';
|
||||
@ -38,7 +39,21 @@ const FilePreview: React.FC<FilePreviewProps> = ({
|
||||
onPrevious,
|
||||
onNext
|
||||
}) => {
|
||||
if (!file) return null;
|
||||
if (!file) {
|
||||
return (
|
||||
<Box style={{ width: '100%', height: '100%' }}>
|
||||
<Center style={{ width: '100%', height: '100%' }}>
|
||||
<InsertDriveFileIcon
|
||||
style={{
|
||||
fontSize: '4rem',
|
||||
color: 'var(--mantine-color-gray-4)',
|
||||
opacity: 0.6
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const hasMultipleFiles = totalFiles > 1;
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
import React from "react";
|
||||
import { Text } from "@mantine/core";
|
||||
import { Text, Anchor } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import { useFilesModalContext } from "../../../contexts/FilesModalContext";
|
||||
import { useAllFiles } from "../../../contexts/FileContext";
|
||||
|
||||
export interface FileStatusIndicatorProps {
|
||||
selectedFiles?: File[];
|
||||
@ -12,13 +15,39 @@ const FileStatusIndicator = ({
|
||||
placeholder,
|
||||
}: FileStatusIndicatorProps) => {
|
||||
const { t } = useTranslation();
|
||||
const defaultPlaceholder = placeholder || t("files.placeholder", "Select a PDF file in the main view to get started");
|
||||
|
||||
// Only show content when no files are selected
|
||||
const { openFilesModal } = useFilesModalContext();
|
||||
const { files: workbenchFiles } = useAllFiles();
|
||||
|
||||
// Check if there are no files in the workbench
|
||||
if (workbenchFiles.length === 0) {
|
||||
return (
|
||||
<Text size="sm" c="dimmed">
|
||||
{t("files.noFiles", "No files uploaded. ")}{" "}
|
||||
<Anchor
|
||||
size="sm"
|
||||
onClick={openFilesModal}
|
||||
style={{ cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: '4px' }}
|
||||
>
|
||||
<FolderIcon style={{ fontSize: '14px' }} />
|
||||
{t("files.addFiles", "Add files")}
|
||||
</Anchor>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
// Show selection status when there are files in workbench
|
||||
if (selectedFiles.length === 0) {
|
||||
return (
|
||||
<Text size="sm" c="dimmed">
|
||||
{defaultPlaceholder}
|
||||
{t("files.selectFromWorkbench", "Select files from the workbench or ") + " "}
|
||||
<Anchor
|
||||
size="sm"
|
||||
onClick={openFilesModal}
|
||||
style={{ cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: '4px' }}
|
||||
>
|
||||
<FolderIcon style={{ fontSize: '14px' }} />
|
||||
{t("files.addFiles", "Add files")}
|
||||
</Anchor>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ export interface ToolStepProps {
|
||||
_stepNumber?: number; // Internal prop set by ToolStepContainer
|
||||
_excludeFromCount?: boolean; // Internal prop to exclude from visible count calculation
|
||||
_noPadding?: boolean; // Internal prop to exclude from default left padding
|
||||
alwaysShowTooltip?: boolean; // Force tooltip to show even when collapsed
|
||||
tooltip?: {
|
||||
content?: React.ReactNode;
|
||||
tips?: TooltipTip[];
|
||||
@ -38,9 +39,10 @@ export interface ToolStepProps {
|
||||
const renderTooltipTitle = (
|
||||
title: string,
|
||||
tooltip: ToolStepProps['tooltip'],
|
||||
isCollapsed: boolean
|
||||
isCollapsed: boolean,
|
||||
alwaysShowTooltip: boolean = false
|
||||
) => {
|
||||
if (tooltip && !isCollapsed) {
|
||||
if (tooltip && (!isCollapsed || alwaysShowTooltip)) {
|
||||
return (
|
||||
<Tooltip
|
||||
content={tooltip.content}
|
||||
@ -77,6 +79,7 @@ const ToolStep = ({
|
||||
showNumber,
|
||||
_stepNumber,
|
||||
_noPadding,
|
||||
alwaysShowTooltip = false,
|
||||
tooltip
|
||||
}: ToolStepProps) => {
|
||||
if (!isVisible) return null;
|
||||
@ -118,7 +121,7 @@ const ToolStep = ({
|
||||
{stepNumber}
|
||||
</Text>
|
||||
)}
|
||||
{renderTooltipTitle(title, tooltip, isCollapsed)}
|
||||
{renderTooltipTitle(title, tooltip, isCollapsed, alwaysShowTooltip)}
|
||||
</Flex>
|
||||
|
||||
{isCollapsed ? (
|
||||
|
53
frontend/src/components/tools/shared/ToolWorkflowTitle.tsx
Normal file
53
frontend/src/components/tools/shared/ToolWorkflowTitle.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import { Flex, Text, Divider } from '@mantine/core';
|
||||
import { Tooltip } from '../../shared/Tooltip';
|
||||
|
||||
export interface ToolWorkflowTitleProps {
|
||||
title: string;
|
||||
tooltip?: {
|
||||
content?: React.ReactNode;
|
||||
tips?: any[];
|
||||
header?: {
|
||||
title: string;
|
||||
logo?: React.ReactNode;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function ToolWorkflowTitle({ title, tooltip }: ToolWorkflowTitleProps) {
|
||||
if (tooltip) {
|
||||
return (
|
||||
<>
|
||||
<Flex justify="center" w="100%">
|
||||
<Tooltip
|
||||
content={tooltip.content}
|
||||
tips={tooltip.tips}
|
||||
header={tooltip.header}
|
||||
sidebarTooltip={true}
|
||||
>
|
||||
<Flex align="center" gap="xs" onClick={(e) => e.stopPropagation()}>
|
||||
<Text fw={500} size="xl" p="md">
|
||||
{title}
|
||||
</Text>
|
||||
<span className="material-symbols-rounded" style={{ fontSize: '1.2rem', color: 'var(--icon-files-color)' }}>
|
||||
gpp_maybe
|
||||
</span>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
<Divider />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex justify="center" w="100%">
|
||||
<Text fw={500} size="xl" p="md">
|
||||
{title}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Divider />
|
||||
</>
|
||||
);
|
||||
}
|
@ -3,6 +3,7 @@ import { Stack } from '@mantine/core';
|
||||
import { createToolSteps, ToolStepProvider } from './ToolStep';
|
||||
import OperationButton from './OperationButton';
|
||||
import { ToolOperationHook } from '../../../hooks/tools/shared/useToolOperation';
|
||||
import { ToolWorkflowTitle, ToolWorkflowTitleProps } from './ToolWorkflowTitle';
|
||||
|
||||
export interface FilesStepConfig {
|
||||
selectedFiles: File[];
|
||||
@ -45,7 +46,10 @@ export interface ReviewStepConfig {
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
export interface TitleConfig extends ToolWorkflowTitleProps {}
|
||||
|
||||
export interface ToolFlowConfig {
|
||||
title?: TitleConfig;
|
||||
files: FilesStepConfig;
|
||||
steps: MiddleStepConfig[];
|
||||
executeButton?: ExecuteButtonConfig;
|
||||
@ -63,6 +67,8 @@ export function createToolFlow(config: ToolFlowConfig) {
|
||||
return (
|
||||
<Stack gap="sm" p="sm" h="95vh" w="100%" style={{ overflow: 'auto' }}>
|
||||
<ToolStepProvider forceStepNumbers={config.forceStepNumbers}>
|
||||
{config.title && <ToolWorkflowTitle {...config.title} />}
|
||||
|
||||
{/* Files Step */}
|
||||
{config.files.isVisible !== false && steps.createFilesStep({
|
||||
selectedFiles: config.files.selectedFiles,
|
||||
|
Loading…
x
Reference in New Issue
Block a user