# Description of Changes - Addition of the get all info on PDF tool --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
189 lines
7.0 KiB
TypeScript
189 lines
7.0 KiB
TypeScript
import { useEffect, useMemo, useRef } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
|
|
import LinkIcon from '@mui/icons-material/Link';
|
|
import { Stack, Group, Divider, Text, UnstyledButton } from '@mantine/core';
|
|
import { createToolFlow } from '@app/components/tools/shared/createToolFlow';
|
|
import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool';
|
|
import { BaseToolProps, ToolComponent } from '@app/types/tool';
|
|
import { useGetPdfInfoParameters, defaultParameters } from '@app/hooks/tools/getPdfInfo/useGetPdfInfoParameters';
|
|
import GetPdfInfoResults from '@app/components/tools/getPdfInfo/GetPdfInfoResults';
|
|
import { useGetPdfInfoOperation, GetPdfInfoOperationHook } from '@app/hooks/tools/getPdfInfo/useGetPdfInfoOperation';
|
|
import GetPdfInfoReportView from '@app/components/tools/getPdfInfo/GetPdfInfoReportView';
|
|
import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext';
|
|
import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext';
|
|
import type { PdfInfoReportData } from '@app/types/getPdfInfo';
|
|
|
|
const CHAPTERS = [
|
|
{ id: 'summary', labelKey: 'getPdfInfo.summary.title', fallback: 'PDF Summary' },
|
|
{ id: 'metadata', labelKey: 'getPdfInfo.sections.metadata', fallback: 'Metadata' },
|
|
{ id: 'formFields', labelKey: 'getPdfInfo.sections.formFields', fallback: 'Form Fields' },
|
|
{ id: 'basicInfo', labelKey: 'getPdfInfo.sections.basicInfo', fallback: 'Basic Info' },
|
|
{ id: 'documentInfo', labelKey: 'getPdfInfo.sections.documentInfo', fallback: 'Document Info' },
|
|
{ id: 'compliance', labelKey: 'getPdfInfo.sections.compliance', fallback: 'Compliance' },
|
|
{ id: 'encryption', labelKey: 'getPdfInfo.sections.encryption', fallback: 'Encryption' },
|
|
{ id: 'permissions', labelKey: 'getPdfInfo.sections.permissions', fallback: 'Permissions' },
|
|
{ id: 'toc', labelKey: 'getPdfInfo.sections.tableOfContents', fallback: 'Table of Contents' },
|
|
{ id: 'other', labelKey: 'getPdfInfo.sections.other', fallback: 'Other' },
|
|
{ id: 'perPage', labelKey: 'getPdfInfo.sections.perPageInfo', fallback: 'Per Page Info' },
|
|
];
|
|
|
|
const GetPdfInfo = (props: BaseToolProps) => {
|
|
const { t } = useTranslation();
|
|
const { actions: navigationActions } = useNavigationActions();
|
|
const navigationState = useNavigationState();
|
|
const {
|
|
registerCustomWorkbenchView,
|
|
unregisterCustomWorkbenchView,
|
|
setCustomWorkbenchViewData,
|
|
clearCustomWorkbenchViewData,
|
|
} = useToolWorkflow();
|
|
|
|
const REPORT_VIEW_ID = 'getPdfInfoReport';
|
|
const REPORT_WORKBENCH_ID = 'custom:getPdfInfoReport' as const;
|
|
const reportIcon = useMemo(() => <PictureAsPdfIcon fontSize="small" />, []);
|
|
|
|
const base = useBaseTool(
|
|
'getPdfInfo',
|
|
useGetPdfInfoParameters,
|
|
useGetPdfInfoOperation,
|
|
props
|
|
);
|
|
|
|
const operation = base.operation as GetPdfInfoOperationHook;
|
|
const hasResults = operation.results.length > 0;
|
|
const showResultsStep = hasResults || base.operation.isLoading || !!base.operation.errorMessage;
|
|
|
|
useEffect(() => {
|
|
registerCustomWorkbenchView({
|
|
id: REPORT_VIEW_ID,
|
|
workbenchId: REPORT_WORKBENCH_ID,
|
|
label: t('getPdfInfo.report.shortTitle', 'PDF Information'),
|
|
icon: reportIcon,
|
|
component: GetPdfInfoReportView,
|
|
});
|
|
|
|
return () => {
|
|
clearCustomWorkbenchViewData(REPORT_VIEW_ID);
|
|
unregisterCustomWorkbenchView(REPORT_VIEW_ID);
|
|
};
|
|
}, [
|
|
clearCustomWorkbenchViewData,
|
|
registerCustomWorkbenchView,
|
|
reportIcon,
|
|
t,
|
|
unregisterCustomWorkbenchView,
|
|
]);
|
|
|
|
const reportData = useMemo<PdfInfoReportData | null>(() => {
|
|
if (operation.results.length === 0) return null;
|
|
const generatedAt = operation.results[0].summaryGeneratedAt ?? Date.now();
|
|
return {
|
|
generatedAt,
|
|
entries: operation.results,
|
|
};
|
|
}, [operation.results]);
|
|
|
|
const lastReportGeneratedAtRef = useRef<number | null>(null);
|
|
useEffect(() => {
|
|
if (reportData) {
|
|
setCustomWorkbenchViewData(REPORT_VIEW_ID, reportData);
|
|
const generatedAt = reportData.generatedAt ?? null;
|
|
const isNewReport = generatedAt && generatedAt !== lastReportGeneratedAtRef.current;
|
|
if (isNewReport) {
|
|
lastReportGeneratedAtRef.current = generatedAt;
|
|
if (navigationState.selectedTool === 'getPdfInfo' && navigationState.workbench !== REPORT_WORKBENCH_ID) {
|
|
navigationActions.setWorkbench(REPORT_WORKBENCH_ID);
|
|
}
|
|
}
|
|
} else {
|
|
clearCustomWorkbenchViewData(REPORT_VIEW_ID);
|
|
lastReportGeneratedAtRef.current = null;
|
|
}
|
|
}, [
|
|
clearCustomWorkbenchViewData,
|
|
navigationActions,
|
|
navigationState.selectedTool,
|
|
navigationState.workbench,
|
|
reportData,
|
|
setCustomWorkbenchViewData,
|
|
]);
|
|
|
|
return createToolFlow({
|
|
files: {
|
|
selectedFiles: base.selectedFiles,
|
|
isCollapsed: hasResults,
|
|
},
|
|
steps: [
|
|
{
|
|
title: t('getPdfInfo.indexTitle', 'Index'),
|
|
isVisible: Boolean(reportData),
|
|
isCollapsed: false,
|
|
content: (
|
|
<Stack gap={0}>
|
|
{CHAPTERS.map((c, idx) => (
|
|
<Stack key={c.id} gap={0}>
|
|
<UnstyledButton
|
|
onClick={() => {
|
|
if (!reportData) return;
|
|
setCustomWorkbenchViewData(REPORT_VIEW_ID, { ...reportData, scrollTo: c.id });
|
|
if (navigationState.workbench !== REPORT_WORKBENCH_ID) {
|
|
navigationActions.setWorkbench(REPORT_WORKBENCH_ID);
|
|
}
|
|
}}
|
|
style={{ width: '100%', textAlign: 'left', padding: '8px 4px' }}
|
|
>
|
|
<Group justify="flex-start" gap="sm">
|
|
<LinkIcon fontSize="small" style={{ opacity: 0.7 }} />
|
|
<Text size="md" c="dimmed">
|
|
{t(c.labelKey, c.fallback)}
|
|
</Text>
|
|
</Group>
|
|
</UnstyledButton>
|
|
{idx < CHAPTERS.length - 1 && <Divider my={6} />}
|
|
</Stack>
|
|
))}
|
|
</Stack>
|
|
),
|
|
},
|
|
{
|
|
title: t('getPdfInfo.results', 'Results'),
|
|
isVisible: showResultsStep,
|
|
isCollapsed: false,
|
|
content: (
|
|
<GetPdfInfoResults
|
|
operation={operation}
|
|
isLoading={base.operation.isLoading}
|
|
errorMessage={base.operation.errorMessage}
|
|
/>
|
|
),
|
|
},
|
|
],
|
|
executeButton: {
|
|
text: t('getPdfInfo.submit', 'Generate'),
|
|
loadingText: t('loading', 'Loading...'),
|
|
onClick: base.handleExecute,
|
|
disabled:
|
|
!base.params.validateParameters() ||
|
|
!base.hasFiles ||
|
|
base.operation.isLoading ||
|
|
!base.endpointEnabled,
|
|
isVisible: true,
|
|
},
|
|
review: {
|
|
isVisible: false,
|
|
operation: base.operation,
|
|
title: t('getPdfInfo.results', 'Results'),
|
|
onUndo: base.handleUndo,
|
|
},
|
|
});
|
|
};
|
|
|
|
const GetPdfInfoTool = GetPdfInfo as ToolComponent;
|
|
GetPdfInfoTool.tool = () => useGetPdfInfoOperation;
|
|
GetPdfInfoTool.getDefaultParameters = () => ({ ...defaultParameters });
|
|
|
|
export default GetPdfInfoTool;
|
|
|
|
|