mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-17 13:52:14 +01:00
Addition of the Show JavaScript tool (#4877)
# Description of Changes - Added the show javascript 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.
This commit is contained in:
150
frontend/src/core/tools/ShowJS.tsx
Normal file
150
frontend/src/core/tools/ShowJS.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CodeRoundedIcon from '@mui/icons-material/CodeRounded';
|
||||
import { createToolFlow } from '@app/components/tools/shared/createToolFlow';
|
||||
import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool';
|
||||
import type { BaseToolProps, ToolComponent } from '@app/types/tool';
|
||||
import { useShowJSParameters, defaultParameters } from '@app/hooks/tools/showJS/useShowJSParameters';
|
||||
import { useShowJSOperation, type ShowJSOperationHook } from '@app/hooks/tools/showJS/useShowJSOperation';
|
||||
import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext';
|
||||
import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext';
|
||||
import ShowJSView from '@app/components/tools/showJS/ShowJSView';
|
||||
import { useFileSelection } from '@app/contexts/file/fileHooks';
|
||||
|
||||
const ShowJS = (props: BaseToolProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { actions: navigationActions } = useNavigationActions();
|
||||
const navigationState = useNavigationState();
|
||||
|
||||
const {
|
||||
registerCustomWorkbenchView,
|
||||
unregisterCustomWorkbenchView,
|
||||
setCustomWorkbenchViewData,
|
||||
clearCustomWorkbenchViewData,
|
||||
} = useToolWorkflow();
|
||||
|
||||
const VIEW_ID = 'showJSView';
|
||||
const WORKBENCH_ID = 'custom:showJS' as const;
|
||||
const viewIcon = useMemo(() => <CodeRoundedIcon fontSize="small" />, []);
|
||||
|
||||
const base = useBaseTool('showJS', useShowJSParameters, useShowJSOperation, props, { minFiles: 1 });
|
||||
const operation = base.operation as ShowJSOperationHook;
|
||||
const hasResults = Boolean(operation.scriptText);
|
||||
const { clearSelections } = useFileSelection();
|
||||
|
||||
useEffect(() => {
|
||||
registerCustomWorkbenchView({
|
||||
id: VIEW_ID,
|
||||
workbenchId: WORKBENCH_ID,
|
||||
label: t('showJS.view.title', 'JavaScript'),
|
||||
icon: viewIcon,
|
||||
component: ({ data }) => <ShowJSView data={data} />,
|
||||
});
|
||||
|
||||
return () => {
|
||||
clearCustomWorkbenchViewData(VIEW_ID);
|
||||
unregisterCustomWorkbenchView(VIEW_ID);
|
||||
};
|
||||
}, [clearCustomWorkbenchViewData, registerCustomWorkbenchView, t, unregisterCustomWorkbenchView, viewIcon]);
|
||||
|
||||
const lastShownRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (operation.scriptText) {
|
||||
setCustomWorkbenchViewData(VIEW_ID, {
|
||||
scriptText: operation.scriptText,
|
||||
downloadUrl: operation.downloadUrl,
|
||||
downloadFilename: operation.downloadFilename,
|
||||
});
|
||||
const marker = operation.scriptText.length;
|
||||
const isNew = lastShownRef.current == null || marker !== lastShownRef.current;
|
||||
if (isNew) {
|
||||
lastShownRef.current = marker;
|
||||
if (navigationState.selectedTool === 'showJS' && navigationState.workbench !== WORKBENCH_ID) {
|
||||
navigationActions.setWorkbench(WORKBENCH_ID);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clearCustomWorkbenchViewData(VIEW_ID);
|
||||
lastShownRef.current = null;
|
||||
}
|
||||
}, [
|
||||
clearCustomWorkbenchViewData,
|
||||
navigationActions,
|
||||
navigationState.selectedTool,
|
||||
navigationState.workbench,
|
||||
operation.scriptText,
|
||||
setCustomWorkbenchViewData,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if ((base.selectedFiles?.length ?? 0) === 0) {
|
||||
try { base.operation.resetResults(); } catch { /* noop */ }
|
||||
try { clearCustomWorkbenchViewData(VIEW_ID); } catch { /* noop */ }
|
||||
if (navigationState.workbench === WORKBENCH_ID) {
|
||||
try { navigationActions.setWorkbench('fileEditor'); } catch { /* noop */ }
|
||||
}
|
||||
lastShownRef.current = null;
|
||||
}
|
||||
}, [
|
||||
base.selectedFiles?.length,
|
||||
base.operation,
|
||||
clearCustomWorkbenchViewData,
|
||||
navigationActions,
|
||||
navigationState.workbench,
|
||||
]);
|
||||
|
||||
return createToolFlow({
|
||||
files: {
|
||||
selectedFiles: base.selectedFiles,
|
||||
isCollapsed: false,
|
||||
},
|
||||
steps: [],
|
||||
executeButton: {
|
||||
text: hasResults ? t('back', 'Back') : t('showJS.submit', 'Extract JavaScript'),
|
||||
loadingText: t('loading', 'Loading...'),
|
||||
onClick: hasResults
|
||||
? async () => {
|
||||
// Clear results and deselect files so user can pick another file
|
||||
try {
|
||||
await base.operation.resetResults();
|
||||
} catch { /* noop */ }
|
||||
try {
|
||||
clearSelections();
|
||||
} catch { /* noop */ }
|
||||
// Close the custom JS view and send user back to file manager to pick another file
|
||||
try {
|
||||
clearCustomWorkbenchViewData(VIEW_ID);
|
||||
} catch { /* noop */ }
|
||||
try {
|
||||
navigationActions.setWorkbench('fileEditor');
|
||||
} catch { /* noop */ }
|
||||
}
|
||||
: base.handleExecute,
|
||||
disabled: hasResults
|
||||
? false
|
||||
: (
|
||||
!base.hasFiles ||
|
||||
(base.selectedFiles?.length ?? 0) !== 1 ||
|
||||
base.operation.isLoading ||
|
||||
base.endpointLoading ||
|
||||
base.endpointEnabled === false
|
||||
),
|
||||
isVisible: true,
|
||||
},
|
||||
review: {
|
||||
isVisible: hasResults,
|
||||
operation: base.operation,
|
||||
title: t('showJS.results', 'Result'),
|
||||
onUndo: undefined,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const ShowJSTool = ShowJS as ToolComponent;
|
||||
ShowJSTool.tool = () => useShowJSOperation;
|
||||
ShowJSTool.getDefaultParameters = () => ({ ...defaultParameters });
|
||||
|
||||
export default ShowJSTool;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user