From d2b38ef4b85be298555849bfcbabfc786d7f44b7 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Tue, 28 Oct 2025 10:29:36 +0000 Subject: [PATCH 1/4] Restructure frontend code to allow for extensions (#4721) # Description of Changes Move frontend code into `core` folder and add infrastructure for `proprietary` folder to include premium, non-OSS features --- .github/workflows/build.yml | 2 + frontend/index.html | 2 +- frontend/package-lock.json | 49 ++++ frontend/package.json | 10 +- .../public/locales/en-GB/translation.json | 4 + frontend/src/App.css | 38 --- frontend/src/App.tsx | 114 --------- frontend/src/core/App.tsx | 24 ++ frontend/src/core/components/AppProviders.tsx | 67 +++++ .../src/{ => core}/components/FileManager.tsx | 22 +- .../components/StorageStatsCard.tsx | 6 +- .../providers/PDFAnnotationProvider.tsx | 0 .../annotation/shared/BaseAnnotationTool.tsx | 6 +- .../annotation/shared/ColorPicker.tsx | 0 .../annotation/shared/DrawingCanvas.tsx | 4 +- .../annotation/shared/DrawingControls.tsx | 0 .../annotation/shared/ImageUploader.tsx | 0 .../annotation/shared/TextInputWithFont.tsx | 2 +- .../annotation/tools/DrawingTool.tsx | 4 +- .../components/annotation/tools/ImageTool.tsx | 4 +- .../components/annotation/tools/TextTool.tsx | 4 +- .../components/fileEditor/AddFileCard.tsx | 8 +- .../fileEditor/FileEditor.module.css | 0 .../components/fileEditor/FileEditor.tsx | 22 +- .../fileEditor/FileEditorThumbnail.tsx | 20 +- .../fileEditor/fileEditorRightRailButtons.tsx | 4 +- .../fileManager/CompactFileDetails.tsx | 4 +- .../components/fileManager/DesktopLayout.tsx | 14 +- .../components/fileManager/DragOverlay.tsx | 0 .../fileManager/EmptyFilesState.tsx | 6 +- .../components/fileManager/FileActions.tsx | 2 +- .../components/fileManager/FileDetails.tsx | 10 +- .../fileManager/FileHistoryGroup.tsx | 4 +- .../components/fileManager/FileInfoCard.tsx | 6 +- .../components/fileManager/FileListArea.tsx | 8 +- .../components/fileManager/FileListItem.tsx | 12 +- .../fileManager/FileSourceButtons.tsx | 4 +- .../fileManager/HiddenFileInput.tsx | 2 +- .../components/fileManager/MobileLayout.tsx | 14 +- .../components/fileManager/SearchInput.tsx | 2 +- .../components/hotkeys/HotkeyDisplay.tsx | 4 +- .../components/layout/Workbench.css | 0 .../components/layout/Workbench.tsx | 34 +-- .../components/onboarding/OnboardingTour.css | 0 .../components/onboarding/OnboardingTour.tsx | 10 +- .../onboarding/TourWelcomeModal.tsx | 2 +- .../pageEditor/BulkSelectionPanel.tsx | 10 +- .../components/pageEditor/DragDropGrid.tsx | 2 +- .../components/pageEditor/FileThumbnail.tsx | 6 +- .../pageEditor/PageEditor.module.css | 0 .../components/pageEditor/PageEditor.tsx | 38 +-- .../pageEditor/PageEditorControls.tsx | 0 .../pageEditor/PageSelectByNumberButton.tsx | 6 +- .../components/pageEditor/PageThumbnail.tsx | 10 +- .../AdvancedSelectionPanel.tsx | 8 +- .../bulkSelectionPanel/BulkSelection.ts | 0 .../BulkSelectionPanel.module.css | 0 .../bulkSelectionPanel/OperatorsSection.tsx | 4 +- .../bulkSelectionPanel/PageSelectionInput.tsx | 8 +- .../bulkSelectionPanel/SelectPages.tsx | 2 +- .../SelectedPagesDisplay.tsx | 2 +- .../pageEditor/commands/pageCommands.ts | 8 +- .../components/pageEditor/constants.ts | 0 .../pageEditor/hooks/usePageDocument.ts | 6 +- .../pageEditor/hooks/usePageEditorState.ts | 0 .../pageEditor/pageEditorRightRailButtons.tsx | 6 +- .../shared/AdminAnalyticsChoiceModal.tsx | 6 +- .../components/shared/AllToolsNavButton.tsx | 8 +- .../components/shared/AppConfigModal.css | 0 .../components/shared/AppConfigModal.tsx | 12 +- .../{ => core}/components/shared/Badge.tsx | 0 .../components/shared/ButtonSelector.test.tsx | 2 +- .../components/shared/ButtonSelector.tsx | 2 +- .../components/shared/CardSelector.tsx | 2 +- .../shared/DismissAllErrorsButton.tsx | 4 +- .../shared/DropdownListWithFooter.tsx | 0 .../components/shared/ErrorBoundary.tsx | 0 .../{ => core}/components/shared/FileCard.tsx | 6 +- .../components/shared/FileDropdownMenu.tsx | 2 +- .../{ => core}/components/shared/FileGrid.tsx | 6 +- .../components/shared/FilePickerModal.tsx | 2 +- .../components/shared/FilePreview.tsx | 10 +- .../components/shared/FileUploadButton.tsx | 0 .../{ => core}/components/shared/FitText.tsx | 2 +- .../{ => core}/components/shared/Footer.tsx | 2 +- .../shared/HoverActionMenu.module.css | 0 .../components/shared/HoverActionMenu.tsx | 2 +- .../components/shared/LandingPage.tsx | 8 +- .../shared/LanguageSelector.module.css | 0 .../components/shared/LanguageSelector.tsx | 8 +- .../components/shared/LoadingFallback.tsx | 19 ++ .../components/shared/LocalIcon.tsx | 2 +- .../components/shared/MultiSelectControls.tsx | 0 .../shared/NavigationWarningModal.tsx | 2 +- .../components/shared/ObscuredOverlay.tsx | 2 +- .../ObscuredOverlay.module.css | 0 .../components/shared/QuickAccessBar.tsx | 30 +-- .../shared/RainbowThemeProvider.tsx | 14 +- .../components/shared/RightRail.tsx | 26 +- .../components/shared/SkeletonLoader.tsx | 0 .../components/shared/TextInput.tsx | 4 +- .../components/shared/ToolChain.tsx | 4 +- .../{ => core}/components/shared/ToolIcon.tsx | 0 .../{ => core}/components/shared/Tooltip.tsx | 18 +- .../components/shared/TopControls.tsx | 10 +- .../shared/config/OverviewHeader.tsx | 15 ++ .../shared/config/configNavSections.tsx | 6 +- .../config/configSections/GeneralSection.tsx | 4 +- .../config/configSections/HotkeysSection.tsx | 12 +- .../shared/config/configSections/Overview.tsx | 39 +-- .../components/shared/config/types.ts | 0 .../shared/filePreview/DocumentStack.tsx | 0 .../shared/filePreview/DocumentThumbnail.tsx | 2 +- .../shared/filePreview/HoverOverlay.tsx | 0 .../shared/filePreview/NavigationArrows.tsx | 0 .../shared/fitText/FitText.README.md | 0 .../components/shared/fitText/textFit.ts | 0 .../quickAccessBar/ActiveToolButton.tsx | 10 +- .../shared/quickAccessBar/QuickAccessBar.css | 0 .../shared/quickAccessBar/QuickAccessBar.ts | 2 +- .../shared/rightRail/RightRail.README.md | 0 .../components/shared/rightRail/RightRail.css | 0 .../rightRail/ViewerAnnotationControls.tsx | 20 +- .../sliderWithInput/SliderWithInput.tsx | 0 .../shared/textInput/TextInput.module.css | 0 .../shared/tooltip/Tooltip.README.md | 0 .../shared/tooltip/Tooltip.module.css | 0 .../shared/tooltip/TooltipContent.tsx | 4 +- .../components/toast/Toast.README.md | 0 .../components/toast/ToastContext.tsx | 2 +- .../components/toast/ToastRenderer.css | 0 .../components/toast/ToastRenderer.tsx | 8 +- .../src/{ => core}/components/toast/index.ts | 6 +- .../src/{ => core}/components/toast/types.ts | 0 .../components/tools/FullscreenToolList.tsx | 20 +- .../tools/FullscreenToolSurface.tsx | 20 +- .../components/tools/SearchResults.tsx | 14 +- .../components/tools/ToolLoadingFallback.tsx | 0 .../{ => core}/components/tools/ToolPanel.css | 0 .../{ => core}/components/tools/ToolPanel.tsx | 30 +-- .../components/tools/ToolPanelModePrompt.css | 0 .../components/tools/ToolPanelModePrompt.tsx | 8 +- .../components/tools/ToolPicker.tsx | 24 +- .../components/tools/ToolRenderer.tsx | 8 +- .../addAttachments/AddAttachmentsSettings.tsx | 4 +- .../AddPageNumbersAppearanceSettings.tsx | 4 +- .../AddPageNumbersAutomationSettings.tsx | 6 +- .../AddPageNumbersPositionSettings.tsx | 6 +- .../PageNumberPreview.module.css | 0 .../addPageNumbers/PageNumberPreview.tsx | 8 +- .../useAddPageNumbersOperation.ts | 6 +- .../useAddPageNumbersParameters.ts | 4 +- .../addPassword/AddPasswordSettings.test.tsx | 4 +- .../tools/addPassword/AddPasswordSettings.tsx | 2 +- .../addStamp/AddStampAutomationSettings.tsx | 6 +- .../StampPositionFormattingSettings.tsx | 8 +- .../tools/addStamp/StampPreview.module.css | 0 .../tools/addStamp/StampPreview.tsx | 10 +- .../tools/addStamp/StampPreviewUtils.ts | 2 +- .../tools/addStamp/StampSetupSettings.tsx | 8 +- .../tools/addStamp/useAddStampOperation.ts | 6 +- .../tools/addStamp/useAddStampParameters.ts | 4 +- .../AddWatermarkSingleStepSettings.tsx | 12 +- .../addWatermark/WatermarkFormatting.tsx | 4 +- .../tools/addWatermark/WatermarkImageFile.tsx | 4 +- .../addWatermark/WatermarkStyleSettings.tsx | 2 +- .../tools/addWatermark/WatermarkTextStyle.tsx | 4 +- .../addWatermark/WatermarkTypeSettings.tsx | 2 +- .../tools/addWatermark/WatermarkWording.tsx | 4 +- .../AdjustContrastBasicSettings.tsx | 4 +- .../AdjustContrastColorSettings.tsx | 4 +- .../adjustContrast/AdjustContrastPreview.tsx | 8 +- .../AdjustContrastSingleStepSettings.tsx | 6 +- .../components/tools/adjustContrast/utils.ts | 2 +- .../AdjustPageScaleSettings.test.tsx | 4 +- .../AdjustPageScaleSettings.tsx | 2 +- .../tools/autoRename/AutoRenameSettings.tsx | 2 +- .../tools/automate/AutomationCreation.tsx | 16 +- .../tools/automate/AutomationEntry.tsx | 8 +- .../tools/automate/AutomationRun.tsx | 10 +- .../tools/automate/AutomationSelection.tsx | 10 +- .../tools/automate/IconSelector.tsx | 2 +- .../tools/automate/ToolConfigurationModal.tsx | 8 +- .../components/tools/automate/ToolList.tsx | 10 +- .../tools/automate/ToolSelector.tsx | 12 +- .../components/tools/automate/iconMap.ts | 0 .../BookletImpositionSettings.tsx | 4 +- .../certSign/CertSignAutomationSettings.tsx | 10 +- .../certSign/CertificateFilesSettings.tsx | 4 +- .../certSign/CertificateFormatSettings.tsx | 2 +- .../certSign/CertificateTypeSettings.tsx | 6 +- .../certSign/SignatureAppearanceSettings.tsx | 2 +- .../ChangeMetadataSingleStep.tsx | 12 +- .../steps/AdvancedOptionsStep.tsx | 6 +- .../steps/CustomMetadataStep.tsx | 2 +- .../changeMetadata/steps/DeleteAllStep.tsx | 2 +- .../steps/DocumentDatesStep.tsx | 2 +- .../steps/StandardMetadataStep.tsx | 2 +- .../ChangePermissionsSettings.test.tsx | 6 +- .../ChangePermissionsSettings.tsx | 2 +- .../tools/compress/CompressSettings.tsx | 4 +- .../convert/ConvertFromEmailSettings.tsx | 2 +- .../convert/ConvertFromImageSettings.tsx | 4 +- .../tools/convert/ConvertFromWebSettings.tsx | 2 +- .../tools/convert/ConvertSettings.tsx | 30 +-- .../tools/convert/ConvertToImageSettings.tsx | 4 +- .../tools/convert/ConvertToPdfaSettings.tsx | 6 +- .../tools/convert/GroupedFormatDropdown.tsx | 0 .../tools/crop/CropAreaSelector.tsx | 4 +- .../tools/crop/CropAutomationSettings.tsx | 6 +- .../tools/crop/CropCoordinateInputs.tsx | 2 +- .../components/tools/crop/CropSettings.tsx | 18 +- .../extractImages/ExtractImagesSettings.tsx | 2 +- .../tools/flatten/FlattenSettings.tsx | 2 +- .../tools/fullscreen/CompactToolItem.tsx | 10 +- .../tools/fullscreen/DetailedToolItem.tsx | 8 +- .../components/tools/fullscreen/shared.ts | 8 +- .../tools/merge/MergeFileSorter.test.tsx | 2 +- .../tools/merge/MergeFileSorter.tsx | 0 .../tools/merge/MergeSettings.test.tsx | 4 +- .../components/tools/merge/MergeSettings.tsx | 2 +- .../tools/ocr/AdvancedOCRSettings.tsx | 2 +- .../tools/ocr/LanguagePicker.module.css | 0 .../components/tools/ocr/LanguagePicker.tsx | 4 +- .../components/tools/ocr/OCRSettings.tsx | 4 +- .../OverlayPdfsSettings.module.css | 0 .../tools/overlayPdfs/OverlayPdfsSettings.tsx | 8 +- .../tools/pageLayout/PageLayoutSettings.tsx | 4 +- .../components/tools/pageLayout/constants.ts | 0 .../redact/RedactAdvancedSettings.test.tsx | 4 +- .../tools/redact/RedactAdvancedSettings.tsx | 2 +- .../tools/redact/RedactModeSelector.tsx | 4 +- .../redact/RedactSingleStepSettings.test.tsx | 4 +- .../tools/redact/RedactSingleStepSettings.tsx | 8 +- .../tools/redact/WordsToRedactInput.test.tsx | 2 +- .../tools/redact/WordsToRedactInput.tsx | 0 .../RemoveAnnotationsSettings.tsx | 2 +- .../removeBlanks/RemoveBlanksSettings.tsx | 4 +- .../RemoveCertificateSignSettings.tsx | 2 +- .../tools/removePages/RemovePagesSettings.tsx | 4 +- .../RemovePasswordSettings.test.tsx | 4 +- .../removePassword/RemovePasswordSettings.tsx | 2 +- .../ReorganizePagesSettings.tsx | 4 +- .../tools/reorganizePages/constants.ts | 0 .../tools/repair/RepairSettings.tsx | 2 +- .../replaceColor/ReplaceColorSettings.tsx | 2 +- .../tools/rotate/RotateAutomationSettings.tsx | 4 +- .../tools/rotate/RotateSettings.tsx | 6 +- .../tools/sanitize/SanitizeSettings.test.tsx | 4 +- .../tools/sanitize/SanitizeSettings.tsx | 2 +- .../ScannerImageSplitSettings.tsx | 2 +- .../tools/shared/ErrorNotification.tsx | 0 .../components/tools/shared/FileMetadata.tsx | 2 +- .../tools/shared/FileStatusIndicator.tsx | 8 +- .../components/tools/shared/FilesToolStep.tsx | 4 +- .../tools/shared/NavigationControls.tsx | 0 .../components/tools/shared/NoToolsFound.tsx | 0 .../tools/shared/NumberInputWithUnit.tsx | 0 .../tools/shared/OperationButton.tsx | 0 .../tools/shared/ResultsPreview.tsx | 6 +- .../tools/shared/ReviewToolStep.tsx | 10 +- .../tools/shared/SubcategoryHeader.tsx | 0 .../tools/shared/SuggestedToolsSection.tsx | 4 +- .../components/tools/shared/ToolStep.tsx | 14 +- .../tools/shared/ToolWorkflowTitle.tsx | 4 +- .../tools/shared/createToolFlow.tsx | 10 +- .../tools/shared/renderToolButtons.tsx | 10 +- .../components/tools/sign/PenSizeSelector.tsx | 0 .../components/tools/sign/SignSettings.tsx | 16 +- .../SingleLargePageSettings.tsx | 2 +- .../tools/split/SplitAutomationSettings.tsx | 6 +- .../components/tools/split/SplitSettings.tsx | 6 +- .../tools/toolPicker/FavoriteStar.tsx | 0 .../tools/toolPicker/ToolButton.tsx | 22 +- .../tools/toolPicker/ToolPicker.css | 0 .../tools/toolPicker/ToolSearch.tsx | 12 +- .../unlockPdfForms/UnlockPdfFormsSettings.tsx | 2 +- .../ValidateSignatureReportView.tsx | 10 +- .../ValidateSignatureResults.tsx | 10 +- .../ValidateSignatureSettings.tsx | 4 +- .../reportView/FieldBlock.tsx | 2 +- .../reportView/FileSummaryHeader.tsx | 4 +- .../reportView/SignatureSection.tsx | 8 +- .../reportView/SignatureStatusBadge.tsx | 6 +- .../reportView/ThumbnailPreview.tsx | 2 +- .../validateSignature/reportView/styles.css | 0 .../tooltips/useAddPasswordPermissionsTips.ts | 2 +- .../components/tooltips/useAddPasswordTips.ts | 2 +- .../tooltips/useAdjustPageScaleTips.ts | 2 +- .../components/tooltips/useAdvancedOCRTips.ts | 2 +- .../components/tooltips/useAutoRenameTips.ts | 2 +- .../tooltips/useBookletImpositionTips.ts | 2 +- .../tooltips/useCertSignTooltips.ts | 2 +- .../tooltips/useCertificateTypeTips.ts | 2 +- .../tooltips/useChangeMetadataTips.ts | 2 +- .../tooltips/useChangePermissionsTips.ts | 2 +- .../components/tooltips/useCompressTips.ts | 2 +- .../components/tooltips/useCropTooltips.ts | 0 .../components/tooltips/useFlattenTips.ts | 2 +- .../components/tooltips/useMergeTips.tsx | 2 +- .../components/tooltips/useOCRTips.ts | 2 +- .../components/tooltips/useOverlayPdfsTips.ts | 2 +- .../tooltips/usePageSelectionTips.ts | 2 +- .../tooltips/usePageSelectionTips.tsx | 2 +- .../components/tooltips/useRedactTips.ts | 2 +- .../tooltips/useRemoveBlanksTips.ts | 2 +- .../components/tooltips/useRemovePagesTips.ts | 2 +- .../tooltips/useRemovePasswordTips.ts | 2 +- .../tooltips/useReplaceColorTips.ts | 2 +- .../components/tooltips/useRotateTips.ts | 2 +- .../tooltips/useScannerImageSplitTips.ts | 2 +- .../components/tooltips/useSignModeTips.ts | 2 +- .../tooltips/useSignatureAppearanceTips.ts | 2 +- .../components/tooltips/useSplitMethodTips.ts | 2 +- .../tooltips/useSplitSettingsTips.ts | 4 +- .../components/tooltips/useWatermarkTips.ts | 2 +- .../components/viewer/CustomSearchLayer.tsx | 4 +- .../components/viewer/EmbedPdfViewer.tsx | 24 +- .../components/viewer/ExportAPIBridge.tsx | 2 +- .../components/viewer/HistoryAPIBridge.tsx | 4 +- .../components/viewer/LocalEmbedPDF.tsx | 28 +-- .../viewer/LocalEmbedPDFWithAnnotations.tsx | 20 +- .../components/viewer/PanAPIBridge.tsx | 2 +- .../components/viewer/PdfViewerToolbar.tsx | 2 +- .../components/viewer/RotateAPIBridge.tsx | 2 +- .../components/viewer/ScrollAPIBridge.tsx | 2 +- .../components/viewer/SearchAPIBridge.tsx | 2 +- .../components/viewer/SearchInterface.tsx | 4 +- .../components/viewer/SelectionAPIBridge.tsx | 2 +- .../components/viewer/SignatureAPIBridge.tsx | 4 +- .../components/viewer/SpreadAPIBridge.tsx | 2 +- .../components/viewer/ThumbnailAPIBridge.tsx | 2 +- .../components/viewer/ThumbnailSidebar.tsx | 2 +- .../{ => core}/components/viewer/Viewer.tsx | 2 +- .../components/viewer/ZoomAPIBridge.tsx | 2 +- .../components/viewer/constants/search.ts | 0 .../viewer/useViewerRightRailButtons.tsx | 12 +- .../components/viewer/viewerTypes.ts | 0 .../constants/addWatermarkConstants.ts | 0 frontend/src/{ => core}/constants/app.ts | 0 .../src/{ => core}/constants/automation.ts | 0 .../{ => core}/constants/convertConstants.ts | 0 .../constants/convertSupportedFornats.ts | 0 .../src/{ => core}/constants/cropConstants.ts | 2 +- .../{ => core}/constants/pageSizeConstants.ts | 0 .../{ => core}/constants/splitConstants.ts | 2 +- frontend/src/{ => core}/constants/theme.ts | 0 .../src/{ => core}/constants/toolPanel.ts | 0 .../{ => core}/contexts/AppConfigContext.tsx | 14 +- .../src/{ => core}/contexts/FileContext.tsx | 16 +- .../contexts/FileManagerContext.tsx | 12 +- .../{ => core}/contexts/FilesModalContext.tsx | 8 +- .../src/{ => core}/contexts/HotkeyContext.tsx | 8 +- .../{ => core}/contexts/IndexedDBContext.tsx | 8 +- .../{ => core}/contexts/NavigationContext.tsx | 6 +- .../{ => core}/contexts/OnboardingContext.tsx | 25 +- .../contexts/PreferencesContext.tsx | 2 +- .../{ => core}/contexts/RightRailContext.tsx | 2 +- .../{ => core}/contexts/SidebarContext.tsx | 2 +- .../{ => core}/contexts/SignatureContext.tsx | 4 +- .../contexts/ToolRegistryContext.tsx | 4 +- .../contexts/ToolRegistryProvider.tsx | 8 +- .../contexts/ToolWorkflowContext.tsx | 26 +- .../contexts/TourOrchestrationContext.tsx | 14 +- .../src/{ => core}/contexts/ViewerContext.tsx | 2 +- .../{ => core}/contexts/file/FileReducer.ts | 4 +- .../src/{ => core}/contexts/file/contexts.ts | 2 +- .../{ => core}/contexts/file/fileActions.ts | 18 +- .../src/{ => core}/contexts/file/fileHooks.ts | 6 +- .../{ => core}/contexts/file/fileSelectors.ts | 4 +- .../src/{ => core}/contexts/file/lifecycle.ts | 4 +- .../toolWorkflow/toolWorkflowState.ts | 4 +- frontend/src/{ => core}/data/toolsTaxonomy.ts | 10 +- .../core/data/useProprietaryToolRegistry.tsx | 15 ++ .../data/useTranslatedToolRegistry.tsx | 230 +++++++++--------- .../useAddAttachmentsOperation.ts | 6 +- .../useAddAttachmentsParameters.ts | 0 .../useAddPasswordOperation.test.ts | 6 +- .../addPassword/useAddPasswordOperation.ts | 10 +- .../useAddPasswordParameters.test.ts | 4 +- .../addPassword/useAddPasswordParameters.ts | 6 +- .../addWatermark/useAddWatermarkOperation.ts | 6 +- .../addWatermark/useAddWatermarkParameters.ts | 4 +- .../useAdjustContrastOperation.ts | 10 +- .../useAdjustContrastParameters.ts | 2 +- .../useAdjustPageScaleOperation.ts | 6 +- .../useAdjustPageScaleParameters.test.ts | 2 +- .../useAdjustPageScaleParameters.ts | 4 +- .../autoRename/useAutoRenameOperation.ts | 6 +- .../autoRename/useAutoRenameParameters.ts | 4 +- .../tools/automate/useAutomateOperation.ts | 8 +- .../hooks/tools/automate/useAutomationForm.ts | 8 +- .../tools/automate/useSavedAutomations.ts | 10 +- .../tools/automate/useSuggestedAutomations.ts | 6 +- .../useBookletImpositionOperation.ts | 6 +- .../useBookletImpositionParameters.ts | 4 +- .../tools/certSign/useCertSignOperation.ts | 6 +- .../tools/certSign/useCertSignParameters.ts | 4 +- .../useChangeMetadataOperation.test.ts | 6 +- .../useChangeMetadataOperation.ts | 6 +- .../useChangeMetadataParameters.test.ts | 4 +- .../useChangeMetadataParameters.ts | 6 +- .../changeMetadata/useMetadataExtraction.ts | 6 +- .../useChangePermissionsOperation.test.ts | 6 +- .../useChangePermissionsOperation.ts | 6 +- .../useChangePermissionsParameters.test.ts | 2 +- .../useChangePermissionsParameters.ts | 4 +- .../tools/compress/useCompressOperation.ts | 6 +- .../tools/compress/useCompressParameters.ts | 4 +- .../tools/convert/useConvertOperation.ts | 10 +- .../convert/useConvertParameters.test.ts | 4 +- .../tools/convert/useConvertParameters.ts | 10 +- .../useConvertParametersAutoDetection.test.ts | 2 +- .../hooks/tools/crop/useCropOperation.ts | 6 +- .../hooks/tools/crop/useCropParameters.ts | 8 +- .../useExtractImagesOperation.ts | 8 +- .../useExtractImagesParameters.ts | 2 +- .../tools/flatten/useFlattenOperation.ts | 6 +- .../tools/flatten/useFlattenParameters.ts | 4 +- .../tools/merge/useMergeOperation.test.ts | 6 +- .../hooks/tools/merge/useMergeOperation.ts | 6 +- .../tools/merge/useMergeParameters.test.ts | 2 +- .../hooks/tools/merge/useMergeParameters.ts | 4 +- .../hooks/tools/ocr/useOCROperation.ts | 8 +- .../hooks/tools/ocr/useOCRParameters.ts | 4 +- .../overlayPdfs/useOverlayPdfsOperation.ts | 6 +- .../overlayPdfs/useOverlayPdfsParameters.ts | 4 +- .../pageLayout/usePageLayoutOperation.ts | 6 +- .../pageLayout/usePageLayoutParameters.ts | 4 +- .../tools/redact/useRedactOperation.test.ts | 8 +- .../hooks/tools/redact/useRedactOperation.ts | 6 +- .../tools/redact/useRedactParameters.test.ts | 2 +- .../hooks/tools/redact/useRedactParameters.ts | 4 +- .../useRemoveAnnotationsOperation.ts | 6 +- .../useRemoveAnnotationsParameters.ts | 2 +- .../removeBlanks/useRemoveBlanksOperation.ts | 8 +- .../removeBlanks/useRemoveBlanksParameters.ts | 4 +- .../useRemoveCertificateSignOperation.ts | 6 +- .../useRemoveCertificateSignParameters.ts | 4 +- .../removeImage/useRemoveImageOperation.ts | 6 +- .../removeImage/useRemoveImageParameters.ts | 4 +- .../removePages/useRemovePagesOperation.ts | 8 +- .../removePages/useRemovePagesParameters.ts | 6 +- .../useRemovePasswordOperation.test.ts | 6 +- .../useRemovePasswordOperation.ts | 6 +- .../useRemovePasswordParameters.test.ts | 2 +- .../useRemovePasswordParameters.ts | 4 +- .../useReorganizePagesOperation.ts | 6 +- .../useReorganizePagesParameters.ts | 0 .../hooks/tools/repair/useRepairOperation.ts | 6 +- .../hooks/tools/repair/useRepairParameters.ts | 4 +- .../replaceColor/useReplaceColorOperation.ts | 6 +- .../replaceColor/useReplaceColorParameters.ts | 4 +- .../tools/rotate/useRotateOperation.test.ts | 6 +- .../hooks/tools/rotate/useRotateOperation.ts | 6 +- .../tools/rotate/useRotateParameters.test.ts | 2 +- .../hooks/tools/rotate/useRotateParameters.ts | 4 +- .../tools/sanitize/useSanitizeOperation.ts | 6 +- .../sanitize/useSanitizeParameters.test.ts | 2 +- .../tools/sanitize/useSanitizeParameters.ts | 4 +- .../useScannerImageSplitOperation.ts | 8 +- .../useScannerImageSplitParameters.ts | 4 +- .../hooks/tools/shared/useAccordionSteps.ts | 0 .../hooks/tools/shared/useBaseParameters.ts | 0 .../hooks/tools/shared/useBaseTool.ts | 12 +- .../hooks/tools/shared/useOperationResults.ts | 0 .../hooks/tools/shared/useToolApiCalls.ts | 8 +- .../hooks/tools/shared/useToolOperation.ts | 26 +- .../hooks/tools/shared/useToolResources.ts | 6 +- .../hooks/tools/shared/useToolState.ts | 0 .../hooks/tools/sign/useSignOperation.ts | 6 +- .../hooks/tools/sign/useSignParameters.ts | 2 +- .../useSingleLargePageOperation.ts | 6 +- .../useSingleLargePageParameters.ts | 4 +- .../hooks/tools/split/useSplitOperation.ts | 10 +- .../hooks/tools/split/useSplitParameters.ts | 6 +- .../useUnlockPdfFormsOperation.ts | 6 +- .../useUnlockPdfFormsParameters.ts | 4 +- .../hooks/tools/useFavoriteToolItems.ts | 4 +- .../hooks/tools/useToolPanelGeometry.ts | 0 .../hooks/tools/useUserToolActivity.ts | 2 +- .../CenteredMessageSection.ts | 4 +- .../outputtedPDFSections/FieldBoxSection.ts | 4 +- .../outputtedPDFSections/SignatureSection.ts | 12 +- .../StatusBadgeSection.ts | 0 .../outputtedPDFSections/SummarySection.ts | 10 +- .../outputtedPDFSections/ThumbnailSection.ts | 2 +- .../validateSignature/signatureReportPdf.ts | 16 +- .../useValidateSignatureOperation.ts | 22 +- .../useValidateSignatureParameters.ts | 2 +- .../validateSignature/utils/pdfPageHelpers.ts | 2 +- .../validateSignature/utils/pdfPalette.ts | 0 .../tools/validateSignature/utils/pdfText.ts | 0 .../validateSignature/utils/reportStatus.ts | 4 +- .../validateSignature/utils/signatureCsv.ts | 4 +- .../utils/signatureReportBuilder.ts | 8 +- .../utils/signatureStatus.ts | 4 +- .../validateSignature/utils/signatureUtils.ts | 4 +- frontend/src/{ => core}/hooks/useBaseUrl.ts | 2 +- .../src/{ => core}/hooks/useCookieConsent.ts | 4 +- .../src/{ => core}/hooks/useDocumentMeta.ts | 0 .../src/{ => core}/hooks/useEndpointConfig.ts | 13 +- .../hooks/useEnhancedProcessedFiles.ts | 6 +- .../src/{ => core}/hooks/useFileHandler.ts | 2 +- .../src/{ => core}/hooks/useFileManager.ts | 8 +- .../src/{ => core}/hooks/useFileWithUrl.ts | 2 +- frontend/src/{ => core}/hooks/useFocusTrap.ts | 0 .../{ => core}/hooks/useGoogleDrivePicker.ts | 2 +- .../{ => core}/hooks/useIndexedDBThumbnail.ts | 8 +- .../src/{ => core}/hooks/useIsOverflowing.ts | 0 .../src/{ => core}/hooks/usePDFProcessor.ts | 6 +- .../hooks/usePdfSignatureDetection.ts | 4 +- .../src/{ => core}/hooks/useProcessedFiles.ts | 4 +- .../src/{ => core}/hooks/useRainbowTheme.ts | 4 +- frontend/src/core/hooks/useRequestHeaders.ts | 3 + .../{ => core}/hooks/useRightRailButtons.ts | 4 +- .../src/{ => core}/hooks/useScarfTracking.ts | 6 +- .../core/hooks/useShouldShowWelcomeModal.ts | 11 + .../{ => core}/hooks/useSidebarNavigation.ts | 8 +- .../src/{ => core}/hooks/useSuggestedTools.ts | 8 +- .../hooks/useThumbnailGeneration.ts | 6 +- .../{ => core}/hooks/useToolManagement.tsx | 10 +- .../src/{ => core}/hooks/useToolNavigation.ts | 8 +- .../src/{ => core}/hooks/useToolParameters.ts | 0 .../src/{ => core}/hooks/useToolSections.ts | 4 +- .../{ => core}/hooks/useTooltipPosition.ts | 6 +- .../src/{ => core}/hooks/useTranslation.ts | 0 frontend/src/{ => core}/hooks/useUndoRedo.ts | 0 frontend/src/{ => core}/hooks/useUrlSync.ts | 10 +- frontend/src/{ => core}/i18n.ts | 0 frontend/src/{ => core}/i18n/config.ts | 0 frontend/src/{ => core}/pages/HomePage.css | 0 frontend/src/{ => core}/pages/HomePage.tsx | 34 +-- frontend/src/core/services/apiClient.ts | 25 ++ frontend/src/core/services/apiClientSetup.ts | 5 + .../{ => core}/services/automationStorage.ts | 0 .../services/documentManipulationService.ts | 2 +- .../services/enhancedPDFProcessingService.ts | 14 +- .../src/{ => core}/services/errorUtils.ts | 0 .../src/{ => core}/services/fileAnalyzer.ts | 4 +- .../services/fileProcessingService.ts | 6 +- .../src/{ => core}/services/fileStorage.ts | 6 +- .../{ => core}/services/fileStubHelpers.ts | 8 +- .../services/googleDrivePickerService.ts | 2 +- .../{ => core}/services/httpErrorHandler.ts | 6 +- .../{ => core}/services/indexedDBManager.ts | 0 .../{ => core}/services/pdfExportHelpers.ts | 6 +- .../{ => core}/services/pdfExportService.ts | 2 +- .../{ => core}/services/pdfMetadataService.ts | 6 +- .../services/pdfProcessingService.ts | 8 +- .../{ => core}/services/pdfWorkerManager.ts | 0 .../{ => core}/services/preferencesService.ts | 4 +- .../{ => core}/services/processingCache.ts | 2 +- .../services/processingErrorHandler.ts | 2 +- .../services/signatureDetectionService.ts | 0 .../{ => core}/services/specialErrorToasts.ts | 2 +- .../services/thumbnailGenerationService.ts | 7 +- .../src/{ => core}/services/zipFileService.ts | 6 +- frontend/src/{ => core}/setupTests.js | 0 frontend/src/{ => core}/setupTests.ts | 0 .../src/{ => core}/styles/cookieconsent.css | 0 frontend/src/{ => core/styles}/index.css | 0 .../src/{ => core}/styles/rainbow.module.css | 0 frontend/src/{ => core}/styles/tailwind.css | 0 frontend/src/{ => core}/styles/theme.css | 21 -- frontend/src/{ => core}/styles/zIndex.ts | 0 .../tests/convert/ConvertE2E.spec.ts | 2 +- .../tests/convert/ConvertIntegration.test.tsx | 16 +- .../ConvertSmartDetectionIntegration.test.tsx | 18 +- .../src/{ => core}/tests/convert/README.md | 0 .../helpers/conversionEndpointDiscovery.ts | 2 +- .../tests/missingTranslations.test.ts | 6 +- .../{ => core}/tests/test-fixtures/README.md | 0 .../tests/test-fixtures/corrupted.pdf | 0 .../{ => core}/tests/test-fixtures/sample.csv | 0 .../{ => core}/tests/test-fixtures/sample.doc | 0 .../tests/test-fixtures/sample.docx | Bin .../{ => core}/tests/test-fixtures/sample.eml | 0 .../{ => core}/tests/test-fixtures/sample.htm | 0 .../tests/test-fixtures/sample.html | 0 .../{ => core}/tests/test-fixtures/sample.jpg | Bin .../{ => core}/tests/test-fixtures/sample.md | 0 .../{ => core}/tests/test-fixtures/sample.pdf | Bin .../{ => core}/tests/test-fixtures/sample.png | Bin .../tests/test-fixtures/sample.pptx | 0 .../{ => core}/tests/test-fixtures/sample.svg | 0 .../{ => core}/tests/test-fixtures/sample.txt | 0 .../tests/test-fixtures/sample.xlsx | 0 .../{ => core}/tests/test-fixtures/sample.xml | 0 .../src/{ => core}/tests/translation.test.ts | 2 +- .../{ => core}/tests/utils/testFileHelpers.ts | 2 +- frontend/src/{ => core}/theme/mantineTheme.ts | 0 .../src/{ => core}/tools/AddAttachments.tsx | 16 +- .../src/{ => core}/tools/AddPageNumbers.tsx | 18 +- frontend/src/{ => core}/tools/AddPassword.tsx | 20 +- frontend/src/{ => core}/tools/AddStamp.tsx | 26 +- .../src/{ => core}/tools/AddWatermark.tsx | 24 +- .../src/{ => core}/tools/AdjustContrast.tsx | 20 +- .../src/{ => core}/tools/AdjustPageScale.tsx | 14 +- frontend/src/{ => core}/tools/AutoRename.tsx | 12 +- frontend/src/{ => core}/tools/Automate.tsx | 28 +-- .../{ => core}/tools/BookletImposition.tsx | 14 +- frontend/src/{ => core}/tools/CertSign.tsx | 24 +- .../src/{ => core}/tools/ChangeMetadata.tsx | 24 +- .../{ => core}/tools/ChangePermissions.tsx | 14 +- frontend/src/{ => core}/tools/Compress.tsx | 14 +- frontend/src/{ => core}/tools/Convert.tsx | 14 +- frontend/src/{ => core}/tools/Crop.tsx | 14 +- .../src/{ => core}/tools/ExtractImages.tsx | 12 +- frontend/src/{ => core}/tools/Flatten.tsx | 14 +- frontend/src/{ => core}/tools/Merge.tsx | 18 +- frontend/src/{ => core}/tools/OCR.tsx | 20 +- frontend/src/{ => core}/tools/OverlayPdfs.tsx | 14 +- frontend/src/{ => core}/tools/PageLayout.tsx | 12 +- frontend/src/{ => core}/tools/Redact.tsx | 18 +- .../{ => core}/tools/RemoveAnnotations.tsx | 12 +- .../src/{ => core}/tools/RemoveBlanks.tsx | 14 +- .../tools/RemoveCertificateSign.tsx | 10 +- frontend/src/{ => core}/tools/RemoveImage.tsx | 10 +- frontend/src/{ => core}/tools/RemovePages.tsx | 14 +- .../src/{ => core}/tools/RemovePassword.tsx | 14 +- .../src/{ => core}/tools/ReorganizePages.tsx | 16 +- frontend/src/{ => core}/tools/Repair.tsx | 10 +- .../src/{ => core}/tools/ReplaceColor.tsx | 14 +- frontend/src/{ => core}/tools/Rotate.tsx | 14 +- frontend/src/{ => core}/tools/Sanitize.tsx | 12 +- .../{ => core}/tools/ScannerImageSplit.tsx | 14 +- frontend/src/{ => core}/tools/Sign.tsx | 22 +- .../src/{ => core}/tools/SingleLargePage.tsx | 10 +- frontend/src/{ => core}/tools/Split.tsx | 20 +- frontend/src/{ => core}/tools/SwaggerUI.tsx | 4 +- .../src/{ => core}/tools/UnlockPdfForms.tsx | 10 +- .../{ => core}/tools/ValidateSignature.tsx | 22 +- frontend/src/{ => core}/types/automation.ts | 2 +- frontend/src/{ => core}/types/file.ts | 2 +- frontend/src/{ => core}/types/fileContext.ts | 4 +- .../src/{ => core}/types/fileIdSafety.d.ts | 2 +- frontend/src/{ => core}/types/metadata.ts | 0 frontend/src/{ => core}/types/navigation.ts | 4 +- .../src/{ => core}/types/navigationActions.ts | 4 +- frontend/src/{ => core}/types/pageEditor.ts | 2 +- frontend/src/{ => core}/types/parameters.ts | 0 frontend/src/{ => core}/types/processing.ts | 0 frontend/src/core/types/proprietaryToolId.ts | 16 ++ frontend/src/{ => core}/types/rightRail.ts | 0 frontend/src/{ => core}/types/sidebar.ts | 0 frontend/src/{ => core}/types/tips.ts | 0 frontend/src/{ => core}/types/tool.ts | 2 +- frontend/src/{ => core}/types/toolId.ts | 29 ++- .../src/{ => core}/types/validateSignature.ts | 0 frontend/src/{ => core}/types/workbench.ts | 0 .../{ => core}/utils/automationExecutor.ts | 12 +- .../utils/automationFileProcessor.ts | 6 +- .../{ => core}/utils/bulkselection/README.md | 0 .../bulkselection/parseSelection.test.ts | 2 +- .../utils/bulkselection/parseSelection.ts | 0 .../src/{ => core}/utils/clickHandlers.ts | 0 .../src/{ => core}/utils/convertUtils.test.ts | 2 +- frontend/src/{ => core}/utils/convertUtils.ts | 2 +- .../src/{ => core}/utils/cropCoordinates.ts | 0 .../src/{ => core}/utils/downloadUtils.ts | 6 +- frontend/src/{ => core}/utils/fileHash.ts | 0 .../src/{ => core}/utils/fileHistoryUtils.ts | 2 +- frontend/src/{ => core}/utils/fileIdSafety.ts | 2 +- .../utils/fileResponseUtils.test.ts | 2 +- .../src/{ => core}/utils/fileResponseUtils.ts | 0 frontend/src/{ => core}/utils/fileUtils.ts | 0 frontend/src/{ => core}/utils/fuzzySearch.ts | 0 frontend/src/{ => core}/utils/genericUtils.ts | 0 frontend/src/{ => core}/utils/hotkeys.ts | 0 .../src/{ => core}/utils/languageMapping.ts | 0 .../src/{ => core}/utils/pageSelection.ts | 0 .../src/{ => core}/utils/resourceManager.ts | 2 +- .../src/{ => core}/utils/scarfTracking.ts | 0 frontend/src/{ => core}/utils/scriptLoader.ts | 0 frontend/src/{ => core}/utils/sidebarUtils.ts | 2 +- .../{ => core}/utils/signatureFlattening.ts | 8 +- frontend/src/{ => core}/utils/storageUtils.ts | 2 +- frontend/src/{ => core}/utils/textUtils.ts | 0 .../src/{ => core}/utils/thumbnailUtils.ts | 2 +- .../src/{ => core}/utils/toolErrorHandler.ts | 0 .../{ => core}/utils/toolResponseProcessor.ts | 2 +- frontend/src/{ => core}/utils/toolSearch.ts | 6 +- frontend/src/{ => core}/utils/toolSynonyms.ts | 0 frontend/src/{ => core}/utils/urlMapping.ts | 2 +- frontend/src/{ => core}/utils/urlRouting.ts | 14 +- frontend/src/global.d.ts | 9 +- frontend/src/index.tsx | 8 +- frontend/src/proprietary/App.tsx | 37 +++ .../src/{ => proprietary}/auth/UseSession.tsx | 4 +- .../auth/springAuthClient.ts | 0 .../proprietary/components/AppProviders.tsx | 13 + .../components/shared/DividerWithText.tsx | 2 +- .../components/shared/LoginRightCarousel.tsx | 2 +- .../shared/config/OverviewHeader.tsx | 42 ++++ .../dividerWithText/DividerWithText.css | 0 .../components/shared/loginSlides.ts | 2 +- .../data/useProprietaryToolRegistry.tsx | 13 + .../proprietary/hooks/useRequestHeaders.ts | 4 + .../hooks/useShouldShowWelcomeModal.ts | 17 ++ .../{ => proprietary}/routes/AuthCallback.tsx | 2 +- .../src/{ => proprietary}/routes/Landing.tsx | 8 +- .../src/{ => proprietary}/routes/Login.tsx | 22 +- .../src/{ => proprietary}/routes/Signup.tsx | 20 +- .../routes/authShared/AuthLayout.module.css | 0 .../routes/authShared/AuthLayout.tsx | 6 +- .../routes/authShared/auth.css | 0 .../routes/login/EmailPasswordForm.tsx | 2 +- .../routes/login/ErrorMessage.tsx | 0 .../routes/login/LoggedInState.tsx | 2 +- .../routes/login/LoginHeader.tsx | 2 +- .../routes/login/NavigationLink.tsx | 0 .../routes/login/OAuthButtons.tsx | 2 +- .../routes/signup/AuthService.ts | 7 +- .../routes/signup/SignupForm.tsx | 6 +- .../routes/signup/SignupFormValidation.ts | 0 .../proprietary/services/apiClientSetup.ts | 29 +++ .../src/proprietary/styles/auth-theme.css | 24 ++ .../proprietary/types/proprietaryToolId.ts | 19 ++ frontend/src/services/apiClient.ts | 51 ---- frontend/tsconfig.core.json | 15 ++ frontend/tsconfig.json | 6 + frontend/tsconfig.proprietary.json | 13 + frontend/vite.config.ts | 13 +- frontend/vitest.config.ts | 22 +- 725 files changed, 2485 insertions(+), 2226 deletions(-) delete mode 100644 frontend/src/App.css delete mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/core/App.tsx create mode 100644 frontend/src/core/components/AppProviders.tsx rename frontend/src/{ => core}/components/FileManager.tsx (88%) rename frontend/src/{ => core}/components/StorageStatsCard.tsx (92%) rename frontend/src/{ => core}/components/annotation/providers/PDFAnnotationProvider.tsx (100%) rename frontend/src/{ => core}/components/annotation/shared/BaseAnnotationTool.tsx (90%) rename frontend/src/{ => core}/components/annotation/shared/ColorPicker.tsx (100%) rename frontend/src/{ => core}/components/annotation/shared/DrawingCanvas.tsx (98%) rename frontend/src/{ => core}/components/annotation/shared/DrawingControls.tsx (100%) rename frontend/src/{ => core}/components/annotation/shared/ImageUploader.tsx (100%) rename frontend/src/{ => core}/components/annotation/shared/TextInputWithFont.tsx (98%) rename frontend/src/{ => core}/components/annotation/tools/DrawingTool.tsx (87%) rename frontend/src/{ => core}/components/annotation/tools/ImageTool.tsx (90%) rename frontend/src/{ => core}/components/annotation/tools/TextTool.tsx (88%) rename frontend/src/{ => core}/components/fileEditor/AddFileCard.tsx (96%) rename frontend/src/{ => core}/components/fileEditor/FileEditor.module.css (100%) rename frontend/src/{ => core}/components/fileEditor/FileEditor.tsx (95%) rename frontend/src/{ => core}/components/fileEditor/FileEditorThumbnail.tsx (95%) rename frontend/src/{ => core}/components/fileEditor/fileEditorRightRailButtons.tsx (95%) rename frontend/src/{ => core}/components/fileManager/CompactFileDetails.tsx (97%) rename frontend/src/{ => core}/components/fileManager/DesktopLayout.tsx (83%) rename frontend/src/{ => core}/components/fileManager/DragOverlay.tsx (100%) rename frontend/src/{ => core}/components/fileManager/EmptyFilesState.tsx (95%) rename frontend/src/{ => core}/components/fileManager/FileActions.tsx (97%) rename frontend/src/{ => core}/components/fileManager/FileDetails.tsx (90%) rename frontend/src/{ => core}/components/fileManager/FileHistoryGroup.tsx (94%) rename frontend/src/{ => core}/components/fileManager/FileInfoCard.tsx (94%) rename frontend/src/{ => core}/components/fileManager/FileListArea.tsx (91%) rename frontend/src/{ => core}/components/fileManager/FileListItem.tsx (95%) rename frontend/src/{ => core}/components/fileManager/FileSourceButtons.tsx (96%) rename frontend/src/{ => core}/components/fileManager/HiddenFileInput.tsx (83%) rename frontend/src/{ => core}/components/fileManager/MobileLayout.tsx (85%) rename frontend/src/{ => core}/components/fileManager/SearchInput.tsx (91%) rename frontend/src/{ => core}/components/hotkeys/HotkeyDisplay.tsx (93%) rename frontend/src/{ => core}/components/layout/Workbench.css (100%) rename frontend/src/{ => core}/components/layout/Workbench.tsx (84%) rename frontend/src/{ => core}/components/onboarding/OnboardingTour.css (100%) rename frontend/src/{ => core}/components/onboarding/OnboardingTour.tsx (97%) rename frontend/src/{ => core}/components/onboarding/TourWelcomeModal.tsx (96%) rename frontend/src/{ => core}/components/pageEditor/BulkSelectionPanel.tsx (80%) rename frontend/src/{ => core}/components/pageEditor/DragDropGrid.tsx (98%) rename frontend/src/{ => core}/components/pageEditor/FileThumbnail.tsx (98%) rename frontend/src/{ => core}/components/pageEditor/PageEditor.module.css (100%) rename frontend/src/{ => core}/components/pageEditor/PageEditor.tsx (95%) rename frontend/src/{ => core}/components/pageEditor/PageEditorControls.tsx (100%) rename frontend/src/{ => core}/components/pageEditor/PageSelectByNumberButton.tsx (89%) rename frontend/src/{ => core}/components/pageEditor/PageThumbnail.tsx (97%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx (92%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/BulkSelection.ts (100%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css (100%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx (92%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx (90%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/SelectPages.tsx (96%) rename frontend/src/{ => core}/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx (90%) rename frontend/src/{ => core}/components/pageEditor/commands/pageCommands.ts (98%) rename frontend/src/{ => core}/components/pageEditor/constants.ts (100%) rename frontend/src/{ => core}/components/pageEditor/hooks/usePageDocument.ts (97%) rename frontend/src/{ => core}/components/pageEditor/hooks/usePageEditorState.ts (100%) rename frontend/src/{ => core}/components/pageEditor/pageEditorRightRailButtons.tsx (96%) rename frontend/src/{ => core}/components/shared/AdminAnalyticsChoiceModal.tsx (94%) rename frontend/src/{ => core}/components/shared/AllToolsNavButton.tsx (89%) rename frontend/src/{ => core}/components/shared/AppConfigModal.css (100%) rename frontend/src/{ => core}/components/shared/AppConfigModal.tsx (92%) rename frontend/src/{ => core}/components/shared/Badge.tsx (100%) rename frontend/src/{ => core}/components/shared/ButtonSelector.test.tsx (98%) rename frontend/src/{ => core}/components/shared/ButtonSelector.tsx (97%) rename frontend/src/{ => core}/components/shared/CardSelector.tsx (97%) rename frontend/src/{ => core}/components/shared/DismissAllErrorsButton.tsx (91%) rename frontend/src/{ => core}/components/shared/DropdownListWithFooter.tsx (100%) rename frontend/src/{ => core}/components/shared/ErrorBoundary.tsx (100%) rename frontend/src/{ => core}/components/shared/FileCard.tsx (97%) rename frontend/src/{ => core}/components/shared/FileDropdownMenu.tsx (98%) rename frontend/src/{ => core}/components/shared/FileGrid.tsx (97%) rename frontend/src/{ => core}/components/shared/FilePickerModal.tsx (99%) rename frontend/src/{ => core}/components/shared/FilePreview.tsx (86%) rename frontend/src/{ => core}/components/shared/FileUploadButton.tsx (100%) rename frontend/src/{ => core}/components/shared/FitText.tsx (97%) rename frontend/src/{ => core}/components/shared/Footer.tsx (97%) rename frontend/src/{ => core}/components/shared/HoverActionMenu.module.css (100%) rename frontend/src/{ => core}/components/shared/HoverActionMenu.tsx (95%) rename frontend/src/{ => core}/components/shared/LandingPage.tsx (96%) rename frontend/src/{ => core}/components/shared/LanguageSelector.module.css (100%) rename frontend/src/{ => core}/components/shared/LanguageSelector.tsx (97%) create mode 100644 frontend/src/core/components/shared/LoadingFallback.tsx rename frontend/src/{ => core}/components/shared/LocalIcon.tsx (95%) rename frontend/src/{ => core}/components/shared/MultiSelectControls.tsx (100%) rename frontend/src/{ => core}/components/shared/NavigationWarningModal.tsx (98%) rename frontend/src/{ => core}/components/shared/ObscuredOverlay.tsx (93%) rename frontend/src/{ => core}/components/shared/ObscuredOverlay/ObscuredOverlay.module.css (100%) rename frontend/src/{ => core}/components/shared/QuickAccessBar.tsx (88%) rename frontend/src/{ => core}/components/shared/RainbowThemeProvider.tsx (78%) rename frontend/src/{ => core}/components/shared/RightRail.tsx (89%) rename frontend/src/{ => core}/components/shared/SkeletonLoader.tsx (100%) rename frontend/src/{ => core}/components/shared/TextInput.tsx (95%) rename frontend/src/{ => core}/components/shared/ToolChain.tsx (97%) rename frontend/src/{ => core}/components/shared/ToolIcon.tsx (100%) rename frontend/src/{ => core}/components/shared/Tooltip.tsx (95%) rename frontend/src/{ => core}/components/shared/TopControls.tsx (93%) create mode 100644 frontend/src/core/components/shared/config/OverviewHeader.tsx rename frontend/src/{ => core}/components/shared/config/configNavSections.tsx (83%) rename frontend/src/{ => core}/components/shared/config/configSections/GeneralSection.tsx (96%) rename frontend/src/{ => core}/components/shared/config/configSections/HotkeysSection.tsx (94%) rename frontend/src/{ => core}/components/shared/config/configSections/Overview.tsx (67%) rename frontend/src/{ => core}/components/shared/config/types.ts (100%) rename frontend/src/{ => core}/components/shared/filePreview/DocumentStack.tsx (100%) rename frontend/src/{ => core}/components/shared/filePreview/DocumentThumbnail.tsx (96%) rename frontend/src/{ => core}/components/shared/filePreview/HoverOverlay.tsx (100%) rename frontend/src/{ => core}/components/shared/filePreview/NavigationArrows.tsx (100%) rename frontend/src/{ => core}/components/shared/fitText/FitText.README.md (100%) rename frontend/src/{ => core}/components/shared/fitText/textFit.ts (100%) rename frontend/src/{ => core}/components/shared/quickAccessBar/ActiveToolButton.tsx (95%) rename frontend/src/{ => core}/components/shared/quickAccessBar/QuickAccessBar.css (100%) rename frontend/src/{ => core}/components/shared/quickAccessBar/QuickAccessBar.ts (97%) rename frontend/src/{ => core}/components/shared/rightRail/RightRail.README.md (100%) rename frontend/src/{ => core}/components/shared/rightRail/RightRail.css (100%) rename frontend/src/{ => core}/components/shared/rightRail/ViewerAnnotationControls.tsx (92%) rename frontend/src/{ => core}/components/shared/sliderWithInput/SliderWithInput.tsx (100%) rename frontend/src/{ => core}/components/shared/textInput/TextInput.module.css (100%) rename frontend/src/{ => core}/components/shared/tooltip/Tooltip.README.md (100%) rename frontend/src/{ => core}/components/shared/tooltip/Tooltip.module.css (100%) rename frontend/src/{ => core}/components/shared/tooltip/TooltipContent.tsx (95%) rename frontend/src/{ => core}/components/toast/Toast.README.md (100%) rename frontend/src/{ => core}/components/toast/ToastContext.tsx (98%) rename frontend/src/{ => core}/components/toast/ToastRenderer.css (100%) rename frontend/src/{ => core}/components/toast/ToastRenderer.tsx (94%) rename frontend/src/{ => core}/components/toast/index.ts (87%) rename frontend/src/{ => core}/components/toast/types.ts (100%) rename frontend/src/{ => core}/components/tools/FullscreenToolList.tsx (93%) rename frontend/src/{ => core}/components/tools/FullscreenToolSurface.tsx (88%) rename frontend/src/{ => core}/components/tools/SearchResults.tsx (82%) rename frontend/src/{ => core}/components/tools/ToolLoadingFallback.tsx (100%) rename frontend/src/{ => core}/components/tools/ToolPanel.css (100%) rename frontend/src/{ => core}/components/tools/ToolPanel.tsx (87%) rename frontend/src/{ => core}/components/tools/ToolPanelModePrompt.css (100%) rename frontend/src/{ => core}/components/tools/ToolPanelModePrompt.tsx (96%) rename frontend/src/{ => core}/components/tools/ToolPicker.tsx (91%) rename frontend/src/{ => core}/components/tools/ToolRenderer.tsx (82%) rename frontend/src/{ => core}/components/tools/addAttachments/AddAttachmentsSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx (94%) rename frontend/src/{ => core}/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx (81%) rename frontend/src/{ => core}/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/addPageNumbers/PageNumberPreview.module.css (100%) rename frontend/src/{ => core}/components/tools/addPageNumbers/PageNumberPreview.tsx (96%) rename frontend/src/{ => core}/components/tools/addPageNumbers/useAddPageNumbersOperation.ts (81%) rename frontend/src/{ => core}/components/tools/addPageNumbers/useAddPageNumbersParameters.ts (85%) rename frontend/src/{ => core}/components/tools/addPassword/AddPasswordSettings.test.tsx (96%) rename frontend/src/{ => core}/components/tools/addPassword/AddPasswordSettings.tsx (95%) rename frontend/src/{ => core}/components/tools/addStamp/AddStampAutomationSettings.tsx (80%) rename frontend/src/{ => core}/components/tools/addStamp/StampPositionFormattingSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/addStamp/StampPreview.module.css (100%) rename frontend/src/{ => core}/components/tools/addStamp/StampPreview.tsx (96%) rename frontend/src/{ => core}/components/tools/addStamp/StampPreviewUtils.ts (98%) rename frontend/src/{ => core}/components/tools/addStamp/StampSetupSettings.tsx (91%) rename frontend/src/{ => core}/components/tools/addStamp/useAddStampOperation.ts (87%) rename frontend/src/{ => core}/components/tools/addStamp/useAddStampParameters.ts (88%) rename frontend/src/{ => core}/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx (78%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkFormatting.tsx (93%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkImageFile.tsx (82%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkStyleSettings.tsx (95%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkTextStyle.tsx (87%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkTypeSettings.tsx (92%) rename frontend/src/{ => core}/components/tools/addWatermark/WatermarkWording.tsx (86%) rename frontend/src/{ => core}/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx (84%) rename frontend/src/{ => core}/components/tools/adjustContrast/AdjustContrastColorSettings.tsx (83%) rename frontend/src/{ => core}/components/tools/adjustContrast/AdjustContrastPreview.tsx (90%) rename frontend/src/{ => core}/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx (71%) rename frontend/src/{ => core}/components/tools/adjustContrast/utils.ts (95%) rename frontend/src/{ => core}/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx (89%) rename frontend/src/{ => core}/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx (94%) rename frontend/src/{ => core}/components/tools/autoRename/AutoRenameSettings.tsx (88%) rename frontend/src/{ => core}/components/tools/automate/AutomationCreation.tsx (93%) rename frontend/src/{ => core}/components/tools/automate/AutomationEntry.tsx (97%) rename frontend/src/{ => core}/components/tools/automate/AutomationRun.tsx (95%) rename frontend/src/{ => core}/components/tools/automate/AutomationSelection.tsx (88%) rename frontend/src/{ => core}/components/tools/automate/IconSelector.tsx (98%) rename frontend/src/{ => core}/components/tools/automate/ToolConfigurationModal.tsx (93%) rename frontend/src/{ => core}/components/tools/automate/ToolList.tsx (95%) rename frontend/src/{ => core}/components/tools/automate/ToolSelector.tsx (95%) rename frontend/src/{ => core}/components/tools/automate/iconMap.ts (100%) rename frontend/src/{ => core}/components/tools/bookletImposition/BookletImpositionSettings.tsx (97%) rename frontend/src/{ => core}/components/tools/certSign/CertSignAutomationSettings.tsx (78%) rename frontend/src/{ => core}/components/tools/certSign/CertificateFilesSettings.tsx (95%) rename frontend/src/{ => core}/components/tools/certSign/CertificateFormatSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/certSign/CertificateTypeSettings.tsx (91%) rename frontend/src/{ => core}/components/tools/certSign/SignatureAppearanceSettings.tsx (98%) rename frontend/src/{ => core}/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx (83%) rename frontend/src/{ => core}/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx (87%) rename frontend/src/{ => core}/components/tools/changeMetadata/steps/CustomMetadataStep.tsx (95%) rename frontend/src/{ => core}/components/tools/changeMetadata/steps/DeleteAllStep.tsx (86%) rename frontend/src/{ => core}/components/tools/changeMetadata/steps/DocumentDatesStep.tsx (92%) rename frontend/src/{ => core}/components/tools/changeMetadata/steps/StandardMetadataStep.tsx (95%) rename frontend/src/{ => core}/components/tools/changePermissions/ChangePermissionsSettings.test.tsx (95%) rename frontend/src/{ => core}/components/tools/changePermissions/ChangePermissionsSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/compress/CompressSettings.tsx (97%) rename frontend/src/{ => core}/components/tools/convert/ConvertFromEmailSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/convert/ConvertFromImageSettings.tsx (94%) rename frontend/src/{ => core}/components/tools/convert/ConvertFromWebSettings.tsx (94%) rename frontend/src/{ => core}/components/tools/convert/ConvertSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/convert/ConvertToImageSettings.tsx (93%) rename frontend/src/{ => core}/components/tools/convert/ConvertToPdfaSettings.tsx (88%) rename frontend/src/{ => core}/components/tools/convert/GroupedFormatDropdown.tsx (100%) rename frontend/src/{ => core}/components/tools/crop/CropAreaSelector.tsx (98%) rename frontend/src/{ => core}/components/tools/crop/CropAutomationSettings.tsx (84%) rename frontend/src/{ => core}/components/tools/crop/CropCoordinateInputs.tsx (97%) rename frontend/src/{ => core}/components/tools/crop/CropSettings.tsx (91%) rename frontend/src/{ => core}/components/tools/extractImages/ExtractImagesSettings.tsx (93%) rename frontend/src/{ => core}/components/tools/flatten/FlattenSettings.tsx (92%) rename frontend/src/{ => core}/components/tools/fullscreen/CompactToolItem.tsx (90%) rename frontend/src/{ => core}/components/tools/fullscreen/DetailedToolItem.tsx (90%) rename frontend/src/{ => core}/components/tools/fullscreen/shared.ts (83%) rename frontend/src/{ => core}/components/tools/merge/MergeFileSorter.test.tsx (98%) rename frontend/src/{ => core}/components/tools/merge/MergeFileSorter.tsx (100%) rename frontend/src/{ => core}/components/tools/merge/MergeSettings.test.tsx (95%) rename frontend/src/{ => core}/components/tools/merge/MergeSettings.tsx (93%) rename frontend/src/{ => core}/components/tools/ocr/AdvancedOCRSettings.tsx (97%) rename frontend/src/{ => core}/components/tools/ocr/LanguagePicker.module.css (100%) rename frontend/src/{ => core}/components/tools/ocr/LanguagePicker.tsx (96%) rename frontend/src/{ => core}/components/tools/ocr/OCRSettings.tsx (91%) rename frontend/src/{ => core}/components/tools/overlayPdfs/OverlayPdfsSettings.module.css (100%) rename frontend/src/{ => core}/components/tools/overlayPdfs/OverlayPdfsSettings.tsx (95%) rename frontend/src/{ => core}/components/tools/pageLayout/PageLayoutSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/pageLayout/constants.ts (100%) rename frontend/src/{ => core}/components/tools/redact/RedactAdvancedSettings.test.tsx (97%) rename frontend/src/{ => core}/components/tools/redact/RedactAdvancedSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/redact/RedactModeSelector.tsx (85%) rename frontend/src/{ => core}/components/tools/redact/RedactSingleStepSettings.test.tsx (97%) rename frontend/src/{ => core}/components/tools/redact/RedactSingleStepSettings.tsx (82%) rename frontend/src/{ => core}/components/tools/redact/WordsToRedactInput.test.tsx (98%) rename frontend/src/{ => core}/components/tools/redact/WordsToRedactInput.tsx (100%) rename frontend/src/{ => core}/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx (92%) rename frontend/src/{ => core}/components/tools/removeBlanks/RemoveBlanksSettings.tsx (92%) rename frontend/src/{ => core}/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx (85%) rename frontend/src/{ => core}/components/tools/removePages/RemovePagesSettings.tsx (90%) rename frontend/src/{ => core}/components/tools/removePassword/RemovePasswordSettings.test.tsx (95%) rename frontend/src/{ => core}/components/tools/removePassword/RemovePasswordSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/reorganizePages/ReorganizePagesSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/reorganizePages/constants.ts (100%) rename frontend/src/{ => core}/components/tools/repair/RepairSettings.tsx (88%) rename frontend/src/{ => core}/components/tools/replaceColor/ReplaceColorSettings.tsx (97%) rename frontend/src/{ => core}/components/tools/rotate/RotateAutomationSettings.tsx (89%) rename frontend/src/{ => core}/components/tools/rotate/RotateSettings.tsx (93%) rename frontend/src/{ => core}/components/tools/sanitize/SanitizeSettings.test.tsx (97%) rename frontend/src/{ => core}/components/tools/sanitize/SanitizeSettings.tsx (93%) rename frontend/src/{ => core}/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx (95%) rename frontend/src/{ => core}/components/tools/shared/ErrorNotification.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/FileMetadata.tsx (88%) rename frontend/src/{ => core}/components/tools/shared/FileStatusIndicator.tsx (94%) rename frontend/src/{ => core}/components/tools/shared/FilesToolStep.tsx (83%) rename frontend/src/{ => core}/components/tools/shared/NavigationControls.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/NoToolsFound.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/NumberInputWithUnit.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/OperationButton.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/ResultsPreview.tsx (92%) rename frontend/src/{ => core}/components/tools/shared/ReviewToolStep.tsx (90%) rename frontend/src/{ => core}/components/tools/shared/SubcategoryHeader.tsx (100%) rename frontend/src/{ => core}/components/tools/shared/SuggestedToolsSection.tsx (90%) rename frontend/src/{ => core}/components/tools/shared/ToolStep.tsx (92%) rename frontend/src/{ => core}/components/tools/shared/ToolWorkflowTitle.tsx (91%) rename frontend/src/{ => core}/components/tools/shared/createToolFlow.tsx (89%) rename frontend/src/{ => core}/components/tools/shared/renderToolButtons.tsx (81%) rename frontend/src/{ => core}/components/tools/sign/PenSizeSelector.tsx (100%) rename frontend/src/{ => core}/components/tools/sign/SignSettings.tsx (94%) rename frontend/src/{ => core}/components/tools/singleLargePage/SingleLargePageSettings.tsx (87%) rename frontend/src/{ => core}/components/tools/split/SplitAutomationSettings.tsx (88%) rename frontend/src/{ => core}/components/tools/split/SplitSettings.tsx (96%) rename frontend/src/{ => core}/components/tools/toolPicker/FavoriteStar.tsx (100%) rename frontend/src/{ => core}/components/tools/toolPicker/ToolButton.tsx (89%) rename frontend/src/{ => core}/components/tools/toolPicker/ToolPicker.css (100%) rename frontend/src/{ => core}/components/tools/toolPicker/ToolSearch.tsx (93%) rename frontend/src/{ => core}/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx (87%) rename frontend/src/{ => core}/components/tools/validateSignature/ValidateSignatureReportView.tsx (92%) rename frontend/src/{ => core}/components/tools/validateSignature/ValidateSignatureResults.tsx (94%) rename frontend/src/{ => core}/components/tools/validateSignature/ValidateSignatureSettings.tsx (91%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/FieldBlock.tsx (89%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/FileSummaryHeader.tsx (89%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/SignatureSection.tsx (89%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx (82%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/ThumbnailPreview.tsx (88%) rename frontend/src/{ => core}/components/tools/validateSignature/reportView/styles.css (100%) rename frontend/src/{ => core}/components/tooltips/useAddPasswordPermissionsTips.ts (90%) rename frontend/src/{ => core}/components/tooltips/useAddPasswordTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useAdjustPageScaleTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useAdvancedOCRTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useAutoRenameTips.ts (93%) rename frontend/src/{ => core}/components/tooltips/useBookletImpositionTips.ts (98%) rename frontend/src/{ => core}/components/tooltips/useCertSignTooltips.ts (98%) rename frontend/src/{ => core}/components/tooltips/useCertificateTypeTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useChangeMetadataTips.ts (98%) rename frontend/src/{ => core}/components/tooltips/useChangePermissionsTips.ts (93%) rename frontend/src/{ => core}/components/tooltips/useCompressTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useCropTooltips.ts (100%) rename frontend/src/{ => core}/components/tooltips/useFlattenTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useMergeTips.tsx (93%) rename frontend/src/{ => core}/components/tooltips/useOCRTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useOverlayPdfsTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/usePageSelectionTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/usePageSelectionTips.tsx (98%) rename frontend/src/{ => core}/components/tooltips/useRedactTips.ts (98%) rename frontend/src/{ => core}/components/tooltips/useRemoveBlanksTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useRemovePagesTips.ts (96%) rename frontend/src/{ => core}/components/tooltips/useRemovePasswordTips.ts (91%) rename frontend/src/{ => core}/components/tooltips/useReplaceColorTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useRotateTips.ts (94%) rename frontend/src/{ => core}/components/tooltips/useScannerImageSplitTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useSignModeTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useSignatureAppearanceTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useSplitMethodTips.ts (95%) rename frontend/src/{ => core}/components/tooltips/useSplitSettingsTips.ts (97%) rename frontend/src/{ => core}/components/tooltips/useWatermarkTips.ts (99%) rename frontend/src/{ => core}/components/viewer/CustomSearchLayer.tsx (96%) rename frontend/src/{ => core}/components/viewer/EmbedPdfViewer.tsx (93%) rename frontend/src/{ => core}/components/viewer/ExportAPIBridge.tsx (91%) rename frontend/src/{ => core}/components/viewer/HistoryAPIBridge.tsx (96%) rename frontend/src/{ => core}/components/viewer/LocalEmbedPDF.tsx (91%) rename frontend/src/{ => core}/components/viewer/LocalEmbedPDFWithAnnotations.tsx (93%) rename frontend/src/{ => core}/components/viewer/PanAPIBridge.tsx (94%) rename frontend/src/{ => core}/components/viewer/PdfViewerToolbar.tsx (99%) rename frontend/src/{ => core}/components/viewer/RotateAPIBridge.tsx (94%) rename frontend/src/{ => core}/components/viewer/ScrollAPIBridge.tsx (93%) rename frontend/src/{ => core}/components/viewer/SearchAPIBridge.tsx (97%) rename frontend/src/{ => core}/components/viewer/SearchInterface.tsx (98%) rename frontend/src/{ => core}/components/viewer/SelectionAPIBridge.tsx (97%) rename frontend/src/{ => core}/components/viewer/SignatureAPIBridge.tsx (98%) rename frontend/src/{ => core}/components/viewer/SpreadAPIBridge.tsx (95%) rename frontend/src/{ => core}/components/viewer/ThumbnailAPIBridge.tsx (91%) rename frontend/src/{ => core}/components/viewer/ThumbnailSidebar.tsx (99%) rename frontend/src/{ => core}/components/viewer/Viewer.tsx (84%) rename frontend/src/{ => core}/components/viewer/ZoomAPIBridge.tsx (96%) rename frontend/src/{ => core}/components/viewer/constants/search.ts (100%) rename frontend/src/{ => core}/components/viewer/useViewerRightRailButtons.tsx (91%) rename frontend/src/{ => core}/components/viewer/viewerTypes.ts (100%) rename frontend/src/{ => core}/constants/addWatermarkConstants.ts (100%) rename frontend/src/{ => core}/constants/app.ts (100%) rename frontend/src/{ => core}/constants/automation.ts (100%) rename frontend/src/{ => core}/constants/convertConstants.ts (100%) rename frontend/src/{ => core}/constants/convertSupportedFornats.ts (100%) rename frontend/src/{ => core}/constants/cropConstants.ts (80%) rename frontend/src/{ => core}/constants/pageSizeConstants.ts (100%) rename frontend/src/{ => core}/constants/splitConstants.ts (97%) rename frontend/src/{ => core}/constants/theme.ts (100%) rename frontend/src/{ => core}/constants/toolPanel.ts (100%) rename frontend/src/{ => core}/contexts/AppConfigContext.tsx (90%) rename frontend/src/{ => core}/contexts/FileContext.tsx (94%) rename frontend/src/{ => core}/contexts/FileManagerContext.tsx (98%) rename frontend/src/{ => core}/contexts/FilesModalContext.tsx (94%) rename frontend/src/{ => core}/contexts/HotkeyContext.tsx (96%) rename frontend/src/{ => core}/contexts/IndexedDBContext.tsx (97%) rename frontend/src/{ => core}/contexts/NavigationContext.tsx (98%) rename frontend/src/{ => core}/contexts/OnboardingContext.tsx (63%) rename frontend/src/{ => core}/contexts/PreferencesContext.tsx (94%) rename frontend/src/{ => core}/contexts/RightRailContext.tsx (97%) rename frontend/src/{ => core}/contexts/SidebarContext.tsx (97%) rename frontend/src/{ => core}/contexts/SignatureContext.tsx (97%) rename frontend/src/{ => core}/contexts/ToolRegistryContext.tsx (90%) rename frontend/src/{ => core}/contexts/ToolRegistryProvider.tsx (75%) rename frontend/src/{ => core}/contexts/ToolWorkflowContext.tsx (94%) rename frontend/src/{ => core}/contexts/TourOrchestrationContext.tsx (93%) rename frontend/src/{ => core}/contexts/ViewerContext.tsx (99%) rename frontend/src/{ => core}/contexts/file/FileReducer.ts (98%) rename frontend/src/{ => core}/contexts/file/contexts.ts (94%) rename frontend/src/{ => core}/contexts/file/fileActions.ts (97%) rename frontend/src/{ => core}/contexts/file/fileHooks.ts (97%) rename frontend/src/{ => core}/contexts/file/fileSelectors.ts (98%) rename frontend/src/{ => core}/contexts/file/lifecycle.ts (98%) rename frontend/src/{ => core}/contexts/toolWorkflow/toolWorkflowState.ts (93%) rename frontend/src/{ => core}/data/toolsTaxonomy.ts (95%) create mode 100644 frontend/src/core/data/useProprietaryToolRegistry.tsx rename frontend/src/{ => core}/data/useTranslatedToolRegistry.tsx (78%) rename frontend/src/{ => core}/hooks/tools/addAttachments/useAddAttachmentsOperation.ts (83%) rename frontend/src/{ => core}/hooks/tools/addAttachments/useAddAttachmentsParameters.ts (100%) rename frontend/src/{ => core}/hooks/tools/addPassword/useAddPasswordOperation.test.ts (93%) rename frontend/src/{ => core}/hooks/tools/addPassword/useAddPasswordOperation.ts (73%) rename frontend/src/{ => core}/hooks/tools/addPassword/useAddPasswordParameters.test.ts (96%) rename frontend/src/{ => core}/hooks/tools/addPassword/useAddPasswordParameters.ts (83%) rename frontend/src/{ => core}/hooks/tools/addWatermark/useAddWatermarkOperation.ts (87%) rename frontend/src/{ => core}/hooks/tools/addWatermark/useAddWatermarkParameters.ts (88%) rename frontend/src/{ => core}/hooks/tools/adjustContrast/useAdjustContrastOperation.ts (89%) rename frontend/src/{ => core}/hooks/tools/adjustContrast/useAdjustContrastParameters.ts (88%) rename frontend/src/{ => core}/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts (76%) rename frontend/src/{ => core}/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts (97%) rename frontend/src/{ => core}/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts (82%) rename frontend/src/{ => core}/hooks/tools/autoRename/useAutoRenameOperation.ts (81%) rename frontend/src/{ => core}/hooks/tools/autoRename/useAutoRenameParameters.ts (74%) rename frontend/src/{ => core}/hooks/tools/automate/useAutomateOperation.ts (84%) rename frontend/src/{ => core}/hooks/tools/automate/useAutomationForm.ts (95%) rename frontend/src/{ => core}/hooks/tools/automate/useSavedAutomations.ts (87%) rename frontend/src/{ => core}/hooks/tools/automate/useSuggestedAutomations.ts (97%) rename frontend/src/{ => core}/hooks/tools/bookletImposition/useBookletImpositionOperation.ts (87%) rename frontend/src/{ => core}/hooks/tools/bookletImposition/useBookletImpositionParameters.ts (85%) rename frontend/src/{ => core}/hooks/tools/certSign/useCertSignOperation.ts (88%) rename frontend/src/{ => core}/hooks/tools/certSign/useCertSignParameters.ts (91%) rename frontend/src/{ => core}/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts (94%) rename frontend/src/{ => core}/hooks/tools/changeMetadata/useChangeMetadataOperation.ts (90%) rename frontend/src/{ => core}/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts (98%) rename frontend/src/{ => core}/hooks/tools/changeMetadata/useChangeMetadataParameters.ts (93%) rename frontend/src/{ => core}/hooks/tools/changeMetadata/useMetadataExtraction.ts (90%) rename frontend/src/{ => core}/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts (92%) rename frontend/src/{ => core}/hooks/tools/changePermissions/useChangePermissionsOperation.ts (85%) rename frontend/src/{ => core}/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts (97%) rename frontend/src/{ => core}/hooks/tools/changePermissions/useChangePermissionsParameters.ts (86%) rename frontend/src/{ => core}/hooks/tools/compress/useCompressOperation.ts (82%) rename frontend/src/{ => core}/hooks/tools/compress/useCompressParameters.ts (85%) rename frontend/src/{ => core}/hooks/tools/convert/useConvertOperation.ts (94%) rename frontend/src/{ => core}/hooks/tools/convert/useConvertParameters.test.ts (98%) rename frontend/src/{ => core}/hooks/tools/convert/useConvertParameters.ts (97%) rename frontend/src/{ => core}/hooks/tools/convert/useConvertParametersAutoDetection.test.ts (99%) rename frontend/src/{ => core}/hooks/tools/crop/useCropOperation.ts (81%) rename frontend/src/{ => core}/hooks/tools/crop/useCropParameters.ts (94%) rename frontend/src/{ => core}/hooks/tools/extractImages/useExtractImagesOperation.ts (80%) rename frontend/src/{ => core}/hooks/tools/extractImages/useExtractImagesParameters.ts (85%) rename frontend/src/{ => core}/hooks/tools/flatten/useFlattenOperation.ts (78%) rename frontend/src/{ => core}/hooks/tools/flatten/useFlattenParameters.ts (72%) rename frontend/src/{ => core}/hooks/tools/merge/useMergeOperation.test.ts (94%) rename frontend/src/{ => core}/hooks/tools/merge/useMergeOperation.ts (87%) rename frontend/src/{ => core}/hooks/tools/merge/useMergeParameters.test.ts (95%) rename frontend/src/{ => core}/hooks/tools/merge/useMergeParameters.ts (75%) rename frontend/src/{ => core}/hooks/tools/ocr/useOCROperation.ts (94%) rename frontend/src/{ => core}/hooks/tools/ocr/useOCRParameters.ts (80%) rename frontend/src/{ => core}/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts (85%) rename frontend/src/{ => core}/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts (87%) rename frontend/src/{ => core}/hooks/tools/pageLayout/usePageLayoutOperation.ts (77%) rename frontend/src/{ => core}/hooks/tools/pageLayout/usePageLayoutParameters.ts (76%) rename frontend/src/{ => core}/hooks/tools/redact/useRedactOperation.test.ts (92%) rename frontend/src/{ => core}/hooks/tools/redact/useRedactOperation.ts (87%) rename frontend/src/{ => core}/hooks/tools/redact/useRedactParameters.test.ts (98%) rename frontend/src/{ => core}/hooks/tools/redact/useRedactParameters.ts (89%) rename frontend/src/{ => core}/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts (93%) rename frontend/src/{ => core}/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts (84%) rename frontend/src/{ => core}/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts (82%) rename frontend/src/{ => core}/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts (82%) rename frontend/src/{ => core}/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts (81%) rename frontend/src/{ => core}/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts (78%) rename frontend/src/{ => core}/hooks/tools/removeImage/useRemoveImageOperation.ts (79%) rename frontend/src/{ => core}/hooks/tools/removeImage/useRemoveImageParameters.ts (69%) rename frontend/src/{ => core}/hooks/tools/removePages/useRemovePagesOperation.ts (76%) rename frontend/src/{ => core}/hooks/tools/removePages/useRemovePagesParameters.ts (71%) rename frontend/src/{ => core}/hooks/tools/removePassword/useRemovePasswordOperation.test.ts (91%) rename frontend/src/{ => core}/hooks/tools/removePassword/useRemovePasswordOperation.ts (77%) rename frontend/src/{ => core}/hooks/tools/removePassword/useRemovePasswordParameters.test.ts (97%) rename frontend/src/{ => core}/hooks/tools/removePassword/useRemovePasswordParameters.ts (76%) rename frontend/src/{ => core}/hooks/tools/reorganizePages/useReorganizePagesOperation.ts (82%) rename frontend/src/{ => core}/hooks/tools/reorganizePages/useReorganizePagesParameters.ts (100%) rename frontend/src/{ => core}/hooks/tools/repair/useRepairOperation.ts (76%) rename frontend/src/{ => core}/hooks/tools/repair/useRepairParameters.ts (76%) rename frontend/src/{ => core}/hooks/tools/replaceColor/useReplaceColorOperation.ts (82%) rename frontend/src/{ => core}/hooks/tools/replaceColor/useReplaceColorParameters.ts (85%) rename frontend/src/{ => core}/hooks/tools/rotate/useRotateOperation.test.ts (93%) rename frontend/src/{ => core}/hooks/tools/rotate/useRotateOperation.ts (82%) rename frontend/src/{ => core}/hooks/tools/rotate/useRotateParameters.test.ts (98%) rename frontend/src/{ => core}/hooks/tools/rotate/useRotateParameters.ts (92%) rename frontend/src/{ => core}/hooks/tools/sanitize/useSanitizeOperation.ts (83%) rename frontend/src/{ => core}/hooks/tools/sanitize/useSanitizeParameters.test.ts (96%) rename frontend/src/{ => core}/hooks/tools/sanitize/useSanitizeParameters.ts (83%) rename frontend/src/{ => core}/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts (90%) rename frontend/src/{ => core}/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts (83%) rename frontend/src/{ => core}/hooks/tools/shared/useAccordionSteps.ts (100%) rename frontend/src/{ => core}/hooks/tools/shared/useBaseParameters.ts (100%) rename frontend/src/{ => core}/hooks/tools/shared/useBaseTool.ts (90%) rename frontend/src/{ => core}/hooks/tools/shared/useOperationResults.ts (100%) rename frontend/src/{ => core}/hooks/tools/shared/useToolApiCalls.ts (93%) rename frontend/src/{ => core}/hooks/tools/shared/useToolOperation.ts (96%) rename frontend/src/{ => core}/hooks/tools/shared/useToolResources.ts (95%) rename frontend/src/{ => core}/hooks/tools/shared/useToolState.ts (100%) rename frontend/src/{ => core}/hooks/tools/sign/useSignOperation.ts (86%) rename frontend/src/{ => core}/hooks/tools/sign/useSignParameters.ts (95%) rename frontend/src/{ => core}/hooks/tools/singleLargePage/useSingleLargePageOperation.ts (76%) rename frontend/src/{ => core}/hooks/tools/singleLargePage/useSingleLargePageParameters.ts (76%) rename frontend/src/{ => core}/hooks/tools/split/useSplitOperation.ts (90%) rename frontend/src/{ => core}/hooks/tools/split/useSplitParameters.ts (86%) rename frontend/src/{ => core}/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts (76%) rename frontend/src/{ => core}/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts (76%) rename frontend/src/{ => core}/hooks/tools/useFavoriteToolItems.ts (85%) rename frontend/src/{ => core}/hooks/tools/useToolPanelGeometry.ts (100%) rename frontend/src/{ => core}/hooks/tools/useUserToolActivity.ts (97%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts (90%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts (90%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts (89%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection.ts (100%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts (89%) rename frontend/src/{ => core}/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts (93%) rename frontend/src/{ => core}/hooks/tools/validateSignature/signatureReportPdf.ts (81%) rename frontend/src/{ => core}/hooks/tools/validateSignature/useValidateSignatureOperation.ts (88%) rename frontend/src/{ => core}/hooks/tools/validateSignature/useValidateSignatureParameters.ts (81%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/pdfPageHelpers.ts (96%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/pdfPalette.ts (100%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/pdfText.ts (100%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/reportStatus.ts (84%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/signatureCsv.ts (94%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/signatureReportBuilder.ts (83%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/signatureStatus.ts (93%) rename frontend/src/{ => core}/hooks/tools/validateSignature/utils/signatureUtils.ts (95%) rename frontend/src/{ => core}/hooks/useBaseUrl.ts (69%) rename frontend/src/{ => core}/hooks/useCookieConsent.ts (98%) rename frontend/src/{ => core}/hooks/useDocumentMeta.ts (100%) rename frontend/src/{ => core}/hooks/useEndpointConfig.ts (91%) rename frontend/src/{ => core}/hooks/useEnhancedProcessedFiles.ts (98%) rename frontend/src/{ => core}/hooks/useFileHandler.ts (90%) rename frontend/src/{ => core}/hooks/useFileManager.ts (95%) rename frontend/src/{ => core}/hooks/useFileWithUrl.ts (96%) rename frontend/src/{ => core}/hooks/useFocusTrap.ts (100%) rename frontend/src/{ => core}/hooks/useGoogleDrivePicker.ts (98%) rename frontend/src/{ => core}/hooks/useIndexedDBThumbnail.ts (91%) rename frontend/src/{ => core}/hooks/useIsOverflowing.ts (100%) rename frontend/src/{ => core}/hooks/usePDFProcessor.ts (95%) rename frontend/src/{ => core}/hooks/usePdfSignatureDetection.ts (93%) rename frontend/src/{ => core}/hooks/useProcessedFiles.ts (96%) rename frontend/src/{ => core}/hooks/useRainbowTheme.ts (97%) create mode 100644 frontend/src/core/hooks/useRequestHeaders.ts rename frontend/src/{ => core}/hooks/useRightRailButtons.ts (92%) rename frontend/src/{ => core}/hooks/useScarfTracking.ts (88%) create mode 100644 frontend/src/core/hooks/useShouldShowWelcomeModal.ts rename frontend/src/{ => core}/hooks/useSidebarNavigation.ts (87%) rename frontend/src/{ => core}/hooks/useSuggestedTools.ts (88%) rename frontend/src/{ => core}/hooks/useThumbnailGeneration.ts (97%) rename frontend/src/{ => core}/hooks/useToolManagement.tsx (89%) rename frontend/src/{ => core}/hooks/useToolNavigation.ts (83%) rename frontend/src/{ => core}/hooks/useToolParameters.ts (100%) rename frontend/src/{ => core}/hooks/useToolSections.ts (98%) rename frontend/src/{ => core}/hooks/useTooltipPosition.ts (96%) rename frontend/src/{ => core}/hooks/useTranslation.ts (100%) rename frontend/src/{ => core}/hooks/useUndoRedo.ts (100%) rename frontend/src/{ => core}/hooks/useUrlSync.ts (93%) rename frontend/src/{ => core}/i18n.ts (100%) rename frontend/src/{ => core}/i18n/config.ts (100%) rename frontend/src/{ => core}/pages/HomePage.css (100%) rename frontend/src/{ => core}/pages/HomePage.tsx (90%) create mode 100644 frontend/src/core/services/apiClient.ts create mode 100644 frontend/src/core/services/apiClientSetup.ts rename frontend/src/{ => core}/services/automationStorage.ts (100%) rename frontend/src/{ => core}/services/documentManipulationService.ts (98%) rename frontend/src/{ => core}/services/enhancedPDFProcessingService.ts (97%) rename frontend/src/{ => core}/services/errorUtils.ts (100%) rename frontend/src/{ => core}/services/fileAnalyzer.ts (98%) rename frontend/src/{ => core}/services/fileProcessingService.ts (97%) rename frontend/src/{ => core}/services/fileStorage.ts (98%) rename frontend/src/{ => core}/services/fileStubHelpers.ts (81%) rename frontend/src/{ => core}/services/googleDrivePickerService.ts (99%) rename frontend/src/{ => core}/services/httpErrorHandler.ts (97%) rename frontend/src/{ => core}/services/indexedDBManager.ts (100%) rename frontend/src/{ => core}/services/pdfExportHelpers.ts (91%) rename frontend/src/{ => core}/services/pdfExportService.ts (99%) rename frontend/src/{ => core}/services/pdfMetadataService.ts (97%) rename frontend/src/{ => core}/services/pdfProcessingService.ts (95%) rename frontend/src/{ => core}/services/pdfWorkerManager.ts (100%) rename frontend/src/{ => core}/services/preferencesService.ts (93%) rename frontend/src/{ => core}/services/processingCache.ts (99%) rename frontend/src/{ => core}/services/processingErrorHandler.ts (99%) rename frontend/src/{ => core}/services/signatureDetectionService.ts (100%) rename frontend/src/{ => core}/services/specialErrorToasts.ts (97%) rename frontend/src/{ => core}/services/thumbnailGenerationService.ts (98%) rename frontend/src/{ => core}/services/zipFileService.ts (99%) rename frontend/src/{ => core}/setupTests.js (100%) rename frontend/src/{ => core}/setupTests.ts (100%) rename frontend/src/{ => core}/styles/cookieconsent.css (100%) rename frontend/src/{ => core/styles}/index.css (100%) rename frontend/src/{ => core}/styles/rainbow.module.css (100%) rename frontend/src/{ => core}/styles/tailwind.css (100%) rename frontend/src/{ => core}/styles/theme.css (95%) rename frontend/src/{ => core}/styles/zIndex.ts (100%) rename frontend/src/{ => core}/tests/convert/ConvertE2E.spec.ts (99%) rename frontend/src/{ => core}/tests/convert/ConvertIntegration.test.tsx (97%) rename frontend/src/{ => core}/tests/convert/ConvertSmartDetectionIntegration.test.tsx (96%) rename frontend/src/{ => core}/tests/convert/README.md (100%) rename frontend/src/{ => core}/tests/helpers/conversionEndpointDiscovery.ts (99%) rename frontend/src/{ => core}/tests/missingTranslations.test.ts (96%) rename frontend/src/{ => core}/tests/test-fixtures/README.md (100%) rename frontend/src/{ => core}/tests/test-fixtures/corrupted.pdf (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.csv (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.doc (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.docx (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.eml (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.htm (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.html (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.jpg (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.md (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.pdf (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.png (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.pptx (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.svg (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.txt (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.xlsx (100%) rename frontend/src/{ => core}/tests/test-fixtures/sample.xml (100%) rename frontend/src/{ => core}/tests/translation.test.ts (95%) rename frontend/src/{ => core}/tests/utils/testFileHelpers.ts (90%) rename frontend/src/{ => core}/theme/mantineTheme.ts (100%) rename frontend/src/{ => core}/tools/AddAttachments.tsx (81%) rename frontend/src/{ => core}/tools/AddPageNumbers.tsx (81%) rename frontend/src/{ => core}/tools/AddPassword.tsx (81%) rename frontend/src/{ => core}/tools/AddStamp.tsx (85%) rename frontend/src/{ => core}/tools/AddWatermark.tsx (87%) rename frontend/src/{ => core}/tools/AdjustContrast.tsx (79%) rename frontend/src/{ => core}/tools/AdjustPageScale.tsx (70%) rename frontend/src/{ => core}/tools/AutoRename.tsx (70%) rename frontend/src/{ => core}/tools/Automate.tsx (88%) rename frontend/src/{ => core}/tools/BookletImposition.tsx (70%) rename frontend/src/{ => core}/tools/CertSign.tsx (80%) rename frontend/src/{ => core}/tools/ChangeMetadata.tsx (81%) rename frontend/src/{ => core}/tools/ChangePermissions.tsx (72%) rename frontend/src/{ => core}/tools/Compress.tsx (72%) rename frontend/src/{ => core}/tools/Convert.tsx (88%) rename frontend/src/{ => core}/tools/Crop.tsx (72%) rename frontend/src/{ => core}/tools/ExtractImages.tsx (73%) rename frontend/src/{ => core}/tools/Flatten.tsx (74%) rename frontend/src/{ => core}/tools/Merge.tsx (81%) rename frontend/src/{ => core}/tools/OCR.tsx (85%) rename frontend/src/{ => core}/tools/OverlayPdfs.tsx (72%) rename frontend/src/{ => core}/tools/PageLayout.tsx (73%) rename frontend/src/{ => core}/tools/Redact.tsx (85%) rename frontend/src/{ => core}/tools/RemoveAnnotations.tsx (69%) rename frontend/src/{ => core}/tools/RemoveBlanks.tsx (73%) rename frontend/src/{ => core}/tools/RemoveCertificateSign.tsx (71%) rename frontend/src/{ => core}/tools/RemoveImage.tsx (71%) rename frontend/src/{ => core}/tools/RemovePages.tsx (72%) rename frontend/src/{ => core}/tools/RemovePassword.tsx (72%) rename frontend/src/{ => core}/tools/ReorganizePages.tsx (79%) rename frontend/src/{ => core}/tools/Repair.tsx (73%) rename frontend/src/{ => core}/tools/ReplaceColor.tsx (71%) rename frontend/src/{ => core}/tools/Rotate.tsx (71%) rename frontend/src/{ => core}/tools/Sanitize.tsx (76%) rename frontend/src/{ => core}/tools/ScannerImageSplit.tsx (70%) rename frontend/src/{ => core}/tools/Sign.tsx (88%) rename frontend/src/{ => core}/tools/SingleLargePage.tsx (72%) rename frontend/src/{ => core}/tools/Split.tsx (80%) rename frontend/src/{ => core}/tools/SwaggerUI.tsx (85%) rename frontend/src/{ => core}/tools/UnlockPdfForms.tsx (72%) rename frontend/src/{ => core}/tools/ValidateSignature.tsx (84%) rename frontend/src/{ => core}/types/automation.ts (90%) rename frontend/src/{ => core}/types/file.ts (96%) rename frontend/src/{ => core}/types/fileContext.ts (99%) rename frontend/src/{ => core}/types/fileIdSafety.d.ts (96%) rename frontend/src/{ => core}/types/metadata.ts (100%) rename frontend/src/{ => core}/types/navigation.ts (74%) rename frontend/src/{ => core}/types/navigationActions.ts (86%) rename frontend/src/{ => core}/types/pageEditor.ts (97%) rename frontend/src/{ => core}/types/parameters.ts (100%) rename frontend/src/{ => core}/types/processing.ts (100%) create mode 100644 frontend/src/core/types/proprietaryToolId.ts rename frontend/src/{ => core}/types/rightRail.ts (100%) rename frontend/src/{ => core}/types/sidebar.ts (100%) rename frontend/src/{ => core}/types/tips.ts (100%) rename frontend/src/{ => core}/types/tool.ts (96%) rename frontend/src/{ => core}/types/toolId.ts (80%) rename frontend/src/{ => core}/types/validateSignature.ts (100%) rename frontend/src/{ => core}/types/workbench.ts (100%) rename frontend/src/{ => core}/utils/automationExecutor.ts (94%) rename frontend/src/{ => core}/utils/automationFileProcessor.ts (96%) rename frontend/src/{ => core}/utils/bulkselection/README.md (100%) rename frontend/src/{ => core}/utils/bulkselection/parseSelection.test.ts (99%) rename frontend/src/{ => core}/utils/bulkselection/parseSelection.ts (100%) rename frontend/src/{ => core}/utils/clickHandlers.ts (100%) rename frontend/src/{ => core}/utils/convertUtils.test.ts (99%) rename frontend/src/{ => core}/utils/convertUtils.ts (98%) rename frontend/src/{ => core}/utils/cropCoordinates.ts (100%) rename frontend/src/{ => core}/utils/downloadUtils.ts (96%) rename frontend/src/{ => core}/utils/fileHash.ts (100%) rename frontend/src/{ => core}/utils/fileHistoryUtils.ts (98%) rename frontend/src/{ => core}/utils/fileIdSafety.ts (87%) rename frontend/src/{ => core}/utils/fileResponseUtils.test.ts (99%) rename frontend/src/{ => core}/utils/fileResponseUtils.ts (100%) rename frontend/src/{ => core}/utils/fileUtils.ts (100%) rename frontend/src/{ => core}/utils/fuzzySearch.ts (100%) rename frontend/src/{ => core}/utils/genericUtils.ts (100%) rename frontend/src/{ => core}/utils/hotkeys.ts (100%) rename frontend/src/{ => core}/utils/languageMapping.ts (100%) rename frontend/src/{ => core}/utils/pageSelection.ts (100%) rename frontend/src/{ => core}/utils/resourceManager.ts (96%) rename frontend/src/{ => core}/utils/scarfTracking.ts (100%) rename frontend/src/{ => core}/utils/scriptLoader.ts (100%) rename frontend/src/{ => core}/utils/sidebarUtils.ts (93%) rename frontend/src/{ => core}/utils/signatureFlattening.ts (98%) rename frontend/src/{ => core}/utils/storageUtils.ts (96%) rename frontend/src/{ => core}/utils/textUtils.ts (100%) rename frontend/src/{ => core}/utils/thumbnailUtils.ts (99%) rename frontend/src/{ => core}/utils/toolErrorHandler.ts (100%) rename frontend/src/{ => core}/utils/toolResponseProcessor.ts (96%) rename frontend/src/{ => core}/utils/toolSearch.ts (95%) rename frontend/src/{ => core}/utils/toolSynonyms.ts (100%) rename frontend/src/{ => core}/utils/urlMapping.ts (98%) rename frontend/src/{ => core}/utils/urlRouting.ts (90%) create mode 100644 frontend/src/proprietary/App.tsx rename frontend/src/{ => proprietary}/auth/UseSession.tsx (97%) rename frontend/src/{ => proprietary}/auth/springAuthClient.ts (100%) create mode 100644 frontend/src/proprietary/components/AppProviders.tsx rename frontend/src/{ => proprietary}/components/shared/DividerWithText.tsx (93%) rename frontend/src/{ => proprietary}/components/shared/LoginRightCarousel.tsx (99%) create mode 100644 frontend/src/proprietary/components/shared/config/OverviewHeader.tsx rename frontend/src/{ => proprietary}/components/shared/dividerWithText/DividerWithText.css (100%) rename frontend/src/{ => proprietary}/components/shared/loginSlides.ts (96%) create mode 100644 frontend/src/proprietary/data/useProprietaryToolRegistry.tsx create mode 100644 frontend/src/proprietary/hooks/useRequestHeaders.ts create mode 100644 frontend/src/proprietary/hooks/useShouldShowWelcomeModal.ts rename frontend/src/{ => proprietary}/routes/AuthCallback.tsx (97%) rename frontend/src/{ => proprietary}/routes/Landing.tsx (90%) rename frontend/src/{ => proprietary}/routes/Login.tsx (89%) rename frontend/src/{ => proprietary}/routes/Signup.tsx (83%) rename frontend/src/{ => proprietary}/routes/authShared/AuthLayout.module.css (100%) rename frontend/src/{ => proprietary}/routes/authShared/AuthLayout.tsx (91%) rename frontend/src/{ => proprietary}/routes/authShared/auth.css (100%) rename frontend/src/{ => proprietary}/routes/login/EmailPasswordForm.tsx (98%) rename frontend/src/{ => proprietary}/routes/login/ErrorMessage.tsx (100%) rename frontend/src/{ => proprietary}/routes/login/LoggedInState.tsx (96%) rename frontend/src/{ => proprietary}/routes/login/LoginHeader.tsx (92%) rename frontend/src/{ => proprietary}/routes/login/NavigationLink.tsx (100%) rename frontend/src/{ => proprietary}/routes/login/OAuthButtons.tsx (98%) rename frontend/src/{ => proprietary}/routes/signup/AuthService.ts (91%) rename frontend/src/{ => proprietary}/routes/signup/SignupForm.tsx (97%) rename frontend/src/{ => proprietary}/routes/signup/SignupFormValidation.ts (100%) create mode 100644 frontend/src/proprietary/services/apiClientSetup.ts create mode 100644 frontend/src/proprietary/styles/auth-theme.css create mode 100644 frontend/src/proprietary/types/proprietaryToolId.ts delete mode 100644 frontend/src/services/apiClient.ts create mode 100644 frontend/tsconfig.core.json create mode 100644 frontend/tsconfig.proprietary.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c86df9bd3..be04dbd64c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -152,6 +152,8 @@ jobs: cache-dependency-path: frontend/package-lock.json - name: Install frontend dependencies run: cd frontend && npm ci + - name: Type-check frontend + run: cd frontend && npm run prebuild && npm run typecheck:all - name: Lint frontend run: cd frontend && npm run lint - name: Build frontend diff --git a/frontend/index.html b/frontend/index.html index b563bdcd8a..b8c8bcc577 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -18,6 +18,6 @@
- + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6a769c90b7..c884272c4b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -94,6 +94,7 @@ "typescript": "^5.9.2", "typescript-eslint": "^8.44.1", "vite": "^7.1.7", + "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" } }, @@ -7977,6 +7978,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, "node_modules/gonzales-pe": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", @@ -13298,6 +13306,27 @@ "node": ">=18" } }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "dev": true, + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -13828,6 +13857,26 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-tsconfig-paths": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, "node_modules/vite/node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 053a7d67b6..892e485690 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -57,12 +57,15 @@ }, "scripts": { "predev": "npm run generate-icons", - "dev": "npm run typecheck && vite", + "dev": "vite", "prebuild": "npm run generate-icons", "lint": "eslint --max-warnings=0", - "build": "npm run typecheck && vite build", + "build": "vite build", "preview": "vite preview", "typecheck": "tsc --noEmit", + "typecheck:core": "tsc --noEmit --project tsconfig.core.json", + "typecheck:proprietary": "tsc --noEmit --project tsconfig.proprietary.json", + "typecheck:all": "npm run typecheck:core && npm run typecheck:proprietary", "check": "npm run typecheck && npm run lint && npm run test:run", "generate-licenses": "node scripts/generate-licenses.js", "generate-icons": "node scripts/generate-icons.js", @@ -120,9 +123,9 @@ "@vitejs/plugin-react-swc": "^4.1.0", "@vitest/coverage-v8": "^3.2.4", "eslint": "^9.36.0", - "eslint-plugin-react-hooks": "^5.2.0", "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", + "eslint-plugin-react-hooks": "^5.2.0", "jsdom": "^27.0.0", "license-checker": "^25.0.1", "madge": "^8.0.0", @@ -134,6 +137,7 @@ "typescript": "^5.9.2", "typescript-eslint": "^8.44.1", "vite": "^7.1.7", + "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" }, "depcheck": { diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 973717879e..92b41f96c6 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -3848,6 +3848,10 @@ "preview": "Preview" }, "config": { + "overview": { + "title": "Application Configuration", + "description": "Current application settings and configuration details." + }, "account": { "overview": { "title": "Account Settings", diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index 74b5e05345..0000000000 --- a/frontend/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx deleted file mode 100644 index ddadbc8c8b..0000000000 --- a/frontend/src/App.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { Suspense } from "react"; -import { Routes, Route } from "react-router-dom"; -import { RainbowThemeProvider } from "./components/shared/RainbowThemeProvider"; -import { FileContextProvider } from "./contexts/FileContext"; -import { NavigationProvider } from "./contexts/NavigationContext"; -import { ToolRegistryProvider } from "./contexts/ToolRegistryProvider"; -import { FilesModalProvider } from "./contexts/FilesModalContext"; -import { ToolWorkflowProvider } from "./contexts/ToolWorkflowContext"; -import { HotkeyProvider } from "./contexts/HotkeyContext"; -import { SidebarProvider } from "./contexts/SidebarContext"; -import { PreferencesProvider } from "./contexts/PreferencesContext"; -import { AppConfigProvider } from "./contexts/AppConfigContext"; -import { OnboardingProvider } from "./contexts/OnboardingContext"; -import { TourOrchestrationProvider } from "./contexts/TourOrchestrationContext"; -import ErrorBoundary from "./components/shared/ErrorBoundary"; -import OnboardingTour from "./components/onboarding/OnboardingTour"; -import { useScarfTracking } from "./hooks/useScarfTracking"; - -// Import auth components -import { AuthProvider } from "./auth/UseSession"; -import Landing from "./routes/Landing"; -import Login from "./routes/Login"; -import Signup from "./routes/Signup"; -import AuthCallback from "./routes/AuthCallback"; - -// Import global styles -import "./styles/tailwind.css"; -import "./styles/cookieconsent.css"; -import "./index.css"; -import { RightRailProvider } from "./contexts/RightRailContext"; -import { ViewerProvider } from "./contexts/ViewerContext"; -import { SignatureProvider } from "./contexts/SignatureContext"; - -// Import file ID debugging helpers (development only) -import "./utils/fileIdSafety"; - -// Loading component for i18next suspense -const LoadingFallback = () => ( -
- Loading... -
-); - -// Component to initialize scarf tracking (must be inside AppConfigProvider) -function ScarfTrackingInitializer() { - useScarfTracking(); - return null; -} - -export default function App() { - return ( - }> - - - - - - {/* Auth routes - no FileContext or other providers needed */} - } /> - } /> - } /> - - {/* Main app routes - wrapped with all providers */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - /> - - - - - - - ); -} diff --git a/frontend/src/core/App.tsx b/frontend/src/core/App.tsx new file mode 100644 index 0000000000..e87843325a --- /dev/null +++ b/frontend/src/core/App.tsx @@ -0,0 +1,24 @@ +import { Suspense } from "react"; +import { AppProviders } from "@app/components/AppProviders"; +import { LoadingFallback } from "@app/components/shared/LoadingFallback"; +import HomePage from "@app/pages/HomePage"; +import OnboardingTour from "@app/components/onboarding/OnboardingTour"; + +// Import global styles +import "@app/styles/tailwind.css"; +import "@app/styles/cookieconsent.css"; +import "@app/styles/index.css"; + +// Import file ID debugging helpers (development only) +import "@app/utils/fileIdSafety"; + +export default function App() { + return ( + }> + + + + + + ); +} diff --git a/frontend/src/core/components/AppProviders.tsx b/frontend/src/core/components/AppProviders.tsx new file mode 100644 index 0000000000..4dbd632b9d --- /dev/null +++ b/frontend/src/core/components/AppProviders.tsx @@ -0,0 +1,67 @@ +import { ReactNode } from "react"; +import { RainbowThemeProvider } from "@app/components/shared/RainbowThemeProvider"; +import { FileContextProvider } from "@app/contexts/FileContext"; +import { NavigationProvider } from "@app/contexts/NavigationContext"; +import { ToolRegistryProvider } from "@app/contexts/ToolRegistryProvider"; +import { FilesModalProvider } from "@app/contexts/FilesModalContext"; +import { ToolWorkflowProvider } from "@app/contexts/ToolWorkflowContext"; +import { HotkeyProvider } from "@app/contexts/HotkeyContext"; +import { SidebarProvider } from "@app/contexts/SidebarContext"; +import { PreferencesProvider } from "@app/contexts/PreferencesContext"; +import { AppConfigProvider } from "@app/contexts/AppConfigContext"; +import { RightRailProvider } from "@app/contexts/RightRailContext"; +import { ViewerProvider } from "@app/contexts/ViewerContext"; +import { SignatureProvider } from "@app/contexts/SignatureContext"; +import { OnboardingProvider } from "@app/contexts/OnboardingContext"; +import { TourOrchestrationProvider } from "@app/contexts/TourOrchestrationContext"; +import ErrorBoundary from "@app/components/shared/ErrorBoundary"; +import { useScarfTracking } from "@app/hooks/useScarfTracking"; + +// Component to initialize scarf tracking (must be inside AppConfigProvider) +function ScarfTrackingInitializer() { + useScarfTracking(); + return null; +} + +/** + * Core application providers + * Contains all providers needed for the core + */ +export function AppProviders({ children }: { children: ReactNode }) { + return ( + + + + + + + + + + + + + + + + + + {children} + + + + + + + + + + + + + + + + + ); +} diff --git a/frontend/src/components/FileManager.tsx b/frontend/src/core/components/FileManager.tsx similarity index 88% rename from frontend/src/components/FileManager.tsx rename to frontend/src/core/components/FileManager.tsx index 4f8c203caf..440ab4acb4 100644 --- a/frontend/src/components/FileManager.tsx +++ b/frontend/src/core/components/FileManager.tsx @@ -1,17 +1,17 @@ import React, { useState, useCallback, useEffect } from 'react'; import { Modal } from '@mantine/core'; import { Dropzone } from '@mantine/dropzone'; -import { StirlingFileStub } from '../types/fileContext'; -import { useFileManager } from '../hooks/useFileManager'; -import { useFilesModalContext } from '../contexts/FilesModalContext'; -import { Tool } from '../types/tool'; -import MobileLayout from './fileManager/MobileLayout'; -import DesktopLayout from './fileManager/DesktopLayout'; -import DragOverlay from './fileManager/DragOverlay'; -import { FileManagerProvider } from '../contexts/FileManagerContext'; -import { Z_INDEX_FILE_MANAGER_MODAL } from '../styles/zIndex'; -import { isGoogleDriveConfigured } from '../services/googleDrivePickerService'; -import { loadScript } from '../utils/scriptLoader'; +import { StirlingFileStub } from '@app/types/fileContext'; +import { useFileManager } from '@app/hooks/useFileManager'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import { Tool } from '@app/types/tool'; +import MobileLayout from '@app/components/fileManager/MobileLayout'; +import DesktopLayout from '@app/components/fileManager/DesktopLayout'; +import DragOverlay from '@app/components/fileManager/DragOverlay'; +import { FileManagerProvider } from '@app/contexts/FileManagerContext'; +import { Z_INDEX_FILE_MANAGER_MODAL } from '@app/styles/zIndex'; +import { isGoogleDriveConfigured } from '@app/services/googleDrivePickerService'; +import { loadScript } from '@app/utils/scriptLoader'; interface FileManagerProps { selectedTool?: Tool | null; diff --git a/frontend/src/components/StorageStatsCard.tsx b/frontend/src/core/components/StorageStatsCard.tsx similarity index 92% rename from frontend/src/components/StorageStatsCard.tsx rename to frontend/src/core/components/StorageStatsCard.tsx index 31c9912088..d04fd11ac4 100644 --- a/frontend/src/components/StorageStatsCard.tsx +++ b/frontend/src/core/components/StorageStatsCard.tsx @@ -3,9 +3,9 @@ import { Card, Group, Text, Button, Progress } from "@mantine/core"; import { useTranslation } from "react-i18next"; import StorageIcon from "@mui/icons-material/Storage"; import DeleteIcon from "@mui/icons-material/Delete"; -import { StorageStats } from "../services/fileStorage"; -import { formatFileSize } from "../utils/fileUtils"; -import { getStorageUsagePercent } from "../utils/storageUtils"; +import { StorageStats } from "@app/services/fileStorage"; +import { formatFileSize } from "@app/utils/fileUtils"; +import { getStorageUsagePercent } from "@app/utils/storageUtils"; interface StorageStatsCardProps { storageStats: StorageStats | null; diff --git a/frontend/src/components/annotation/providers/PDFAnnotationProvider.tsx b/frontend/src/core/components/annotation/providers/PDFAnnotationProvider.tsx similarity index 100% rename from frontend/src/components/annotation/providers/PDFAnnotationProvider.tsx rename to frontend/src/core/components/annotation/providers/PDFAnnotationProvider.tsx diff --git a/frontend/src/components/annotation/shared/BaseAnnotationTool.tsx b/frontend/src/core/components/annotation/shared/BaseAnnotationTool.tsx similarity index 90% rename from frontend/src/components/annotation/shared/BaseAnnotationTool.tsx rename to frontend/src/core/components/annotation/shared/BaseAnnotationTool.tsx index cf30f2e7e9..c61b61cfde 100644 --- a/frontend/src/components/annotation/shared/BaseAnnotationTool.tsx +++ b/frontend/src/core/components/annotation/shared/BaseAnnotationTool.tsx @@ -1,9 +1,9 @@ import React, { useState } from 'react'; import { Stack, Alert, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { DrawingControls } from './DrawingControls'; -import { ColorPicker } from './ColorPicker'; -import { usePDFAnnotation } from '../providers/PDFAnnotationProvider'; +import { DrawingControls } from '@app/components/annotation/shared/DrawingControls'; +import { ColorPicker } from '@app/components/annotation/shared/ColorPicker'; +import { usePDFAnnotation } from '@app/components/annotation/providers/PDFAnnotationProvider'; export interface AnnotationToolConfig { enableDrawing?: boolean; diff --git a/frontend/src/components/annotation/shared/ColorPicker.tsx b/frontend/src/core/components/annotation/shared/ColorPicker.tsx similarity index 100% rename from frontend/src/components/annotation/shared/ColorPicker.tsx rename to frontend/src/core/components/annotation/shared/ColorPicker.tsx diff --git a/frontend/src/components/annotation/shared/DrawingCanvas.tsx b/frontend/src/core/components/annotation/shared/DrawingCanvas.tsx similarity index 98% rename from frontend/src/components/annotation/shared/DrawingCanvas.tsx rename to frontend/src/core/components/annotation/shared/DrawingCanvas.tsx index 87362f74dd..4b9de1cbb5 100644 --- a/frontend/src/components/annotation/shared/DrawingCanvas.tsx +++ b/frontend/src/core/components/annotation/shared/DrawingCanvas.tsx @@ -1,7 +1,7 @@ import React, { useRef, useState } from 'react'; import { Paper, Button, Modal, Stack, Text, Popover, ColorPicker as MantineColorPicker } from '@mantine/core'; -import { ColorSwatchButton } from './ColorPicker'; -import PenSizeSelector from '../../tools/sign/PenSizeSelector'; +import { ColorSwatchButton } from '@app/components/annotation/shared/ColorPicker'; +import PenSizeSelector from '@app/components/tools/sign/PenSizeSelector'; import SignaturePad from 'signature_pad'; interface DrawingCanvasProps { diff --git a/frontend/src/components/annotation/shared/DrawingControls.tsx b/frontend/src/core/components/annotation/shared/DrawingControls.tsx similarity index 100% rename from frontend/src/components/annotation/shared/DrawingControls.tsx rename to frontend/src/core/components/annotation/shared/DrawingControls.tsx diff --git a/frontend/src/components/annotation/shared/ImageUploader.tsx b/frontend/src/core/components/annotation/shared/ImageUploader.tsx similarity index 100% rename from frontend/src/components/annotation/shared/ImageUploader.tsx rename to frontend/src/core/components/annotation/shared/ImageUploader.tsx diff --git a/frontend/src/components/annotation/shared/TextInputWithFont.tsx b/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx similarity index 98% rename from frontend/src/components/annotation/shared/TextInputWithFont.tsx rename to frontend/src/core/components/annotation/shared/TextInputWithFont.tsx index b7af602953..aca7430ce7 100644 --- a/frontend/src/components/annotation/shared/TextInputWithFont.tsx +++ b/frontend/src/core/components/annotation/shared/TextInputWithFont.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Stack, TextInput, Select, Combobox, useCombobox, Group, Box } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ColorPicker } from './ColorPicker'; +import { ColorPicker } from '@app/components/annotation/shared/ColorPicker'; interface TextInputWithFontProps { text: string; diff --git a/frontend/src/components/annotation/tools/DrawingTool.tsx b/frontend/src/core/components/annotation/tools/DrawingTool.tsx similarity index 87% rename from frontend/src/components/annotation/tools/DrawingTool.tsx rename to frontend/src/core/components/annotation/tools/DrawingTool.tsx index 80b950a332..f3643de35c 100644 --- a/frontend/src/components/annotation/tools/DrawingTool.tsx +++ b/frontend/src/core/components/annotation/tools/DrawingTool.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { Stack } from '@mantine/core'; -import { BaseAnnotationTool } from '../shared/BaseAnnotationTool'; -import { DrawingCanvas } from '../shared/DrawingCanvas'; +import { BaseAnnotationTool } from '@app/components/annotation/shared/BaseAnnotationTool'; +import { DrawingCanvas } from '@app/components/annotation/shared/DrawingCanvas'; interface DrawingToolProps { onDrawingChange?: (data: string | null) => void; diff --git a/frontend/src/components/annotation/tools/ImageTool.tsx b/frontend/src/core/components/annotation/tools/ImageTool.tsx similarity index 90% rename from frontend/src/components/annotation/tools/ImageTool.tsx rename to frontend/src/core/components/annotation/tools/ImageTool.tsx index 744882b43e..d9b4defec0 100644 --- a/frontend/src/components/annotation/tools/ImageTool.tsx +++ b/frontend/src/core/components/annotation/tools/ImageTool.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { Stack } from '@mantine/core'; -import { BaseAnnotationTool } from '../shared/BaseAnnotationTool'; -import { ImageUploader } from '../shared/ImageUploader'; +import { BaseAnnotationTool } from '@app/components/annotation/shared/BaseAnnotationTool'; +import { ImageUploader } from '@app/components/annotation/shared/ImageUploader'; interface ImageToolProps { onImageChange?: (data: string | null) => void; diff --git a/frontend/src/components/annotation/tools/TextTool.tsx b/frontend/src/core/components/annotation/tools/TextTool.tsx similarity index 88% rename from frontend/src/components/annotation/tools/TextTool.tsx rename to frontend/src/core/components/annotation/tools/TextTool.tsx index 0f9aa28833..471198d8e3 100644 --- a/frontend/src/components/annotation/tools/TextTool.tsx +++ b/frontend/src/core/components/annotation/tools/TextTool.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { Stack } from '@mantine/core'; -import { BaseAnnotationTool } from '../shared/BaseAnnotationTool'; -import { TextInputWithFont } from '../shared/TextInputWithFont'; +import { BaseAnnotationTool } from '@app/components/annotation/shared/BaseAnnotationTool'; +import { TextInputWithFont } from '@app/components/annotation/shared/TextInputWithFont'; interface TextToolProps { onTextChange?: (text: string) => void; diff --git a/frontend/src/components/fileEditor/AddFileCard.tsx b/frontend/src/core/components/fileEditor/AddFileCard.tsx similarity index 96% rename from frontend/src/components/fileEditor/AddFileCard.tsx rename to frontend/src/core/components/fileEditor/AddFileCard.tsx index a873b7211e..fe833c17fa 100644 --- a/frontend/src/components/fileEditor/AddFileCard.tsx +++ b/frontend/src/core/components/fileEditor/AddFileCard.tsx @@ -2,10 +2,10 @@ import React, { useRef, useState } from 'react'; import { Button, Group, useMantineColorScheme } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import AddIcon from '@mui/icons-material/Add'; -import { useFilesModalContext } from '../../contexts/FilesModalContext'; -import LocalIcon from '../shared/LocalIcon'; -import { BASE_PATH } from '../../constants/app'; -import styles from './FileEditor.module.css'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { BASE_PATH } from '@app/constants/app'; +import styles from '@app/components/fileEditor/FileEditor.module.css'; interface AddFileCardProps { onFileSelect: (files: File[]) => void; diff --git a/frontend/src/components/fileEditor/FileEditor.module.css b/frontend/src/core/components/fileEditor/FileEditor.module.css similarity index 100% rename from frontend/src/components/fileEditor/FileEditor.module.css rename to frontend/src/core/components/fileEditor/FileEditor.module.css diff --git a/frontend/src/components/fileEditor/FileEditor.tsx b/frontend/src/core/components/fileEditor/FileEditor.tsx similarity index 95% rename from frontend/src/components/fileEditor/FileEditor.tsx rename to frontend/src/core/components/fileEditor/FileEditor.tsx index 8d894389e9..fbafa8b896 100644 --- a/frontend/src/components/fileEditor/FileEditor.tsx +++ b/frontend/src/core/components/fileEditor/FileEditor.tsx @@ -3,17 +3,17 @@ import { Text, Center, Box, LoadingOverlay, Stack } from '@mantine/core'; import { Dropzone } from '@mantine/dropzone'; -import { useFileSelection, useFileState, useFileManagement, useFileActions, useFileContext } from '../../contexts/FileContext'; -import { useNavigationActions } from '../../contexts/NavigationContext'; -import { zipFileService } from '../../services/zipFileService'; -import { detectFileExtension } from '../../utils/fileUtils'; -import FileEditorThumbnail from './FileEditorThumbnail'; -import AddFileCard from './AddFileCard'; -import FilePickerModal from '../shared/FilePickerModal'; -import { FileId, StirlingFile } from '../../types/fileContext'; -import { alert } from '../toast'; -import { downloadBlob } from '../../utils/downloadUtils'; -import { useFileEditorRightRailButtons } from './fileEditorRightRailButtons'; +import { useFileSelection, useFileState, useFileManagement, useFileActions, useFileContext } from '@app/contexts/FileContext'; +import { useNavigationActions } from '@app/contexts/NavigationContext'; +import { zipFileService } from '@app/services/zipFileService'; +import { detectFileExtension } from '@app/utils/fileUtils'; +import FileEditorThumbnail from '@app/components/fileEditor/FileEditorThumbnail'; +import AddFileCard from '@app/components/fileEditor/AddFileCard'; +import FilePickerModal from '@app/components/shared/FilePickerModal'; +import { FileId, StirlingFile } from '@app/types/fileContext'; +import { alert } from '@app/components/toast'; +import { downloadBlob } from '@app/utils/downloadUtils'; +import { useFileEditorRightRailButtons } from '@app/components/fileEditor/fileEditorRightRailButtons'; interface FileEditorProps { diff --git a/frontend/src/components/fileEditor/FileEditorThumbnail.tsx b/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx similarity index 95% rename from frontend/src/components/fileEditor/FileEditorThumbnail.tsx rename to frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx index 7f6bf09503..93ed2b05a0 100644 --- a/frontend/src/components/fileEditor/FileEditorThumbnail.tsx +++ b/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx @@ -1,7 +1,7 @@ import React, { useState, useCallback, useRef, useMemo } from 'react'; import { Text, ActionIcon, CheckboxIndicator, Tooltip, Modal, Button, Group, Stack } from '@mantine/core'; import { useMediaQuery } from '@mantine/hooks'; -import { alert } from '../toast'; +import { alert } from '@app/components/toast'; import { useTranslation } from 'react-i18next'; import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined'; import CloseIcon from '@mui/icons-material/Close'; @@ -11,16 +11,16 @@ import PushPinIcon from '@mui/icons-material/PushPin'; import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; -import { StirlingFileStub } from '../../types/fileContext'; -import { zipFileService } from '../../services/zipFileService'; +import { StirlingFileStub } from '@app/types/fileContext'; +import { zipFileService } from '@app/services/zipFileService'; -import styles from './FileEditor.module.css'; -import { useFileContext } from '../../contexts/FileContext'; -import { useFileState } from '../../contexts/file/fileHooks'; -import { FileId } from '../../types/file'; -import { formatFileSize } from '../../utils/fileUtils'; -import ToolChain from '../shared/ToolChain'; -import HoverActionMenu, { HoverAction } from '../shared/HoverActionMenu'; +import styles from '@app/components/fileEditor/FileEditor.module.css'; +import { useFileContext } from '@app/contexts/FileContext'; +import { useFileState } from '@app/contexts/file/fileHooks'; +import { FileId } from '@app/types/file'; +import { formatFileSize } from '@app/utils/fileUtils'; +import ToolChain from '@app/components/shared/ToolChain'; +import HoverActionMenu, { HoverAction } from '@app/components/shared/HoverActionMenu'; diff --git a/frontend/src/components/fileEditor/fileEditorRightRailButtons.tsx b/frontend/src/core/components/fileEditor/fileEditorRightRailButtons.tsx similarity index 95% rename from frontend/src/components/fileEditor/fileEditorRightRailButtons.tsx rename to frontend/src/core/components/fileEditor/fileEditorRightRailButtons.tsx index 054f7c535a..1895371da7 100644 --- a/frontend/src/components/fileEditor/fileEditorRightRailButtons.tsx +++ b/frontend/src/core/components/fileEditor/fileEditorRightRailButtons.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useRightRailButtons, RightRailButtonWithAction } from '../../hooks/useRightRailButtons'; -import LocalIcon from '../shared/LocalIcon'; +import { useRightRailButtons, RightRailButtonWithAction } from '@app/hooks/useRightRailButtons'; +import LocalIcon from '@app/components/shared/LocalIcon'; interface FileEditorRightRailButtonsParams { totalItems: number; diff --git a/frontend/src/components/fileManager/CompactFileDetails.tsx b/frontend/src/core/components/fileManager/CompactFileDetails.tsx similarity index 97% rename from frontend/src/components/fileManager/CompactFileDetails.tsx rename to frontend/src/core/components/fileManager/CompactFileDetails.tsx index c7e8334044..6da3b553ed 100644 --- a/frontend/src/components/fileManager/CompactFileDetails.tsx +++ b/frontend/src/core/components/fileManager/CompactFileDetails.tsx @@ -4,8 +4,8 @@ import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { useTranslation } from 'react-i18next'; -import { getFileSize } from '../../utils/fileUtils'; -import { StirlingFileStub } from '../../types/fileContext'; +import { getFileSize } from '@app/utils/fileUtils'; +import { StirlingFileStub } from '@app/types/fileContext'; interface CompactFileDetailsProps { currentFile: StirlingFileStub | null; diff --git a/frontend/src/components/fileManager/DesktopLayout.tsx b/frontend/src/core/components/fileManager/DesktopLayout.tsx similarity index 83% rename from frontend/src/components/fileManager/DesktopLayout.tsx rename to frontend/src/core/components/fileManager/DesktopLayout.tsx index 78f90a97ab..c4bd72e169 100644 --- a/frontend/src/components/fileManager/DesktopLayout.tsx +++ b/frontend/src/core/components/fileManager/DesktopLayout.tsx @@ -1,12 +1,12 @@ import React from 'react'; import { Grid } from '@mantine/core'; -import FileSourceButtons from './FileSourceButtons'; -import FileDetails from './FileDetails'; -import SearchInput from './SearchInput'; -import FileListArea from './FileListArea'; -import FileActions from './FileActions'; -import HiddenFileInput from './HiddenFileInput'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; +import FileSourceButtons from '@app/components/fileManager/FileSourceButtons'; +import FileDetails from '@app/components/fileManager/FileDetails'; +import SearchInput from '@app/components/fileManager/SearchInput'; +import FileListArea from '@app/components/fileManager/FileListArea'; +import FileActions from '@app/components/fileManager/FileActions'; +import HiddenFileInput from '@app/components/fileManager/HiddenFileInput'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; const DesktopLayout: React.FC = () => { const { diff --git a/frontend/src/components/fileManager/DragOverlay.tsx b/frontend/src/core/components/fileManager/DragOverlay.tsx similarity index 100% rename from frontend/src/components/fileManager/DragOverlay.tsx rename to frontend/src/core/components/fileManager/DragOverlay.tsx diff --git a/frontend/src/components/fileManager/EmptyFilesState.tsx b/frontend/src/core/components/fileManager/EmptyFilesState.tsx similarity index 95% rename from frontend/src/components/fileManager/EmptyFilesState.tsx rename to frontend/src/core/components/fileManager/EmptyFilesState.tsx index 55a3766b98..c9f72a7ada 100644 --- a/frontend/src/components/fileManager/EmptyFilesState.tsx +++ b/frontend/src/core/components/fileManager/EmptyFilesState.tsx @@ -2,9 +2,9 @@ import React, { useState } from 'react'; import { Button, Group, Text, Stack, useMantineColorScheme } from '@mantine/core'; import HistoryIcon from '@mui/icons-material/History'; import { useTranslation } from 'react-i18next'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; -import LocalIcon from '../shared/LocalIcon'; -import { BASE_PATH } from '../../constants/app'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { BASE_PATH } from '@app/constants/app'; const EmptyFilesState: React.FC = () => { const { t } = useTranslation(); diff --git a/frontend/src/components/fileManager/FileActions.tsx b/frontend/src/core/components/fileManager/FileActions.tsx similarity index 97% rename from frontend/src/components/fileManager/FileActions.tsx rename to frontend/src/core/components/fileManager/FileActions.tsx index 7bc8d27bc3..d32ed03149 100644 --- a/frontend/src/components/fileManager/FileActions.tsx +++ b/frontend/src/core/components/fileManager/FileActions.tsx @@ -4,7 +4,7 @@ import SelectAllIcon from "@mui/icons-material/SelectAll"; import DeleteIcon from "@mui/icons-material/Delete"; import DownloadIcon from "@mui/icons-material/Download"; import { useTranslation } from "react-i18next"; -import { useFileManagerContext } from "../../contexts/FileManagerContext"; +import { useFileManagerContext } from "@app/contexts/FileManagerContext"; const FileActions: React.FC = () => { const { t } = useTranslation(); diff --git a/frontend/src/components/fileManager/FileDetails.tsx b/frontend/src/core/components/fileManager/FileDetails.tsx similarity index 90% rename from frontend/src/components/fileManager/FileDetails.tsx rename to frontend/src/core/components/fileManager/FileDetails.tsx index d4ef7bd07a..428dbb53a6 100644 --- a/frontend/src/components/fileManager/FileDetails.tsx +++ b/frontend/src/core/components/fileManager/FileDetails.tsx @@ -1,11 +1,11 @@ import React, { useEffect, useState } from 'react'; import { Stack, Button, Box } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useIndexedDBThumbnail } from '../../hooks/useIndexedDBThumbnail'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; -import FilePreview from '../shared/FilePreview'; -import FileInfoCard from './FileInfoCard'; -import CompactFileDetails from './CompactFileDetails'; +import { useIndexedDBThumbnail } from '@app/hooks/useIndexedDBThumbnail'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; +import FilePreview from '@app/components/shared/FilePreview'; +import FileInfoCard from '@app/components/fileManager/FileInfoCard'; +import CompactFileDetails from '@app/components/fileManager/CompactFileDetails'; interface FileDetailsProps { compact?: boolean; diff --git a/frontend/src/components/fileManager/FileHistoryGroup.tsx b/frontend/src/core/components/fileManager/FileHistoryGroup.tsx similarity index 94% rename from frontend/src/components/fileManager/FileHistoryGroup.tsx rename to frontend/src/core/components/fileManager/FileHistoryGroup.tsx index 771499584a..75d8f0e50d 100644 --- a/frontend/src/components/fileManager/FileHistoryGroup.tsx +++ b/frontend/src/core/components/fileManager/FileHistoryGroup.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Box, Text, Collapse, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { StirlingFileStub } from '../../types/fileContext'; -import FileListItem from './FileListItem'; +import { StirlingFileStub } from '@app/types/fileContext'; +import FileListItem from '@app/components/fileManager/FileListItem'; interface FileHistoryGroupProps { leafFile: StirlingFileStub; diff --git a/frontend/src/components/fileManager/FileInfoCard.tsx b/frontend/src/core/components/fileManager/FileInfoCard.tsx similarity index 94% rename from frontend/src/components/fileManager/FileInfoCard.tsx rename to frontend/src/core/components/fileManager/FileInfoCard.tsx index 160ddcc62c..f898cbc67c 100644 --- a/frontend/src/components/fileManager/FileInfoCard.tsx +++ b/frontend/src/core/components/fileManager/FileInfoCard.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Stack, Card, Box, Text, Badge, Group, Divider, ScrollArea } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { detectFileExtension, getFileSize } from '../../utils/fileUtils'; -import { StirlingFileStub } from '../../types/fileContext'; -import ToolChain from '../shared/ToolChain'; +import { detectFileExtension, getFileSize } from '@app/utils/fileUtils'; +import { StirlingFileStub } from '@app/types/fileContext'; +import ToolChain from '@app/components/shared/ToolChain'; interface FileInfoCardProps { currentFile: StirlingFileStub | null; diff --git a/frontend/src/components/fileManager/FileListArea.tsx b/frontend/src/core/components/fileManager/FileListArea.tsx similarity index 91% rename from frontend/src/components/fileManager/FileListArea.tsx rename to frontend/src/core/components/fileManager/FileListArea.tsx index 556ecc4f12..439af6996d 100644 --- a/frontend/src/components/fileManager/FileListArea.tsx +++ b/frontend/src/core/components/fileManager/FileListArea.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { Center, ScrollArea, Text, Stack } from '@mantine/core'; import CloudIcon from '@mui/icons-material/Cloud'; import { useTranslation } from 'react-i18next'; -import FileListItem from './FileListItem'; -import FileHistoryGroup from './FileHistoryGroup'; -import EmptyFilesState from './EmptyFilesState'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; +import FileListItem from '@app/components/fileManager/FileListItem'; +import FileHistoryGroup from '@app/components/fileManager/FileHistoryGroup'; +import EmptyFilesState from '@app/components/fileManager/EmptyFilesState'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; interface FileListAreaProps { scrollAreaHeight: string; diff --git a/frontend/src/components/fileManager/FileListItem.tsx b/frontend/src/core/components/fileManager/FileListItem.tsx similarity index 95% rename from frontend/src/components/fileManager/FileListItem.tsx rename to frontend/src/core/components/fileManager/FileListItem.tsx index a721961ec7..d8c0aac70a 100644 --- a/frontend/src/components/fileManager/FileListItem.tsx +++ b/frontend/src/core/components/fileManager/FileListItem.tsx @@ -7,12 +7,12 @@ import HistoryIcon from '@mui/icons-material/History'; import RestoreIcon from '@mui/icons-material/Restore'; import UnarchiveIcon from '@mui/icons-material/Unarchive'; import { useTranslation } from 'react-i18next'; -import { getFileSize, getFileDate } from '../../utils/fileUtils'; -import { FileId, StirlingFileStub } from '../../types/fileContext'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; -import { zipFileService } from '../../services/zipFileService'; -import ToolChain from '../shared/ToolChain'; -import { Z_INDEX_OVER_FILE_MANAGER_MODAL } from '../../styles/zIndex'; +import { getFileSize, getFileDate } from '@app/utils/fileUtils'; +import { FileId, StirlingFileStub } from '@app/types/fileContext'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; +import { zipFileService } from '@app/services/zipFileService'; +import ToolChain from '@app/components/shared/ToolChain'; +import { Z_INDEX_OVER_FILE_MANAGER_MODAL } from '@app/styles/zIndex'; interface FileListItemProps { file: StirlingFileStub; diff --git a/frontend/src/components/fileManager/FileSourceButtons.tsx b/frontend/src/core/components/fileManager/FileSourceButtons.tsx similarity index 96% rename from frontend/src/components/fileManager/FileSourceButtons.tsx rename to frontend/src/core/components/fileManager/FileSourceButtons.tsx index 78ab8ce39e..71abaa53f0 100644 --- a/frontend/src/components/fileManager/FileSourceButtons.tsx +++ b/frontend/src/core/components/fileManager/FileSourceButtons.tsx @@ -4,8 +4,8 @@ import HistoryIcon from '@mui/icons-material/History'; import UploadIcon from '@mui/icons-material/Upload'; import CloudIcon from '@mui/icons-material/Cloud'; import { useTranslation } from 'react-i18next'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; -import { useGoogleDrivePicker } from '../../hooks/useGoogleDrivePicker'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; +import { useGoogleDrivePicker } from '@app/hooks/useGoogleDrivePicker'; interface FileSourceButtonsProps { horizontal?: boolean; diff --git a/frontend/src/components/fileManager/HiddenFileInput.tsx b/frontend/src/core/components/fileManager/HiddenFileInput.tsx similarity index 83% rename from frontend/src/components/fileManager/HiddenFileInput.tsx rename to frontend/src/core/components/fileManager/HiddenFileInput.tsx index 8dee9e2783..27482df519 100644 --- a/frontend/src/components/fileManager/HiddenFileInput.tsx +++ b/frontend/src/core/components/fileManager/HiddenFileInput.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; const HiddenFileInput: React.FC = () => { const { fileInputRef, onFileInputChange } = useFileManagerContext(); diff --git a/frontend/src/components/fileManager/MobileLayout.tsx b/frontend/src/core/components/fileManager/MobileLayout.tsx similarity index 85% rename from frontend/src/components/fileManager/MobileLayout.tsx rename to frontend/src/core/components/fileManager/MobileLayout.tsx index 3f101ab0b0..0701874852 100644 --- a/frontend/src/components/fileManager/MobileLayout.tsx +++ b/frontend/src/core/components/fileManager/MobileLayout.tsx @@ -1,12 +1,12 @@ import React from 'react'; import { Box } from '@mantine/core'; -import FileSourceButtons from './FileSourceButtons'; -import FileDetails from './FileDetails'; -import SearchInput from './SearchInput'; -import FileListArea from './FileListArea'; -import FileActions from './FileActions'; -import HiddenFileInput from './HiddenFileInput'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; +import FileSourceButtons from '@app/components/fileManager/FileSourceButtons'; +import FileDetails from '@app/components/fileManager/FileDetails'; +import SearchInput from '@app/components/fileManager/SearchInput'; +import FileListArea from '@app/components/fileManager/FileListArea'; +import FileActions from '@app/components/fileManager/FileActions'; +import HiddenFileInput from '@app/components/fileManager/HiddenFileInput'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; const MobileLayout: React.FC = () => { const { diff --git a/frontend/src/components/fileManager/SearchInput.tsx b/frontend/src/core/components/fileManager/SearchInput.tsx similarity index 91% rename from frontend/src/components/fileManager/SearchInput.tsx rename to frontend/src/core/components/fileManager/SearchInput.tsx index f47da0dcaa..2b318604c6 100644 --- a/frontend/src/components/fileManager/SearchInput.tsx +++ b/frontend/src/core/components/fileManager/SearchInput.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { TextInput } from '@mantine/core'; import SearchIcon from '@mui/icons-material/Search'; import { useTranslation } from 'react-i18next'; -import { useFileManagerContext } from '../../contexts/FileManagerContext'; +import { useFileManagerContext } from '@app/contexts/FileManagerContext'; interface SearchInputProps { style?: React.CSSProperties; diff --git a/frontend/src/components/hotkeys/HotkeyDisplay.tsx b/frontend/src/core/components/hotkeys/HotkeyDisplay.tsx similarity index 93% rename from frontend/src/components/hotkeys/HotkeyDisplay.tsx rename to frontend/src/core/components/hotkeys/HotkeyDisplay.tsx index 1b5953a63e..7f6d9f26dd 100644 --- a/frontend/src/components/hotkeys/HotkeyDisplay.tsx +++ b/frontend/src/core/components/hotkeys/HotkeyDisplay.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { HotkeyBinding } from '../../utils/hotkeys'; -import { useHotkeys } from '../../contexts/HotkeyContext'; +import { HotkeyBinding } from '@app/utils/hotkeys'; +import { useHotkeys } from '@app/contexts/HotkeyContext'; interface HotkeyDisplayProps { binding: HotkeyBinding | null | undefined; diff --git a/frontend/src/components/layout/Workbench.css b/frontend/src/core/components/layout/Workbench.css similarity index 100% rename from frontend/src/components/layout/Workbench.css rename to frontend/src/core/components/layout/Workbench.css diff --git a/frontend/src/components/layout/Workbench.tsx b/frontend/src/core/components/layout/Workbench.tsx similarity index 84% rename from frontend/src/components/layout/Workbench.tsx rename to frontend/src/core/components/layout/Workbench.tsx index da4447a700..91595195dd 100644 --- a/frontend/src/components/layout/Workbench.tsx +++ b/frontend/src/core/components/layout/Workbench.tsx @@ -1,22 +1,22 @@ import { Box } from '@mantine/core'; -import { useRainbowThemeContext } from '../shared/RainbowThemeProvider'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { useFileHandler } from '../../hooks/useFileHandler'; -import { useFileState } from '../../contexts/FileContext'; -import { useNavigationState, useNavigationActions } from '../../contexts/NavigationContext'; -import { isBaseWorkbench } from '../../types/workbench'; -import { useViewer } from '../../contexts/ViewerContext'; -import { useAppConfig } from '../../contexts/AppConfigContext'; -import './Workbench.css'; +import { useRainbowThemeContext } from '@app/components/shared/RainbowThemeProvider'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useFileHandler } from '@app/hooks/useFileHandler'; +import { useFileState } from '@app/contexts/FileContext'; +import { useNavigationState, useNavigationActions } from '@app/contexts/NavigationContext'; +import { isBaseWorkbench } from '@app/types/workbench'; +import { useViewer } from '@app/contexts/ViewerContext'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import '@app/components/layout/Workbench.css'; -import TopControls from '../shared/TopControls'; -import FileEditor from '../fileEditor/FileEditor'; -import PageEditor from '../pageEditor/PageEditor'; -import PageEditorControls from '../pageEditor/PageEditorControls'; -import Viewer from '../viewer/Viewer'; -import LandingPage from '../shared/LandingPage'; -import Footer from '../shared/Footer'; -import DismissAllErrorsButton from '../shared/DismissAllErrorsButton'; +import TopControls from '@app/components/shared/TopControls'; +import FileEditor from '@app/components/fileEditor/FileEditor'; +import PageEditor from '@app/components/pageEditor/PageEditor'; +import PageEditorControls from '@app/components/pageEditor/PageEditorControls'; +import Viewer from '@app/components/viewer/Viewer'; +import LandingPage from '@app/components/shared/LandingPage'; +import Footer from '@app/components/shared/Footer'; +import DismissAllErrorsButton from '@app/components/shared/DismissAllErrorsButton'; // No props needed - component uses contexts directly export default function Workbench() { diff --git a/frontend/src/components/onboarding/OnboardingTour.css b/frontend/src/core/components/onboarding/OnboardingTour.css similarity index 100% rename from frontend/src/components/onboarding/OnboardingTour.css rename to frontend/src/core/components/onboarding/OnboardingTour.css diff --git a/frontend/src/components/onboarding/OnboardingTour.tsx b/frontend/src/core/components/onboarding/OnboardingTour.tsx similarity index 97% rename from frontend/src/components/onboarding/OnboardingTour.tsx rename to frontend/src/core/components/onboarding/OnboardingTour.tsx index b52da494ba..4a4a770f1f 100644 --- a/frontend/src/components/onboarding/OnboardingTour.tsx +++ b/frontend/src/core/components/onboarding/OnboardingTour.tsx @@ -1,14 +1,14 @@ import React from "react"; import { TourProvider, useTour, type StepType } from '@reactour/tour'; -import { useOnboarding } from '../../contexts/OnboardingContext'; +import { useOnboarding } from '@app/contexts/OnboardingContext'; import { useTranslation } from 'react-i18next'; import { CloseButton, ActionIcon } from '@mantine/core'; -import { useFilesModalContext } from '../../contexts/FilesModalContext'; -import { useTourOrchestration } from '../../contexts/TourOrchestrationContext'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import { useTourOrchestration } from '@app/contexts/TourOrchestrationContext'; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import CheckIcon from '@mui/icons-material/Check'; -import TourWelcomeModal from './TourWelcomeModal'; -import './OnboardingTour.css'; +import TourWelcomeModal from '@app/components/onboarding/TourWelcomeModal'; +import '@app/components/onboarding/OnboardingTour.css'; // Enum case order defines order steps will appear enum TourStep { diff --git a/frontend/src/components/onboarding/TourWelcomeModal.tsx b/frontend/src/core/components/onboarding/TourWelcomeModal.tsx similarity index 96% rename from frontend/src/components/onboarding/TourWelcomeModal.tsx rename to frontend/src/core/components/onboarding/TourWelcomeModal.tsx index 82aeaf26aa..0e4eea9c95 100644 --- a/frontend/src/components/onboarding/TourWelcomeModal.tsx +++ b/frontend/src/core/components/onboarding/TourWelcomeModal.tsx @@ -1,6 +1,6 @@ import { Modal, Title, Text, Button, Stack, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; interface TourWelcomeModalProps { opened: boolean; diff --git a/frontend/src/components/pageEditor/BulkSelectionPanel.tsx b/frontend/src/core/components/pageEditor/BulkSelectionPanel.tsx similarity index 80% rename from frontend/src/components/pageEditor/BulkSelectionPanel.tsx rename to frontend/src/core/components/pageEditor/BulkSelectionPanel.tsx index 16ec84453e..50b304e0b6 100644 --- a/frontend/src/components/pageEditor/BulkSelectionPanel.tsx +++ b/frontend/src/core/components/pageEditor/BulkSelectionPanel.tsx @@ -1,9 +1,9 @@ import { useState, useEffect } from 'react'; -import classes from './bulkSelectionPanel/BulkSelectionPanel.module.css'; -import { parseSelectionWithDiagnostics } from '../../utils/bulkselection/parseSelection'; -import PageSelectionInput from './bulkSelectionPanel/PageSelectionInput'; -import SelectedPagesDisplay from './bulkSelectionPanel/SelectedPagesDisplay'; -import AdvancedSelectionPanel from './bulkSelectionPanel/AdvancedSelectionPanel'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; +import { parseSelectionWithDiagnostics } from '@app/utils/bulkselection/parseSelection'; +import PageSelectionInput from '@app/components/pageEditor/bulkSelectionPanel/PageSelectionInput'; +import SelectedPagesDisplay from '@app/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay'; +import AdvancedSelectionPanel from '@app/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel'; interface BulkSelectionPanelProps { csvInput: string; diff --git a/frontend/src/components/pageEditor/DragDropGrid.tsx b/frontend/src/core/components/pageEditor/DragDropGrid.tsx similarity index 98% rename from frontend/src/components/pageEditor/DragDropGrid.tsx rename to frontend/src/core/components/pageEditor/DragDropGrid.tsx index 7159295677..c76aa2a432 100644 --- a/frontend/src/components/pageEditor/DragDropGrid.tsx +++ b/frontend/src/core/components/pageEditor/DragDropGrid.tsx @@ -1,7 +1,7 @@ import React, { useRef, useEffect, useState, useCallback } from 'react'; import { Box } from '@mantine/core'; import { useVirtualizer } from '@tanstack/react-virtual'; -import { GRID_CONSTANTS } from './constants'; +import { GRID_CONSTANTS } from '@app/components/pageEditor/constants'; interface DragDropItem { id: string; diff --git a/frontend/src/components/pageEditor/FileThumbnail.tsx b/frontend/src/core/components/pageEditor/FileThumbnail.tsx similarity index 98% rename from frontend/src/components/pageEditor/FileThumbnail.tsx rename to frontend/src/core/components/pageEditor/FileThumbnail.tsx index b7b18e2398..9cfc1e4c3e 100644 --- a/frontend/src/components/pageEditor/FileThumbnail.tsx +++ b/frontend/src/core/components/pageEditor/FileThumbnail.tsx @@ -9,9 +9,9 @@ import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; -import styles from './PageEditor.module.css'; -import { useFileContext } from '../../contexts/FileContext'; -import { FileId } from '../../types/file'; +import styles from '@app/components/pageEditor/PageEditor.module.css'; +import { useFileContext } from '@app/contexts/FileContext'; +import { FileId } from '@app/types/file'; interface FileItem { id: FileId; diff --git a/frontend/src/components/pageEditor/PageEditor.module.css b/frontend/src/core/components/pageEditor/PageEditor.module.css similarity index 100% rename from frontend/src/components/pageEditor/PageEditor.module.css rename to frontend/src/core/components/pageEditor/PageEditor.module.css diff --git a/frontend/src/components/pageEditor/PageEditor.tsx b/frontend/src/core/components/pageEditor/PageEditor.tsx similarity index 95% rename from frontend/src/components/pageEditor/PageEditor.tsx rename to frontend/src/core/components/pageEditor/PageEditor.tsx index 13f702e69e..079ea747e4 100644 --- a/frontend/src/components/pageEditor/PageEditor.tsx +++ b/frontend/src/core/components/pageEditor/PageEditor.tsx @@ -1,19 +1,19 @@ import { useState, useCallback, useRef, useEffect } from "react"; import { Text, Center, Box, LoadingOverlay, Stack } from "@mantine/core"; -import { useFileState, useFileActions } from "../../contexts/FileContext"; -import { useNavigationGuard } from "../../contexts/NavigationContext"; -import { PDFDocument, PageEditorFunctions } from "../../types/pageEditor"; -import { pdfExportService } from "../../services/pdfExportService"; -import { documentManipulationService } from "../../services/documentManipulationService"; -import { exportProcessedDocumentsToFiles } from "../../services/pdfExportHelpers"; -import { createStirlingFilesAndStubs } from "../../services/fileStubHelpers"; +import { useFileState, useFileActions } from "@app/contexts/FileContext"; +import { useNavigationGuard } from "@app/contexts/NavigationContext"; +import { PDFDocument, PageEditorFunctions } from "@app/types/pageEditor"; +import { pdfExportService } from "@app/services/pdfExportService"; +import { documentManipulationService } from "@app/services/documentManipulationService"; +import { exportProcessedDocumentsToFiles } from "@app/services/pdfExportHelpers"; +import { createStirlingFilesAndStubs } from "@app/services/fileStubHelpers"; // Thumbnail generation is now handled by individual PageThumbnail components -import './PageEditor.module.css'; -import PageThumbnail from './PageThumbnail'; -import DragDropGrid from './DragDropGrid'; -import SkeletonLoader from '../shared/SkeletonLoader'; -import NavigationWarningModal from '../shared/NavigationWarningModal'; -import { FileId } from "../../types/file"; +import '@app/components/pageEditor/PageEditor.module.css'; +import PageThumbnail from '@app/components/pageEditor/PageThumbnail'; +import DragDropGrid from '@app/components/pageEditor/DragDropGrid'; +import SkeletonLoader from '@app/components/shared/SkeletonLoader'; +import NavigationWarningModal from '@app/components/shared/NavigationWarningModal'; +import { FileId } from "@app/types/file"; import { DeletePagesCommand, @@ -22,12 +22,12 @@ import { BulkRotateCommand, PageBreakCommand, UndoManager -} from './commands/pageCommands'; -import { GRID_CONSTANTS } from './constants'; -import { usePageDocument } from './hooks/usePageDocument'; -import { usePageEditorState } from './hooks/usePageEditorState'; -import { parseSelection } from "../../utils/bulkselection/parseSelection"; -import { usePageEditorRightRailButtons } from "./pageEditorRightRailButtons"; +} from '@app/components/pageEditor/commands/pageCommands'; +import { GRID_CONSTANTS } from '@app/components/pageEditor/constants'; +import { usePageDocument } from '@app/components/pageEditor/hooks/usePageDocument'; +import { usePageEditorState } from '@app/components/pageEditor/hooks/usePageEditorState'; +import { parseSelection } from "@app/utils/bulkselection/parseSelection"; +import { usePageEditorRightRailButtons } from "@app/components/pageEditor/pageEditorRightRailButtons"; export interface PageEditorProps { onFunctionsReady?: (functions: PageEditorFunctions) => void; diff --git a/frontend/src/components/pageEditor/PageEditorControls.tsx b/frontend/src/core/components/pageEditor/PageEditorControls.tsx similarity index 100% rename from frontend/src/components/pageEditor/PageEditorControls.tsx rename to frontend/src/core/components/pageEditor/PageEditorControls.tsx diff --git a/frontend/src/components/pageEditor/PageSelectByNumberButton.tsx b/frontend/src/core/components/pageEditor/PageSelectByNumberButton.tsx similarity index 89% rename from frontend/src/components/pageEditor/PageSelectByNumberButton.tsx rename to frontend/src/core/components/pageEditor/PageSelectByNumberButton.tsx index 3017d3a117..896da57809 100644 --- a/frontend/src/components/pageEditor/PageSelectByNumberButton.tsx +++ b/frontend/src/core/components/pageEditor/PageSelectByNumberButton.tsx @@ -1,7 +1,7 @@ import { ActionIcon, Popover } from '@mantine/core'; -import LocalIcon from '../shared/LocalIcon'; -import { Tooltip } from '../shared/Tooltip'; -import BulkSelectionPanel from './BulkSelectionPanel'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import BulkSelectionPanel from '@app/components/pageEditor/BulkSelectionPanel'; interface PageSelectByNumberButtonProps { disabled: boolean; diff --git a/frontend/src/components/pageEditor/PageThumbnail.tsx b/frontend/src/core/components/pageEditor/PageThumbnail.tsx similarity index 97% rename from frontend/src/components/pageEditor/PageThumbnail.tsx rename to frontend/src/core/components/pageEditor/PageThumbnail.tsx index f6d77a3e45..f0124b2c6d 100644 --- a/frontend/src/components/pageEditor/PageThumbnail.tsx +++ b/frontend/src/core/components/pageEditor/PageThumbnail.tsx @@ -9,11 +9,11 @@ import DeleteIcon from '@mui/icons-material/Delete'; import ContentCutIcon from '@mui/icons-material/ContentCut'; import AddIcon from '@mui/icons-material/Add'; import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; -import { PDFPage, PDFDocument } from '../../types/pageEditor'; -import { useThumbnailGeneration } from '../../hooks/useThumbnailGeneration'; -import { useFilesModalContext } from '../../contexts/FilesModalContext'; -import styles from './PageEditor.module.css'; -import HoverActionMenu, { HoverAction } from '../shared/HoverActionMenu'; +import { PDFPage, PDFDocument } from '@app/types/pageEditor'; +import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import styles from '@app/components/pageEditor/PageEditor.module.css'; +import HoverActionMenu, { HoverAction } from '@app/components/shared/HoverActionMenu'; interface PageThumbnailProps { diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx b/frontend/src/core/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx similarity index 92% rename from frontend/src/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx index e61caab6ae..c8d170dde3 100644 --- a/frontend/src/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx +++ b/frontend/src/core/components/pageEditor/bulkSelectionPanel/AdvancedSelectionPanel.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Flex } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import classes from './BulkSelectionPanel.module.css'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; import { appendExpression, insertOperatorSmart, @@ -10,9 +10,9 @@ import { everyNthExpression, rangeExpression, LogicalOperator, -} from './BulkSelection'; -import SelectPages from './SelectPages'; -import OperatorsSection from './OperatorsSection'; +} from '@app/components/pageEditor/bulkSelectionPanel/BulkSelection'; +import SelectPages from '@app/components/pageEditor/bulkSelectionPanel/SelectPages'; +import OperatorsSection from '@app/components/pageEditor/bulkSelectionPanel/OperatorsSection'; interface AdvancedSelectionPanelProps { csvInput: string; diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/BulkSelection.ts b/frontend/src/core/components/pageEditor/bulkSelectionPanel/BulkSelection.ts similarity index 100% rename from frontend/src/components/pageEditor/bulkSelectionPanel/BulkSelection.ts rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/BulkSelection.ts diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css b/frontend/src/core/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css similarity index 100% rename from frontend/src/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx b/frontend/src/core/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx similarity index 92% rename from frontend/src/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx index 37d35953cd..49812da618 100644 --- a/frontend/src/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx +++ b/frontend/src/core/components/pageEditor/bulkSelectionPanel/OperatorsSection.tsx @@ -1,7 +1,7 @@ import { Button, Text, Group, Divider } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import classes from './BulkSelectionPanel.module.css'; -import { LogicalOperator } from './BulkSelection'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; +import { LogicalOperator } from '@app/components/pageEditor/bulkSelectionPanel/BulkSelection'; interface OperatorsSectionProps { csvInput: string; diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx b/frontend/src/core/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx similarity index 90% rename from frontend/src/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx index 46652d85ae..6a7bbec535 100644 --- a/frontend/src/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx +++ b/frontend/src/core/components/pageEditor/bulkSelectionPanel/PageSelectionInput.tsx @@ -1,9 +1,9 @@ import { TextInput, Button, Text, Flex, Switch } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import LocalIcon from '../../shared/LocalIcon'; -import { Tooltip } from '../../shared/Tooltip'; -import { usePageSelectionTips } from '../../tooltips/usePageSelectionTips'; -import classes from './BulkSelectionPanel.module.css'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { usePageSelectionTips } from '@app/components/tooltips/usePageSelectionTips'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; interface PageSelectionInputProps { csvInput: string; diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/SelectPages.tsx b/frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectPages.tsx similarity index 96% rename from frontend/src/components/pageEditor/bulkSelectionPanel/SelectPages.tsx rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectPages.tsx index c2787d05e9..70652af45d 100644 --- a/frontend/src/components/pageEditor/bulkSelectionPanel/SelectPages.tsx +++ b/frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectPages.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { Button, Text, NumberInput, Group } from '@mantine/core'; -import classes from './BulkSelectionPanel.module.css'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; interface SelectPagesProps { title: string; diff --git a/frontend/src/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx b/frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx similarity index 90% rename from frontend/src/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx rename to frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx index 26fcfb8daf..dbcdb6cf90 100644 --- a/frontend/src/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx +++ b/frontend/src/core/components/pageEditor/bulkSelectionPanel/SelectedPagesDisplay.tsx @@ -1,5 +1,5 @@ import { Text } from '@mantine/core'; -import classes from './BulkSelectionPanel.module.css'; +import classes from '@app/components/pageEditor/bulkSelectionPanel/BulkSelectionPanel.module.css'; interface SelectedPagesDisplayProps { selectedPageIds: string[]; diff --git a/frontend/src/components/pageEditor/commands/pageCommands.ts b/frontend/src/core/components/pageEditor/commands/pageCommands.ts similarity index 98% rename from frontend/src/components/pageEditor/commands/pageCommands.ts rename to frontend/src/core/components/pageEditor/commands/pageCommands.ts index 7ac6a83771..b39fe663d8 100644 --- a/frontend/src/components/pageEditor/commands/pageCommands.ts +++ b/frontend/src/core/components/pageEditor/commands/pageCommands.ts @@ -1,5 +1,5 @@ -import { FileId } from '../../../types/file'; -import { PDFDocument, PDFPage } from '../../../types/pageEditor'; +import { FileId } from '@app/types/file'; +import { PDFDocument, PDFPage } from '@app/types/pageEditor'; // V1-style DOM-first command system (replaces the old React state commands) export abstract class DOMCommand { @@ -694,7 +694,7 @@ export class InsertFilesCommand extends DOMCommand { private async generateThumbnailsForInsertedPages(updatedDocument: PDFDocument): Promise { try { - const { thumbnailGenerationService } = await import('../../../services/thumbnailGenerationService'); + const { thumbnailGenerationService } = await import('@app/services/thumbnailGenerationService'); // Group pages by file ID to generate thumbnails efficiently const pagesByFileId = new Map(); @@ -776,7 +776,7 @@ export class InsertFilesCommand extends DOMCommand { const clonedArrayBuffer = arrayBuffer.slice(0); // Use PDF.js via the worker manager to extract pages - const { pdfWorkerManager } = await import('../../../services/pdfWorkerManager'); + const { pdfWorkerManager } = await import('@app/services/pdfWorkerManager'); const pdf = await pdfWorkerManager.createDocument(clonedArrayBuffer); const pageCount = pdf.numPages; diff --git a/frontend/src/components/pageEditor/constants.ts b/frontend/src/core/components/pageEditor/constants.ts similarity index 100% rename from frontend/src/components/pageEditor/constants.ts rename to frontend/src/core/components/pageEditor/constants.ts diff --git a/frontend/src/components/pageEditor/hooks/usePageDocument.ts b/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts similarity index 97% rename from frontend/src/components/pageEditor/hooks/usePageDocument.ts rename to frontend/src/core/components/pageEditor/hooks/usePageDocument.ts index e921903f90..1d3ecfb227 100644 --- a/frontend/src/components/pageEditor/hooks/usePageDocument.ts +++ b/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react'; -import { useFileState } from '../../../contexts/FileContext'; -import { PDFDocument, PDFPage } from '../../../types/pageEditor'; -import { FileId } from '../../../types/file'; +import { useFileState } from '@app/contexts/FileContext'; +import { PDFDocument, PDFPage } from '@app/types/pageEditor'; +import { FileId } from '@app/types/file'; export interface PageDocumentHook { document: PDFDocument | null; diff --git a/frontend/src/components/pageEditor/hooks/usePageEditorState.ts b/frontend/src/core/components/pageEditor/hooks/usePageEditorState.ts similarity index 100% rename from frontend/src/components/pageEditor/hooks/usePageEditorState.ts rename to frontend/src/core/components/pageEditor/hooks/usePageEditorState.ts diff --git a/frontend/src/components/pageEditor/pageEditorRightRailButtons.tsx b/frontend/src/core/components/pageEditor/pageEditorRightRailButtons.tsx similarity index 96% rename from frontend/src/components/pageEditor/pageEditorRightRailButtons.tsx rename to frontend/src/core/components/pageEditor/pageEditorRightRailButtons.tsx index 23faa99afa..03479c943a 100644 --- a/frontend/src/components/pageEditor/pageEditorRightRailButtons.tsx +++ b/frontend/src/core/components/pageEditor/pageEditorRightRailButtons.tsx @@ -1,8 +1,8 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useRightRailButtons, RightRailButtonWithAction } from '../../hooks/useRightRailButtons'; -import LocalIcon from '../shared/LocalIcon'; -import PageSelectByNumberButton from './PageSelectByNumberButton'; +import { useRightRailButtons, RightRailButtonWithAction } from '@app/hooks/useRightRailButtons'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import PageSelectByNumberButton from '@app/components/pageEditor/PageSelectByNumberButton'; interface PageEditorRightRailButtonsParams { totalPages: number; diff --git a/frontend/src/components/shared/AdminAnalyticsChoiceModal.tsx b/frontend/src/core/components/shared/AdminAnalyticsChoiceModal.tsx similarity index 94% rename from frontend/src/components/shared/AdminAnalyticsChoiceModal.tsx rename to frontend/src/core/components/shared/AdminAnalyticsChoiceModal.tsx index 96c1ba6bfd..7a8974a3aa 100644 --- a/frontend/src/components/shared/AdminAnalyticsChoiceModal.tsx +++ b/frontend/src/core/components/shared/AdminAnalyticsChoiceModal.tsx @@ -1,9 +1,9 @@ import { Modal, Stack, Button, Text, Title, Anchor } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import { useState } from 'react'; -import { Z_ANALYTICS_MODAL } from '../../styles/zIndex'; -import { useAppConfig } from '../../contexts/AppConfigContext'; -import apiClient from '../../services/apiClient'; +import { Z_ANALYTICS_MODAL } from '@app/styles/zIndex'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import apiClient from '@app/services/apiClient'; interface AdminAnalyticsChoiceModalProps { opened: boolean; diff --git a/frontend/src/components/shared/AllToolsNavButton.tsx b/frontend/src/core/components/shared/AllToolsNavButton.tsx similarity index 89% rename from frontend/src/components/shared/AllToolsNavButton.tsx rename to frontend/src/core/components/shared/AllToolsNavButton.tsx index 62fad704ed..9a333878ad 100644 --- a/frontend/src/components/shared/AllToolsNavButton.tsx +++ b/frontend/src/core/components/shared/AllToolsNavButton.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { ActionIcon } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { Tooltip } from './Tooltip'; +import { Tooltip } from '@app/components/shared/Tooltip'; import AppsIcon from '@mui/icons-material/AppsRounded'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { useSidebarNavigation } from '../../hooks/useSidebarNavigation'; -import { handleUnlessSpecialClick } from '../../utils/clickHandlers'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; +import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; interface AllToolsNavButtonProps { activeButton: string; diff --git a/frontend/src/components/shared/AppConfigModal.css b/frontend/src/core/components/shared/AppConfigModal.css similarity index 100% rename from frontend/src/components/shared/AppConfigModal.css rename to frontend/src/core/components/shared/AppConfigModal.css diff --git a/frontend/src/components/shared/AppConfigModal.tsx b/frontend/src/core/components/shared/AppConfigModal.tsx similarity index 92% rename from frontend/src/components/shared/AppConfigModal.tsx rename to frontend/src/core/components/shared/AppConfigModal.tsx index eb7125b726..fb10bdad78 100644 --- a/frontend/src/components/shared/AppConfigModal.tsx +++ b/frontend/src/core/components/shared/AppConfigModal.tsx @@ -1,12 +1,12 @@ import React, { useMemo, useState, useEffect } from 'react'; import { Modal, Text, ActionIcon } from '@mantine/core'; import { useMediaQuery } from '@mantine/hooks'; -import LocalIcon from './LocalIcon'; -import Overview from './config/configSections/Overview'; -import { createConfigNavSections } from './config/configNavSections'; -import { NavKey } from './config/types'; -import './AppConfigModal.css'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import Overview from '@app/components/shared/config/configSections/Overview'; +import { createConfigNavSections } from '@app/components/shared/config/configNavSections'; +import { NavKey } from '@app/components/shared/config/types'; +import '@app/components/shared/AppConfigModal.css'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; interface AppConfigModalProps { opened: boolean; diff --git a/frontend/src/components/shared/Badge.tsx b/frontend/src/core/components/shared/Badge.tsx similarity index 100% rename from frontend/src/components/shared/Badge.tsx rename to frontend/src/core/components/shared/Badge.tsx diff --git a/frontend/src/components/shared/ButtonSelector.test.tsx b/frontend/src/core/components/shared/ButtonSelector.test.tsx similarity index 98% rename from frontend/src/components/shared/ButtonSelector.test.tsx rename to frontend/src/core/components/shared/ButtonSelector.test.tsx index e3adf1def4..12a509abd6 100644 --- a/frontend/src/components/shared/ButtonSelector.test.tsx +++ b/frontend/src/core/components/shared/ButtonSelector.test.tsx @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import ButtonSelector from './ButtonSelector'; +import ButtonSelector from '@app/components/shared/ButtonSelector'; // Wrapper component to provide Mantine context const TestWrapper = ({ children }: { children: React.ReactNode }) => ( diff --git a/frontend/src/components/shared/ButtonSelector.tsx b/frontend/src/core/components/shared/ButtonSelector.tsx similarity index 97% rename from frontend/src/components/shared/ButtonSelector.tsx rename to frontend/src/core/components/shared/ButtonSelector.tsx index 97b109ef26..3354f06d7c 100644 --- a/frontend/src/components/shared/ButtonSelector.tsx +++ b/frontend/src/core/components/shared/ButtonSelector.tsx @@ -1,5 +1,5 @@ import { Button, Group, Stack, Text } from "@mantine/core"; -import FitText from "./FitText"; +import FitText from "@app/components/shared/FitText"; export interface ButtonOption { value: T; diff --git a/frontend/src/components/shared/CardSelector.tsx b/frontend/src/core/components/shared/CardSelector.tsx similarity index 97% rename from frontend/src/components/shared/CardSelector.tsx rename to frontend/src/core/components/shared/CardSelector.tsx index a8e4a27257..8ab206b706 100644 --- a/frontend/src/components/shared/CardSelector.tsx +++ b/frontend/src/core/components/shared/CardSelector.tsx @@ -1,5 +1,5 @@ import { Stack, Card, Text, Flex } from '@mantine/core'; -import { Tooltip } from './Tooltip'; +import { Tooltip } from '@app/components/shared/Tooltip'; import { useTranslation } from 'react-i18next'; export interface CardOption { diff --git a/frontend/src/components/shared/DismissAllErrorsButton.tsx b/frontend/src/core/components/shared/DismissAllErrorsButton.tsx similarity index 91% rename from frontend/src/components/shared/DismissAllErrorsButton.tsx rename to frontend/src/core/components/shared/DismissAllErrorsButton.tsx index 44a579f343..4b320539c2 100644 --- a/frontend/src/components/shared/DismissAllErrorsButton.tsx +++ b/frontend/src/core/components/shared/DismissAllErrorsButton.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Button, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useFileState } from '../../contexts/FileContext'; -import { useFileActions } from '../../contexts/file/fileHooks'; +import { useFileState } from '@app/contexts/FileContext'; +import { useFileActions } from '@app/contexts/file/fileHooks'; import CloseIcon from '@mui/icons-material/Close'; interface DismissAllErrorsButtonProps { diff --git a/frontend/src/components/shared/DropdownListWithFooter.tsx b/frontend/src/core/components/shared/DropdownListWithFooter.tsx similarity index 100% rename from frontend/src/components/shared/DropdownListWithFooter.tsx rename to frontend/src/core/components/shared/DropdownListWithFooter.tsx diff --git a/frontend/src/components/shared/ErrorBoundary.tsx b/frontend/src/core/components/shared/ErrorBoundary.tsx similarity index 100% rename from frontend/src/components/shared/ErrorBoundary.tsx rename to frontend/src/core/components/shared/ErrorBoundary.tsx diff --git a/frontend/src/components/shared/FileCard.tsx b/frontend/src/core/components/shared/FileCard.tsx similarity index 97% rename from frontend/src/components/shared/FileCard.tsx rename to frontend/src/core/components/shared/FileCard.tsx index 50d43dc06e..6eff26db9b 100644 --- a/frontend/src/components/shared/FileCard.tsx +++ b/frontend/src/core/components/shared/FileCard.tsx @@ -6,9 +6,9 @@ import StorageIcon from "@mui/icons-material/Storage"; import VisibilityIcon from "@mui/icons-material/Visibility"; import EditIcon from "@mui/icons-material/Edit"; -import { StirlingFileStub } from "../../types/fileContext"; -import { getFileSize, getFileDate } from "../../utils/fileUtils"; -import { useIndexedDBThumbnail } from "../../hooks/useIndexedDBThumbnail"; +import { StirlingFileStub } from "@app/types/fileContext"; +import { getFileSize, getFileDate } from "@app/utils/fileUtils"; +import { useIndexedDBThumbnail } from "@app/hooks/useIndexedDBThumbnail"; interface FileCardProps { file: File; diff --git a/frontend/src/components/shared/FileDropdownMenu.tsx b/frontend/src/core/components/shared/FileDropdownMenu.tsx similarity index 98% rename from frontend/src/components/shared/FileDropdownMenu.tsx rename to frontend/src/core/components/shared/FileDropdownMenu.tsx index b03995fc7c..8a78e76313 100644 --- a/frontend/src/components/shared/FileDropdownMenu.tsx +++ b/frontend/src/core/components/shared/FileDropdownMenu.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Menu, Loader, Group, Text } from '@mantine/core'; import VisibilityIcon from '@mui/icons-material/Visibility'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; -import FitText from './FitText'; +import FitText from '@app/components/shared/FitText'; interface FileDropdownMenuProps { displayName: string; diff --git a/frontend/src/components/shared/FileGrid.tsx b/frontend/src/core/components/shared/FileGrid.tsx similarity index 97% rename from frontend/src/components/shared/FileGrid.tsx rename to frontend/src/core/components/shared/FileGrid.tsx index 678bedca1b..5bd31008db 100644 --- a/frontend/src/components/shared/FileGrid.tsx +++ b/frontend/src/core/components/shared/FileGrid.tsx @@ -3,9 +3,9 @@ import { Box, Flex, Group, Text, Button, TextInput, Select } from "@mantine/core import { useTranslation } from "react-i18next"; import SearchIcon from "@mui/icons-material/Search"; import SortIcon from "@mui/icons-material/Sort"; -import FileCard from "./FileCard"; -import { StirlingFileStub } from "../../types/fileContext"; -import { FileId } from "../../types/file"; +import FileCard from "@app/components/shared/FileCard"; +import { StirlingFileStub } from "@app/types/fileContext"; +import { FileId } from "@app/types/file"; interface FileGridProps { files: Array<{ file: File; record?: StirlingFileStub }>; diff --git a/frontend/src/components/shared/FilePickerModal.tsx b/frontend/src/core/components/shared/FilePickerModal.tsx similarity index 99% rename from frontend/src/components/shared/FilePickerModal.tsx rename to frontend/src/core/components/shared/FilePickerModal.tsx index bb571b5897..336070a742 100644 --- a/frontend/src/components/shared/FilePickerModal.tsx +++ b/frontend/src/core/components/shared/FilePickerModal.tsx @@ -15,7 +15,7 @@ import { } from '@mantine/core'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import { useTranslation } from 'react-i18next'; -import { FileId } from '../../types/file'; +import { FileId } from '@app/types/file'; interface FilePickerModalProps { opened: boolean; diff --git a/frontend/src/components/shared/FilePreview.tsx b/frontend/src/core/components/shared/FilePreview.tsx similarity index 86% rename from frontend/src/components/shared/FilePreview.tsx rename to frontend/src/core/components/shared/FilePreview.tsx index eb2917029a..4377c851c0 100644 --- a/frontend/src/components/shared/FilePreview.tsx +++ b/frontend/src/core/components/shared/FilePreview.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Box, Center } from '@mantine/core'; import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; -import { StirlingFileStub } from '../../types/fileContext'; -import DocumentThumbnail from './filePreview/DocumentThumbnail'; -import DocumentStack from './filePreview/DocumentStack'; -import HoverOverlay from './filePreview/HoverOverlay'; -import NavigationArrows from './filePreview/NavigationArrows'; +import { StirlingFileStub } from '@app/types/fileContext'; +import DocumentThumbnail from '@app/components/shared/filePreview/DocumentThumbnail'; +import DocumentStack from '@app/components/shared/filePreview/DocumentStack'; +import HoverOverlay from '@app/components/shared/filePreview/HoverOverlay'; +import NavigationArrows from '@app/components/shared/filePreview/NavigationArrows'; export interface FilePreviewProps { // Core file data diff --git a/frontend/src/components/shared/FileUploadButton.tsx b/frontend/src/core/components/shared/FileUploadButton.tsx similarity index 100% rename from frontend/src/components/shared/FileUploadButton.tsx rename to frontend/src/core/components/shared/FileUploadButton.tsx diff --git a/frontend/src/components/shared/FitText.tsx b/frontend/src/core/components/shared/FitText.tsx similarity index 97% rename from frontend/src/components/shared/FitText.tsx rename to frontend/src/core/components/shared/FitText.tsx index 0a5e2711b2..efdb1c2263 100644 --- a/frontend/src/components/shared/FitText.tsx +++ b/frontend/src/core/components/shared/FitText.tsx @@ -1,5 +1,5 @@ import React, { CSSProperties, useMemo, useRef } from 'react'; -import { useAdjustFontSizeToFit } from './fitText/textFit'; +import { useAdjustFontSizeToFit } from '@app/components/shared/fitText/textFit'; type FitTextProps = { text: string; diff --git a/frontend/src/components/shared/Footer.tsx b/frontend/src/core/components/shared/Footer.tsx similarity index 97% rename from frontend/src/components/shared/Footer.tsx rename to frontend/src/core/components/shared/Footer.tsx index 68a42a5e5d..89aca8e07f 100644 --- a/frontend/src/components/shared/Footer.tsx +++ b/frontend/src/core/components/shared/Footer.tsx @@ -1,6 +1,6 @@ import { Flex } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useCookieConsent } from '../../hooks/useCookieConsent'; +import { useCookieConsent } from '@app/hooks/useCookieConsent'; interface FooterProps { privacyPolicy?: string; diff --git a/frontend/src/components/shared/HoverActionMenu.module.css b/frontend/src/core/components/shared/HoverActionMenu.module.css similarity index 100% rename from frontend/src/components/shared/HoverActionMenu.module.css rename to frontend/src/core/components/shared/HoverActionMenu.module.css diff --git a/frontend/src/components/shared/HoverActionMenu.tsx b/frontend/src/core/components/shared/HoverActionMenu.tsx similarity index 95% rename from frontend/src/components/shared/HoverActionMenu.tsx rename to frontend/src/core/components/shared/HoverActionMenu.tsx index 1c55f5f0ab..51b3155b35 100644 --- a/frontend/src/components/shared/HoverActionMenu.tsx +++ b/frontend/src/core/components/shared/HoverActionMenu.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ActionIcon, Tooltip } from '@mantine/core'; -import styles from './HoverActionMenu.module.css'; +import styles from '@app/components/shared/HoverActionMenu.module.css'; export interface HoverAction { id: string; diff --git a/frontend/src/components/shared/LandingPage.tsx b/frontend/src/core/components/shared/LandingPage.tsx similarity index 96% rename from frontend/src/components/shared/LandingPage.tsx rename to frontend/src/core/components/shared/LandingPage.tsx index 293efc1b4d..f25aaedfcb 100644 --- a/frontend/src/components/shared/LandingPage.tsx +++ b/frontend/src/core/components/shared/LandingPage.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Container, Button, Group, useMantineColorScheme } from '@mantine/core'; import { Dropzone } from '@mantine/dropzone'; -import LocalIcon from './LocalIcon'; +import LocalIcon from '@app/components/shared/LocalIcon'; import { useTranslation } from 'react-i18next'; -import { useFileHandler } from '../../hooks/useFileHandler'; -import { useFilesModalContext } from '../../contexts/FilesModalContext'; -import { BASE_PATH } from '../../constants/app'; +import { useFileHandler } from '@app/hooks/useFileHandler'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import { BASE_PATH } from '@app/constants/app'; const LandingPage = () => { const { addFiles } = useFileHandler(); diff --git a/frontend/src/components/shared/LanguageSelector.module.css b/frontend/src/core/components/shared/LanguageSelector.module.css similarity index 100% rename from frontend/src/components/shared/LanguageSelector.module.css rename to frontend/src/core/components/shared/LanguageSelector.module.css diff --git a/frontend/src/components/shared/LanguageSelector.tsx b/frontend/src/core/components/shared/LanguageSelector.tsx similarity index 97% rename from frontend/src/components/shared/LanguageSelector.tsx rename to frontend/src/core/components/shared/LanguageSelector.tsx index 507dab16b0..53e239064e 100644 --- a/frontend/src/components/shared/LanguageSelector.tsx +++ b/frontend/src/core/components/shared/LanguageSelector.tsx @@ -1,10 +1,10 @@ import React, { useState, useEffect } from 'react'; import { Menu, Button, ScrollArea, ActionIcon, Tooltip } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { supportedLanguages } from '../../i18n'; -import LocalIcon from './LocalIcon'; -import styles from './LanguageSelector.module.css'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; +import { supportedLanguages } from '@app/i18n'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import styles from '@app/components/shared/LanguageSelector.module.css'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; // Types interface LanguageSelectorProps { diff --git a/frontend/src/core/components/shared/LoadingFallback.tsx b/frontend/src/core/components/shared/LoadingFallback.tsx new file mode 100644 index 0000000000..dced852150 --- /dev/null +++ b/frontend/src/core/components/shared/LoadingFallback.tsx @@ -0,0 +1,19 @@ +/** + * Loading fallback component for i18next suspense + */ +export function LoadingFallback() { + return ( +
+ Loading... +
+ ); +} diff --git a/frontend/src/components/shared/LocalIcon.tsx b/frontend/src/core/components/shared/LocalIcon.tsx similarity index 95% rename from frontend/src/components/shared/LocalIcon.tsx rename to frontend/src/core/components/shared/LocalIcon.tsx index 6d16c6c34d..25f85688c3 100644 --- a/frontend/src/components/shared/LocalIcon.tsx +++ b/frontend/src/core/components/shared/LocalIcon.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { addCollection, Icon } from '@iconify/react'; -import iconSet from '../../assets/material-symbols-icons.json'; +import iconSet from '../../../assets/material-symbols-icons.json'; // Load icons synchronously at import time - guaranteed to be ready on first render let iconsLoaded = false; diff --git a/frontend/src/components/shared/MultiSelectControls.tsx b/frontend/src/core/components/shared/MultiSelectControls.tsx similarity index 100% rename from frontend/src/components/shared/MultiSelectControls.tsx rename to frontend/src/core/components/shared/MultiSelectControls.tsx diff --git a/frontend/src/components/shared/NavigationWarningModal.tsx b/frontend/src/core/components/shared/NavigationWarningModal.tsx similarity index 98% rename from frontend/src/components/shared/NavigationWarningModal.tsx rename to frontend/src/core/components/shared/NavigationWarningModal.tsx index 8188be4352..faff074279 100644 --- a/frontend/src/components/shared/NavigationWarningModal.tsx +++ b/frontend/src/core/components/shared/NavigationWarningModal.tsx @@ -1,5 +1,5 @@ import { Modal, Text, Button, Group, Stack } from "@mantine/core"; -import { useNavigationGuard } from "../../contexts/NavigationContext"; +import { useNavigationGuard } from "@app/contexts/NavigationContext"; import { useTranslation } from "react-i18next"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; diff --git a/frontend/src/components/shared/ObscuredOverlay.tsx b/frontend/src/core/components/shared/ObscuredOverlay.tsx similarity index 93% rename from frontend/src/components/shared/ObscuredOverlay.tsx rename to frontend/src/core/components/shared/ObscuredOverlay.tsx index 0e918151fd..2329d624dc 100644 --- a/frontend/src/components/shared/ObscuredOverlay.tsx +++ b/frontend/src/core/components/shared/ObscuredOverlay.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import styles from './ObscuredOverlay/ObscuredOverlay.module.css'; +import styles from '@app/components/shared/ObscuredOverlay/ObscuredOverlay.module.css'; type ObscuredOverlayProps = { obscured: boolean; diff --git a/frontend/src/components/shared/ObscuredOverlay/ObscuredOverlay.module.css b/frontend/src/core/components/shared/ObscuredOverlay/ObscuredOverlay.module.css similarity index 100% rename from frontend/src/components/shared/ObscuredOverlay/ObscuredOverlay.module.css rename to frontend/src/core/components/shared/ObscuredOverlay/ObscuredOverlay.module.css diff --git a/frontend/src/components/shared/QuickAccessBar.tsx b/frontend/src/core/components/shared/QuickAccessBar.tsx similarity index 88% rename from frontend/src/components/shared/QuickAccessBar.tsx rename to frontend/src/core/components/shared/QuickAccessBar.tsx index a1acf5cd56..d10d4df079 100644 --- a/frontend/src/components/shared/QuickAccessBar.tsx +++ b/frontend/src/core/components/shared/QuickAccessBar.tsx @@ -1,25 +1,25 @@ import React, { useState, useRef, forwardRef, useEffect } from "react"; import { ActionIcon, Stack, Divider } from "@mantine/core"; import { useTranslation } from 'react-i18next'; -import LocalIcon from './LocalIcon'; -import { useRainbowThemeContext } from "./RainbowThemeProvider"; -import { useIsOverflowing } from '../../hooks/useIsOverflowing'; -import { useFilesModalContext } from '../../contexts/FilesModalContext'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { useSidebarNavigation } from '../../hooks/useSidebarNavigation'; -import { handleUnlessSpecialClick } from '../../utils/clickHandlers'; -import { ButtonConfig } from '../../types/sidebar'; -import './quickAccessBar/QuickAccessBar.css'; -import AllToolsNavButton from './AllToolsNavButton'; -import ActiveToolButton from "./quickAccessBar/ActiveToolButton"; -import AppConfigModal from './AppConfigModal'; -import { useAppConfig } from '../../contexts/AppConfigContext'; -import { useOnboarding } from '../../contexts/OnboardingContext'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { useRainbowThemeContext } from "@app/components/shared/RainbowThemeProvider"; +import { useIsOverflowing } from '@app/hooks/useIsOverflowing'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; +import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; +import { ButtonConfig } from '@app/types/sidebar'; +import '@app/components/shared/quickAccessBar/QuickAccessBar.css'; +import AllToolsNavButton from '@app/components/shared/AllToolsNavButton'; +import ActiveToolButton from "@app/components/shared/quickAccessBar/ActiveToolButton"; +import AppConfigModal from '@app/components/shared/AppConfigModal'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import { useOnboarding } from '@app/contexts/OnboardingContext'; import { isNavButtonActive, getNavButtonStyle, getActiveNavButton, -} from './quickAccessBar/QuickAccessBar'; +} from '@app/components/shared/quickAccessBar/QuickAccessBar'; const QuickAccessBar = forwardRef((_, ref) => { const { t } = useTranslation(); diff --git a/frontend/src/components/shared/RainbowThemeProvider.tsx b/frontend/src/core/components/shared/RainbowThemeProvider.tsx similarity index 78% rename from frontend/src/components/shared/RainbowThemeProvider.tsx rename to frontend/src/core/components/shared/RainbowThemeProvider.tsx index 18efba2565..992aa79b5c 100644 --- a/frontend/src/components/shared/RainbowThemeProvider.tsx +++ b/frontend/src/core/components/shared/RainbowThemeProvider.tsx @@ -1,12 +1,12 @@ import { createContext, useContext, ReactNode } from 'react'; import { MantineProvider } from '@mantine/core'; -import { useRainbowTheme } from '../../hooks/useRainbowTheme'; -import { mantineTheme } from '../../theme/mantineTheme'; -import rainbowStyles from '../../styles/rainbow.module.css'; -import { ToastProvider } from '../toast'; -import ToastRenderer from '../toast/ToastRenderer'; -import { ToastPortalBinder } from '../toast'; -import type { ThemeMode } from '../../constants/theme'; +import { useRainbowTheme } from '@app/hooks/useRainbowTheme'; +import { mantineTheme } from '@app/theme/mantineTheme'; +import rainbowStyles from '@app/styles/rainbow.module.css'; +import { ToastProvider } from '@app/components/toast'; +import ToastRenderer from '@app/components/toast/ToastRenderer'; +import { ToastPortalBinder } from '@app/components/toast'; +import type { ThemeMode } from '@app/constants/theme'; interface RainbowThemeContextType { themeMode: ThemeMode; diff --git a/frontend/src/components/shared/RightRail.tsx b/frontend/src/core/components/shared/RightRail.tsx similarity index 89% rename from frontend/src/components/shared/RightRail.tsx rename to frontend/src/core/components/shared/RightRail.tsx index 149aa9eaaf..551ef13280 100644 --- a/frontend/src/components/shared/RightRail.tsx +++ b/frontend/src/core/components/shared/RightRail.tsx @@ -1,21 +1,21 @@ import React, { useCallback, useMemo } from 'react'; import { ActionIcon, Divider } from '@mantine/core'; -import './rightRail/RightRail.css'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { useRightRail } from '../../contexts/RightRailContext'; -import { useFileState, useFileSelection } from '../../contexts/FileContext'; -import { useNavigationState } from '../../contexts/NavigationContext'; +import '@app/components/shared/rightRail/RightRail.css'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useRightRail } from '@app/contexts/RightRailContext'; +import { useFileState, useFileSelection } from '@app/contexts/FileContext'; +import { useNavigationState } from '@app/contexts/NavigationContext'; import { useTranslation } from 'react-i18next'; -import LanguageSelector from '../shared/LanguageSelector'; -import { useRainbowThemeContext } from '../shared/RainbowThemeProvider'; -import { Tooltip } from '../shared/Tooltip'; -import { ViewerContext } from '../../contexts/ViewerContext'; -import { useSignature } from '../../contexts/SignatureContext'; -import LocalIcon from './LocalIcon'; +import LanguageSelector from '@app/components/shared/LanguageSelector'; +import { useRainbowThemeContext } from '@app/components/shared/RainbowThemeProvider'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { ViewerContext } from '@app/contexts/ViewerContext'; +import { useSignature } from '@app/contexts/SignatureContext'; +import LocalIcon from '@app/components/shared/LocalIcon'; -import { useSidebarContext } from '../../contexts/SidebarContext'; -import { RightRailButtonConfig, RightRailRenderContext, RightRailSection } from '../../types/rightRail'; +import { useSidebarContext } from '@app/contexts/SidebarContext'; +import { RightRailButtonConfig, RightRailRenderContext, RightRailSection } from '@app/types/rightRail'; const SECTION_ORDER: RightRailSection[] = ['top', 'middle', 'bottom']; diff --git a/frontend/src/components/shared/SkeletonLoader.tsx b/frontend/src/core/components/shared/SkeletonLoader.tsx similarity index 100% rename from frontend/src/components/shared/SkeletonLoader.tsx rename to frontend/src/core/components/shared/SkeletonLoader.tsx diff --git a/frontend/src/components/shared/TextInput.tsx b/frontend/src/core/components/shared/TextInput.tsx similarity index 95% rename from frontend/src/components/shared/TextInput.tsx rename to frontend/src/core/components/shared/TextInput.tsx index 80c26dfdd8..0203e83c07 100644 --- a/frontend/src/components/shared/TextInput.tsx +++ b/frontend/src/core/components/shared/TextInput.tsx @@ -1,7 +1,7 @@ import React, { forwardRef } from 'react'; import { useMantineColorScheme } from '@mantine/core'; -import LocalIcon from './LocalIcon'; -import styles from './textInput/TextInput.module.css'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import styles from '@app/components/shared/textInput/TextInput.module.css'; /** * Props for the TextInput component diff --git a/frontend/src/components/shared/ToolChain.tsx b/frontend/src/core/components/shared/ToolChain.tsx similarity index 97% rename from frontend/src/components/shared/ToolChain.tsx rename to frontend/src/core/components/shared/ToolChain.tsx index 4d9a4bd512..d3c25f6533 100644 --- a/frontend/src/components/shared/ToolChain.tsx +++ b/frontend/src/core/components/shared/ToolChain.tsx @@ -5,9 +5,9 @@ import React from 'react'; import { Text, Tooltip, Badge, Group } from '@mantine/core'; -import { ToolOperation } from '../../types/file'; +import { ToolOperation } from '@app/types/file'; import { useTranslation } from 'react-i18next'; -import { ToolId } from '../../types/toolId'; +import { ToolId } from '@app/types/toolId'; interface ToolChainProps { toolChain: ToolOperation[]; diff --git a/frontend/src/components/shared/ToolIcon.tsx b/frontend/src/core/components/shared/ToolIcon.tsx similarity index 100% rename from frontend/src/components/shared/ToolIcon.tsx rename to frontend/src/core/components/shared/ToolIcon.tsx diff --git a/frontend/src/components/shared/Tooltip.tsx b/frontend/src/core/components/shared/Tooltip.tsx similarity index 95% rename from frontend/src/components/shared/Tooltip.tsx rename to frontend/src/core/components/shared/Tooltip.tsx index 775cbbee13..77db24d466 100644 --- a/frontend/src/components/shared/Tooltip.tsx +++ b/frontend/src/core/components/shared/Tooltip.tsx @@ -1,14 +1,14 @@ import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react'; import { createPortal } from 'react-dom'; -import LocalIcon from './LocalIcon'; -import { addEventListenerWithCleanup } from '../../utils/genericUtils'; -import { useTooltipPosition } from '../../hooks/useTooltipPosition'; -import { TooltipTip } from '../../types/tips'; -import { TooltipContent } from './tooltip/TooltipContent'; -import { useSidebarContext } from '../../contexts/SidebarContext'; -import { BASE_PATH } from '../../constants/app'; -import styles from './tooltip/Tooltip.module.css'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { addEventListenerWithCleanup } from '@app/utils/genericUtils'; +import { useTooltipPosition } from '@app/hooks/useTooltipPosition'; +import { TooltipTip } from '@app/types/tips'; +import { TooltipContent } from '@app/components/shared/tooltip/TooltipContent'; +import { useSidebarContext } from '@app/contexts/SidebarContext'; +import { BASE_PATH } from '@app/constants/app'; +import styles from '@app/components/shared/tooltip/Tooltip.module.css'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; export interface TooltipProps { sidebarTooltip?: boolean; diff --git a/frontend/src/components/shared/TopControls.tsx b/frontend/src/core/components/shared/TopControls.tsx similarity index 93% rename from frontend/src/components/shared/TopControls.tsx rename to frontend/src/core/components/shared/TopControls.tsx index 62f01f9ef5..6c6ac6999b 100644 --- a/frontend/src/components/shared/TopControls.tsx +++ b/frontend/src/core/components/shared/TopControls.tsx @@ -1,14 +1,14 @@ import React, { useState, useCallback } from "react"; import { SegmentedControl, Loader } from "@mantine/core"; -import { useRainbowThemeContext } from "./RainbowThemeProvider"; -import rainbowStyles from '../../styles/rainbow.module.css'; +import { useRainbowThemeContext } from "@app/components/shared/RainbowThemeProvider"; +import rainbowStyles from '@app/styles/rainbow.module.css'; import VisibilityIcon from "@mui/icons-material/Visibility"; import EditNoteIcon from "@mui/icons-material/EditNote"; import FolderIcon from "@mui/icons-material/Folder"; import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf"; -import { WorkbenchType, isValidWorkbench } from '../../types/workbench'; -import type { CustomWorkbenchViewInstance } from '../../contexts/ToolWorkflowContext'; -import { FileDropdownMenu } from './FileDropdownMenu'; +import { WorkbenchType, isValidWorkbench } from '@app/types/workbench'; +import type { CustomWorkbenchViewInstance } from '@app/contexts/ToolWorkflowContext'; +import { FileDropdownMenu } from '@app/components/shared/FileDropdownMenu'; const viewOptionStyle: React.CSSProperties = { diff --git a/frontend/src/core/components/shared/config/OverviewHeader.tsx b/frontend/src/core/components/shared/config/OverviewHeader.tsx new file mode 100644 index 0000000000..7be820620a --- /dev/null +++ b/frontend/src/core/components/shared/config/OverviewHeader.tsx @@ -0,0 +1,15 @@ +import { Text } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; + +export function OverviewHeader() { + const { t } = useTranslation(); + + return ( +
+ {t('config.overview.title', 'Application Configuration')} + + {t('config.overview.description', 'Current application settings and configuration details.')} + +
+ ); +} diff --git a/frontend/src/components/shared/config/configNavSections.tsx b/frontend/src/core/components/shared/config/configNavSections.tsx similarity index 83% rename from frontend/src/components/shared/config/configNavSections.tsx rename to frontend/src/core/components/shared/config/configNavSections.tsx index 0232db2aa6..c0d3153e1b 100644 --- a/frontend/src/components/shared/config/configNavSections.tsx +++ b/frontend/src/core/components/shared/config/configNavSections.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { NavKey } from './types'; -import HotkeysSection from './configSections/HotkeysSection'; -import GeneralSection from './configSections/GeneralSection'; +import { NavKey } from '@app/components/shared/config/types'; +import HotkeysSection from '@app/components/shared/config/configSections/HotkeysSection'; +import GeneralSection from '@app/components/shared/config/configSections/GeneralSection'; export interface ConfigNavItem { key: NavKey; diff --git a/frontend/src/components/shared/config/configSections/GeneralSection.tsx b/frontend/src/core/components/shared/config/configSections/GeneralSection.tsx similarity index 96% rename from frontend/src/components/shared/config/configSections/GeneralSection.tsx rename to frontend/src/core/components/shared/config/configSections/GeneralSection.tsx index 937ff3d077..da71d3c6c6 100644 --- a/frontend/src/components/shared/config/configSections/GeneralSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/GeneralSection.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { Paper, Stack, Switch, Text, Tooltip, NumberInput, SegmentedControl } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { usePreferences } from '../../../../contexts/PreferencesContext'; -import type { ToolPanelMode } from '../../../../constants/toolPanel'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import type { ToolPanelMode } from '@app/constants/toolPanel'; const DEFAULT_AUTO_UNZIP_FILE_LIMIT = 4; diff --git a/frontend/src/components/shared/config/configSections/HotkeysSection.tsx b/frontend/src/core/components/shared/config/configSections/HotkeysSection.tsx similarity index 94% rename from frontend/src/components/shared/config/configSections/HotkeysSection.tsx rename to frontend/src/core/components/shared/config/configSections/HotkeysSection.tsx index 520f1730a1..2839ccb9d8 100644 --- a/frontend/src/components/shared/config/configSections/HotkeysSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/HotkeysSection.tsx @@ -1,12 +1,12 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Alert, Badge, Box, Button, Divider, Group, Paper, Stack, Text, TextInput } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useToolWorkflow } from '../../../../contexts/ToolWorkflowContext'; -import { useHotkeys } from '../../../../contexts/HotkeyContext'; -import { ToolId } from '../../../../types/toolId'; -import HotkeyDisplay from '../../../hotkeys/HotkeyDisplay'; -import { bindingEquals, eventToBinding, HotkeyBinding } from '../../../../utils/hotkeys'; -import { ToolRegistryEntry } from 'src/data/toolsTaxonomy'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useHotkeys } from '@app/contexts/HotkeyContext'; +import { ToolId } from '@app/types/toolId'; +import HotkeyDisplay from '@app/components/hotkeys/HotkeyDisplay'; +import { bindingEquals, eventToBinding, HotkeyBinding } from '@app/utils/hotkeys'; +import { ToolRegistryEntry } from "@app/data/toolsTaxonomy"; const rowStyle: React.CSSProperties = { display: 'flex', diff --git a/frontend/src/components/shared/config/configSections/Overview.tsx b/frontend/src/core/components/shared/config/configSections/Overview.tsx similarity index 67% rename from frontend/src/components/shared/config/configSections/Overview.tsx rename to frontend/src/core/components/shared/config/configSections/Overview.tsx index f7f46a27b3..52f0a9a543 100644 --- a/frontend/src/components/shared/config/configSections/Overview.tsx +++ b/frontend/src/core/components/shared/config/configSections/Overview.tsx @@ -1,13 +1,10 @@ import React from 'react'; -import { Stack, Text, Code, Group, Badge, Alert, Loader, Button } from '@mantine/core'; -import { useAppConfig } from '../../../../contexts/AppConfigContext'; -import { useAuth } from '../../../../auth/UseSession'; -import { useNavigate } from 'react-router-dom'; +import { Stack, Text, Code, Group, Badge, Alert, Loader } from '@mantine/core'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import { OverviewHeader } from '@app/components/shared/config/OverviewHeader'; const Overview: React.FC = () => { const { config, loading, error } = useAppConfig(); - const { signOut, user } = useAuth(); - const navigate = useNavigate(); const renderConfigSection = (title: string, data: any) => { if (!data || typeof data !== 'object') return null; @@ -58,15 +55,6 @@ const Overview: React.FC = () => { SSOAutoLogin: config.SSOAutoLogin, } : null; - const handleLogout = async () => { - try { - await signOut(); - navigate('/login'); - } catch (error) { - console.error('Logout error:', error); - } - }; - if (loading) { return ( @@ -86,26 +74,7 @@ const Overview: React.FC = () => { return ( -
-
-
- Application Configuration - - Current application settings and configuration details. - - {user?.email && ( - - Signed in as: {user.email} - - )} -
- {user && ( - - )} -
-
+ {config && ( <> diff --git a/frontend/src/components/shared/config/types.ts b/frontend/src/core/components/shared/config/types.ts similarity index 100% rename from frontend/src/components/shared/config/types.ts rename to frontend/src/core/components/shared/config/types.ts diff --git a/frontend/src/components/shared/filePreview/DocumentStack.tsx b/frontend/src/core/components/shared/filePreview/DocumentStack.tsx similarity index 100% rename from frontend/src/components/shared/filePreview/DocumentStack.tsx rename to frontend/src/core/components/shared/filePreview/DocumentStack.tsx diff --git a/frontend/src/components/shared/filePreview/DocumentThumbnail.tsx b/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx similarity index 96% rename from frontend/src/components/shared/filePreview/DocumentThumbnail.tsx rename to frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx index 71b95db271..ffa465fc9a 100644 --- a/frontend/src/components/shared/filePreview/DocumentThumbnail.tsx +++ b/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Box, Center, Image } from '@mantine/core'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; -import { StirlingFileStub } from '../../../types/fileContext'; +import { StirlingFileStub } from '@app/types/fileContext'; export interface DocumentThumbnailProps { file: File | StirlingFileStub | null; diff --git a/frontend/src/components/shared/filePreview/HoverOverlay.tsx b/frontend/src/core/components/shared/filePreview/HoverOverlay.tsx similarity index 100% rename from frontend/src/components/shared/filePreview/HoverOverlay.tsx rename to frontend/src/core/components/shared/filePreview/HoverOverlay.tsx diff --git a/frontend/src/components/shared/filePreview/NavigationArrows.tsx b/frontend/src/core/components/shared/filePreview/NavigationArrows.tsx similarity index 100% rename from frontend/src/components/shared/filePreview/NavigationArrows.tsx rename to frontend/src/core/components/shared/filePreview/NavigationArrows.tsx diff --git a/frontend/src/components/shared/fitText/FitText.README.md b/frontend/src/core/components/shared/fitText/FitText.README.md similarity index 100% rename from frontend/src/components/shared/fitText/FitText.README.md rename to frontend/src/core/components/shared/fitText/FitText.README.md diff --git a/frontend/src/components/shared/fitText/textFit.ts b/frontend/src/core/components/shared/fitText/textFit.ts similarity index 100% rename from frontend/src/components/shared/fitText/textFit.ts rename to frontend/src/core/components/shared/fitText/textFit.ts diff --git a/frontend/src/components/shared/quickAccessBar/ActiveToolButton.tsx b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx similarity index 95% rename from frontend/src/components/shared/quickAccessBar/ActiveToolButton.tsx rename to frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx index 9a08414b11..043cb09f91 100644 --- a/frontend/src/components/shared/quickAccessBar/ActiveToolButton.tsx +++ b/frontend/src/core/components/shared/quickAccessBar/ActiveToolButton.tsx @@ -15,11 +15,11 @@ import React, { useEffect, useRef, useState } from 'react'; import { ActionIcon } from '@mantine/core'; import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; -import { useToolWorkflow } from '../../../contexts/ToolWorkflowContext'; -import { useSidebarNavigation } from '../../../hooks/useSidebarNavigation'; -import { handleUnlessSpecialClick } from '../../../utils/clickHandlers'; -import FitText from '../FitText'; -import { Tooltip } from '../Tooltip'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useSidebarNavigation } from '@app/hooks/useSidebarNavigation'; +import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; +import FitText from '@app/components/shared/FitText'; +import { Tooltip } from '@app/components/shared/Tooltip'; interface ActiveToolButtonProps { activeButton: string; diff --git a/frontend/src/components/shared/quickAccessBar/QuickAccessBar.css b/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css similarity index 100% rename from frontend/src/components/shared/quickAccessBar/QuickAccessBar.css rename to frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.css diff --git a/frontend/src/components/shared/quickAccessBar/QuickAccessBar.ts b/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.ts similarity index 97% rename from frontend/src/components/shared/quickAccessBar/QuickAccessBar.ts rename to frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.ts index 03e0288347..84658daefb 100644 --- a/frontend/src/components/shared/quickAccessBar/QuickAccessBar.ts +++ b/frontend/src/core/components/shared/quickAccessBar/QuickAccessBar.ts @@ -1,4 +1,4 @@ -import { ButtonConfig } from '../../../types/sidebar'; +import { ButtonConfig } from '@app/types/sidebar'; // Border radius constants export const ROUND_BORDER_RADIUS = '0.5rem'; diff --git a/frontend/src/components/shared/rightRail/RightRail.README.md b/frontend/src/core/components/shared/rightRail/RightRail.README.md similarity index 100% rename from frontend/src/components/shared/rightRail/RightRail.README.md rename to frontend/src/core/components/shared/rightRail/RightRail.README.md diff --git a/frontend/src/components/shared/rightRail/RightRail.css b/frontend/src/core/components/shared/rightRail/RightRail.css similarity index 100% rename from frontend/src/components/shared/rightRail/RightRail.css rename to frontend/src/core/components/shared/rightRail/RightRail.css diff --git a/frontend/src/components/shared/rightRail/ViewerAnnotationControls.tsx b/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx similarity index 92% rename from frontend/src/components/shared/rightRail/ViewerAnnotationControls.tsx rename to frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx index 0ffa3102e8..ba49ffb704 100644 --- a/frontend/src/components/shared/rightRail/ViewerAnnotationControls.tsx +++ b/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx @@ -1,16 +1,16 @@ import React, { useState, useEffect } from 'react'; import { ActionIcon, Popover } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import LocalIcon from '../LocalIcon'; -import { Tooltip } from '../Tooltip'; -import { ViewerContext } from '../../../contexts/ViewerContext'; -import { useSignature } from '../../../contexts/SignatureContext'; -import { ColorSwatchButton, ColorPicker } from '../../annotation/shared/ColorPicker'; -import { useFileState, useFileContext } from '../../../contexts/FileContext'; -import { generateThumbnailWithMetadata } from '../../../utils/thumbnailUtils'; -import { createProcessedFile } from '../../../contexts/file/fileActions'; -import { createStirlingFile, createNewStirlingFileStub } from '../../../types/fileContext'; -import { useNavigationState } from '../../../contexts/NavigationContext'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { ViewerContext } from '@app/contexts/ViewerContext'; +import { useSignature } from '@app/contexts/SignatureContext'; +import { ColorSwatchButton, ColorPicker } from '@app/components/annotation/shared/ColorPicker'; +import { useFileState, useFileContext } from '@app/contexts/FileContext'; +import { generateThumbnailWithMetadata } from '@app/utils/thumbnailUtils'; +import { createProcessedFile } from '@app/contexts/file/fileActions'; +import { createStirlingFile, createNewStirlingFileStub } from '@app/types/fileContext'; +import { useNavigationState } from '@app/contexts/NavigationContext'; interface ViewerAnnotationControlsProps { currentView: string; diff --git a/frontend/src/components/shared/sliderWithInput/SliderWithInput.tsx b/frontend/src/core/components/shared/sliderWithInput/SliderWithInput.tsx similarity index 100% rename from frontend/src/components/shared/sliderWithInput/SliderWithInput.tsx rename to frontend/src/core/components/shared/sliderWithInput/SliderWithInput.tsx diff --git a/frontend/src/components/shared/textInput/TextInput.module.css b/frontend/src/core/components/shared/textInput/TextInput.module.css similarity index 100% rename from frontend/src/components/shared/textInput/TextInput.module.css rename to frontend/src/core/components/shared/textInput/TextInput.module.css diff --git a/frontend/src/components/shared/tooltip/Tooltip.README.md b/frontend/src/core/components/shared/tooltip/Tooltip.README.md similarity index 100% rename from frontend/src/components/shared/tooltip/Tooltip.README.md rename to frontend/src/core/components/shared/tooltip/Tooltip.README.md diff --git a/frontend/src/components/shared/tooltip/Tooltip.module.css b/frontend/src/core/components/shared/tooltip/Tooltip.module.css similarity index 100% rename from frontend/src/components/shared/tooltip/Tooltip.module.css rename to frontend/src/core/components/shared/tooltip/Tooltip.module.css diff --git a/frontend/src/components/shared/tooltip/TooltipContent.tsx b/frontend/src/core/components/shared/tooltip/TooltipContent.tsx similarity index 95% rename from frontend/src/components/shared/tooltip/TooltipContent.tsx rename to frontend/src/core/components/shared/tooltip/TooltipContent.tsx index 0e347cd1cc..8bd85966a3 100644 --- a/frontend/src/components/shared/tooltip/TooltipContent.tsx +++ b/frontend/src/core/components/shared/tooltip/TooltipContent.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import styles from './Tooltip.module.css'; -import { TooltipTip } from '../../../types/tips'; +import styles from '@app/components/shared/tooltip/Tooltip.module.css'; +import { TooltipTip } from '@app/types/tips'; interface TooltipContentProps { content?: React.ReactNode; diff --git a/frontend/src/components/toast/Toast.README.md b/frontend/src/core/components/toast/Toast.README.md similarity index 100% rename from frontend/src/components/toast/Toast.README.md rename to frontend/src/core/components/toast/Toast.README.md diff --git a/frontend/src/components/toast/ToastContext.tsx b/frontend/src/core/components/toast/ToastContext.tsx similarity index 98% rename from frontend/src/components/toast/ToastContext.tsx rename to frontend/src/core/components/toast/ToastContext.tsx index 1b0cc1539f..dd1d0f8361 100644 --- a/frontend/src/components/toast/ToastContext.tsx +++ b/frontend/src/core/components/toast/ToastContext.tsx @@ -1,5 +1,5 @@ import React, { createContext, useCallback, useContext, useMemo, useRef, useState, useEffect } from 'react'; -import { ToastApi, ToastInstance, ToastOptions } from './types'; +import { ToastApi, ToastInstance, ToastOptions } from '@app/components/toast/types'; function normalizeProgress(value: number | undefined): number | undefined { if (typeof value !== 'number' || Number.isNaN(value)) return undefined; diff --git a/frontend/src/components/toast/ToastRenderer.css b/frontend/src/core/components/toast/ToastRenderer.css similarity index 100% rename from frontend/src/components/toast/ToastRenderer.css rename to frontend/src/core/components/toast/ToastRenderer.css diff --git a/frontend/src/components/toast/ToastRenderer.tsx b/frontend/src/core/components/toast/ToastRenderer.tsx similarity index 94% rename from frontend/src/components/toast/ToastRenderer.tsx rename to frontend/src/core/components/toast/ToastRenderer.tsx index 38993bc301..825ad3591e 100644 --- a/frontend/src/components/toast/ToastRenderer.tsx +++ b/frontend/src/core/components/toast/ToastRenderer.tsx @@ -1,7 +1,7 @@ -import { useToast } from './ToastContext'; -import { ToastInstance, ToastLocation } from './types'; -import { LocalIcon } from '../shared/LocalIcon'; -import './ToastRenderer.css'; +import { useToast } from '@app/components/toast/ToastContext'; +import { ToastInstance, ToastLocation } from '@app/components/toast/types'; +import { LocalIcon } from '@app/components/shared/LocalIcon'; +import '@app/components/toast/ToastRenderer.css'; const locationToClass: Record = { 'top-left': 'toast-container--top-left', diff --git a/frontend/src/components/toast/index.ts b/frontend/src/core/components/toast/index.ts similarity index 87% rename from frontend/src/components/toast/index.ts rename to frontend/src/core/components/toast/index.ts index d0b1045f24..e13ab38018 100644 --- a/frontend/src/components/toast/index.ts +++ b/frontend/src/core/components/toast/index.ts @@ -1,6 +1,6 @@ -import { ToastOptions } from './types'; -import { useToast, ToastProvider } from './ToastContext'; -import ToastRenderer from './ToastRenderer'; +import { ToastOptions } from '@app/components/toast/types'; +import { useToast, ToastProvider } from '@app/components/toast/ToastContext'; +import ToastRenderer from '@app/components/toast/ToastRenderer'; export { useToast, ToastProvider, ToastRenderer }; diff --git a/frontend/src/components/toast/types.ts b/frontend/src/core/components/toast/types.ts similarity index 100% rename from frontend/src/components/toast/types.ts rename to frontend/src/core/components/toast/types.ts diff --git a/frontend/src/components/tools/FullscreenToolList.tsx b/frontend/src/core/components/tools/FullscreenToolList.tsx similarity index 93% rename from frontend/src/components/tools/FullscreenToolList.tsx rename to frontend/src/core/components/tools/FullscreenToolList.tsx index 686fdf1826..4c01b492ba 100644 --- a/frontend/src/components/tools/FullscreenToolList.tsx +++ b/frontend/src/core/components/tools/FullscreenToolList.tsx @@ -1,18 +1,18 @@ import { useMemo } from 'react'; import { Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ToolRegistryEntry, getSubcategoryLabel, getSubcategoryColor, getSubcategoryIcon } from '../../data/toolsTaxonomy'; -import { ToolId } from '../../types/toolId'; -import { useToolSections } from '../../hooks/useToolSections'; -import NoToolsFound from './shared/NoToolsFound'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; +import { ToolRegistryEntry, getSubcategoryLabel, getSubcategoryColor, getSubcategoryIcon } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import { useToolSections } from '@app/hooks/useToolSections'; +import NoToolsFound from '@app/components/tools/shared/NoToolsFound'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; import StarRoundedIcon from '@mui/icons-material/StarRounded'; import ThumbUpRoundedIcon from '@mui/icons-material/ThumbUpRounded'; -import Badge from '../shared/Badge'; -import './ToolPanel.css'; -import DetailedToolItem from './fullscreen/DetailedToolItem'; -import CompactToolItem from './fullscreen/CompactToolItem'; -import { useFavoriteToolItems } from '../../hooks/tools/useFavoriteToolItems'; +import Badge from '@app/components/shared/Badge'; +import '@app/components/tools/ToolPanel.css'; +import DetailedToolItem from '@app/components/tools/fullscreen/DetailedToolItem'; +import CompactToolItem from '@app/components/tools/fullscreen/CompactToolItem'; +import { useFavoriteToolItems } from '@app/hooks/tools/useFavoriteToolItems'; interface FullscreenToolListProps { filteredTools: Array<{ item: [ToolId, ToolRegistryEntry]; matchedText?: string }>; diff --git a/frontend/src/components/tools/FullscreenToolSurface.tsx b/frontend/src/core/components/tools/FullscreenToolSurface.tsx similarity index 88% rename from frontend/src/components/tools/FullscreenToolSurface.tsx rename to frontend/src/core/components/tools/FullscreenToolSurface.tsx index 05cf475719..169aab44c5 100644 --- a/frontend/src/components/tools/FullscreenToolSurface.tsx +++ b/frontend/src/core/components/tools/FullscreenToolSurface.tsx @@ -2,16 +2,16 @@ import { useState, useRef } from 'react'; import { ActionIcon, ScrollArea, Switch, useMantineColorScheme } from '@mantine/core'; import DoubleArrowIcon from '@mui/icons-material/DoubleArrow'; import { useTranslation } from 'react-i18next'; -import ToolSearch from './toolPicker/ToolSearch'; -import FullscreenToolList from './FullscreenToolList'; -import { ToolRegistryEntry } from '../../data/toolsTaxonomy'; -import { ToolId } from '../../types/toolId'; -import { useFocusTrap } from '../../hooks/useFocusTrap'; -import { BASE_PATH } from '../../constants/app'; -import { Tooltip } from '../shared/Tooltip'; -import './ToolPanel.css'; -import { ToolPanelGeometry } from '../../hooks/tools/useToolPanelGeometry'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; +import ToolSearch from '@app/components/tools/toolPicker/ToolSearch'; +import FullscreenToolList from '@app/components/tools/FullscreenToolList'; +import { ToolRegistryEntry } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import { useFocusTrap } from '@app/hooks/useFocusTrap'; +import { BASE_PATH } from '@app/constants/app'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import '@app/components/tools/ToolPanel.css'; +import { ToolPanelGeometry } from '@app/hooks/tools/useToolPanelGeometry'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; interface FullscreenToolSurfaceProps { searchQuery: string; diff --git a/frontend/src/components/tools/SearchResults.tsx b/frontend/src/core/components/tools/SearchResults.tsx similarity index 82% rename from frontend/src/components/tools/SearchResults.tsx rename to frontend/src/core/components/tools/SearchResults.tsx index 5fef3d8584..17e8142eb8 100644 --- a/frontend/src/components/tools/SearchResults.tsx +++ b/frontend/src/core/components/tools/SearchResults.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { Box, Stack } from '@mantine/core'; -import { getSubcategoryLabel, ToolRegistryEntry } from '../../data/toolsTaxonomy'; -import { ToolId } from '../../types/toolId'; -import ToolButton from './toolPicker/ToolButton'; +import { getSubcategoryLabel, ToolRegistryEntry } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import ToolButton from '@app/components/tools/toolPicker/ToolButton'; import { useTranslation } from 'react-i18next'; -import { useToolSections } from '../../hooks/useToolSections'; -import SubcategoryHeader from './shared/SubcategoryHeader'; -import NoToolsFound from './shared/NoToolsFound'; -import "./toolPicker/ToolPicker.css"; +import { useToolSections } from '@app/hooks/useToolSections'; +import SubcategoryHeader from '@app/components/tools/shared/SubcategoryHeader'; +import NoToolsFound from '@app/components/tools/shared/NoToolsFound'; +import "@app/components/tools/toolPicker/ToolPicker.css"; interface SearchResultsProps { filteredTools: Array<{ item: [ToolId, ToolRegistryEntry]; matchedText?: string }>; diff --git a/frontend/src/components/tools/ToolLoadingFallback.tsx b/frontend/src/core/components/tools/ToolLoadingFallback.tsx similarity index 100% rename from frontend/src/components/tools/ToolLoadingFallback.tsx rename to frontend/src/core/components/tools/ToolLoadingFallback.tsx diff --git a/frontend/src/components/tools/ToolPanel.css b/frontend/src/core/components/tools/ToolPanel.css similarity index 100% rename from frontend/src/components/tools/ToolPanel.css rename to frontend/src/core/components/tools/ToolPanel.css diff --git a/frontend/src/components/tools/ToolPanel.tsx b/frontend/src/core/components/tools/ToolPanel.tsx similarity index 87% rename from frontend/src/components/tools/ToolPanel.tsx rename to frontend/src/core/components/tools/ToolPanel.tsx index 27364c1ba0..4b6ea3eb40 100644 --- a/frontend/src/components/tools/ToolPanel.tsx +++ b/frontend/src/core/components/tools/ToolPanel.tsx @@ -1,23 +1,23 @@ import { useEffect, useMemo } from 'react'; -import { useRainbowThemeContext } from '../shared/RainbowThemeProvider'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { usePreferences } from '../../contexts/PreferencesContext'; -import ToolPicker from './ToolPicker'; -import SearchResults from './SearchResults'; -import ToolRenderer from './ToolRenderer'; -import ToolSearch from './toolPicker/ToolSearch'; -import { useSidebarContext } from "../../contexts/SidebarContext"; -import rainbowStyles from '../../styles/rainbow.module.css'; +import { useRainbowThemeContext } from '@app/components/shared/RainbowThemeProvider'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import ToolPicker from '@app/components/tools/ToolPicker'; +import SearchResults from '@app/components/tools/SearchResults'; +import ToolRenderer from '@app/components/tools/ToolRenderer'; +import ToolSearch from '@app/components/tools/toolPicker/ToolSearch'; +import { useSidebarContext } from "@app/contexts/SidebarContext"; +import rainbowStyles from '@app/styles/rainbow.module.css'; import { ActionIcon, ScrollArea } from '@mantine/core'; -import { ToolId } from '../../types/toolId'; +import { ToolId } from '@app/types/toolId'; import { useMediaQuery } from '@mantine/hooks'; import DoubleArrowIcon from '@mui/icons-material/DoubleArrow'; import { useTranslation } from 'react-i18next'; -import FullscreenToolSurface from './FullscreenToolSurface'; -import { useToolPanelGeometry } from '../../hooks/tools/useToolPanelGeometry'; -import { useRightRail } from '../../contexts/RightRailContext'; -import { Tooltip } from '../shared/Tooltip'; -import './ToolPanel.css'; +import FullscreenToolSurface from '@app/components/tools/FullscreenToolSurface'; +import { useToolPanelGeometry } from '@app/hooks/tools/useToolPanelGeometry'; +import { useRightRail } from '@app/contexts/RightRailContext'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import '@app/components/tools/ToolPanel.css'; // No props needed - component uses context diff --git a/frontend/src/components/tools/ToolPanelModePrompt.css b/frontend/src/core/components/tools/ToolPanelModePrompt.css similarity index 100% rename from frontend/src/components/tools/ToolPanelModePrompt.css rename to frontend/src/core/components/tools/ToolPanelModePrompt.css diff --git a/frontend/src/components/tools/ToolPanelModePrompt.tsx b/frontend/src/core/components/tools/ToolPanelModePrompt.tsx similarity index 96% rename from frontend/src/components/tools/ToolPanelModePrompt.tsx rename to frontend/src/core/components/tools/ToolPanelModePrompt.tsx index 770cf2eee0..af0eb11bd4 100644 --- a/frontend/src/components/tools/ToolPanelModePrompt.tsx +++ b/frontend/src/core/components/tools/ToolPanelModePrompt.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react'; import { Badge, Button, Card, Group, Modal, Stack, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; -import { usePreferences } from '../../contexts/PreferencesContext'; -import './ToolPanelModePrompt.css'; -import type { ToolPanelMode } from '../../constants/toolPanel'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import '@app/components/tools/ToolPanelModePrompt.css'; +import type { ToolPanelMode } from '@app/constants/toolPanel'; const ToolPanelModePrompt = () => { const { t } = useTranslation(); diff --git a/frontend/src/components/tools/ToolPicker.tsx b/frontend/src/core/components/tools/ToolPicker.tsx similarity index 91% rename from frontend/src/components/tools/ToolPicker.tsx rename to frontend/src/core/components/tools/ToolPicker.tsx index f158f036e0..396f97ed62 100644 --- a/frontend/src/components/tools/ToolPicker.tsx +++ b/frontend/src/core/components/tools/ToolPicker.tsx @@ -1,18 +1,18 @@ import React, { useMemo, useRef, useLayoutEffect, useState } from "react"; import { Box, Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ToolRegistryEntry } from "../../data/toolsTaxonomy"; -import "./toolPicker/ToolPicker.css"; -import { useToolSections } from "../../hooks/useToolSections"; -import type { SubcategoryGroup } from "../../hooks/useToolSections"; -import { useFavoriteToolItems } from "../../hooks/tools/useFavoriteToolItems"; -import NoToolsFound from "./shared/NoToolsFound"; -import { renderToolButtons } from "./shared/renderToolButtons"; -import Badge from "../shared/Badge"; -import SubcategoryHeader from "./shared/SubcategoryHeader"; -import ToolButton from "./toolPicker/ToolButton"; -import { useToolWorkflow } from "../../contexts/ToolWorkflowContext"; -import { ToolId } from "../../types/toolId"; +import { ToolRegistryEntry } from "@app/data/toolsTaxonomy"; +import "@app/components/tools/toolPicker/ToolPicker.css"; +import { useToolSections } from "@app/hooks/useToolSections"; +import type { SubcategoryGroup } from "@app/hooks/useToolSections"; +import { useFavoriteToolItems } from "@app/hooks/tools/useFavoriteToolItems"; +import NoToolsFound from "@app/components/tools/shared/NoToolsFound"; +import { renderToolButtons } from "@app/components/tools/shared/renderToolButtons"; +import Badge from "@app/components/shared/Badge"; +import SubcategoryHeader from "@app/components/tools/shared/SubcategoryHeader"; +import ToolButton from "@app/components/tools/toolPicker/ToolButton"; +import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext"; +import { ToolId } from "@app/types/toolId"; interface ToolPickerProps { selectedToolKey: string | null; diff --git a/frontend/src/components/tools/ToolRenderer.tsx b/frontend/src/core/components/tools/ToolRenderer.tsx similarity index 82% rename from frontend/src/components/tools/ToolRenderer.tsx rename to frontend/src/core/components/tools/ToolRenderer.tsx index 89d1b025ca..bfa2eb91a0 100644 --- a/frontend/src/components/tools/ToolRenderer.tsx +++ b/frontend/src/core/components/tools/ToolRenderer.tsx @@ -1,8 +1,8 @@ import { Suspense } from "react"; -import { useToolWorkflow } from "../../contexts/ToolWorkflowContext"; -import { BaseToolProps } from "../../types/tool"; -import { ToolId } from "../../types/toolId"; -import ToolLoadingFallback from "./ToolLoadingFallback"; +import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext"; +import { BaseToolProps } from "@app/types/tool"; +import { ToolId } from "@app/types/toolId"; +import ToolLoadingFallback from "@app/components/tools/ToolLoadingFallback"; interface ToolRendererProps extends BaseToolProps { selectedToolKey: ToolId; diff --git a/frontend/src/components/tools/addAttachments/AddAttachmentsSettings.tsx b/frontend/src/core/components/tools/addAttachments/AddAttachmentsSettings.tsx similarity index 96% rename from frontend/src/components/tools/addAttachments/AddAttachmentsSettings.tsx rename to frontend/src/core/components/tools/addAttachments/AddAttachmentsSettings.tsx index 632ed71f14..80078d0d74 100644 --- a/frontend/src/components/tools/addAttachments/AddAttachmentsSettings.tsx +++ b/frontend/src/core/components/tools/addAttachments/AddAttachmentsSettings.tsx @@ -6,8 +6,8 @@ import { Stack, Text, Group, ActionIcon, Alert, ScrollArea, Button } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddAttachmentsParameters } from "../../../hooks/tools/addAttachments/useAddAttachmentsParameters"; -import LocalIcon from "../../shared/LocalIcon"; +import { AddAttachmentsParameters } from "@app/hooks/tools/addAttachments/useAddAttachmentsParameters"; +import LocalIcon from "@app/components/shared/LocalIcon"; interface AddAttachmentsSettingsProps { parameters: AddAttachmentsParameters; diff --git a/frontend/src/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx similarity index 94% rename from frontend/src/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx rename to frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx index 0b7ecb02eb..09b0218a87 100644 --- a/frontend/src/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings.tsx @@ -4,8 +4,8 @@ import { Stack, Select, TextInput, NumberInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddPageNumbersParameters } from "./useAddPageNumbersParameters"; -import { Tooltip } from "../../shared/Tooltip"; +import { AddPageNumbersParameters } from "@app/components/tools/addPageNumbers/useAddPageNumbersParameters"; +import { Tooltip } from "@app/components/shared/Tooltip"; interface AddPageNumbersAppearanceSettingsProps { parameters: AddPageNumbersParameters; diff --git a/frontend/src/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx similarity index 81% rename from frontend/src/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx rename to frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx index 86888d0e47..2cb4ff17cf 100644 --- a/frontend/src/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersAutomationSettings.tsx @@ -6,9 +6,9 @@ import { Stack, Divider, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddPageNumbersParameters } from "./useAddPageNumbersParameters"; -import AddPageNumbersPositionSettings from "./AddPageNumbersPositionSettings"; -import AddPageNumbersAppearanceSettings from "./AddPageNumbersAppearanceSettings"; +import { AddPageNumbersParameters } from "@app/components/tools/addPageNumbers/useAddPageNumbersParameters"; +import AddPageNumbersPositionSettings from "@app/components/tools/addPageNumbers/AddPageNumbersPositionSettings"; +import AddPageNumbersAppearanceSettings from "@app/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings"; interface AddPageNumbersAutomationSettingsProps { parameters: AddPageNumbersParameters; diff --git a/frontend/src/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx similarity index 89% rename from frontend/src/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx rename to frontend/src/core/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx index 2907ff4988..c64f1cac12 100644 --- a/frontend/src/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/AddPageNumbersPositionSettings.tsx @@ -4,9 +4,9 @@ import { Stack, TextInput, NumberInput, Divider, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddPageNumbersParameters } from "./useAddPageNumbersParameters"; -import { Tooltip } from "../../shared/Tooltip"; -import PageNumberPreview from "./PageNumberPreview"; +import { AddPageNumbersParameters } from "@app/components/tools/addPageNumbers/useAddPageNumbersParameters"; +import { Tooltip } from "@app/components/shared/Tooltip"; +import PageNumberPreview from "@app/components/tools/addPageNumbers/PageNumberPreview"; interface AddPageNumbersPositionSettingsProps { parameters: AddPageNumbersParameters; diff --git a/frontend/src/components/tools/addPageNumbers/PageNumberPreview.module.css b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.module.css similarity index 100% rename from frontend/src/components/tools/addPageNumbers/PageNumberPreview.module.css rename to frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.module.css diff --git a/frontend/src/components/tools/addPageNumbers/PageNumberPreview.tsx b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx similarity index 96% rename from frontend/src/components/tools/addPageNumbers/PageNumberPreview.tsx rename to frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx index b22e55efee..830703f217 100644 --- a/frontend/src/components/tools/addPageNumbers/PageNumberPreview.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx @@ -1,9 +1,9 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { AddPageNumbersParameters } from './useAddPageNumbersParameters'; -import { pdfWorkerManager } from '../../../services/pdfWorkerManager'; -import { useThumbnailGeneration } from '../../../hooks/useThumbnailGeneration'; -import styles from './PageNumberPreview.module.css'; +import { AddPageNumbersParameters } from '@app/components/tools/addPageNumbers/useAddPageNumbersParameters'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; +import styles from '@app/components/tools/addPageNumbers/PageNumberPreview.module.css'; // Simple utilities for page numbers (adapted from stamp) const A4_ASPECT_RATIO = 0.707; diff --git a/frontend/src/components/tools/addPageNumbers/useAddPageNumbersOperation.ts b/frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersOperation.ts similarity index 81% rename from frontend/src/components/tools/addPageNumbers/useAddPageNumbersOperation.ts rename to frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersOperation.ts index 775ee90092..160aaa39a5 100644 --- a/frontend/src/components/tools/addPageNumbers/useAddPageNumbersOperation.ts +++ b/frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../../../hooks/tools/shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AddPageNumbersParameters, defaultParameters } from './useAddPageNumbersParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AddPageNumbersParameters, defaultParameters } from '@app/components/tools/addPageNumbers/useAddPageNumbersParameters'; export const buildAddPageNumbersFormData = (parameters: AddPageNumbersParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/components/tools/addPageNumbers/useAddPageNumbersParameters.ts b/frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersParameters.ts similarity index 85% rename from frontend/src/components/tools/addPageNumbers/useAddPageNumbersParameters.ts rename to frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersParameters.ts index ca5c1e2e1c..a8b910697e 100644 --- a/frontend/src/components/tools/addPageNumbers/useAddPageNumbersParameters.ts +++ b/frontend/src/core/components/tools/addPageNumbers/useAddPageNumbersParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, type BaseParametersHook } from '../../../hooks/tools/shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, type BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AddPageNumbersParameters extends BaseParameters { customMargin: 'small' | 'medium' | 'large' | 'x-large'; diff --git a/frontend/src/components/tools/addPassword/AddPasswordSettings.test.tsx b/frontend/src/core/components/tools/addPassword/AddPasswordSettings.test.tsx similarity index 96% rename from frontend/src/components/tools/addPassword/AddPasswordSettings.test.tsx rename to frontend/src/core/components/tools/addPassword/AddPasswordSettings.test.tsx index b483eca748..4dea56e1ea 100644 --- a/frontend/src/components/tools/addPassword/AddPasswordSettings.test.tsx +++ b/frontend/src/core/components/tools/addPassword/AddPasswordSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import AddPasswordSettings from './AddPasswordSettings'; -import { defaultParameters } from '../../../hooks/tools/addPassword/useAddPasswordParameters'; +import AddPasswordSettings from '@app/components/tools/addPassword/AddPasswordSettings'; +import { defaultParameters } from '@app/hooks/tools/addPassword/useAddPasswordParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/addPassword/AddPasswordSettings.tsx b/frontend/src/core/components/tools/addPassword/AddPasswordSettings.tsx similarity index 95% rename from frontend/src/components/tools/addPassword/AddPasswordSettings.tsx rename to frontend/src/core/components/tools/addPassword/AddPasswordSettings.tsx index beb8c432cf..e0aa7dfc7f 100644 --- a/frontend/src/components/tools/addPassword/AddPasswordSettings.tsx +++ b/frontend/src/core/components/tools/addPassword/AddPasswordSettings.tsx @@ -1,6 +1,6 @@ import { Stack, PasswordInput, Select } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddPasswordParameters } from "../../../hooks/tools/addPassword/useAddPasswordParameters"; +import { AddPasswordParameters } from "@app/hooks/tools/addPassword/useAddPasswordParameters"; interface AddPasswordSettingsProps { parameters: AddPasswordParameters; diff --git a/frontend/src/components/tools/addStamp/AddStampAutomationSettings.tsx b/frontend/src/core/components/tools/addStamp/AddStampAutomationSettings.tsx similarity index 80% rename from frontend/src/components/tools/addStamp/AddStampAutomationSettings.tsx rename to frontend/src/core/components/tools/addStamp/AddStampAutomationSettings.tsx index 25091d854e..c9a9dbd968 100644 --- a/frontend/src/components/tools/addStamp/AddStampAutomationSettings.tsx +++ b/frontend/src/core/components/tools/addStamp/AddStampAutomationSettings.tsx @@ -7,9 +7,9 @@ */ import { Stack } from "@mantine/core"; -import { AddStampParameters } from "./useAddStampParameters"; -import StampSetupSettings from "./StampSetupSettings"; -import StampPositionFormattingSettings from "./StampPositionFormattingSettings"; +import { AddStampParameters } from "@app/components/tools/addStamp/useAddStampParameters"; +import StampSetupSettings from "@app/components/tools/addStamp/StampSetupSettings"; +import StampPositionFormattingSettings from "@app/components/tools/addStamp/StampPositionFormattingSettings"; interface AddStampAutomationSettingsProps { parameters: AddStampParameters; diff --git a/frontend/src/components/tools/addStamp/StampPositionFormattingSettings.tsx b/frontend/src/core/components/tools/addStamp/StampPositionFormattingSettings.tsx similarity index 96% rename from frontend/src/components/tools/addStamp/StampPositionFormattingSettings.tsx rename to frontend/src/core/components/tools/addStamp/StampPositionFormattingSettings.tsx index d1c0d0c9f2..058b38bc40 100644 --- a/frontend/src/components/tools/addStamp/StampPositionFormattingSettings.tsx +++ b/frontend/src/core/components/tools/addStamp/StampPositionFormattingSettings.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; import { Group, Select, Stack, ColorInput, Button, Slider, Text, NumberInput } from "@mantine/core"; -import { AddStampParameters } from "./useAddStampParameters"; -import LocalIcon from "../../shared/LocalIcon"; -import styles from "./StampPreview.module.css"; -import { Tooltip } from "../../shared/Tooltip"; +import { AddStampParameters } from "@app/components/tools/addStamp/useAddStampParameters"; +import LocalIcon from "@app/components/shared/LocalIcon"; +import styles from "@app/components/tools/addStamp/StampPreview.module.css"; +import { Tooltip } from "@app/components/shared/Tooltip"; interface StampPositionFormattingSettingsProps { parameters: AddStampParameters; diff --git a/frontend/src/components/tools/addStamp/StampPreview.module.css b/frontend/src/core/components/tools/addStamp/StampPreview.module.css similarity index 100% rename from frontend/src/components/tools/addStamp/StampPreview.module.css rename to frontend/src/core/components/tools/addStamp/StampPreview.module.css diff --git a/frontend/src/components/tools/addStamp/StampPreview.tsx b/frontend/src/core/components/tools/addStamp/StampPreview.tsx similarity index 96% rename from frontend/src/components/tools/addStamp/StampPreview.tsx rename to frontend/src/core/components/tools/addStamp/StampPreview.tsx index b6299f4749..2c2d52f901 100644 --- a/frontend/src/components/tools/addStamp/StampPreview.tsx +++ b/frontend/src/core/components/tools/addStamp/StampPreview.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { AddStampParameters } from './useAddStampParameters'; -import { pdfWorkerManager } from '../../../services/pdfWorkerManager'; -import { useThumbnailGeneration } from '../../../hooks/useThumbnailGeneration'; -import { A4_ASPECT_RATIO, getFirstSelectedPage, getFontFamily, computeStampPreviewStyle, getAlphabetPreviewScale } from './StampPreviewUtils'; -import styles from './StampPreview.module.css'; +import { AddStampParameters } from '@app/components/tools/addStamp/useAddStampParameters'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; +import { A4_ASPECT_RATIO, getFirstSelectedPage, getFontFamily, computeStampPreviewStyle, getAlphabetPreviewScale } from '@app/components/tools/addStamp/StampPreviewUtils'; +import styles from '@app/components/tools/addStamp/StampPreview.module.css'; type Props = { parameters: AddStampParameters; diff --git a/frontend/src/components/tools/addStamp/StampPreviewUtils.ts b/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts similarity index 98% rename from frontend/src/components/tools/addStamp/StampPreviewUtils.ts rename to frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts index 0001aec456..173d18a6a9 100644 --- a/frontend/src/components/tools/addStamp/StampPreviewUtils.ts +++ b/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts @@ -1,4 +1,4 @@ -import type { AddStampParameters } from './useAddStampParameters'; +import type { AddStampParameters } from '@app/components/tools/addStamp/useAddStampParameters'; export type ContainerSize = { width: number; height: number }; export type PageSizePts = { widthPts: number; heightPts: number } | null; diff --git a/frontend/src/components/tools/addStamp/StampSetupSettings.tsx b/frontend/src/core/components/tools/addStamp/StampSetupSettings.tsx similarity index 91% rename from frontend/src/components/tools/addStamp/StampSetupSettings.tsx rename to frontend/src/core/components/tools/addStamp/StampSetupSettings.tsx index 8d13073a52..ac53a9a5ab 100644 --- a/frontend/src/components/tools/addStamp/StampSetupSettings.tsx +++ b/frontend/src/core/components/tools/addStamp/StampSetupSettings.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; import { Stack, Textarea, TextInput, Select, Button, Text, Divider } from "@mantine/core"; -import { AddStampParameters } from "./useAddStampParameters"; -import ButtonSelector from "../../shared/ButtonSelector"; -import styles from "./StampPreview.module.css"; -import { getDefaultFontSizeForAlphabet } from "./StampPreviewUtils"; +import { AddStampParameters } from "@app/components/tools/addStamp/useAddStampParameters"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; +import styles from "@app/components/tools/addStamp/StampPreview.module.css"; +import { getDefaultFontSizeForAlphabet } from "@app/components/tools/addStamp/StampPreviewUtils"; interface StampSetupSettingsProps { parameters: AddStampParameters; diff --git a/frontend/src/components/tools/addStamp/useAddStampOperation.ts b/frontend/src/core/components/tools/addStamp/useAddStampOperation.ts similarity index 87% rename from frontend/src/components/tools/addStamp/useAddStampOperation.ts rename to frontend/src/core/components/tools/addStamp/useAddStampOperation.ts index c41c440fcf..12b9c0a1a1 100644 --- a/frontend/src/components/tools/addStamp/useAddStampOperation.ts +++ b/frontend/src/core/components/tools/addStamp/useAddStampOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../../../hooks/tools/shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AddStampParameters, defaultParameters } from './useAddStampParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AddStampParameters, defaultParameters } from '@app/components/tools/addStamp/useAddStampParameters'; export const buildAddStampFormData = (parameters: AddStampParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/components/tools/addStamp/useAddStampParameters.ts b/frontend/src/core/components/tools/addStamp/useAddStampParameters.ts similarity index 88% rename from frontend/src/components/tools/addStamp/useAddStampParameters.ts rename to frontend/src/core/components/tools/addStamp/useAddStampParameters.ts index 3df4900f8f..3f6ee99e9e 100644 --- a/frontend/src/components/tools/addStamp/useAddStampParameters.ts +++ b/frontend/src/core/components/tools/addStamp/useAddStampParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, type BaseParametersHook } from '../../../hooks/tools/shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, type BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AddStampParameters extends BaseParameters { stampType?: 'text' | 'image'; diff --git a/frontend/src/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx b/frontend/src/core/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx similarity index 78% rename from frontend/src/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx rename to frontend/src/core/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx index 90e75e98aa..347c4f1857 100644 --- a/frontend/src/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx +++ b/frontend/src/core/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx @@ -7,12 +7,12 @@ */ import { Stack } from "@mantine/core"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; -import WatermarkTypeSettings from "./WatermarkTypeSettings"; -import WatermarkWording from "./WatermarkWording"; -import WatermarkTextStyle from "./WatermarkTextStyle"; -import WatermarkImageFile from "./WatermarkImageFile"; -import WatermarkFormatting from "./WatermarkFormatting"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import WatermarkTypeSettings from "@app/components/tools/addWatermark/WatermarkTypeSettings"; +import WatermarkWording from "@app/components/tools/addWatermark/WatermarkWording"; +import WatermarkTextStyle from "@app/components/tools/addWatermark/WatermarkTextStyle"; +import WatermarkImageFile from "@app/components/tools/addWatermark/WatermarkImageFile"; +import WatermarkFormatting from "@app/components/tools/addWatermark/WatermarkFormatting"; interface AddWatermarkSingleStepSettingsProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/addWatermark/WatermarkFormatting.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkFormatting.tsx similarity index 93% rename from frontend/src/components/tools/addWatermark/WatermarkFormatting.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkFormatting.tsx index 4ebe62356f..1e9b224e84 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkFormatting.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkFormatting.tsx @@ -1,7 +1,7 @@ import { Stack, Checkbox, Group } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; -import NumberInputWithUnit from "../shared/NumberInputWithUnit"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import NumberInputWithUnit from "@app/components/tools/shared/NumberInputWithUnit"; interface WatermarkFormattingProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/addWatermark/WatermarkImageFile.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkImageFile.tsx similarity index 82% rename from frontend/src/components/tools/addWatermark/WatermarkImageFile.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkImageFile.tsx index e64b03646b..39f614845a 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkImageFile.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkImageFile.tsx @@ -1,7 +1,7 @@ import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; -import FileUploadButton from "../../shared/FileUploadButton"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import FileUploadButton from "@app/components/shared/FileUploadButton"; interface WatermarkImageFileProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/addWatermark/WatermarkStyleSettings.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkStyleSettings.tsx similarity index 95% rename from frontend/src/components/tools/addWatermark/WatermarkStyleSettings.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkStyleSettings.tsx index f92ca48e5c..89a74076d0 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkStyleSettings.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkStyleSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, NumberInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; interface WatermarkStyleSettingsProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/addWatermark/WatermarkTextStyle.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkTextStyle.tsx similarity index 87% rename from frontend/src/components/tools/addWatermark/WatermarkTextStyle.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkTextStyle.tsx index a445084b05..b4a1dcd3dc 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkTextStyle.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkTextStyle.tsx @@ -1,7 +1,7 @@ import { Stack, Text, Select, ColorInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; -import { alphabetOptions } from "../../../constants/addWatermarkConstants"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import { alphabetOptions } from "@app/constants/addWatermarkConstants"; interface WatermarkTextStyleProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/addWatermark/WatermarkTypeSettings.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkTypeSettings.tsx similarity index 92% rename from frontend/src/components/tools/addWatermark/WatermarkTypeSettings.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkTypeSettings.tsx index 2c7548df8c..19bb42d836 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkTypeSettings.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkTypeSettings.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import ButtonSelector from "../../shared/ButtonSelector"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; interface WatermarkTypeSettingsProps { watermarkType?: 'text' | 'image'; diff --git a/frontend/src/components/tools/addWatermark/WatermarkWording.tsx b/frontend/src/core/components/tools/addWatermark/WatermarkWording.tsx similarity index 86% rename from frontend/src/components/tools/addWatermark/WatermarkWording.tsx rename to frontend/src/core/components/tools/addWatermark/WatermarkWording.tsx index cee909fcad..eb3655c860 100644 --- a/frontend/src/components/tools/addWatermark/WatermarkWording.tsx +++ b/frontend/src/core/components/tools/addWatermark/WatermarkWording.tsx @@ -1,8 +1,8 @@ import React from "react"; import { Stack, TextInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters"; -import { removeEmojis } from "../../../utils/textUtils"; +import { AddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import { removeEmojis } from "@app/utils/textUtils"; interface WatermarkWordingProps { parameters: AddWatermarkParameters; diff --git a/frontend/src/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx b/frontend/src/core/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx similarity index 84% rename from frontend/src/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx index 196b6a91ca..061eac659c 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx @@ -1,7 +1,7 @@ import { Stack } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import SliderWithInput from '../../shared/sliderWithInput/SliderWithInput'; +import { AdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; +import SliderWithInput from '@app/components/shared/sliderWithInput/SliderWithInput'; interface Props { parameters: AdjustContrastParameters; diff --git a/frontend/src/components/tools/adjustContrast/AdjustContrastColorSettings.tsx b/frontend/src/core/components/tools/adjustContrast/AdjustContrastColorSettings.tsx similarity index 83% rename from frontend/src/components/tools/adjustContrast/AdjustContrastColorSettings.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastColorSettings.tsx index bd7e455fb1..f713ca24bd 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastColorSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastColorSettings.tsx @@ -1,7 +1,7 @@ import { Stack } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import SliderWithInput from '../../shared/sliderWithInput/SliderWithInput'; +import { AdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; +import SliderWithInput from '@app/components/shared/sliderWithInput/SliderWithInput'; interface Props { parameters: AdjustContrastParameters; diff --git a/frontend/src/components/tools/adjustContrast/AdjustContrastPreview.tsx b/frontend/src/core/components/tools/adjustContrast/AdjustContrastPreview.tsx similarity index 90% rename from frontend/src/components/tools/adjustContrast/AdjustContrastPreview.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastPreview.tsx index 79b71fffb3..3fb42b46c6 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastPreview.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastPreview.tsx @@ -1,10 +1,10 @@ import { useEffect, useRef, useState } from 'react'; -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import { useThumbnailGeneration } from '../../../hooks/useThumbnailGeneration'; -import ObscuredOverlay from '../../shared/ObscuredOverlay'; +import { AdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; +import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; +import ObscuredOverlay from '@app/components/shared/ObscuredOverlay'; import { Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { applyAdjustmentsToCanvas } from './utils'; +import { applyAdjustmentsToCanvas } from '@app/components/tools/adjustContrast/utils'; interface Props { file: File | null; diff --git a/frontend/src/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx b/frontend/src/core/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx similarity index 71% rename from frontend/src/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx index ebd2c4d06a..5fc9fe10f1 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx @@ -1,7 +1,7 @@ import { Stack } from '@mantine/core'; -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import AdjustContrastBasicSettings from './AdjustContrastBasicSettings'; -import AdjustContrastColorSettings from './AdjustContrastColorSettings'; +import { AdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; +import AdjustContrastBasicSettings from '@app/components/tools/adjustContrast/AdjustContrastBasicSettings'; +import AdjustContrastColorSettings from '@app/components/tools/adjustContrast/AdjustContrastColorSettings'; interface Props { parameters: AdjustContrastParameters; diff --git a/frontend/src/components/tools/adjustContrast/utils.ts b/frontend/src/core/components/tools/adjustContrast/utils.ts similarity index 95% rename from frontend/src/components/tools/adjustContrast/utils.ts rename to frontend/src/core/components/tools/adjustContrast/utils.ts index 16dfc199fa..939c05acc8 100644 --- a/frontend/src/components/tools/adjustContrast/utils.ts +++ b/frontend/src/core/components/tools/adjustContrast/utils.ts @@ -1,4 +1,4 @@ -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; +import { AdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; export function applyAdjustmentsToCanvas(src: HTMLCanvasElement, params: AdjustContrastParameters): HTMLCanvasElement { const out = document.createElement('canvas'); diff --git a/frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx b/frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx similarity index 89% rename from frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx rename to frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx index d71655cdc4..c5e5fc9336 100644 --- a/frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx +++ b/frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import AdjustPageScaleSettings from './AdjustPageScaleSettings'; -import { AdjustPageScaleParameters, PageSize } from '../../../hooks/tools/adjustPageScale/useAdjustPageScaleParameters'; +import AdjustPageScaleSettings from '@app/components/tools/adjustPageScale/AdjustPageScaleSettings'; +import { AdjustPageScaleParameters, PageSize } from '@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string, fallback?: string) => fallback || `mock-${key}`); diff --git a/frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx b/frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx similarity index 94% rename from frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx rename to frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx index 9262bcba4a..104be7faa6 100644 --- a/frontend/src/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx +++ b/frontend/src/core/components/tools/adjustPageScale/AdjustPageScaleSettings.tsx @@ -1,6 +1,6 @@ import { Stack, NumberInput, Select } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { AdjustPageScaleParameters, PageSize } from "../../../hooks/tools/adjustPageScale/useAdjustPageScaleParameters"; +import { AdjustPageScaleParameters, PageSize } from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters"; interface AdjustPageScaleSettingsProps { parameters: AdjustPageScaleParameters; diff --git a/frontend/src/components/tools/autoRename/AutoRenameSettings.tsx b/frontend/src/core/components/tools/autoRename/AutoRenameSettings.tsx similarity index 88% rename from frontend/src/components/tools/autoRename/AutoRenameSettings.tsx rename to frontend/src/core/components/tools/autoRename/AutoRenameSettings.tsx index 9c3ec4de67..f0e268d4ca 100644 --- a/frontend/src/components/tools/autoRename/AutoRenameSettings.tsx +++ b/frontend/src/core/components/tools/autoRename/AutoRenameSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { AutoRenameParameters } from '../../../hooks/tools/autoRename/useAutoRenameParameters'; +import { AutoRenameParameters } from '@app/hooks/tools/autoRename/useAutoRenameParameters'; interface AutoRenameSettingsProps { parameters: AutoRenameParameters; diff --git a/frontend/src/components/tools/automate/AutomationCreation.tsx b/frontend/src/core/components/tools/automate/AutomationCreation.tsx similarity index 93% rename from frontend/src/components/tools/automate/AutomationCreation.tsx rename to frontend/src/core/components/tools/automate/AutomationCreation.tsx index a05ab509d7..836c14fed7 100644 --- a/frontend/src/components/tools/automate/AutomationCreation.tsx +++ b/frontend/src/core/components/tools/automate/AutomationCreation.tsx @@ -10,14 +10,14 @@ import { Divider, Modal } from '@mantine/core'; -import { Z_INDEX_AUTOMATE_MODAL } from '../../../styles/zIndex'; +import { Z_INDEX_AUTOMATE_MODAL } from '@app/styles/zIndex'; import CheckIcon from '@mui/icons-material/Check'; -import { ToolRegistry } from '../../../data/toolsTaxonomy'; -import ToolConfigurationModal from './ToolConfigurationModal'; -import ToolList from './ToolList'; -import IconSelector from './IconSelector'; -import { AutomationConfig, AutomationMode, AutomationTool } from '../../../types/automation'; -import { useAutomationForm } from '../../../hooks/tools/automate/useAutomationForm'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import ToolConfigurationModal from '@app/components/tools/automate/ToolConfigurationModal'; +import ToolList from '@app/components/tools/automate/ToolList'; +import IconSelector from '@app/components/tools/automate/IconSelector'; +import { AutomationConfig, AutomationMode, AutomationTool } from '@app/types/automation'; +import { useAutomationForm } from '@app/hooks/tools/automate/useAutomationForm'; interface AutomationCreationProps { @@ -106,7 +106,7 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o }; try { - const { automationStorage } = await import('../../../services/automationStorage'); + const { automationStorage } = await import('@app/services/automationStorage'); let savedAutomation; if (mode === AutomationMode.EDIT && existingAutomation) { diff --git a/frontend/src/components/tools/automate/AutomationEntry.tsx b/frontend/src/core/components/tools/automate/AutomationEntry.tsx similarity index 97% rename from frontend/src/components/tools/automate/AutomationEntry.tsx rename to frontend/src/core/components/tools/automate/AutomationEntry.tsx index f29a63a189..7871033b9b 100644 --- a/frontend/src/components/tools/automate/AutomationEntry.tsx +++ b/frontend/src/core/components/tools/automate/AutomationEntry.tsx @@ -5,10 +5,10 @@ import MoreVertIcon from '@mui/icons-material/MoreVert'; import EditIcon from '@mui/icons-material/Edit'; import DeleteIcon from '@mui/icons-material/Delete'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; -import { Tooltip } from '../../shared/Tooltip'; -import { ToolIcon } from '../../shared/ToolIcon'; -import { ToolRegistry } from '../../../data/toolsTaxonomy'; -import { ToolId } from 'src/types/toolId'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { ToolIcon } from '@app/components/shared/ToolIcon'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import { ToolId } from "@app/types/toolId"; interface AutomationEntryProps { /** Optional title for the automation (usually for custom ones) */ diff --git a/frontend/src/components/tools/automate/AutomationRun.tsx b/frontend/src/core/components/tools/automate/AutomationRun.tsx similarity index 95% rename from frontend/src/components/tools/automate/AutomationRun.tsx rename to frontend/src/core/components/tools/automate/AutomationRun.tsx index 67d55d1b15..41c56558f8 100644 --- a/frontend/src/components/tools/automate/AutomationRun.tsx +++ b/frontend/src/core/components/tools/automate/AutomationRun.tsx @@ -3,11 +3,11 @@ import { useTranslation } from "react-i18next"; import { Button, Text, Stack, Group, Card, Progress } from "@mantine/core"; import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import CheckIcon from "@mui/icons-material/Check"; -import { useFileSelection } from "../../../contexts/FileContext"; -import { useToolRegistry } from "../../../contexts/ToolRegistryContext"; -import { AutomationConfig, ExecutionStep } from "../../../types/automation"; -import { AUTOMATION_CONSTANTS, EXECUTION_STATUS } from "../../../constants/automation"; -import { useResourceCleanup } from "../../../utils/resourceManager"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { useToolRegistry } from "@app/contexts/ToolRegistryContext"; +import { AutomationConfig, ExecutionStep } from "@app/types/automation"; +import { AUTOMATION_CONSTANTS, EXECUTION_STATUS } from "@app/constants/automation"; +import { useResourceCleanup } from "@app/utils/resourceManager"; interface AutomationRunProps { automation: AutomationConfig; diff --git a/frontend/src/components/tools/automate/AutomationSelection.tsx b/frontend/src/core/components/tools/automate/AutomationSelection.tsx similarity index 88% rename from frontend/src/components/tools/automate/AutomationSelection.tsx rename to frontend/src/core/components/tools/automate/AutomationSelection.tsx index 9c3a637dc5..1b53ff900d 100644 --- a/frontend/src/components/tools/automate/AutomationSelection.tsx +++ b/frontend/src/core/components/tools/automate/AutomationSelection.tsx @@ -2,11 +2,11 @@ import { useTranslation } from "react-i18next"; import { Title, Stack, Divider } from "@mantine/core"; import AddCircleOutline from "@mui/icons-material/AddCircleOutline"; import SettingsIcon from "@mui/icons-material/Settings"; -import AutomationEntry from "./AutomationEntry"; -import { useSuggestedAutomations } from "../../../hooks/tools/automate/useSuggestedAutomations"; -import { AutomationConfig, SuggestedAutomation } from "../../../types/automation"; -import { iconMap } from './iconMap'; -import { ToolRegistry } from '../../../data/toolsTaxonomy'; +import AutomationEntry from "@app/components/tools/automate/AutomationEntry"; +import { useSuggestedAutomations } from "@app/hooks/tools/automate/useSuggestedAutomations"; +import { AutomationConfig, SuggestedAutomation } from "@app/types/automation"; +import { iconMap } from '@app/components/tools/automate/iconMap'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; interface AutomationSelectionProps { savedAutomations: AutomationConfig[]; diff --git a/frontend/src/components/tools/automate/IconSelector.tsx b/frontend/src/core/components/tools/automate/IconSelector.tsx similarity index 98% rename from frontend/src/components/tools/automate/IconSelector.tsx rename to frontend/src/core/components/tools/automate/IconSelector.tsx index 9294d5635b..3b7733cf0d 100644 --- a/frontend/src/components/tools/automate/IconSelector.tsx +++ b/frontend/src/core/components/tools/automate/IconSelector.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Box, Text, Stack, Button, SimpleGrid, Tooltip, Popover } from "@mantine/core"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; -import { iconMap, iconOptions } from './iconMap'; +import { iconMap, iconOptions } from '@app/components/tools/automate/iconMap'; interface IconSelectorProps { value?: string; diff --git a/frontend/src/components/tools/automate/ToolConfigurationModal.tsx b/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx similarity index 93% rename from frontend/src/components/tools/automate/ToolConfigurationModal.tsx rename to frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx index 2185d0be7d..a4b415856d 100644 --- a/frontend/src/components/tools/automate/ToolConfigurationModal.tsx +++ b/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx @@ -9,14 +9,14 @@ import { Text, Alert } from '@mantine/core'; -import { Z_INDEX_AUTOMATE_MODAL } from '../../../styles/zIndex'; +import { Z_INDEX_AUTOMATE_MODAL } from '@app/styles/zIndex'; import SettingsIcon from '@mui/icons-material/Settings'; import CheckIcon from '@mui/icons-material/Check'; import CloseIcon from '@mui/icons-material/Close'; import WarningIcon from '@mui/icons-material/Warning'; -import { ToolRegistry } from '../../../data/toolsTaxonomy'; -import { ToolId } from '../../../types/toolId'; -import { getAvailableToExtensions } from '../../../utils/convertUtils'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import { getAvailableToExtensions } from '@app/utils/convertUtils'; interface ToolConfigurationModalProps { opened: boolean; tool: { diff --git a/frontend/src/components/tools/automate/ToolList.tsx b/frontend/src/core/components/tools/automate/ToolList.tsx similarity index 95% rename from frontend/src/components/tools/automate/ToolList.tsx rename to frontend/src/core/components/tools/automate/ToolList.tsx index a0215c1f27..7a5c668600 100644 --- a/frontend/src/components/tools/automate/ToolList.tsx +++ b/frontend/src/core/components/tools/automate/ToolList.tsx @@ -4,11 +4,11 @@ import { Text, Stack, Group, ActionIcon } from "@mantine/core"; import SettingsIcon from "@mui/icons-material/Settings"; import CloseIcon from "@mui/icons-material/Close"; import AddCircleOutline from "@mui/icons-material/AddCircleOutline"; -import { AutomationTool } from "../../../types/automation"; -import { ToolRegistry } from "../../../data/toolsTaxonomy"; -import { ToolId } from "../../../types/toolId"; -import ToolSelector from "./ToolSelector"; -import AutomationEntry from "./AutomationEntry"; +import { AutomationTool } from "@app/types/automation"; +import { ToolRegistry } from "@app/data/toolsTaxonomy"; +import { ToolId } from "@app/types/toolId"; +import ToolSelector from "@app/components/tools/automate/ToolSelector"; +import AutomationEntry from "@app/components/tools/automate/AutomationEntry"; interface ToolListProps { tools: AutomationTool[]; diff --git a/frontend/src/components/tools/automate/ToolSelector.tsx b/frontend/src/core/components/tools/automate/ToolSelector.tsx similarity index 95% rename from frontend/src/components/tools/automate/ToolSelector.tsx rename to frontend/src/core/components/tools/automate/ToolSelector.tsx index 6958ca7d4f..3fc6b0a2ac 100644 --- a/frontend/src/components/tools/automate/ToolSelector.tsx +++ b/frontend/src/core/components/tools/automate/ToolSelector.tsx @@ -1,12 +1,12 @@ import { useState, useMemo, useCallback, useRef, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Stack, Text, ScrollArea } from '@mantine/core'; -import { ToolRegistryEntry, ToolRegistry, getToolSupportsAutomate } from '../../../data/toolsTaxonomy'; -import { useToolSections } from '../../../hooks/useToolSections'; -import { renderToolButtons } from '../shared/renderToolButtons'; -import ToolSearch from '../toolPicker/ToolSearch'; -import ToolButton from '../toolPicker/ToolButton'; -import { ToolId } from '../../../types/toolId'; +import { ToolRegistryEntry, ToolRegistry, getToolSupportsAutomate } from '@app/data/toolsTaxonomy'; +import { useToolSections } from '@app/hooks/useToolSections'; +import { renderToolButtons } from '@app/components/tools/shared/renderToolButtons'; +import ToolSearch from '@app/components/tools/toolPicker/ToolSearch'; +import ToolButton from '@app/components/tools/toolPicker/ToolButton'; +import { ToolId } from '@app/types/toolId'; interface ToolSelectorProps { onSelect: (toolKey: string) => void; diff --git a/frontend/src/components/tools/automate/iconMap.ts b/frontend/src/core/components/tools/automate/iconMap.ts similarity index 100% rename from frontend/src/components/tools/automate/iconMap.ts rename to frontend/src/core/components/tools/automate/iconMap.ts diff --git a/frontend/src/components/tools/bookletImposition/BookletImpositionSettings.tsx b/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx similarity index 97% rename from frontend/src/components/tools/bookletImposition/BookletImpositionSettings.tsx rename to frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx index 967ac1d65e..f0c76f04c2 100644 --- a/frontend/src/components/tools/bookletImposition/BookletImpositionSettings.tsx +++ b/frontend/src/core/components/tools/bookletImposition/BookletImpositionSettings.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Stack, Text, Divider, Collapse, Button, NumberInput } from "@mantine/core"; -import { BookletImpositionParameters } from "../../../hooks/tools/bookletImposition/useBookletImpositionParameters"; -import ButtonSelector from "../../shared/ButtonSelector"; +import { BookletImpositionParameters } from "@app/hooks/tools/bookletImposition/useBookletImpositionParameters"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; interface BookletImpositionSettingsProps { parameters: BookletImpositionParameters; diff --git a/frontend/src/components/tools/certSign/CertSignAutomationSettings.tsx b/frontend/src/core/components/tools/certSign/CertSignAutomationSettings.tsx similarity index 78% rename from frontend/src/components/tools/certSign/CertSignAutomationSettings.tsx rename to frontend/src/core/components/tools/certSign/CertSignAutomationSettings.tsx index 74da5b7456..0c4aed6a3a 100644 --- a/frontend/src/components/tools/certSign/CertSignAutomationSettings.tsx +++ b/frontend/src/core/components/tools/certSign/CertSignAutomationSettings.tsx @@ -7,11 +7,11 @@ */ import { Stack } from "@mantine/core"; -import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters"; -import CertificateTypeSettings from "./CertificateTypeSettings"; -import CertificateFormatSettings from "./CertificateFormatSettings"; -import CertificateFilesSettings from "./CertificateFilesSettings"; -import SignatureAppearanceSettings from "./SignatureAppearanceSettings"; +import { CertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; +import CertificateTypeSettings from "@app/components/tools/certSign/CertificateTypeSettings"; +import CertificateFormatSettings from "@app/components/tools/certSign/CertificateFormatSettings"; +import CertificateFilesSettings from "@app/components/tools/certSign/CertificateFilesSettings"; +import SignatureAppearanceSettings from "@app/components/tools/certSign/SignatureAppearanceSettings"; interface CertSignAutomationSettingsProps { parameters: CertSignParameters; diff --git a/frontend/src/components/tools/certSign/CertificateFilesSettings.tsx b/frontend/src/core/components/tools/certSign/CertificateFilesSettings.tsx similarity index 95% rename from frontend/src/components/tools/certSign/CertificateFilesSettings.tsx rename to frontend/src/core/components/tools/certSign/CertificateFilesSettings.tsx index a11ba5b725..ffedbe70d3 100644 --- a/frontend/src/components/tools/certSign/CertificateFilesSettings.tsx +++ b/frontend/src/core/components/tools/certSign/CertificateFilesSettings.tsx @@ -1,7 +1,7 @@ import { Stack, Text, TextInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters"; -import FileUploadButton from "../../shared/FileUploadButton"; +import { CertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; +import FileUploadButton from "@app/components/shared/FileUploadButton"; interface CertificateFilesSettingsProps { parameters: CertSignParameters; diff --git a/frontend/src/components/tools/certSign/CertificateFormatSettings.tsx b/frontend/src/core/components/tools/certSign/CertificateFormatSettings.tsx similarity index 96% rename from frontend/src/components/tools/certSign/CertificateFormatSettings.tsx rename to frontend/src/core/components/tools/certSign/CertificateFormatSettings.tsx index 6fac53f4db..6e584618ee 100644 --- a/frontend/src/components/tools/certSign/CertificateFormatSettings.tsx +++ b/frontend/src/core/components/tools/certSign/CertificateFormatSettings.tsx @@ -1,5 +1,5 @@ import { Stack, Button } from "@mantine/core"; -import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters"; +import { CertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; interface CertificateFormatSettingsProps { parameters: CertSignParameters; diff --git a/frontend/src/components/tools/certSign/CertificateTypeSettings.tsx b/frontend/src/core/components/tools/certSign/CertificateTypeSettings.tsx similarity index 91% rename from frontend/src/components/tools/certSign/CertificateTypeSettings.tsx rename to frontend/src/core/components/tools/certSign/CertificateTypeSettings.tsx index fde6aa1462..4cf85c66cd 100644 --- a/frontend/src/components/tools/certSign/CertificateTypeSettings.tsx +++ b/frontend/src/core/components/tools/certSign/CertificateTypeSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Button } from "@mantine/core"; -import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters"; -import { useAppConfig } from "../../../contexts/AppConfigContext"; +import { CertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; +import { useAppConfig } from "@app/contexts/AppConfigContext"; interface CertificateTypeSettingsProps { parameters: CertSignParameters; @@ -59,4 +59,4 @@ const CertificateTypeSettings = ({ parameters, onParameterChange, disabled = fal ); }; -export default CertificateTypeSettings; \ No newline at end of file +export default CertificateTypeSettings; diff --git a/frontend/src/components/tools/certSign/SignatureAppearanceSettings.tsx b/frontend/src/core/components/tools/certSign/SignatureAppearanceSettings.tsx similarity index 98% rename from frontend/src/components/tools/certSign/SignatureAppearanceSettings.tsx rename to frontend/src/core/components/tools/certSign/SignatureAppearanceSettings.tsx index aa99be742c..f6ddbe241f 100644 --- a/frontend/src/components/tools/certSign/SignatureAppearanceSettings.tsx +++ b/frontend/src/core/components/tools/certSign/SignatureAppearanceSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, Button, TextInput, NumberInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters"; +import { CertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; interface SignatureAppearanceSettingsProps { parameters: CertSignParameters; diff --git a/frontend/src/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx b/frontend/src/core/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx similarity index 83% rename from frontend/src/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx rename to frontend/src/core/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx index ef95718e98..c13bb4f724 100644 --- a/frontend/src/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/ChangeMetadataSingleStep.tsx @@ -1,11 +1,11 @@ import { Stack, Divider, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters, createCustomMetadataFunctions } from "../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; -import { useMetadataExtraction } from "../../../hooks/tools/changeMetadata/useMetadataExtraction"; -import DeleteAllStep from "./steps/DeleteAllStep"; -import StandardMetadataStep from "./steps/StandardMetadataStep"; -import DocumentDatesStep from "./steps/DocumentDatesStep"; -import AdvancedOptionsStep from "./steps/AdvancedOptionsStep"; +import { ChangeMetadataParameters, createCustomMetadataFunctions } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { useMetadataExtraction } from "@app/hooks/tools/changeMetadata/useMetadataExtraction"; +import DeleteAllStep from "@app/components/tools/changeMetadata/steps/DeleteAllStep"; +import StandardMetadataStep from "@app/components/tools/changeMetadata/steps/StandardMetadataStep"; +import DocumentDatesStep from "@app/components/tools/changeMetadata/steps/DocumentDatesStep"; +import AdvancedOptionsStep from "@app/components/tools/changeMetadata/steps/AdvancedOptionsStep"; interface ChangeMetadataSingleStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx b/frontend/src/core/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx similarity index 87% rename from frontend/src/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx rename to frontend/src/core/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx index 0edffe21da..9bf733e109 100644 --- a/frontend/src/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/steps/AdvancedOptionsStep.tsx @@ -1,8 +1,8 @@ import { Stack, Select, Divider } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; -import { TrappedStatus } from "../../../../types/metadata"; -import CustomMetadataStep from "./CustomMetadataStep"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { TrappedStatus } from "@app/types/metadata"; +import CustomMetadataStep from "@app/components/tools/changeMetadata/steps/CustomMetadataStep"; interface AdvancedOptionsStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changeMetadata/steps/CustomMetadataStep.tsx b/frontend/src/core/components/tools/changeMetadata/steps/CustomMetadataStep.tsx similarity index 95% rename from frontend/src/components/tools/changeMetadata/steps/CustomMetadataStep.tsx rename to frontend/src/core/components/tools/changeMetadata/steps/CustomMetadataStep.tsx index beb139e502..3231144078 100644 --- a/frontend/src/components/tools/changeMetadata/steps/CustomMetadataStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/steps/CustomMetadataStep.tsx @@ -1,6 +1,6 @@ import { Stack, TextInput, Button, Group, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; interface CustomMetadataStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changeMetadata/steps/DeleteAllStep.tsx b/frontend/src/core/components/tools/changeMetadata/steps/DeleteAllStep.tsx similarity index 86% rename from frontend/src/components/tools/changeMetadata/steps/DeleteAllStep.tsx rename to frontend/src/core/components/tools/changeMetadata/steps/DeleteAllStep.tsx index fbd983a187..ec86ea57dc 100644 --- a/frontend/src/components/tools/changeMetadata/steps/DeleteAllStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/steps/DeleteAllStep.tsx @@ -1,6 +1,6 @@ import { Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; interface DeleteAllStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx b/frontend/src/core/components/tools/changeMetadata/steps/DocumentDatesStep.tsx similarity index 92% rename from frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx rename to frontend/src/core/components/tools/changeMetadata/steps/DocumentDatesStep.tsx index e46e7799d2..abcf7330c9 100644 --- a/frontend/src/components/tools/changeMetadata/steps/DocumentDatesStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/steps/DocumentDatesStep.tsx @@ -1,7 +1,7 @@ import { Stack } from "@mantine/core"; import { DateTimePicker } from "@mantine/dates"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; interface DocumentDatesStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changeMetadata/steps/StandardMetadataStep.tsx b/frontend/src/core/components/tools/changeMetadata/steps/StandardMetadataStep.tsx similarity index 95% rename from frontend/src/components/tools/changeMetadata/steps/StandardMetadataStep.tsx rename to frontend/src/core/components/tools/changeMetadata/steps/StandardMetadataStep.tsx index 02b5715cd2..3086dd587e 100644 --- a/frontend/src/components/tools/changeMetadata/steps/StandardMetadataStep.tsx +++ b/frontend/src/core/components/tools/changeMetadata/steps/StandardMetadataStep.tsx @@ -1,6 +1,6 @@ import { Stack, TextInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangeMetadataParameters } from "../../../../hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; interface StandardMetadataStepProps { parameters: ChangeMetadataParameters; diff --git a/frontend/src/components/tools/changePermissions/ChangePermissionsSettings.test.tsx b/frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.test.tsx similarity index 95% rename from frontend/src/components/tools/changePermissions/ChangePermissionsSettings.test.tsx rename to frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.test.tsx index d126c7d31f..c50d20580c 100644 --- a/frontend/src/components/tools/changePermissions/ChangePermissionsSettings.test.tsx +++ b/frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.test.tsx @@ -1,9 +1,9 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import ChangePermissionsSettings from './ChangePermissionsSettings'; -import { defaultParameters } from '../../../hooks/tools/changePermissions/useChangePermissionsParameters'; -import type { ChangePermissionsParameters } from '../../../hooks/tools/changePermissions/useChangePermissionsParameters'; +import ChangePermissionsSettings from '@app/components/tools/changePermissions/ChangePermissionsSettings'; +import { defaultParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; +import type { ChangePermissionsParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/changePermissions/ChangePermissionsSettings.tsx b/frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.tsx similarity index 89% rename from frontend/src/components/tools/changePermissions/ChangePermissionsSettings.tsx rename to frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.tsx index 06ac6ac697..db6c4e731c 100644 --- a/frontend/src/components/tools/changePermissions/ChangePermissionsSettings.tsx +++ b/frontend/src/core/components/tools/changePermissions/ChangePermissionsSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ChangePermissionsParameters } from "../../../hooks/tools/changePermissions/useChangePermissionsParameters"; +import { ChangePermissionsParameters } from "@app/hooks/tools/changePermissions/useChangePermissionsParameters"; interface ChangePermissionsSettingsProps { parameters: ChangePermissionsParameters; diff --git a/frontend/src/components/tools/compress/CompressSettings.tsx b/frontend/src/core/components/tools/compress/CompressSettings.tsx similarity index 97% rename from frontend/src/components/tools/compress/CompressSettings.tsx rename to frontend/src/core/components/tools/compress/CompressSettings.tsx index 7304c09b07..7a7c93d675 100644 --- a/frontend/src/components/tools/compress/CompressSettings.tsx +++ b/frontend/src/core/components/tools/compress/CompressSettings.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import { Stack, Text, NumberInput, Select, Divider } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { CompressParameters } from "../../../hooks/tools/compress/useCompressParameters"; -import ButtonSelector from "../../shared/ButtonSelector"; +import { CompressParameters } from "@app/hooks/tools/compress/useCompressParameters"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; interface CompressSettingsProps { parameters: CompressParameters; diff --git a/frontend/src/components/tools/convert/ConvertFromEmailSettings.tsx b/frontend/src/core/components/tools/convert/ConvertFromEmailSettings.tsx similarity index 96% rename from frontend/src/components/tools/convert/ConvertFromEmailSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertFromEmailSettings.tsx index 070fe8b6a1..fd7b1ec977 100644 --- a/frontend/src/components/tools/convert/ConvertFromEmailSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertFromEmailSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, NumberInput, Checkbox } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters'; +import { ConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; interface ConvertFromEmailSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/ConvertFromImageSettings.tsx b/frontend/src/core/components/tools/convert/ConvertFromImageSettings.tsx similarity index 94% rename from frontend/src/components/tools/convert/ConvertFromImageSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertFromImageSettings.tsx index 1767726db6..e56bb6b2af 100644 --- a/frontend/src/components/tools/convert/ConvertFromImageSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertFromImageSettings.tsx @@ -1,7 +1,7 @@ import { Stack, Text, Select, Switch } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { COLOR_TYPES, FIT_OPTIONS } from "../../../constants/convertConstants"; -import { ConvertParameters } from "../../../hooks/tools/convert/useConvertParameters"; +import { COLOR_TYPES, FIT_OPTIONS } from "@app/constants/convertConstants"; +import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters"; interface ConvertFromImageSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/ConvertFromWebSettings.tsx b/frontend/src/core/components/tools/convert/ConvertFromWebSettings.tsx similarity index 94% rename from frontend/src/components/tools/convert/ConvertFromWebSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertFromWebSettings.tsx index 99d0809ab7..f2832cb3a0 100644 --- a/frontend/src/components/tools/convert/ConvertFromWebSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertFromWebSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, NumberInput, Slider } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters'; +import { ConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; interface ConvertFromWebSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/ConvertSettings.tsx b/frontend/src/core/components/tools/convert/ConvertSettings.tsx similarity index 89% rename from frontend/src/components/tools/convert/ConvertSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertSettings.tsx index 9b065e5712..d332f888e3 100644 --- a/frontend/src/components/tools/convert/ConvertSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertSettings.tsx @@ -2,27 +2,27 @@ import { useMemo } from "react"; import { Stack, Text, Group, Divider, UnstyledButton, useMantineTheme, useMantineColorScheme } from "@mantine/core"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import { useTranslation } from "react-i18next"; -import { useMultipleEndpointsEnabled } from "../../../hooks/useEndpointConfig"; -import { isImageFormat, isWebFormat } from "../../../utils/convertUtils"; -import { getConversionEndpoints } from "../../../data/toolsTaxonomy"; -import { useFileSelection } from "../../../contexts/FileContext"; -import { useFileState } from "../../../contexts/FileContext"; -import { detectFileExtension } from "../../../utils/fileUtils"; -import GroupedFormatDropdown from "./GroupedFormatDropdown"; -import ConvertToImageSettings from "./ConvertToImageSettings"; -import ConvertFromImageSettings from "./ConvertFromImageSettings"; -import ConvertFromWebSettings from "./ConvertFromWebSettings"; -import ConvertFromEmailSettings from "./ConvertFromEmailSettings"; -import ConvertToPdfaSettings from "./ConvertToPdfaSettings"; -import { ConvertParameters } from "../../../hooks/tools/convert/useConvertParameters"; +import { useMultipleEndpointsEnabled } from "@app/hooks/useEndpointConfig"; +import { isImageFormat, isWebFormat } from "@app/utils/convertUtils"; +import { getConversionEndpoints } from "@app/data/toolsTaxonomy"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { useFileState } from "@app/contexts/FileContext"; +import { detectFileExtension } from "@app/utils/fileUtils"; +import GroupedFormatDropdown from "@app/components/tools/convert/GroupedFormatDropdown"; +import ConvertToImageSettings from "@app/components/tools/convert/ConvertToImageSettings"; +import ConvertFromImageSettings from "@app/components/tools/convert/ConvertFromImageSettings"; +import ConvertFromWebSettings from "@app/components/tools/convert/ConvertFromWebSettings"; +import ConvertFromEmailSettings from "@app/components/tools/convert/ConvertFromEmailSettings"; +import ConvertToPdfaSettings from "@app/components/tools/convert/ConvertToPdfaSettings"; +import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters"; import { FROM_FORMAT_OPTIONS, EXTENSION_TO_ENDPOINT, COLOR_TYPES, OUTPUT_OPTIONS, FIT_OPTIONS -} from "../../../constants/convertConstants"; -import { StirlingFile } from "../../../types/fileContext"; +} from "@app/constants/convertConstants"; +import { StirlingFile } from "@app/types/fileContext"; interface ConvertSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/ConvertToImageSettings.tsx b/frontend/src/core/components/tools/convert/ConvertToImageSettings.tsx similarity index 93% rename from frontend/src/components/tools/convert/ConvertToImageSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertToImageSettings.tsx index 0d82181f78..e5649f2415 100644 --- a/frontend/src/components/tools/convert/ConvertToImageSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertToImageSettings.tsx @@ -1,7 +1,7 @@ import { Stack, Text, Select, NumberInput, Group } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { COLOR_TYPES, OUTPUT_OPTIONS } from "../../../constants/convertConstants"; -import { ConvertParameters } from "../../../hooks/tools/convert/useConvertParameters"; +import { COLOR_TYPES, OUTPUT_OPTIONS } from "@app/constants/convertConstants"; +import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters"; interface ConvertToImageSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/ConvertToPdfaSettings.tsx b/frontend/src/core/components/tools/convert/ConvertToPdfaSettings.tsx similarity index 88% rename from frontend/src/components/tools/convert/ConvertToPdfaSettings.tsx rename to frontend/src/core/components/tools/convert/ConvertToPdfaSettings.tsx index 18d2bafcbf..0b699693e2 100644 --- a/frontend/src/components/tools/convert/ConvertToPdfaSettings.tsx +++ b/frontend/src/core/components/tools/convert/ConvertToPdfaSettings.tsx @@ -1,8 +1,8 @@ import { Stack, Text, Select, Alert } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters'; -import { usePdfSignatureDetection } from '../../../hooks/usePdfSignatureDetection'; -import { StirlingFile } from '../../../types/fileContext'; +import { ConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; +import { usePdfSignatureDetection } from '@app/hooks/usePdfSignatureDetection'; +import { StirlingFile } from '@app/types/fileContext'; interface ConvertToPdfaSettingsProps { parameters: ConvertParameters; diff --git a/frontend/src/components/tools/convert/GroupedFormatDropdown.tsx b/frontend/src/core/components/tools/convert/GroupedFormatDropdown.tsx similarity index 100% rename from frontend/src/components/tools/convert/GroupedFormatDropdown.tsx rename to frontend/src/core/components/tools/convert/GroupedFormatDropdown.tsx diff --git a/frontend/src/components/tools/crop/CropAreaSelector.tsx b/frontend/src/core/components/tools/crop/CropAreaSelector.tsx similarity index 98% rename from frontend/src/components/tools/crop/CropAreaSelector.tsx rename to frontend/src/core/components/tools/crop/CropAreaSelector.tsx index 03d316c93d..5139f99efe 100644 --- a/frontend/src/components/tools/crop/CropAreaSelector.tsx +++ b/frontend/src/core/components/tools/crop/CropAreaSelector.tsx @@ -7,8 +7,8 @@ import { pdfToDOMCoordinates, constrainDOMRectToThumbnail, isPointInThumbnail -} from '../../../utils/cropCoordinates'; -import { type ResizeHandle } from '../../../constants/cropConstants'; +} from '@app/utils/cropCoordinates'; +import { type ResizeHandle } from '@app/constants/cropConstants'; interface CropAreaSelectorProps { /** PDF bounds for coordinate conversion */ diff --git a/frontend/src/components/tools/crop/CropAutomationSettings.tsx b/frontend/src/core/components/tools/crop/CropAutomationSettings.tsx similarity index 84% rename from frontend/src/components/tools/crop/CropAutomationSettings.tsx rename to frontend/src/core/components/tools/crop/CropAutomationSettings.tsx index a098d39afe..dd668c6072 100644 --- a/frontend/src/components/tools/crop/CropAutomationSettings.tsx +++ b/frontend/src/core/components/tools/crop/CropAutomationSettings.tsx @@ -6,9 +6,9 @@ */ import { Stack } from "@mantine/core"; -import { CropParameters } from "../../../hooks/tools/crop/useCropParameters"; -import { Rectangle } from "../../../utils/cropCoordinates"; -import CropCoordinateInputs from "./CropCoordinateInputs"; +import { CropParameters } from "@app/hooks/tools/crop/useCropParameters"; +import { Rectangle } from "@app/utils/cropCoordinates"; +import CropCoordinateInputs from "@app/components/tools/crop/CropCoordinateInputs"; interface CropAutomationSettingsProps { parameters: CropParameters; diff --git a/frontend/src/components/tools/crop/CropCoordinateInputs.tsx b/frontend/src/core/components/tools/crop/CropCoordinateInputs.tsx similarity index 97% rename from frontend/src/components/tools/crop/CropCoordinateInputs.tsx rename to frontend/src/core/components/tools/crop/CropCoordinateInputs.tsx index 8607e3b942..abed4fd47e 100644 --- a/frontend/src/components/tools/crop/CropCoordinateInputs.tsx +++ b/frontend/src/core/components/tools/crop/CropCoordinateInputs.tsx @@ -1,6 +1,6 @@ import { Stack, Text, Group, NumberInput, Alert } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { Rectangle, PDFBounds } from "../../../utils/cropCoordinates"; +import { Rectangle, PDFBounds } from "@app/utils/cropCoordinates"; interface CropCoordinateInputsProps { cropArea: Rectangle; diff --git a/frontend/src/components/tools/crop/CropSettings.tsx b/frontend/src/core/components/tools/crop/CropSettings.tsx similarity index 91% rename from frontend/src/components/tools/crop/CropSettings.tsx rename to frontend/src/core/components/tools/crop/CropSettings.tsx index 9643b39ae8..fae3afe57e 100644 --- a/frontend/src/components/tools/crop/CropSettings.tsx +++ b/frontend/src/core/components/tools/crop/CropSettings.tsx @@ -2,19 +2,19 @@ import { useMemo, useState, useEffect } from "react"; import { Stack, Text, Box, Group, ActionIcon, Center, Alert } from "@mantine/core"; import { useTranslation } from "react-i18next"; import RestartAltIcon from "@mui/icons-material/RestartAlt"; -import { CropParametersHook } from "../../../hooks/tools/crop/useCropParameters"; -import { useSelectedFiles } from "../../../contexts/file/fileHooks"; -import CropAreaSelector from "./CropAreaSelector"; -import CropCoordinateInputs from "./CropCoordinateInputs"; -import { DEFAULT_CROP_AREA } from "../../../constants/cropConstants"; -import { PAGE_SIZES } from "../../../constants/pageSizeConstants"; +import { CropParametersHook } from "@app/hooks/tools/crop/useCropParameters"; +import { useSelectedFiles } from "@app/contexts/file/fileHooks"; +import CropAreaSelector from "@app/components/tools/crop/CropAreaSelector"; +import CropCoordinateInputs from "@app/components/tools/crop/CropCoordinateInputs"; +import { DEFAULT_CROP_AREA } from "@app/constants/cropConstants"; +import { PAGE_SIZES } from "@app/constants/pageSizeConstants"; import { calculatePDFBounds, PDFBounds, Rectangle -} from "../../../utils/cropCoordinates"; -import { pdfWorkerManager } from "../../../services/pdfWorkerManager"; -import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail"; +} from "@app/utils/cropCoordinates"; +import { pdfWorkerManager } from "@app/services/pdfWorkerManager"; +import DocumentThumbnail from "@app/components/shared/filePreview/DocumentThumbnail"; interface CropSettingsProps { parameters: CropParametersHook; diff --git a/frontend/src/components/tools/extractImages/ExtractImagesSettings.tsx b/frontend/src/core/components/tools/extractImages/ExtractImagesSettings.tsx similarity index 93% rename from frontend/src/components/tools/extractImages/ExtractImagesSettings.tsx rename to frontend/src/core/components/tools/extractImages/ExtractImagesSettings.tsx index 2dde8b53a0..6d4b9dc104 100644 --- a/frontend/src/components/tools/extractImages/ExtractImagesSettings.tsx +++ b/frontend/src/core/components/tools/extractImages/ExtractImagesSettings.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { Stack, Select, Checkbox } from '@mantine/core'; -import { ExtractImagesParameters } from '../../../hooks/tools/extractImages/useExtractImagesParameters'; +import { ExtractImagesParameters } from '@app/hooks/tools/extractImages/useExtractImagesParameters'; interface ExtractImagesSettingsProps { parameters: ExtractImagesParameters; diff --git a/frontend/src/components/tools/flatten/FlattenSettings.tsx b/frontend/src/core/components/tools/flatten/FlattenSettings.tsx similarity index 92% rename from frontend/src/components/tools/flatten/FlattenSettings.tsx rename to frontend/src/core/components/tools/flatten/FlattenSettings.tsx index 8386ad4939..ad3849595f 100644 --- a/frontend/src/components/tools/flatten/FlattenSettings.tsx +++ b/frontend/src/core/components/tools/flatten/FlattenSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { FlattenParameters } from "../../../hooks/tools/flatten/useFlattenParameters"; +import { FlattenParameters } from "@app/hooks/tools/flatten/useFlattenParameters"; interface FlattenSettingsProps { parameters: FlattenParameters; diff --git a/frontend/src/components/tools/fullscreen/CompactToolItem.tsx b/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx similarity index 90% rename from frontend/src/components/tools/fullscreen/CompactToolItem.tsx rename to frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx index 31323ee817..648f79267e 100644 --- a/frontend/src/components/tools/fullscreen/CompactToolItem.tsx +++ b/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { Tooltip } from '../../shared/Tooltip'; -import HotkeyDisplay from '../../hotkeys/HotkeyDisplay'; -import FavoriteStar from '../toolPicker/FavoriteStar'; -import { ToolRegistryEntry, getSubcategoryColor } from '../../../data/toolsTaxonomy'; -import { getIconBackground, getIconStyle, getItemClasses, useToolMeta } from './shared'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import HotkeyDisplay from '@app/components/hotkeys/HotkeyDisplay'; +import FavoriteStar from '@app/components/tools/toolPicker/FavoriteStar'; +import { ToolRegistryEntry, getSubcategoryColor } from '@app/data/toolsTaxonomy'; +import { getIconBackground, getIconStyle, getItemClasses, useToolMeta } from '@app/components/tools/fullscreen/shared'; interface CompactToolItemProps { id: string; diff --git a/frontend/src/components/tools/fullscreen/DetailedToolItem.tsx b/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx similarity index 90% rename from frontend/src/components/tools/fullscreen/DetailedToolItem.tsx rename to frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx index 8363396d9d..2ebf93b357 100644 --- a/frontend/src/components/tools/fullscreen/DetailedToolItem.tsx +++ b/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import HotkeyDisplay from '../../hotkeys/HotkeyDisplay'; -import FavoriteStar from '../toolPicker/FavoriteStar'; -import { ToolRegistryEntry, getSubcategoryColor } from '../../../data/toolsTaxonomy'; -import { getIconBackground, getIconStyle, getItemClasses, useToolMeta } from './shared'; +import HotkeyDisplay from '@app/components/hotkeys/HotkeyDisplay'; +import FavoriteStar from '@app/components/tools/toolPicker/FavoriteStar'; +import { ToolRegistryEntry, getSubcategoryColor } from '@app/data/toolsTaxonomy'; +import { getIconBackground, getIconStyle, getItemClasses, useToolMeta } from '@app/components/tools/fullscreen/shared'; interface DetailedToolItemProps { id: string; diff --git a/frontend/src/components/tools/fullscreen/shared.ts b/frontend/src/core/components/tools/fullscreen/shared.ts similarity index 83% rename from frontend/src/components/tools/fullscreen/shared.ts rename to frontend/src/core/components/tools/fullscreen/shared.ts index 6355c3828b..adaf360982 100644 --- a/frontend/src/components/tools/fullscreen/shared.ts +++ b/frontend/src/core/components/tools/fullscreen/shared.ts @@ -1,7 +1,7 @@ -import { useHotkeys } from '../../../contexts/HotkeyContext'; -import { useToolWorkflow } from '../../../contexts/ToolWorkflowContext'; -import { ToolRegistryEntry } from '../../../data/toolsTaxonomy'; -import { ToolId } from '../../../types/toolId'; +import { useHotkeys } from '@app/contexts/HotkeyContext'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { ToolRegistryEntry } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; export const getItemClasses = (isDetailed: boolean): string => { return isDetailed ? 'tool-panel__fullscreen-item--detailed' : ''; diff --git a/frontend/src/components/tools/merge/MergeFileSorter.test.tsx b/frontend/src/core/components/tools/merge/MergeFileSorter.test.tsx similarity index 98% rename from frontend/src/components/tools/merge/MergeFileSorter.test.tsx rename to frontend/src/core/components/tools/merge/MergeFileSorter.test.tsx index 3027772610..b60c7565b1 100644 --- a/frontend/src/components/tools/merge/MergeFileSorter.test.tsx +++ b/frontend/src/core/components/tools/merge/MergeFileSorter.test.tsx @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import MergeFileSorter from './MergeFileSorter'; +import MergeFileSorter from '@app/components/tools/merge/MergeFileSorter'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/merge/MergeFileSorter.tsx b/frontend/src/core/components/tools/merge/MergeFileSorter.tsx similarity index 100% rename from frontend/src/components/tools/merge/MergeFileSorter.tsx rename to frontend/src/core/components/tools/merge/MergeFileSorter.tsx diff --git a/frontend/src/components/tools/merge/MergeSettings.test.tsx b/frontend/src/core/components/tools/merge/MergeSettings.test.tsx similarity index 95% rename from frontend/src/components/tools/merge/MergeSettings.test.tsx rename to frontend/src/core/components/tools/merge/MergeSettings.test.tsx index 7989fa6d0f..821d708a5a 100644 --- a/frontend/src/components/tools/merge/MergeSettings.test.tsx +++ b/frontend/src/core/components/tools/merge/MergeSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import MergeSettings from './MergeSettings'; -import { MergeParameters } from '../../../hooks/tools/merge/useMergeParameters'; +import MergeSettings from '@app/components/tools/merge/MergeSettings'; +import { MergeParameters } from '@app/hooks/tools/merge/useMergeParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/merge/MergeSettings.tsx b/frontend/src/core/components/tools/merge/MergeSettings.tsx similarity index 93% rename from frontend/src/components/tools/merge/MergeSettings.tsx rename to frontend/src/core/components/tools/merge/MergeSettings.tsx index a126950813..cb036e1711 100644 --- a/frontend/src/components/tools/merge/MergeSettings.tsx +++ b/frontend/src/core/components/tools/merge/MergeSettings.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Stack, Checkbox } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { MergeParameters } from '../../../hooks/tools/merge/useMergeParameters'; +import { MergeParameters } from '@app/hooks/tools/merge/useMergeParameters'; interface MergeSettingsProps { parameters: MergeParameters; diff --git a/frontend/src/components/tools/ocr/AdvancedOCRSettings.tsx b/frontend/src/core/components/tools/ocr/AdvancedOCRSettings.tsx similarity index 97% rename from frontend/src/components/tools/ocr/AdvancedOCRSettings.tsx rename to frontend/src/core/components/tools/ocr/AdvancedOCRSettings.tsx index a6965bb095..ca4d5fc242 100644 --- a/frontend/src/components/tools/ocr/AdvancedOCRSettings.tsx +++ b/frontend/src/core/components/tools/ocr/AdvancedOCRSettings.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Stack, Text, Checkbox } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { OCRParameters } from '../../../hooks/tools/ocr/useOCRParameters'; +import { OCRParameters } from '@app/hooks/tools/ocr/useOCRParameters'; export interface AdvancedOCRParameters { advancedOptions: string[]; diff --git a/frontend/src/components/tools/ocr/LanguagePicker.module.css b/frontend/src/core/components/tools/ocr/LanguagePicker.module.css similarity index 100% rename from frontend/src/components/tools/ocr/LanguagePicker.module.css rename to frontend/src/core/components/tools/ocr/LanguagePicker.module.css diff --git a/frontend/src/components/tools/ocr/LanguagePicker.tsx b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx similarity index 96% rename from frontend/src/components/tools/ocr/LanguagePicker.tsx rename to frontend/src/core/components/tools/ocr/LanguagePicker.tsx index 31f0fe3018..428853b532 100644 --- a/frontend/src/components/tools/ocr/LanguagePicker.tsx +++ b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { Text, Loader } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { tempOcrLanguages, getAutoOcrLanguage } from '../../../utils/languageMapping'; -import DropdownListWithFooter, { DropdownItem } from '../../shared/DropdownListWithFooter'; +import { tempOcrLanguages, getAutoOcrLanguage } from '@app/utils/languageMapping'; +import DropdownListWithFooter, { DropdownItem } from '@app/components/shared/DropdownListWithFooter'; export interface LanguageOption { value: string; diff --git a/frontend/src/components/tools/ocr/OCRSettings.tsx b/frontend/src/core/components/tools/ocr/OCRSettings.tsx similarity index 91% rename from frontend/src/components/tools/ocr/OCRSettings.tsx rename to frontend/src/core/components/tools/ocr/OCRSettings.tsx index 959601166f..abd0d62851 100644 --- a/frontend/src/components/tools/ocr/OCRSettings.tsx +++ b/frontend/src/core/components/tools/ocr/OCRSettings.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Stack, Select, Divider } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import LanguagePicker from './LanguagePicker'; -import { OCRParameters } from '../../../hooks/tools/ocr/useOCRParameters'; +import LanguagePicker from '@app/components/tools/ocr/LanguagePicker'; +import { OCRParameters } from '@app/hooks/tools/ocr/useOCRParameters'; interface OCRSettingsProps { parameters: OCRParameters; diff --git a/frontend/src/components/tools/overlayPdfs/OverlayPdfsSettings.module.css b/frontend/src/core/components/tools/overlayPdfs/OverlayPdfsSettings.module.css similarity index 100% rename from frontend/src/components/tools/overlayPdfs/OverlayPdfsSettings.module.css rename to frontend/src/core/components/tools/overlayPdfs/OverlayPdfsSettings.module.css diff --git a/frontend/src/components/tools/overlayPdfs/OverlayPdfsSettings.tsx b/frontend/src/core/components/tools/overlayPdfs/OverlayPdfsSettings.tsx similarity index 95% rename from frontend/src/components/tools/overlayPdfs/OverlayPdfsSettings.tsx rename to frontend/src/core/components/tools/overlayPdfs/OverlayPdfsSettings.tsx index 43ba64db5a..86b7881839 100644 --- a/frontend/src/components/tools/overlayPdfs/OverlayPdfsSettings.tsx +++ b/frontend/src/core/components/tools/overlayPdfs/OverlayPdfsSettings.tsx @@ -1,9 +1,9 @@ import { Stack, Text, Group, Select, SegmentedControl, NumberInput, Button, ActionIcon, Divider } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { type OverlayPdfsParameters, type OverlayMode } from '../../../hooks/tools/overlayPdfs/useOverlayPdfsParameters'; -import LocalIcon from '../../shared/LocalIcon'; -import { useFilesModalContext } from '../../../contexts/FilesModalContext'; -import styles from './OverlayPdfsSettings.module.css'; +import { type OverlayPdfsParameters, type OverlayMode } from '@app/hooks/tools/overlayPdfs/useOverlayPdfsParameters'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import styles from '@app/components/tools/overlayPdfs/OverlayPdfsSettings.module.css'; interface OverlayPdfsSettingsProps { parameters: OverlayPdfsParameters; diff --git a/frontend/src/components/tools/pageLayout/PageLayoutSettings.tsx b/frontend/src/core/components/tools/pageLayout/PageLayoutSettings.tsx similarity index 89% rename from frontend/src/components/tools/pageLayout/PageLayoutSettings.tsx rename to frontend/src/core/components/tools/pageLayout/PageLayoutSettings.tsx index 296bd73bb7..7b748b6abf 100644 --- a/frontend/src/components/tools/pageLayout/PageLayoutSettings.tsx +++ b/frontend/src/core/components/tools/pageLayout/PageLayoutSettings.tsx @@ -1,7 +1,7 @@ import { Divider, Select, Stack, Switch } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { PageLayoutParameters } from '../../../hooks/tools/pageLayout/usePageLayoutParameters'; -import { getPagesPerSheetOptions } from './constants'; +import { PageLayoutParameters } from '@app/hooks/tools/pageLayout/usePageLayoutParameters'; +import { getPagesPerSheetOptions } from '@app/components/tools/pageLayout/constants'; export default function PageLayoutSettings({ parameters, diff --git a/frontend/src/components/tools/pageLayout/constants.ts b/frontend/src/core/components/tools/pageLayout/constants.ts similarity index 100% rename from frontend/src/components/tools/pageLayout/constants.ts rename to frontend/src/core/components/tools/pageLayout/constants.ts diff --git a/frontend/src/components/tools/redact/RedactAdvancedSettings.test.tsx b/frontend/src/core/components/tools/redact/RedactAdvancedSettings.test.tsx similarity index 97% rename from frontend/src/components/tools/redact/RedactAdvancedSettings.test.tsx rename to frontend/src/core/components/tools/redact/RedactAdvancedSettings.test.tsx index 92f359abd0..064a0b2a8b 100644 --- a/frontend/src/components/tools/redact/RedactAdvancedSettings.test.tsx +++ b/frontend/src/core/components/tools/redact/RedactAdvancedSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import RedactAdvancedSettings from './RedactAdvancedSettings'; -import { defaultParameters } from '../../../hooks/tools/redact/useRedactParameters'; +import RedactAdvancedSettings from '@app/components/tools/redact/RedactAdvancedSettings'; +import { defaultParameters } from '@app/hooks/tools/redact/useRedactParameters'; // Mock useTranslation const mockT = vi.fn((_key: string, fallback: string) => fallback); diff --git a/frontend/src/components/tools/redact/RedactAdvancedSettings.tsx b/frontend/src/core/components/tools/redact/RedactAdvancedSettings.tsx similarity index 96% rename from frontend/src/components/tools/redact/RedactAdvancedSettings.tsx rename to frontend/src/core/components/tools/redact/RedactAdvancedSettings.tsx index 26a96056b6..4e482c7f27 100644 --- a/frontend/src/components/tools/redact/RedactAdvancedSettings.tsx +++ b/frontend/src/core/components/tools/redact/RedactAdvancedSettings.tsx @@ -1,6 +1,6 @@ import { Stack, NumberInput, ColorInput, Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters"; +import { RedactParameters } from "@app/hooks/tools/redact/useRedactParameters"; interface RedactAdvancedSettingsProps { parameters: RedactParameters; diff --git a/frontend/src/components/tools/redact/RedactModeSelector.tsx b/frontend/src/core/components/tools/redact/RedactModeSelector.tsx similarity index 85% rename from frontend/src/components/tools/redact/RedactModeSelector.tsx rename to frontend/src/core/components/tools/redact/RedactModeSelector.tsx index c073bc5205..47f15da668 100644 --- a/frontend/src/components/tools/redact/RedactModeSelector.tsx +++ b/frontend/src/core/components/tools/redact/RedactModeSelector.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; -import { RedactMode } from '../../../hooks/tools/redact/useRedactParameters'; -import ButtonSelector from '../../shared/ButtonSelector'; +import { RedactMode } from '@app/hooks/tools/redact/useRedactParameters'; +import ButtonSelector from '@app/components/shared/ButtonSelector'; interface RedactModeSelectorProps { mode: RedactMode; diff --git a/frontend/src/components/tools/redact/RedactSingleStepSettings.test.tsx b/frontend/src/core/components/tools/redact/RedactSingleStepSettings.test.tsx similarity index 97% rename from frontend/src/components/tools/redact/RedactSingleStepSettings.test.tsx rename to frontend/src/core/components/tools/redact/RedactSingleStepSettings.test.tsx index 2bfe94e066..4b516aa3b4 100644 --- a/frontend/src/components/tools/redact/RedactSingleStepSettings.test.tsx +++ b/frontend/src/core/components/tools/redact/RedactSingleStepSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import RedactSingleStepSettings from './RedactSingleStepSettings'; -import { defaultParameters } from '../../../hooks/tools/redact/useRedactParameters'; +import RedactSingleStepSettings from '@app/components/tools/redact/RedactSingleStepSettings'; +import { defaultParameters } from '@app/hooks/tools/redact/useRedactParameters'; // Mock useTranslation vi.mock('react-i18next', () => ({ diff --git a/frontend/src/components/tools/redact/RedactSingleStepSettings.tsx b/frontend/src/core/components/tools/redact/RedactSingleStepSettings.tsx similarity index 82% rename from frontend/src/components/tools/redact/RedactSingleStepSettings.tsx rename to frontend/src/core/components/tools/redact/RedactSingleStepSettings.tsx index 71e48596aa..badea46343 100644 --- a/frontend/src/components/tools/redact/RedactSingleStepSettings.tsx +++ b/frontend/src/core/components/tools/redact/RedactSingleStepSettings.tsx @@ -1,8 +1,8 @@ import { Stack, Divider } from "@mantine/core"; -import { RedactParameters } from "../../../hooks/tools/redact/useRedactParameters"; -import RedactModeSelector from "./RedactModeSelector"; -import WordsToRedactInput from "./WordsToRedactInput"; -import RedactAdvancedSettings from "./RedactAdvancedSettings"; +import { RedactParameters } from "@app/hooks/tools/redact/useRedactParameters"; +import RedactModeSelector from "@app/components/tools/redact/RedactModeSelector"; +import WordsToRedactInput from "@app/components/tools/redact/WordsToRedactInput"; +import RedactAdvancedSettings from "@app/components/tools/redact/RedactAdvancedSettings"; interface RedactSingleStepSettingsProps { parameters: RedactParameters; diff --git a/frontend/src/components/tools/redact/WordsToRedactInput.test.tsx b/frontend/src/core/components/tools/redact/WordsToRedactInput.test.tsx similarity index 98% rename from frontend/src/components/tools/redact/WordsToRedactInput.test.tsx rename to frontend/src/core/components/tools/redact/WordsToRedactInput.test.tsx index 35bb3dc5d4..84d6f65b99 100644 --- a/frontend/src/components/tools/redact/WordsToRedactInput.test.tsx +++ b/frontend/src/core/components/tools/redact/WordsToRedactInput.test.tsx @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import WordsToRedactInput from './WordsToRedactInput'; +import WordsToRedactInput from '@app/components/tools/redact/WordsToRedactInput'; // Mock useTranslation const mockT = vi.fn((_key: string, fallback: string) => fallback); diff --git a/frontend/src/components/tools/redact/WordsToRedactInput.tsx b/frontend/src/core/components/tools/redact/WordsToRedactInput.tsx similarity index 100% rename from frontend/src/components/tools/redact/WordsToRedactInput.tsx rename to frontend/src/core/components/tools/redact/WordsToRedactInput.tsx diff --git a/frontend/src/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx b/frontend/src/core/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx similarity index 92% rename from frontend/src/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx rename to frontend/src/core/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx index e2618ad428..0b4ee89d9c 100644 --- a/frontend/src/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx +++ b/frontend/src/core/components/tools/removeAnnotations/RemoveAnnotationsSettings.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { Stack, Text, Alert } from '@mantine/core'; -import LocalIcon from '../../shared/LocalIcon'; +import LocalIcon from '@app/components/shared/LocalIcon'; const RemoveAnnotationsSettings = () => { const { t } = useTranslation(); diff --git a/frontend/src/components/tools/removeBlanks/RemoveBlanksSettings.tsx b/frontend/src/core/components/tools/removeBlanks/RemoveBlanksSettings.tsx similarity index 92% rename from frontend/src/components/tools/removeBlanks/RemoveBlanksSettings.tsx rename to frontend/src/core/components/tools/removeBlanks/RemoveBlanksSettings.tsx index fa4ec6e558..e39cab96ce 100644 --- a/frontend/src/components/tools/removeBlanks/RemoveBlanksSettings.tsx +++ b/frontend/src/core/components/tools/removeBlanks/RemoveBlanksSettings.tsx @@ -1,7 +1,7 @@ import { Stack, Text, Checkbox, Slider, NumberInput, Group } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import NumberInputWithUnit from "../shared/NumberInputWithUnit"; -import { RemoveBlanksParameters } from "../../../hooks/tools/removeBlanks/useRemoveBlanksParameters"; +import NumberInputWithUnit from "@app/components/tools/shared/NumberInputWithUnit"; +import { RemoveBlanksParameters } from "@app/hooks/tools/removeBlanks/useRemoveBlanksParameters"; interface RemoveBlanksSettingsProps { parameters: RemoveBlanksParameters; diff --git a/frontend/src/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx b/frontend/src/core/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx similarity index 85% rename from frontend/src/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx rename to frontend/src/core/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx index cb1f480d37..c9463ad76c 100644 --- a/frontend/src/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx +++ b/frontend/src/core/components/tools/removeCertificateSign/RemoveCertificateSignSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { RemoveCertificateSignParameters } from '../../../hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters'; +import { RemoveCertificateSignParameters } from '@app/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters'; interface RemoveCertificateSignSettingsProps { parameters: RemoveCertificateSignParameters; diff --git a/frontend/src/components/tools/removePages/RemovePagesSettings.tsx b/frontend/src/core/components/tools/removePages/RemovePagesSettings.tsx similarity index 90% rename from frontend/src/components/tools/removePages/RemovePagesSettings.tsx rename to frontend/src/core/components/tools/removePages/RemovePagesSettings.tsx index 2d8d0b7d6d..13b3ded2bf 100644 --- a/frontend/src/components/tools/removePages/RemovePagesSettings.tsx +++ b/frontend/src/core/components/tools/removePages/RemovePagesSettings.tsx @@ -1,7 +1,7 @@ import { Stack, TextInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { RemovePagesParameters } from "../../../hooks/tools/removePages/useRemovePagesParameters"; -import { validatePageNumbers } from "../../../utils/pageSelection"; +import { RemovePagesParameters } from "@app/hooks/tools/removePages/useRemovePagesParameters"; +import { validatePageNumbers } from "@app/utils/pageSelection"; interface RemovePagesSettingsProps { parameters: RemovePagesParameters; diff --git a/frontend/src/components/tools/removePassword/RemovePasswordSettings.test.tsx b/frontend/src/core/components/tools/removePassword/RemovePasswordSettings.test.tsx similarity index 95% rename from frontend/src/components/tools/removePassword/RemovePasswordSettings.test.tsx rename to frontend/src/core/components/tools/removePassword/RemovePasswordSettings.test.tsx index 9aac9cd311..bf0a006d6a 100644 --- a/frontend/src/components/tools/removePassword/RemovePasswordSettings.test.tsx +++ b/frontend/src/core/components/tools/removePassword/RemovePasswordSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import RemovePasswordSettings from './RemovePasswordSettings'; -import { defaultParameters } from '../../../hooks/tools/removePassword/useRemovePasswordParameters'; +import RemovePasswordSettings from '@app/components/tools/removePassword/RemovePasswordSettings'; +import { defaultParameters } from '@app/hooks/tools/removePassword/useRemovePasswordParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/removePassword/RemovePasswordSettings.tsx b/frontend/src/core/components/tools/removePassword/RemovePasswordSettings.tsx similarity index 89% rename from frontend/src/components/tools/removePassword/RemovePasswordSettings.tsx rename to frontend/src/core/components/tools/removePassword/RemovePasswordSettings.tsx index cd97dbd964..edc07de7e3 100644 --- a/frontend/src/components/tools/removePassword/RemovePasswordSettings.tsx +++ b/frontend/src/core/components/tools/removePassword/RemovePasswordSettings.tsx @@ -1,6 +1,6 @@ import { Stack, PasswordInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { RemovePasswordParameters } from "../../../hooks/tools/removePassword/useRemovePasswordParameters"; +import { RemovePasswordParameters } from "@app/hooks/tools/removePassword/useRemovePasswordParameters"; interface RemovePasswordSettingsProps { parameters: RemovePasswordParameters; diff --git a/frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx b/frontend/src/core/components/tools/reorganizePages/ReorganizePagesSettings.tsx similarity index 89% rename from frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx rename to frontend/src/core/components/tools/reorganizePages/ReorganizePagesSettings.tsx index 13328a631d..cf23766ada 100644 --- a/frontend/src/components/tools/reorganizePages/ReorganizePagesSettings.tsx +++ b/frontend/src/core/components/tools/reorganizePages/ReorganizePagesSettings.tsx @@ -1,7 +1,7 @@ import { Divider, Select, Stack, TextInput } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { ReorganizePagesParameters } from '../../../hooks/tools/reorganizePages/useReorganizePagesParameters'; -import { getReorganizePagesModeData } from './constants'; +import { ReorganizePagesParameters } from '@app/hooks/tools/reorganizePages/useReorganizePagesParameters'; +import { getReorganizePagesModeData } from '@app/components/tools/reorganizePages/constants'; export default function ReorganizePagesSettings({ parameters, diff --git a/frontend/src/components/tools/reorganizePages/constants.ts b/frontend/src/core/components/tools/reorganizePages/constants.ts similarity index 100% rename from frontend/src/components/tools/reorganizePages/constants.ts rename to frontend/src/core/components/tools/reorganizePages/constants.ts diff --git a/frontend/src/components/tools/repair/RepairSettings.tsx b/frontend/src/core/components/tools/repair/RepairSettings.tsx similarity index 88% rename from frontend/src/components/tools/repair/RepairSettings.tsx rename to frontend/src/core/components/tools/repair/RepairSettings.tsx index ea134b93b1..a18664f7fa 100644 --- a/frontend/src/components/tools/repair/RepairSettings.tsx +++ b/frontend/src/core/components/tools/repair/RepairSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { RepairParameters } from '../../../hooks/tools/repair/useRepairParameters'; +import { RepairParameters } from '@app/hooks/tools/repair/useRepairParameters'; interface RepairSettingsProps { parameters: RepairParameters; diff --git a/frontend/src/components/tools/replaceColor/ReplaceColorSettings.tsx b/frontend/src/core/components/tools/replaceColor/ReplaceColorSettings.tsx similarity index 97% rename from frontend/src/components/tools/replaceColor/ReplaceColorSettings.tsx rename to frontend/src/core/components/tools/replaceColor/ReplaceColorSettings.tsx index ac0db45cea..a49342cd50 100644 --- a/frontend/src/components/tools/replaceColor/ReplaceColorSettings.tsx +++ b/frontend/src/core/components/tools/replaceColor/ReplaceColorSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, Select, ColorInput } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { ReplaceColorParameters } from "../../../hooks/tools/replaceColor/useReplaceColorParameters"; +import { ReplaceColorParameters } from "@app/hooks/tools/replaceColor/useReplaceColorParameters"; interface ReplaceColorSettingsProps { parameters: ReplaceColorParameters; diff --git a/frontend/src/components/tools/rotate/RotateAutomationSettings.tsx b/frontend/src/core/components/tools/rotate/RotateAutomationSettings.tsx similarity index 89% rename from frontend/src/components/tools/rotate/RotateAutomationSettings.tsx rename to frontend/src/core/components/tools/rotate/RotateAutomationSettings.tsx index 8449c2000c..d449578b12 100644 --- a/frontend/src/components/tools/rotate/RotateAutomationSettings.tsx +++ b/frontend/src/core/components/tools/rotate/RotateAutomationSettings.tsx @@ -7,8 +7,8 @@ import { Stack, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { RotateParameters } from "../../../hooks/tools/rotate/useRotateParameters"; -import ButtonSelector from "../../shared/ButtonSelector"; +import { RotateParameters } from "@app/hooks/tools/rotate/useRotateParameters"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; interface RotateAutomationSettingsProps { parameters: RotateParameters; diff --git a/frontend/src/components/tools/rotate/RotateSettings.tsx b/frontend/src/core/components/tools/rotate/RotateSettings.tsx similarity index 93% rename from frontend/src/components/tools/rotate/RotateSettings.tsx rename to frontend/src/core/components/tools/rotate/RotateSettings.tsx index f8c1ea83d5..2136817ffd 100644 --- a/frontend/src/components/tools/rotate/RotateSettings.tsx +++ b/frontend/src/core/components/tools/rotate/RotateSettings.tsx @@ -3,9 +3,9 @@ import { Stack, Text, Box, ActionIcon, Group, Center } from "@mantine/core"; import { useTranslation } from "react-i18next"; import RotateLeftIcon from "@mui/icons-material/RotateLeft"; import RotateRightIcon from "@mui/icons-material/RotateRight"; -import { RotateParametersHook } from "../../../hooks/tools/rotate/useRotateParameters"; -import { useSelectedFiles } from "../../../contexts/file/fileHooks"; -import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail"; +import { RotateParametersHook } from "@app/hooks/tools/rotate/useRotateParameters"; +import { useSelectedFiles } from "@app/contexts/file/fileHooks"; +import DocumentThumbnail from "@app/components/shared/filePreview/DocumentThumbnail"; interface RotateSettingsProps { parameters: RotateParametersHook; diff --git a/frontend/src/components/tools/sanitize/SanitizeSettings.test.tsx b/frontend/src/core/components/tools/sanitize/SanitizeSettings.test.tsx similarity index 97% rename from frontend/src/components/tools/sanitize/SanitizeSettings.test.tsx rename to frontend/src/core/components/tools/sanitize/SanitizeSettings.test.tsx index 055de24662..bb40faefdd 100644 --- a/frontend/src/components/tools/sanitize/SanitizeSettings.test.tsx +++ b/frontend/src/core/components/tools/sanitize/SanitizeSettings.test.tsx @@ -1,8 +1,8 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { MantineProvider } from '@mantine/core'; -import SanitizeSettings from './SanitizeSettings'; -import { SanitizeParameters } from '../../../hooks/tools/sanitize/useSanitizeParameters'; +import SanitizeSettings from '@app/components/tools/sanitize/SanitizeSettings'; +import { SanitizeParameters } from '@app/hooks/tools/sanitize/useSanitizeParameters'; // Mock useTranslation with predictable return values const mockT = vi.fn((key: string) => `mock-${key}`); diff --git a/frontend/src/components/tools/sanitize/SanitizeSettings.tsx b/frontend/src/core/components/tools/sanitize/SanitizeSettings.tsx similarity index 93% rename from frontend/src/components/tools/sanitize/SanitizeSettings.tsx rename to frontend/src/core/components/tools/sanitize/SanitizeSettings.tsx index 21ef7c0aa8..1aaa76010a 100644 --- a/frontend/src/components/tools/sanitize/SanitizeSettings.tsx +++ b/frontend/src/core/components/tools/sanitize/SanitizeSettings.tsx @@ -1,6 +1,6 @@ import { Stack, Text, Checkbox } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { SanitizeParameters, defaultParameters } from "../../../hooks/tools/sanitize/useSanitizeParameters"; +import { SanitizeParameters, defaultParameters } from "@app/hooks/tools/sanitize/useSanitizeParameters"; interface SanitizeSettingsProps { parameters: SanitizeParameters; diff --git a/frontend/src/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx b/frontend/src/core/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx similarity index 95% rename from frontend/src/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx rename to frontend/src/core/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx index e0aef436a6..28afd15d15 100644 --- a/frontend/src/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx +++ b/frontend/src/core/components/tools/scannerImageSplit/ScannerImageSplitSettings.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { NumberInput, Stack } from '@mantine/core'; -import { ScannerImageSplitParameters } from '../../../hooks/tools/scannerImageSplit/useScannerImageSplitParameters'; +import { ScannerImageSplitParameters } from '@app/hooks/tools/scannerImageSplit/useScannerImageSplitParameters'; interface ScannerImageSplitSettingsProps { parameters: ScannerImageSplitParameters; diff --git a/frontend/src/components/tools/shared/ErrorNotification.tsx b/frontend/src/core/components/tools/shared/ErrorNotification.tsx similarity index 100% rename from frontend/src/components/tools/shared/ErrorNotification.tsx rename to frontend/src/core/components/tools/shared/ErrorNotification.tsx diff --git a/frontend/src/components/tools/shared/FileMetadata.tsx b/frontend/src/core/components/tools/shared/FileMetadata.tsx similarity index 88% rename from frontend/src/components/tools/shared/FileMetadata.tsx rename to frontend/src/core/components/tools/shared/FileMetadata.tsx index 8979f344e2..017934c203 100644 --- a/frontend/src/components/tools/shared/FileMetadata.tsx +++ b/frontend/src/core/components/tools/shared/FileMetadata.tsx @@ -1,5 +1,5 @@ import { Stack, Text } from '@mantine/core'; -import { formatFileSize, getFileDate } from '../../../utils/fileUtils'; +import { formatFileSize, getFileDate } from '@app/utils/fileUtils'; export interface FileMetadataProps { file: File; diff --git a/frontend/src/components/tools/shared/FileStatusIndicator.tsx b/frontend/src/core/components/tools/shared/FileStatusIndicator.tsx similarity index 94% rename from frontend/src/components/tools/shared/FileStatusIndicator.tsx rename to frontend/src/core/components/tools/shared/FileStatusIndicator.tsx index f63cfe5932..aed2c5d6ea 100644 --- a/frontend/src/components/tools/shared/FileStatusIndicator.tsx +++ b/frontend/src/core/components/tools/shared/FileStatusIndicator.tsx @@ -3,10 +3,10 @@ import { Text, Anchor } from "@mantine/core"; import { useTranslation } from "react-i18next"; import FolderIcon from '@mui/icons-material/Folder'; import UploadIcon from '@mui/icons-material/Upload'; -import { useFilesModalContext } from "../../../contexts/FilesModalContext"; -import { useAllFiles } from "../../../contexts/FileContext"; -import { useFileManager } from "../../../hooks/useFileManager"; -import { StirlingFile } from "../../../types/fileContext"; +import { useFilesModalContext } from "@app/contexts/FilesModalContext"; +import { useAllFiles } from "@app/contexts/FileContext"; +import { useFileManager } from "@app/hooks/useFileManager"; +import { StirlingFile } from "@app/types/fileContext"; export interface FileStatusIndicatorProps { selectedFiles?: StirlingFile[]; diff --git a/frontend/src/components/tools/shared/FilesToolStep.tsx b/frontend/src/core/components/tools/shared/FilesToolStep.tsx similarity index 83% rename from frontend/src/components/tools/shared/FilesToolStep.tsx rename to frontend/src/core/components/tools/shared/FilesToolStep.tsx index 5ce118bbeb..b1e8933f58 100644 --- a/frontend/src/components/tools/shared/FilesToolStep.tsx +++ b/frontend/src/core/components/tools/shared/FilesToolStep.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import FileStatusIndicator from './FileStatusIndicator'; -import { StirlingFile } from '../../../types/fileContext'; +import FileStatusIndicator from '@app/components/tools/shared/FileStatusIndicator'; +import { StirlingFile } from '@app/types/fileContext'; export interface FilesToolStepProps { selectedFiles: StirlingFile[]; diff --git a/frontend/src/components/tools/shared/NavigationControls.tsx b/frontend/src/core/components/tools/shared/NavigationControls.tsx similarity index 100% rename from frontend/src/components/tools/shared/NavigationControls.tsx rename to frontend/src/core/components/tools/shared/NavigationControls.tsx diff --git a/frontend/src/components/tools/shared/NoToolsFound.tsx b/frontend/src/core/components/tools/shared/NoToolsFound.tsx similarity index 100% rename from frontend/src/components/tools/shared/NoToolsFound.tsx rename to frontend/src/core/components/tools/shared/NoToolsFound.tsx diff --git a/frontend/src/components/tools/shared/NumberInputWithUnit.tsx b/frontend/src/core/components/tools/shared/NumberInputWithUnit.tsx similarity index 100% rename from frontend/src/components/tools/shared/NumberInputWithUnit.tsx rename to frontend/src/core/components/tools/shared/NumberInputWithUnit.tsx diff --git a/frontend/src/components/tools/shared/OperationButton.tsx b/frontend/src/core/components/tools/shared/OperationButton.tsx similarity index 100% rename from frontend/src/components/tools/shared/OperationButton.tsx rename to frontend/src/core/components/tools/shared/OperationButton.tsx diff --git a/frontend/src/components/tools/shared/ResultsPreview.tsx b/frontend/src/core/components/tools/shared/ResultsPreview.tsx similarity index 92% rename from frontend/src/components/tools/shared/ResultsPreview.tsx rename to frontend/src/core/components/tools/shared/ResultsPreview.tsx index 399a3ab5dd..feb4004f7c 100644 --- a/frontend/src/components/tools/shared/ResultsPreview.tsx +++ b/frontend/src/core/components/tools/shared/ResultsPreview.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; import { Box, Text, Loader, Stack, Center, Flex } from '@mantine/core'; -import FilePreview from '../../shared/FilePreview'; -import FileMetadata from './FileMetadata'; -import NavigationControls from './NavigationControls'; +import FilePreview from '@app/components/shared/FilePreview'; +import FileMetadata from '@app/components/tools/shared/FileMetadata'; +import NavigationControls from '@app/components/tools/shared/NavigationControls'; export interface ReviewFile { file: File; diff --git a/frontend/src/components/tools/shared/ReviewToolStep.tsx b/frontend/src/core/components/tools/shared/ReviewToolStep.tsx similarity index 90% rename from frontend/src/components/tools/shared/ReviewToolStep.tsx rename to frontend/src/core/components/tools/shared/ReviewToolStep.tsx index 243e787b50..30c8c906e0 100644 --- a/frontend/src/components/tools/shared/ReviewToolStep.tsx +++ b/frontend/src/core/components/tools/shared/ReviewToolStep.tsx @@ -3,11 +3,11 @@ import { Button, Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import DownloadIcon from "@mui/icons-material/Download"; import UndoIcon from "@mui/icons-material/Undo"; -import ErrorNotification from "./ErrorNotification"; -import ResultsPreview from "./ResultsPreview"; -import { SuggestedToolsSection } from "./SuggestedToolsSection"; -import { ToolOperationHook } from "../../../hooks/tools/shared/useToolOperation"; -import { Tooltip } from "../../shared/Tooltip"; +import ErrorNotification from "@app/components/tools/shared/ErrorNotification"; +import ResultsPreview from "@app/components/tools/shared/ResultsPreview"; +import { SuggestedToolsSection } from "@app/components/tools/shared/SuggestedToolsSection"; +import { ToolOperationHook } from "@app/hooks/tools/shared/useToolOperation"; +import { Tooltip } from "@app/components/shared/Tooltip"; export interface ReviewToolStepProps { isVisible: boolean; diff --git a/frontend/src/components/tools/shared/SubcategoryHeader.tsx b/frontend/src/core/components/tools/shared/SubcategoryHeader.tsx similarity index 100% rename from frontend/src/components/tools/shared/SubcategoryHeader.tsx rename to frontend/src/core/components/tools/shared/SubcategoryHeader.tsx diff --git a/frontend/src/components/tools/shared/SuggestedToolsSection.tsx b/frontend/src/core/components/tools/shared/SuggestedToolsSection.tsx similarity index 90% rename from frontend/src/components/tools/shared/SuggestedToolsSection.tsx rename to frontend/src/core/components/tools/shared/SuggestedToolsSection.tsx index ad8720f192..bd7517c791 100644 --- a/frontend/src/components/tools/shared/SuggestedToolsSection.tsx +++ b/frontend/src/core/components/tools/shared/SuggestedToolsSection.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Stack, Text, Divider, Card, Group, Anchor } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useSuggestedTools } from '../../../hooks/useSuggestedTools'; -import { ToolIcon } from '../../shared/ToolIcon'; +import { useSuggestedTools } from '@app/hooks/useSuggestedTools'; +import { ToolIcon } from '@app/components/shared/ToolIcon'; export function SuggestedToolsSection(): React.ReactElement { const { t } = useTranslation(); diff --git a/frontend/src/components/tools/shared/ToolStep.tsx b/frontend/src/core/components/tools/shared/ToolStep.tsx similarity index 92% rename from frontend/src/components/tools/shared/ToolStep.tsx rename to frontend/src/core/components/tools/shared/ToolStep.tsx index e20af455ca..89c39aad8e 100644 --- a/frontend/src/components/tools/shared/ToolStep.tsx +++ b/frontend/src/core/components/tools/shared/ToolStep.tsx @@ -1,10 +1,10 @@ import React, { createContext, useContext, useMemo } from 'react'; import { Text, Stack, Flex, Divider } from '@mantine/core'; -import LocalIcon from '../../shared/LocalIcon'; -import { Tooltip } from '../../shared/Tooltip'; -import { TooltipTip } from '../../../types/tips'; -import { createFilesToolStep, FilesToolStepProps } from './FilesToolStep'; -import { createReviewToolStep, ReviewToolStepProps } from './ReviewToolStep'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { TooltipTip } from '@app/types/tips'; +import { createFilesToolStep, FilesToolStepProps } from '@app/components/tools/shared/FilesToolStep'; +import { createReviewToolStep, ReviewToolStepProps } from '@app/components/tools/shared/ReviewToolStep'; interface ToolStepContextType { visibleStepCount: number; @@ -227,6 +227,6 @@ export function ToolStepProvider({ children, forceStepNumbers }: { children: Rea ); } -export type { FilesToolStepProps } from './FilesToolStep'; -export type { ReviewToolStepProps } from './ReviewToolStep'; +export type { FilesToolStepProps } from '@app/components/tools/shared/FilesToolStep'; +export type { ReviewToolStepProps } from '@app/components/tools/shared/ReviewToolStep'; export default ToolStep; diff --git a/frontend/src/components/tools/shared/ToolWorkflowTitle.tsx b/frontend/src/core/components/tools/shared/ToolWorkflowTitle.tsx similarity index 91% rename from frontend/src/components/tools/shared/ToolWorkflowTitle.tsx rename to frontend/src/core/components/tools/shared/ToolWorkflowTitle.tsx index 24619387fe..8090b85aaa 100644 --- a/frontend/src/components/tools/shared/ToolWorkflowTitle.tsx +++ b/frontend/src/core/components/tools/shared/ToolWorkflowTitle.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Flex, Text, Divider } from '@mantine/core'; -import LocalIcon from '../../shared/LocalIcon'; -import { Tooltip } from '../../shared/Tooltip'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; export interface ToolWorkflowTitleProps { title: string; diff --git a/frontend/src/components/tools/shared/createToolFlow.tsx b/frontend/src/core/components/tools/shared/createToolFlow.tsx similarity index 89% rename from frontend/src/components/tools/shared/createToolFlow.tsx rename to frontend/src/core/components/tools/shared/createToolFlow.tsx index 53d74c47b7..3ff8a3cc97 100644 --- a/frontend/src/components/tools/shared/createToolFlow.tsx +++ b/frontend/src/core/components/tools/shared/createToolFlow.tsx @@ -1,10 +1,10 @@ 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'; -import { ToolWorkflowTitle, ToolWorkflowTitleProps } from './ToolWorkflowTitle'; -import { StirlingFile } from '../../../types/fileContext'; +import { createToolSteps, ToolStepProvider } from '@app/components/tools/shared/ToolStep'; +import OperationButton from '@app/components/tools/shared/OperationButton'; +import { ToolOperationHook } from '@app/hooks/tools/shared/useToolOperation'; +import { ToolWorkflowTitle, ToolWorkflowTitleProps } from '@app/components/tools/shared/ToolWorkflowTitle'; +import { StirlingFile } from '@app/types/fileContext'; export interface FilesStepConfig { selectedFiles: StirlingFile[]; diff --git a/frontend/src/components/tools/shared/renderToolButtons.tsx b/frontend/src/core/components/tools/shared/renderToolButtons.tsx similarity index 81% rename from frontend/src/components/tools/shared/renderToolButtons.tsx rename to frontend/src/core/components/tools/shared/renderToolButtons.tsx index e2d77ff85b..8e1b986cf0 100644 --- a/frontend/src/components/tools/shared/renderToolButtons.tsx +++ b/frontend/src/core/components/tools/shared/renderToolButtons.tsx @@ -1,11 +1,11 @@ import { Box } from '@mantine/core'; -import ToolButton from '../toolPicker/ToolButton'; -import SubcategoryHeader from './SubcategoryHeader'; +import ToolButton from '@app/components/tools/toolPicker/ToolButton'; +import SubcategoryHeader from '@app/components/tools/shared/SubcategoryHeader'; -import { getSubcategoryLabel } from "../../../data/toolsTaxonomy"; +import { getSubcategoryLabel } from "@app/data/toolsTaxonomy"; import { TFunction } from 'i18next'; -import { SubcategoryGroup } from '../../../hooks/useToolSections'; -import { ToolId } from 'src/types/toolId'; +import { SubcategoryGroup } from '@app/hooks/useToolSections'; +import { ToolId } from "@app/types/toolId"; // Helper function to render tool buttons for a subcategory export const renderToolButtons = ( diff --git a/frontend/src/components/tools/sign/PenSizeSelector.tsx b/frontend/src/core/components/tools/sign/PenSizeSelector.tsx similarity index 100% rename from frontend/src/components/tools/sign/PenSizeSelector.tsx rename to frontend/src/core/components/tools/sign/PenSizeSelector.tsx diff --git a/frontend/src/components/tools/sign/SignSettings.tsx b/frontend/src/core/components/tools/sign/SignSettings.tsx similarity index 94% rename from frontend/src/components/tools/sign/SignSettings.tsx rename to frontend/src/core/components/tools/sign/SignSettings.tsx index 6a4e4bbe8e..09200727d9 100644 --- a/frontend/src/components/tools/sign/SignSettings.tsx +++ b/frontend/src/core/components/tools/sign/SignSettings.tsx @@ -1,16 +1,16 @@ import { useState, useEffect } from 'react'; import { useTranslation } from "react-i18next"; import { Stack, Button, Text, Alert, Tabs, SegmentedControl } from '@mantine/core'; -import { SignParameters } from "../../../hooks/tools/sign/useSignParameters"; -import { SuggestedToolsSection } from "../shared/SuggestedToolsSection"; -import { useSignature } from "../../../contexts/SignatureContext"; +import { SignParameters } from "@app/hooks/tools/sign/useSignParameters"; +import { SuggestedToolsSection } from "@app/components/tools/shared/SuggestedToolsSection"; +import { useSignature } from "@app/contexts/SignatureContext"; // Import the new reusable components -import { DrawingCanvas } from "../../annotation/shared/DrawingCanvas"; -import { DrawingControls } from "../../annotation/shared/DrawingControls"; -import { ImageUploader } from "../../annotation/shared/ImageUploader"; -import { TextInputWithFont } from "../../annotation/shared/TextInputWithFont"; -import { ColorPicker } from "../../annotation/shared/ColorPicker"; +import { DrawingCanvas } from "@app/components/annotation/shared/DrawingCanvas"; +import { DrawingControls } from "@app/components/annotation/shared/DrawingControls"; +import { ImageUploader } from "@app/components/annotation/shared/ImageUploader"; +import { TextInputWithFont } from "@app/components/annotation/shared/TextInputWithFont"; +import { ColorPicker } from "@app/components/annotation/shared/ColorPicker"; interface SignSettingsProps { parameters: SignParameters; diff --git a/frontend/src/components/tools/singleLargePage/SingleLargePageSettings.tsx b/frontend/src/core/components/tools/singleLargePage/SingleLargePageSettings.tsx similarity index 87% rename from frontend/src/components/tools/singleLargePage/SingleLargePageSettings.tsx rename to frontend/src/core/components/tools/singleLargePage/SingleLargePageSettings.tsx index 11bf7009f6..dbd9ccb1a8 100644 --- a/frontend/src/components/tools/singleLargePage/SingleLargePageSettings.tsx +++ b/frontend/src/core/components/tools/singleLargePage/SingleLargePageSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { SingleLargePageParameters } from '../../../hooks/tools/singleLargePage/useSingleLargePageParameters'; +import { SingleLargePageParameters } from '@app/hooks/tools/singleLargePage/useSingleLargePageParameters'; interface SingleLargePageSettingsProps { parameters: SingleLargePageParameters; diff --git a/frontend/src/components/tools/split/SplitAutomationSettings.tsx b/frontend/src/core/components/tools/split/SplitAutomationSettings.tsx similarity index 88% rename from frontend/src/components/tools/split/SplitAutomationSettings.tsx rename to frontend/src/core/components/tools/split/SplitAutomationSettings.tsx index a6ad634e58..ac328897df 100644 --- a/frontend/src/components/tools/split/SplitAutomationSettings.tsx +++ b/frontend/src/core/components/tools/split/SplitAutomationSettings.tsx @@ -7,9 +7,9 @@ import { Stack, Text, Select } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { SplitParameters } from "../../../hooks/tools/split/useSplitParameters"; -import { METHOD_OPTIONS, SplitMethod } from "../../../constants/splitConstants"; -import SplitSettings from "./SplitSettings"; +import { SplitParameters } from "@app/hooks/tools/split/useSplitParameters"; +import { METHOD_OPTIONS, SplitMethod } from "@app/constants/splitConstants"; +import SplitSettings from "@app/components/tools/split/SplitSettings"; interface SplitAutomationSettingsProps { parameters: SplitParameters; diff --git a/frontend/src/components/tools/split/SplitSettings.tsx b/frontend/src/core/components/tools/split/SplitSettings.tsx similarity index 96% rename from frontend/src/components/tools/split/SplitSettings.tsx rename to frontend/src/core/components/tools/split/SplitSettings.tsx index ca20c24cc4..e2349ac889 100644 --- a/frontend/src/components/tools/split/SplitSettings.tsx +++ b/frontend/src/core/components/tools/split/SplitSettings.tsx @@ -1,8 +1,8 @@ import { Stack, TextInput, Checkbox, Anchor, Text } from '@mantine/core'; -import LocalIcon from '../../shared/LocalIcon'; +import LocalIcon from '@app/components/shared/LocalIcon'; import { useTranslation } from 'react-i18next'; -import { SPLIT_METHODS } from '../../../constants/splitConstants'; -import { SplitParameters } from '../../../hooks/tools/split/useSplitParameters'; +import { SPLIT_METHODS } from '@app/constants/splitConstants'; +import { SplitParameters } from '@app/hooks/tools/split/useSplitParameters'; export interface SplitSettingsProps { parameters: SplitParameters; diff --git a/frontend/src/components/tools/toolPicker/FavoriteStar.tsx b/frontend/src/core/components/tools/toolPicker/FavoriteStar.tsx similarity index 100% rename from frontend/src/components/tools/toolPicker/FavoriteStar.tsx rename to frontend/src/core/components/tools/toolPicker/FavoriteStar.tsx diff --git a/frontend/src/components/tools/toolPicker/ToolButton.tsx b/frontend/src/core/components/tools/toolPicker/ToolButton.tsx similarity index 89% rename from frontend/src/components/tools/toolPicker/ToolButton.tsx rename to frontend/src/core/components/tools/toolPicker/ToolButton.tsx index fc39631286..5b756c8baa 100644 --- a/frontend/src/components/tools/toolPicker/ToolButton.tsx +++ b/frontend/src/core/components/tools/toolPicker/ToolButton.tsx @@ -1,17 +1,17 @@ import React from "react"; import { Button } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import { Tooltip } from "../../shared/Tooltip"; -import { ToolIcon } from "../../shared/ToolIcon"; -import { ToolRegistryEntry } from "../../../data/toolsTaxonomy"; -import { useToolNavigation } from "../../../hooks/useToolNavigation"; -import { handleUnlessSpecialClick } from "../../../utils/clickHandlers"; -import FitText from "../../shared/FitText"; -import { useHotkeys } from "../../../contexts/HotkeyContext"; -import HotkeyDisplay from "../../hotkeys/HotkeyDisplay"; -import FavoriteStar from "./FavoriteStar"; -import { useToolWorkflow } from "../../../contexts/ToolWorkflowContext"; -import { ToolId } from "../../../types/toolId"; +import { Tooltip } from "@app/components/shared/Tooltip"; +import { ToolIcon } from "@app/components/shared/ToolIcon"; +import { ToolRegistryEntry } from "@app/data/toolsTaxonomy"; +import { useToolNavigation } from "@app/hooks/useToolNavigation"; +import { handleUnlessSpecialClick } from "@app/utils/clickHandlers"; +import FitText from "@app/components/shared/FitText"; +import { useHotkeys } from "@app/contexts/HotkeyContext"; +import HotkeyDisplay from "@app/components/hotkeys/HotkeyDisplay"; +import FavoriteStar from "@app/components/tools/toolPicker/FavoriteStar"; +import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext"; +import { ToolId } from "@app/types/toolId"; interface ToolButtonProps { id: ToolId; diff --git a/frontend/src/components/tools/toolPicker/ToolPicker.css b/frontend/src/core/components/tools/toolPicker/ToolPicker.css similarity index 100% rename from frontend/src/components/tools/toolPicker/ToolPicker.css rename to frontend/src/core/components/tools/toolPicker/ToolPicker.css diff --git a/frontend/src/components/tools/toolPicker/ToolSearch.tsx b/frontend/src/core/components/tools/toolPicker/ToolSearch.tsx similarity index 93% rename from frontend/src/components/tools/toolPicker/ToolSearch.tsx rename to frontend/src/core/components/tools/toolPicker/ToolSearch.tsx index e4e2f416b2..00c6de54d2 100644 --- a/frontend/src/components/tools/toolPicker/ToolSearch.tsx +++ b/frontend/src/core/components/tools/toolPicker/ToolSearch.tsx @@ -1,12 +1,12 @@ import { useState, useRef, useEffect, useMemo } from "react"; import { Stack, Button, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; -import LocalIcon from '../../shared/LocalIcon'; -import { ToolRegistryEntry } from "../../../data/toolsTaxonomy"; -import { TextInput } from "../../shared/TextInput"; -import "./ToolPicker.css"; -import { rankByFuzzy, idToWords } from "../../../utils/fuzzySearch"; -import { ToolId } from "src/types/toolId"; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { ToolRegistryEntry } from "@app/data/toolsTaxonomy"; +import { TextInput } from "@app/components/shared/TextInput"; +import "@app/components/tools/toolPicker/ToolPicker.css"; +import { rankByFuzzy, idToWords } from "@app/utils/fuzzySearch"; +import { ToolId } from "@app/types/toolId"; interface ToolSearchProps { value: string; diff --git a/frontend/src/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx b/frontend/src/core/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx similarity index 87% rename from frontend/src/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx rename to frontend/src/core/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx index d7ca66f256..d1eea7debe 100644 --- a/frontend/src/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx +++ b/frontend/src/core/components/tools/unlockPdfForms/UnlockPdfFormsSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { UnlockPdfFormsParameters } from '../../../hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters'; +import { UnlockPdfFormsParameters } from '@app/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters'; interface UnlockPdfFormsSettingsProps { parameters: UnlockPdfFormsParameters; diff --git a/frontend/src/components/tools/validateSignature/ValidateSignatureReportView.tsx b/frontend/src/core/components/tools/validateSignature/ValidateSignatureReportView.tsx similarity index 92% rename from frontend/src/components/tools/validateSignature/ValidateSignatureReportView.tsx rename to frontend/src/core/components/tools/validateSignature/ValidateSignatureReportView.tsx index f97fe4d758..16e0b90a77 100644 --- a/frontend/src/components/tools/validateSignature/ValidateSignatureReportView.tsx +++ b/frontend/src/core/components/tools/validateSignature/ValidateSignatureReportView.tsx @@ -1,11 +1,11 @@ import React, { useMemo } from 'react'; import { Badge, Group, Stack, Text, Divider } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import type { SignatureValidationReportData } from '../../../types/validateSignature'; -import './reportView/styles.css'; -import ThumbnailPreview from './reportView/ThumbnailPreview'; -import FileSummaryHeader from './reportView/FileSummaryHeader'; -import SignatureSection from './reportView/SignatureSection'; +import type { SignatureValidationReportData } from '@app/types/validateSignature'; +import '@app/components/tools/validateSignature/reportView/styles.css'; +import ThumbnailPreview from '@app/components/tools/validateSignature/reportView/ThumbnailPreview'; +import FileSummaryHeader from '@app/components/tools/validateSignature/reportView/FileSummaryHeader'; +import SignatureSection from '@app/components/tools/validateSignature/reportView/SignatureSection'; interface ValidateSignatureReportViewProps { data: SignatureValidationReportData; diff --git a/frontend/src/components/tools/validateSignature/ValidateSignatureResults.tsx b/frontend/src/core/components/tools/validateSignature/ValidateSignatureResults.tsx similarity index 94% rename from frontend/src/components/tools/validateSignature/ValidateSignatureResults.tsx rename to frontend/src/core/components/tools/validateSignature/ValidateSignatureResults.tsx index 7cb2c79570..ccda07370e 100644 --- a/frontend/src/components/tools/validateSignature/ValidateSignatureResults.tsx +++ b/frontend/src/core/components/tools/validateSignature/ValidateSignatureResults.tsx @@ -1,11 +1,11 @@ import { useCallback, useMemo, useState } from 'react'; import { Alert, Badge, Button, Divider, Group, Loader, Stack, Text, SegmentedControl } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import type { SignatureValidationReportEntry } from '../../../types/validateSignature'; -import type { ValidateSignatureOperationHook } from '../../../hooks/tools/validateSignature/useValidateSignatureOperation'; -import './reportView/styles.css'; -import FitText from '../../shared/FitText'; -import { SuggestedToolsSection } from '../shared/SuggestedToolsSection'; +import type { SignatureValidationReportEntry } from '@app/types/validateSignature'; +import type { ValidateSignatureOperationHook } from '@app/hooks/tools/validateSignature/useValidateSignatureOperation'; +import '@app/components/tools/validateSignature/reportView/styles.css'; +import FitText from '@app/components/shared/FitText'; +import { SuggestedToolsSection } from '@app/components/tools/shared/SuggestedToolsSection'; interface ValidateSignatureResultsProps { operation: ValidateSignatureOperationHook; diff --git a/frontend/src/components/tools/validateSignature/ValidateSignatureSettings.tsx b/frontend/src/core/components/tools/validateSignature/ValidateSignatureSettings.tsx similarity index 91% rename from frontend/src/components/tools/validateSignature/ValidateSignatureSettings.tsx rename to frontend/src/core/components/tools/validateSignature/ValidateSignatureSettings.tsx index bd7a48de7b..a744212a4a 100644 --- a/frontend/src/components/tools/validateSignature/ValidateSignatureSettings.tsx +++ b/frontend/src/core/components/tools/validateSignature/ValidateSignatureSettings.tsx @@ -1,7 +1,7 @@ import { Card, Group, Stack, Text, Button } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import FileUploadButton from '../../shared/FileUploadButton'; -import { ValidateSignatureParameters } from '../../../hooks/tools/validateSignature/useValidateSignatureParameters'; +import FileUploadButton from '@app/components/shared/FileUploadButton'; +import { ValidateSignatureParameters } from '@app/hooks/tools/validateSignature/useValidateSignatureParameters'; interface ValidateSignatureSettingsProps { parameters: ValidateSignatureParameters; diff --git a/frontend/src/components/tools/validateSignature/reportView/FieldBlock.tsx b/frontend/src/core/components/tools/validateSignature/reportView/FieldBlock.tsx similarity index 89% rename from frontend/src/components/tools/validateSignature/reportView/FieldBlock.tsx rename to frontend/src/core/components/tools/validateSignature/reportView/FieldBlock.tsx index 23d83ca28e..d981662e16 100644 --- a/frontend/src/components/tools/validateSignature/reportView/FieldBlock.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/FieldBlock.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Text } from '@mantine/core'; -import './styles.css'; +import '@app/components/tools/validateSignature/reportView/styles.css'; const FieldBlock = (label: string, value: React.ReactNode) => { const displayValue = diff --git a/frontend/src/components/tools/validateSignature/reportView/FileSummaryHeader.tsx b/frontend/src/core/components/tools/validateSignature/reportView/FileSummaryHeader.tsx similarity index 89% rename from frontend/src/components/tools/validateSignature/reportView/FileSummaryHeader.tsx rename to frontend/src/core/components/tools/validateSignature/reportView/FileSummaryHeader.tsx index 27fc35073b..68b95e3b7a 100644 --- a/frontend/src/components/tools/validateSignature/reportView/FileSummaryHeader.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/FileSummaryHeader.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; -import './styles.css'; -import FieldBlock from './FieldBlock'; +import '@app/components/tools/validateSignature/reportView/styles.css'; +import FieldBlock from '@app/components/tools/validateSignature/reportView/FieldBlock'; const formatDate = (value?: string | null) => { if (!value) return '--'; diff --git a/frontend/src/components/tools/validateSignature/reportView/SignatureSection.tsx b/frontend/src/core/components/tools/validateSignature/reportView/SignatureSection.tsx similarity index 89% rename from frontend/src/components/tools/validateSignature/reportView/SignatureSection.tsx rename to frontend/src/core/components/tools/validateSignature/reportView/SignatureSection.tsx index bf13c00f79..c6bef701fb 100644 --- a/frontend/src/components/tools/validateSignature/reportView/SignatureSection.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/SignatureSection.tsx @@ -1,9 +1,9 @@ import { Divider, Group, Stack, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import type { SignatureValidationSignature } from '../../../../types/validateSignature'; -import SignatureStatusBadge from './SignatureStatusBadge'; -import FieldBlock from './FieldBlock'; -import './styles.css'; +import type { SignatureValidationSignature } from '@app/types/validateSignature'; +import SignatureStatusBadge from '@app/components/tools/validateSignature/reportView/SignatureStatusBadge'; +import FieldBlock from '@app/components/tools/validateSignature/reportView/FieldBlock'; +import '@app/components/tools/validateSignature/reportView/styles.css'; const formatDate = (value?: string | null) => { if (!value) return '-'; diff --git a/frontend/src/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx b/frontend/src/core/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx similarity index 82% rename from frontend/src/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx rename to frontend/src/core/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx index d4879b8595..342c6713e6 100644 --- a/frontend/src/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx @@ -1,8 +1,8 @@ import { Badge, Popover, Text } from '@mantine/core'; -import './styles.css'; +import '@app/components/tools/validateSignature/reportView/styles.css'; import { useTranslation } from 'react-i18next'; -import { computeSignatureStatus } from '../../../../hooks/tools/validateSignature/utils/signatureStatus'; -import type { SignatureValidationSignature } from '../../../../types/validateSignature'; +import { computeSignatureStatus } from '@app/hooks/tools/validateSignature/utils/signatureStatus'; +import type { SignatureValidationSignature } from '@app/types/validateSignature'; const SignatureStatusBadge = ({ signature }: { signature: SignatureValidationSignature }) => { const { t } = useTranslation(); diff --git a/frontend/src/components/tools/validateSignature/reportView/ThumbnailPreview.tsx b/frontend/src/core/components/tools/validateSignature/reportView/ThumbnailPreview.tsx similarity index 88% rename from frontend/src/components/tools/validateSignature/reportView/ThumbnailPreview.tsx rename to frontend/src/core/components/tools/validateSignature/reportView/ThumbnailPreview.tsx index e1caf7eb65..33d76144f3 100644 --- a/frontend/src/components/tools/validateSignature/reportView/ThumbnailPreview.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/ThumbnailPreview.tsx @@ -1,5 +1,5 @@ import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; -import './styles.css'; +import '@app/components/tools/validateSignature/reportView/styles.css'; const ThumbnailPreview = ({ thumbnailUrl, diff --git a/frontend/src/components/tools/validateSignature/reportView/styles.css b/frontend/src/core/components/tools/validateSignature/reportView/styles.css similarity index 100% rename from frontend/src/components/tools/validateSignature/reportView/styles.css rename to frontend/src/core/components/tools/validateSignature/reportView/styles.css diff --git a/frontend/src/components/tooltips/useAddPasswordPermissionsTips.ts b/frontend/src/core/components/tooltips/useAddPasswordPermissionsTips.ts similarity index 90% rename from frontend/src/components/tooltips/useAddPasswordPermissionsTips.ts rename to frontend/src/core/components/tooltips/useAddPasswordPermissionsTips.ts index 696a4f9f37..624dc31dba 100644 --- a/frontend/src/components/tooltips/useAddPasswordPermissionsTips.ts +++ b/frontend/src/core/components/tooltips/useAddPasswordPermissionsTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useAddPasswordPermissionsTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useAddPasswordTips.ts b/frontend/src/core/components/tooltips/useAddPasswordTips.ts similarity index 96% rename from frontend/src/components/tooltips/useAddPasswordTips.ts rename to frontend/src/core/components/tooltips/useAddPasswordTips.ts index ea699152b0..7a361a64c5 100644 --- a/frontend/src/components/tooltips/useAddPasswordTips.ts +++ b/frontend/src/core/components/tooltips/useAddPasswordTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useAddPasswordTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useAdjustPageScaleTips.ts b/frontend/src/core/components/tooltips/useAdjustPageScaleTips.ts similarity index 96% rename from frontend/src/components/tooltips/useAdjustPageScaleTips.ts rename to frontend/src/core/components/tooltips/useAdjustPageScaleTips.ts index dbd6bd9d2b..71bef0dd6c 100644 --- a/frontend/src/components/tooltips/useAdjustPageScaleTips.ts +++ b/frontend/src/core/components/tooltips/useAdjustPageScaleTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useAdjustPageScaleTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useAdvancedOCRTips.ts b/frontend/src/core/components/tooltips/useAdvancedOCRTips.ts similarity index 97% rename from frontend/src/components/tooltips/useAdvancedOCRTips.ts rename to frontend/src/core/components/tooltips/useAdvancedOCRTips.ts index e1b4532c1c..004a970664 100644 --- a/frontend/src/components/tooltips/useAdvancedOCRTips.ts +++ b/frontend/src/core/components/tooltips/useAdvancedOCRTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useAdvancedOCRTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useAutoRenameTips.ts b/frontend/src/core/components/tooltips/useAutoRenameTips.ts similarity index 93% rename from frontend/src/components/tooltips/useAutoRenameTips.ts rename to frontend/src/core/components/tooltips/useAutoRenameTips.ts index 50e8ea9cea..8b77e39b70 100644 --- a/frontend/src/components/tooltips/useAutoRenameTips.ts +++ b/frontend/src/core/components/tooltips/useAutoRenameTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useAutoRenameTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useBookletImpositionTips.ts b/frontend/src/core/components/tooltips/useBookletImpositionTips.ts similarity index 98% rename from frontend/src/components/tooltips/useBookletImpositionTips.ts rename to frontend/src/core/components/tooltips/useBookletImpositionTips.ts index e690bf284f..f453f22b8b 100644 --- a/frontend/src/components/tooltips/useBookletImpositionTips.ts +++ b/frontend/src/core/components/tooltips/useBookletImpositionTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useBookletImpositionTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useCertSignTooltips.ts b/frontend/src/core/components/tooltips/useCertSignTooltips.ts similarity index 98% rename from frontend/src/components/tooltips/useCertSignTooltips.ts rename to frontend/src/core/components/tooltips/useCertSignTooltips.ts index 77245a130d..4cc4805020 100644 --- a/frontend/src/components/tooltips/useCertSignTooltips.ts +++ b/frontend/src/core/components/tooltips/useCertSignTooltips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useCertSignTooltips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useCertificateTypeTips.ts b/frontend/src/core/components/tooltips/useCertificateTypeTips.ts similarity index 96% rename from frontend/src/components/tooltips/useCertificateTypeTips.ts rename to frontend/src/core/components/tooltips/useCertificateTypeTips.ts index 9e6a130764..23633e8a49 100644 --- a/frontend/src/components/tooltips/useCertificateTypeTips.ts +++ b/frontend/src/core/components/tooltips/useCertificateTypeTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useCertificateTypeTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useChangeMetadataTips.ts b/frontend/src/core/components/tooltips/useChangeMetadataTips.ts similarity index 98% rename from frontend/src/components/tooltips/useChangeMetadataTips.ts rename to frontend/src/core/components/tooltips/useChangeMetadataTips.ts index 3b8618955f..60e2e17d26 100644 --- a/frontend/src/components/tooltips/useChangeMetadataTips.ts +++ b/frontend/src/core/components/tooltips/useChangeMetadataTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useDeleteAllTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useChangePermissionsTips.ts b/frontend/src/core/components/tooltips/useChangePermissionsTips.ts similarity index 93% rename from frontend/src/components/tooltips/useChangePermissionsTips.ts rename to frontend/src/core/components/tooltips/useChangePermissionsTips.ts index 39c6fc2993..9075f8a960 100644 --- a/frontend/src/components/tooltips/useChangePermissionsTips.ts +++ b/frontend/src/core/components/tooltips/useChangePermissionsTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useChangePermissionsTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useCompressTips.ts b/frontend/src/core/components/tooltips/useCompressTips.ts similarity index 96% rename from frontend/src/components/tooltips/useCompressTips.ts rename to frontend/src/core/components/tooltips/useCompressTips.ts index c42e8d63a7..c49ceaca21 100644 --- a/frontend/src/components/tooltips/useCompressTips.ts +++ b/frontend/src/core/components/tooltips/useCompressTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useCompressTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useCropTooltips.ts b/frontend/src/core/components/tooltips/useCropTooltips.ts similarity index 100% rename from frontend/src/components/tooltips/useCropTooltips.ts rename to frontend/src/core/components/tooltips/useCropTooltips.ts diff --git a/frontend/src/components/tooltips/useFlattenTips.ts b/frontend/src/core/components/tooltips/useFlattenTips.ts similarity index 97% rename from frontend/src/components/tooltips/useFlattenTips.ts rename to frontend/src/core/components/tooltips/useFlattenTips.ts index a60e5a4bcc..aa927594ba 100644 --- a/frontend/src/components/tooltips/useFlattenTips.ts +++ b/frontend/src/core/components/tooltips/useFlattenTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useFlattenTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useMergeTips.tsx b/frontend/src/core/components/tooltips/useMergeTips.tsx similarity index 93% rename from frontend/src/components/tooltips/useMergeTips.tsx rename to frontend/src/core/components/tooltips/useMergeTips.tsx index 554c71540f..decd109ef0 100644 --- a/frontend/src/components/tooltips/useMergeTips.tsx +++ b/frontend/src/core/components/tooltips/useMergeTips.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useMergeTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useOCRTips.ts b/frontend/src/core/components/tooltips/useOCRTips.ts similarity index 96% rename from frontend/src/components/tooltips/useOCRTips.ts rename to frontend/src/core/components/tooltips/useOCRTips.ts index 0ae5e387eb..d571827119 100644 --- a/frontend/src/components/tooltips/useOCRTips.ts +++ b/frontend/src/core/components/tooltips/useOCRTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useOCRTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useOverlayPdfsTips.ts b/frontend/src/core/components/tooltips/useOverlayPdfsTips.ts similarity index 97% rename from frontend/src/components/tooltips/useOverlayPdfsTips.ts rename to frontend/src/core/components/tooltips/useOverlayPdfsTips.ts index eb49801790..f7502592fb 100644 --- a/frontend/src/components/tooltips/useOverlayPdfsTips.ts +++ b/frontend/src/core/components/tooltips/useOverlayPdfsTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useOverlayPdfsTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/usePageSelectionTips.ts b/frontend/src/core/components/tooltips/usePageSelectionTips.ts similarity index 97% rename from frontend/src/components/tooltips/usePageSelectionTips.ts rename to frontend/src/core/components/tooltips/usePageSelectionTips.ts index 70874968d5..19c03116fa 100644 --- a/frontend/src/components/tooltips/usePageSelectionTips.ts +++ b/frontend/src/core/components/tooltips/usePageSelectionTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const usePageSelectionTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/usePageSelectionTips.tsx b/frontend/src/core/components/tooltips/usePageSelectionTips.tsx similarity index 98% rename from frontend/src/components/tooltips/usePageSelectionTips.tsx rename to frontend/src/core/components/tooltips/usePageSelectionTips.tsx index d510349926..aed449cd40 100644 --- a/frontend/src/components/tooltips/usePageSelectionTips.tsx +++ b/frontend/src/core/components/tooltips/usePageSelectionTips.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; /** * Reusable tooltip for page selection functionality. diff --git a/frontend/src/components/tooltips/useRedactTips.ts b/frontend/src/core/components/tooltips/useRedactTips.ts similarity index 98% rename from frontend/src/components/tooltips/useRedactTips.ts rename to frontend/src/core/components/tooltips/useRedactTips.ts index 6c9910299b..7689a6a2a8 100644 --- a/frontend/src/components/tooltips/useRedactTips.ts +++ b/frontend/src/core/components/tooltips/useRedactTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useRedactModeTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useRemoveBlanksTips.ts b/frontend/src/core/components/tooltips/useRemoveBlanksTips.ts similarity index 97% rename from frontend/src/components/tooltips/useRemoveBlanksTips.ts rename to frontend/src/core/components/tooltips/useRemoveBlanksTips.ts index a011bd4eec..ef054bdb83 100644 --- a/frontend/src/components/tooltips/useRemoveBlanksTips.ts +++ b/frontend/src/core/components/tooltips/useRemoveBlanksTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useRemoveBlanksTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useRemovePagesTips.ts b/frontend/src/core/components/tooltips/useRemovePagesTips.ts similarity index 96% rename from frontend/src/components/tooltips/useRemovePagesTips.ts rename to frontend/src/core/components/tooltips/useRemovePagesTips.ts index 1da2a1ad14..a20fbc81da 100644 --- a/frontend/src/components/tooltips/useRemovePagesTips.ts +++ b/frontend/src/core/components/tooltips/useRemovePagesTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useRemovePagesTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useRemovePasswordTips.ts b/frontend/src/core/components/tooltips/useRemovePasswordTips.ts similarity index 91% rename from frontend/src/components/tooltips/useRemovePasswordTips.ts rename to frontend/src/core/components/tooltips/useRemovePasswordTips.ts index 1ec303cd6f..06ad72abf6 100644 --- a/frontend/src/components/tooltips/useRemovePasswordTips.ts +++ b/frontend/src/core/components/tooltips/useRemovePasswordTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useRemovePasswordTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useReplaceColorTips.ts b/frontend/src/core/components/tooltips/useReplaceColorTips.ts similarity index 97% rename from frontend/src/components/tooltips/useReplaceColorTips.ts rename to frontend/src/core/components/tooltips/useReplaceColorTips.ts index 58cc5f9d54..3fa8f72344 100644 --- a/frontend/src/components/tooltips/useReplaceColorTips.ts +++ b/frontend/src/core/components/tooltips/useReplaceColorTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useReplaceColorTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useRotateTips.ts b/frontend/src/core/components/tooltips/useRotateTips.ts similarity index 94% rename from frontend/src/components/tooltips/useRotateTips.ts rename to frontend/src/core/components/tooltips/useRotateTips.ts index b7dfd57f32..83ad3e85ec 100644 --- a/frontend/src/components/tooltips/useRotateTips.ts +++ b/frontend/src/core/components/tooltips/useRotateTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useRotateTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useScannerImageSplitTips.ts b/frontend/src/core/components/tooltips/useScannerImageSplitTips.ts similarity index 97% rename from frontend/src/components/tooltips/useScannerImageSplitTips.ts rename to frontend/src/core/components/tooltips/useScannerImageSplitTips.ts index 7f84aa3257..022a305534 100644 --- a/frontend/src/components/tooltips/useScannerImageSplitTips.ts +++ b/frontend/src/core/components/tooltips/useScannerImageSplitTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useScannerImageSplitTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useSignModeTips.ts b/frontend/src/core/components/tooltips/useSignModeTips.ts similarity index 97% rename from frontend/src/components/tooltips/useSignModeTips.ts rename to frontend/src/core/components/tooltips/useSignModeTips.ts index 6b68565f1a..a8cbaf49ec 100644 --- a/frontend/src/components/tooltips/useSignModeTips.ts +++ b/frontend/src/core/components/tooltips/useSignModeTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useSignModeTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useSignatureAppearanceTips.ts b/frontend/src/core/components/tooltips/useSignatureAppearanceTips.ts similarity index 97% rename from frontend/src/components/tooltips/useSignatureAppearanceTips.ts rename to frontend/src/core/components/tooltips/useSignatureAppearanceTips.ts index 79dc3f65a5..43ec619143 100644 --- a/frontend/src/components/tooltips/useSignatureAppearanceTips.ts +++ b/frontend/src/core/components/tooltips/useSignatureAppearanceTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useSignatureAppearanceTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useSplitMethodTips.ts b/frontend/src/core/components/tooltips/useSplitMethodTips.ts similarity index 95% rename from frontend/src/components/tooltips/useSplitMethodTips.ts rename to frontend/src/core/components/tooltips/useSplitMethodTips.ts index 0ccead8d69..57105be6e8 100644 --- a/frontend/src/components/tooltips/useSplitMethodTips.ts +++ b/frontend/src/core/components/tooltips/useSplitMethodTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; +import { TooltipContent } from '@app/types/tips'; export const useSplitMethodTips = (): TooltipContent => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useSplitSettingsTips.ts b/frontend/src/core/components/tooltips/useSplitSettingsTips.ts similarity index 97% rename from frontend/src/components/tooltips/useSplitSettingsTips.ts rename to frontend/src/core/components/tooltips/useSplitSettingsTips.ts index bfc80a7d90..5368063486 100644 --- a/frontend/src/components/tooltips/useSplitSettingsTips.ts +++ b/frontend/src/core/components/tooltips/useSplitSettingsTips.ts @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent } from '../../types/tips'; -import { SPLIT_METHODS, type SplitMethod } from '../../constants/splitConstants'; +import { TooltipContent } from '@app/types/tips'; +import { SPLIT_METHODS, type SplitMethod } from '@app/constants/splitConstants'; export const useSplitSettingsTips = (method: SplitMethod | ''): TooltipContent | null => { const { t } = useTranslation(); diff --git a/frontend/src/components/tooltips/useWatermarkTips.ts b/frontend/src/core/components/tooltips/useWatermarkTips.ts similarity index 99% rename from frontend/src/components/tooltips/useWatermarkTips.ts rename to frontend/src/core/components/tooltips/useWatermarkTips.ts index d9ffbd7d9c..ede2b0bf39 100644 --- a/frontend/src/components/tooltips/useWatermarkTips.ts +++ b/frontend/src/core/components/tooltips/useWatermarkTips.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { TooltipContent, TooltipTip } from '../../types/tips'; +import { TooltipContent, TooltipTip } from '@app/types/tips'; // Shared tooltip content to reduce duplication const useSharedWatermarkContent = () => { diff --git a/frontend/src/components/viewer/CustomSearchLayer.tsx b/frontend/src/core/components/viewer/CustomSearchLayer.tsx similarity index 96% rename from frontend/src/components/viewer/CustomSearchLayer.tsx rename to frontend/src/core/components/viewer/CustomSearchLayer.tsx index 62e49d8617..05b50ecab0 100644 --- a/frontend/src/components/viewer/CustomSearchLayer.tsx +++ b/frontend/src/core/components/viewer/CustomSearchLayer.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useMemo } from 'react'; import { useSearch } from '@embedpdf/plugin-search/react'; -import { useViewer } from '../../contexts/ViewerContext'; -import { SEARCH_CONSTANTS } from './constants/search'; +import { useViewer } from '@app/contexts/ViewerContext'; +import { SEARCH_CONSTANTS } from '@app/components/viewer/constants/search'; interface SearchLayerProps { pageIndex: number; diff --git a/frontend/src/components/viewer/EmbedPdfViewer.tsx b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx similarity index 93% rename from frontend/src/components/viewer/EmbedPdfViewer.tsx rename to frontend/src/core/components/viewer/EmbedPdfViewer.tsx index 4daa0c554f..f85058a732 100644 --- a/frontend/src/components/viewer/EmbedPdfViewer.tsx +++ b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx @@ -2,18 +2,18 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Box, Center, Text, ActionIcon } from '@mantine/core'; import CloseIcon from '@mui/icons-material/Close'; -import { useFileState, useFileActions } from "../../contexts/FileContext"; -import { useFileWithUrl } from "../../hooks/useFileWithUrl"; -import { useViewer } from "../../contexts/ViewerContext"; -import { LocalEmbedPDF } from './LocalEmbedPDF'; -import { PdfViewerToolbar } from './PdfViewerToolbar'; -import { ThumbnailSidebar } from './ThumbnailSidebar'; -import { useNavigationGuard, useNavigationState } from '../../contexts/NavigationContext'; -import { useSignature } from '../../contexts/SignatureContext'; -import { createStirlingFilesAndStubs } from '../../services/fileStubHelpers'; -import NavigationWarningModal from '../shared/NavigationWarningModal'; -import { isStirlingFile } from '../../types/fileContext'; -import { useViewerRightRailButtons } from './useViewerRightRailButtons'; +import { useFileState, useFileActions } from "@app/contexts/FileContext"; +import { useFileWithUrl } from "@app/hooks/useFileWithUrl"; +import { useViewer } from "@app/contexts/ViewerContext"; +import { LocalEmbedPDF } from '@app/components/viewer/LocalEmbedPDF'; +import { PdfViewerToolbar } from '@app/components/viewer/PdfViewerToolbar'; +import { ThumbnailSidebar } from '@app/components/viewer/ThumbnailSidebar'; +import { useNavigationGuard, useNavigationState } from '@app/contexts/NavigationContext'; +import { useSignature } from '@app/contexts/SignatureContext'; +import { createStirlingFilesAndStubs } from '@app/services/fileStubHelpers'; +import NavigationWarningModal from '@app/components/shared/NavigationWarningModal'; +import { isStirlingFile } from '@app/types/fileContext'; +import { useViewerRightRailButtons } from '@app/components/viewer/useViewerRightRailButtons'; export interface EmbedPdfViewerProps { sidebarsVisible: boolean; diff --git a/frontend/src/components/viewer/ExportAPIBridge.tsx b/frontend/src/core/components/viewer/ExportAPIBridge.tsx similarity index 91% rename from frontend/src/components/viewer/ExportAPIBridge.tsx rename to frontend/src/core/components/viewer/ExportAPIBridge.tsx index 20983bc920..1bf5d5991c 100644 --- a/frontend/src/components/viewer/ExportAPIBridge.tsx +++ b/frontend/src/core/components/viewer/ExportAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useExportCapability } from '@embedpdf/plugin-export/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and provides export functionality diff --git a/frontend/src/components/viewer/HistoryAPIBridge.tsx b/frontend/src/core/components/viewer/HistoryAPIBridge.tsx similarity index 96% rename from frontend/src/components/viewer/HistoryAPIBridge.tsx rename to frontend/src/core/components/viewer/HistoryAPIBridge.tsx index 352fdee501..bdbf804296 100644 --- a/frontend/src/components/viewer/HistoryAPIBridge.tsx +++ b/frontend/src/core/components/viewer/HistoryAPIBridge.tsx @@ -1,9 +1,9 @@ import { useImperativeHandle, forwardRef, useEffect } from 'react'; import { useHistoryCapability } from '@embedpdf/plugin-history/react'; import { useAnnotationCapability } from '@embedpdf/plugin-annotation/react'; -import { useSignature } from '../../contexts/SignatureContext'; +import { useSignature } from '@app/contexts/SignatureContext'; import { uuidV4 } from '@embedpdf/models'; -import type { HistoryAPI } from './viewerTypes'; +import type { HistoryAPI } from '@app/components/viewer/viewerTypes'; export const HistoryAPIBridge = forwardRef(function HistoryAPIBridge(_, ref) { const { provides: historyApi } = useHistoryCapability(); diff --git a/frontend/src/components/viewer/LocalEmbedPDF.tsx b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx similarity index 91% rename from frontend/src/components/viewer/LocalEmbedPDF.tsx rename to frontend/src/core/components/viewer/LocalEmbedPDF.tsx index d9eae66c45..bfe75df2f2 100644 --- a/frontend/src/components/viewer/LocalEmbedPDF.tsx +++ b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx @@ -23,21 +23,21 @@ import { ExportPluginPackage } from '@embedpdf/plugin-export/react'; import { HistoryPluginPackage } from '@embedpdf/plugin-history/react'; import { AnnotationLayer, AnnotationPluginPackage } from '@embedpdf/plugin-annotation/react'; import { PdfAnnotationSubtype } from '@embedpdf/models'; -import { CustomSearchLayer } from './CustomSearchLayer'; -import { ZoomAPIBridge } from './ZoomAPIBridge'; -import ToolLoadingFallback from '../tools/ToolLoadingFallback'; +import { CustomSearchLayer } from '@app/components/viewer/CustomSearchLayer'; +import { ZoomAPIBridge } from '@app/components/viewer/ZoomAPIBridge'; +import ToolLoadingFallback from '@app/components/tools/ToolLoadingFallback'; import { Center, Stack, Text } from '@mantine/core'; -import { ScrollAPIBridge } from './ScrollAPIBridge'; -import { SelectionAPIBridge } from './SelectionAPIBridge'; -import { PanAPIBridge } from './PanAPIBridge'; -import { SpreadAPIBridge } from './SpreadAPIBridge'; -import { SearchAPIBridge } from './SearchAPIBridge'; -import { ThumbnailAPIBridge } from './ThumbnailAPIBridge'; -import { RotateAPIBridge } from './RotateAPIBridge'; -import { SignatureAPIBridge } from './SignatureAPIBridge'; -import { HistoryAPIBridge } from './HistoryAPIBridge'; -import type { SignatureAPI, HistoryAPI } from './viewerTypes'; -import { ExportAPIBridge } from './ExportAPIBridge'; +import { ScrollAPIBridge } from '@app/components/viewer/ScrollAPIBridge'; +import { SelectionAPIBridge } from '@app/components/viewer/SelectionAPIBridge'; +import { PanAPIBridge } from '@app/components/viewer/PanAPIBridge'; +import { SpreadAPIBridge } from '@app/components/viewer/SpreadAPIBridge'; +import { SearchAPIBridge } from '@app/components/viewer/SearchAPIBridge'; +import { ThumbnailAPIBridge } from '@app/components/viewer/ThumbnailAPIBridge'; +import { RotateAPIBridge } from '@app/components/viewer/RotateAPIBridge'; +import { SignatureAPIBridge } from '@app/components/viewer/SignatureAPIBridge'; +import { HistoryAPIBridge } from '@app/components/viewer/HistoryAPIBridge'; +import type { SignatureAPI, HistoryAPI } from '@app/components/viewer/viewerTypes'; +import { ExportAPIBridge } from '@app/components/viewer/ExportAPIBridge'; interface LocalEmbedPDFProps { file?: File | Blob; diff --git a/frontend/src/components/viewer/LocalEmbedPDFWithAnnotations.tsx b/frontend/src/core/components/viewer/LocalEmbedPDFWithAnnotations.tsx similarity index 93% rename from frontend/src/components/viewer/LocalEmbedPDFWithAnnotations.tsx rename to frontend/src/core/components/viewer/LocalEmbedPDFWithAnnotations.tsx index 02ee4ecc1f..87a5d75143 100644 --- a/frontend/src/components/viewer/LocalEmbedPDFWithAnnotations.tsx +++ b/frontend/src/core/components/viewer/LocalEmbedPDFWithAnnotations.tsx @@ -24,17 +24,17 @@ import { HistoryPluginPackage } from '@embedpdf/plugin-history/react'; import { AnnotationLayer, AnnotationPluginPackage } from '@embedpdf/plugin-annotation/react'; import { PdfAnnotationSubtype } from '@embedpdf/models'; -import { CustomSearchLayer } from './CustomSearchLayer'; -import { ZoomAPIBridge } from './ZoomAPIBridge'; -import ToolLoadingFallback from '../tools/ToolLoadingFallback'; +import { CustomSearchLayer } from '@app/components/viewer/CustomSearchLayer'; +import { ZoomAPIBridge } from '@app/components/viewer/ZoomAPIBridge'; +import ToolLoadingFallback from '@app/components/tools/ToolLoadingFallback'; import { Center, Stack, Text } from '@mantine/core'; -import { ScrollAPIBridge } from './ScrollAPIBridge'; -import { SelectionAPIBridge } from './SelectionAPIBridge'; -import { PanAPIBridge } from './PanAPIBridge'; -import { SpreadAPIBridge } from './SpreadAPIBridge'; -import { SearchAPIBridge } from './SearchAPIBridge'; -import { ThumbnailAPIBridge } from './ThumbnailAPIBridge'; -import { RotateAPIBridge } from './RotateAPIBridge'; +import { ScrollAPIBridge } from '@app/components/viewer/ScrollAPIBridge'; +import { SelectionAPIBridge } from '@app/components/viewer/SelectionAPIBridge'; +import { PanAPIBridge } from '@app/components/viewer/PanAPIBridge'; +import { SpreadAPIBridge } from '@app/components/viewer/SpreadAPIBridge'; +import { SearchAPIBridge } from '@app/components/viewer/SearchAPIBridge'; +import { ThumbnailAPIBridge } from '@app/components/viewer/ThumbnailAPIBridge'; +import { RotateAPIBridge } from '@app/components/viewer/RotateAPIBridge'; interface LocalEmbedPDFWithAnnotationsProps { file?: File | Blob; diff --git a/frontend/src/components/viewer/PanAPIBridge.tsx b/frontend/src/core/components/viewer/PanAPIBridge.tsx similarity index 94% rename from frontend/src/components/viewer/PanAPIBridge.tsx rename to frontend/src/core/components/viewer/PanAPIBridge.tsx index 26e8c73ee1..a2efd10413 100644 --- a/frontend/src/components/viewer/PanAPIBridge.tsx +++ b/frontend/src/core/components/viewer/PanAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { usePan } from '@embedpdf/plugin-pan/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and updates pan state in ViewerContext diff --git a/frontend/src/components/viewer/PdfViewerToolbar.tsx b/frontend/src/core/components/viewer/PdfViewerToolbar.tsx similarity index 99% rename from frontend/src/components/viewer/PdfViewerToolbar.tsx rename to frontend/src/core/components/viewer/PdfViewerToolbar.tsx index 48373ba02a..93d05b3778 100644 --- a/frontend/src/components/viewer/PdfViewerToolbar.tsx +++ b/frontend/src/core/components/viewer/PdfViewerToolbar.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; import { Button, Paper, Group, NumberInput } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; import FirstPageIcon from '@mui/icons-material/FirstPage'; import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; diff --git a/frontend/src/components/viewer/RotateAPIBridge.tsx b/frontend/src/core/components/viewer/RotateAPIBridge.tsx similarity index 94% rename from frontend/src/components/viewer/RotateAPIBridge.tsx rename to frontend/src/core/components/viewer/RotateAPIBridge.tsx index 30aa9b304a..5b12590d70 100644 --- a/frontend/src/components/viewer/RotateAPIBridge.tsx +++ b/frontend/src/core/components/viewer/RotateAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { useRotate } from '@embedpdf/plugin-rotate/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and updates rotation state in ViewerContext diff --git a/frontend/src/components/viewer/ScrollAPIBridge.tsx b/frontend/src/core/components/viewer/ScrollAPIBridge.tsx similarity index 93% rename from frontend/src/components/viewer/ScrollAPIBridge.tsx rename to frontend/src/core/components/viewer/ScrollAPIBridge.tsx index 45522f7f88..f918b3bea8 100644 --- a/frontend/src/components/viewer/ScrollAPIBridge.tsx +++ b/frontend/src/core/components/viewer/ScrollAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useScroll } from '@embedpdf/plugin-scroll/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * ScrollAPIBridge manages scroll state and exposes scroll actions. diff --git a/frontend/src/components/viewer/SearchAPIBridge.tsx b/frontend/src/core/components/viewer/SearchAPIBridge.tsx similarity index 97% rename from frontend/src/components/viewer/SearchAPIBridge.tsx rename to frontend/src/core/components/viewer/SearchAPIBridge.tsx index 67bb4c4464..4b0eadd237 100644 --- a/frontend/src/components/viewer/SearchAPIBridge.tsx +++ b/frontend/src/core/components/viewer/SearchAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { useSearch } from '@embedpdf/plugin-search/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; interface SearchResult { pageIndex: number; diff --git a/frontend/src/components/viewer/SearchInterface.tsx b/frontend/src/core/components/viewer/SearchInterface.tsx similarity index 98% rename from frontend/src/components/viewer/SearchInterface.tsx rename to frontend/src/core/components/viewer/SearchInterface.tsx index ff91153ad3..da6f6472aa 100644 --- a/frontend/src/components/viewer/SearchInterface.tsx +++ b/frontend/src/core/components/viewer/SearchInterface.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { Box, TextInput, ActionIcon, Text, Group } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { LocalIcon } from '../shared/LocalIcon'; -import { ViewerContext } from '../../contexts/ViewerContext'; +import { LocalIcon } from '@app/components/shared/LocalIcon'; +import { ViewerContext } from '@app/contexts/ViewerContext'; interface SearchInterfaceProps { visible: boolean; diff --git a/frontend/src/components/viewer/SelectionAPIBridge.tsx b/frontend/src/core/components/viewer/SelectionAPIBridge.tsx similarity index 97% rename from frontend/src/components/viewer/SelectionAPIBridge.tsx rename to frontend/src/core/components/viewer/SelectionAPIBridge.tsx index f57c8dd78e..3492c81666 100644 --- a/frontend/src/components/viewer/SelectionAPIBridge.tsx +++ b/frontend/src/core/components/viewer/SelectionAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { useSelectionCapability, SelectionRangeX } from '@embedpdf/plugin-selection/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and updates selection state in ViewerContext diff --git a/frontend/src/components/viewer/SignatureAPIBridge.tsx b/frontend/src/core/components/viewer/SignatureAPIBridge.tsx similarity index 98% rename from frontend/src/components/viewer/SignatureAPIBridge.tsx rename to frontend/src/core/components/viewer/SignatureAPIBridge.tsx index 2042c0487d..6eb8d58e05 100644 --- a/frontend/src/components/viewer/SignatureAPIBridge.tsx +++ b/frontend/src/core/components/viewer/SignatureAPIBridge.tsx @@ -1,8 +1,8 @@ import { useImperativeHandle, forwardRef, useEffect } from 'react'; import { useAnnotationCapability } from '@embedpdf/plugin-annotation/react'; import { PdfAnnotationSubtype, uuidV4 } from '@embedpdf/models'; -import { useSignature } from '../../contexts/SignatureContext'; -import type { SignatureAPI } from './viewerTypes'; +import { useSignature } from '@app/contexts/SignatureContext'; +import type { SignatureAPI } from '@app/components/viewer/viewerTypes'; export const SignatureAPIBridge = forwardRef(function SignatureAPIBridge(_, ref) { const { provides: annotationApi } = useAnnotationCapability(); diff --git a/frontend/src/components/viewer/SpreadAPIBridge.tsx b/frontend/src/core/components/viewer/SpreadAPIBridge.tsx similarity index 95% rename from frontend/src/components/viewer/SpreadAPIBridge.tsx rename to frontend/src/core/components/viewer/SpreadAPIBridge.tsx index 81a2eaa995..e256ecc8d7 100644 --- a/frontend/src/components/viewer/SpreadAPIBridge.tsx +++ b/frontend/src/core/components/viewer/SpreadAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useSpread, SpreadMode } from '@embedpdf/plugin-spread/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and updates spread state in ViewerContext diff --git a/frontend/src/components/viewer/ThumbnailAPIBridge.tsx b/frontend/src/core/components/viewer/ThumbnailAPIBridge.tsx similarity index 91% rename from frontend/src/components/viewer/ThumbnailAPIBridge.tsx rename to frontend/src/core/components/viewer/ThumbnailAPIBridge.tsx index fc3a583bcb..a5e3f13d51 100644 --- a/frontend/src/components/viewer/ThumbnailAPIBridge.tsx +++ b/frontend/src/core/components/viewer/ThumbnailAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useThumbnailCapability } from '@embedpdf/plugin-thumbnail/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * ThumbnailAPIBridge provides thumbnail generation functionality. diff --git a/frontend/src/components/viewer/ThumbnailSidebar.tsx b/frontend/src/core/components/viewer/ThumbnailSidebar.tsx similarity index 99% rename from frontend/src/components/viewer/ThumbnailSidebar.tsx rename to frontend/src/core/components/viewer/ThumbnailSidebar.tsx index e6c5159413..510a6c1a62 100644 --- a/frontend/src/components/viewer/ThumbnailSidebar.tsx +++ b/frontend/src/core/components/viewer/ThumbnailSidebar.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; import { Box, ScrollArea } from '@mantine/core'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; interface ThumbnailSidebarProps { visible: boolean; diff --git a/frontend/src/components/viewer/Viewer.tsx b/frontend/src/core/components/viewer/Viewer.tsx similarity index 84% rename from frontend/src/components/viewer/Viewer.tsx rename to frontend/src/core/components/viewer/Viewer.tsx index dab9ff8265..e296c9d6d8 100644 --- a/frontend/src/components/viewer/Viewer.tsx +++ b/frontend/src/core/components/viewer/Viewer.tsx @@ -1,4 +1,4 @@ -import EmbedPdfViewer from './EmbedPdfViewer'; +import EmbedPdfViewer from '@app/components/viewer/EmbedPdfViewer'; export interface ViewerProps { sidebarsVisible: boolean; diff --git a/frontend/src/components/viewer/ZoomAPIBridge.tsx b/frontend/src/core/components/viewer/ZoomAPIBridge.tsx similarity index 96% rename from frontend/src/components/viewer/ZoomAPIBridge.tsx rename to frontend/src/core/components/viewer/ZoomAPIBridge.tsx index 129cf00bd8..000bf47d99 100644 --- a/frontend/src/components/viewer/ZoomAPIBridge.tsx +++ b/frontend/src/core/components/viewer/ZoomAPIBridge.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; import { useZoom } from '@embedpdf/plugin-zoom/react'; -import { useViewer } from '../../contexts/ViewerContext'; +import { useViewer } from '@app/contexts/ViewerContext'; /** * Component that runs inside EmbedPDF context and manages zoom state locally diff --git a/frontend/src/components/viewer/constants/search.ts b/frontend/src/core/components/viewer/constants/search.ts similarity index 100% rename from frontend/src/components/viewer/constants/search.ts rename to frontend/src/core/components/viewer/constants/search.ts diff --git a/frontend/src/components/viewer/useViewerRightRailButtons.tsx b/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx similarity index 91% rename from frontend/src/components/viewer/useViewerRightRailButtons.tsx rename to frontend/src/core/components/viewer/useViewerRightRailButtons.tsx index ea02375187..95153f5d26 100644 --- a/frontend/src/components/viewer/useViewerRightRailButtons.tsx +++ b/frontend/src/core/components/viewer/useViewerRightRailButtons.tsx @@ -1,12 +1,12 @@ import { useMemo, useState } from 'react'; import { ActionIcon, Popover } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useViewer } from '../../contexts/ViewerContext'; -import { useRightRailButtons, RightRailButtonWithAction } from '../../hooks/useRightRailButtons'; -import LocalIcon from '../shared/LocalIcon'; -import { Tooltip } from '../shared/Tooltip'; -import { SearchInterface } from './SearchInterface'; -import ViewerAnnotationControls from '../shared/rightRail/ViewerAnnotationControls'; +import { useViewer } from '@app/contexts/ViewerContext'; +import { useRightRailButtons, RightRailButtonWithAction } from '@app/hooks/useRightRailButtons'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Tooltip } from '@app/components/shared/Tooltip'; +import { SearchInterface } from '@app/components/viewer/SearchInterface'; +import ViewerAnnotationControls from '@app/components/shared/rightRail/ViewerAnnotationControls'; export function useViewerRightRailButtons() { const { t } = useTranslation(); diff --git a/frontend/src/components/viewer/viewerTypes.ts b/frontend/src/core/components/viewer/viewerTypes.ts similarity index 100% rename from frontend/src/components/viewer/viewerTypes.ts rename to frontend/src/core/components/viewer/viewerTypes.ts diff --git a/frontend/src/constants/addWatermarkConstants.ts b/frontend/src/core/constants/addWatermarkConstants.ts similarity index 100% rename from frontend/src/constants/addWatermarkConstants.ts rename to frontend/src/core/constants/addWatermarkConstants.ts diff --git a/frontend/src/constants/app.ts b/frontend/src/core/constants/app.ts similarity index 100% rename from frontend/src/constants/app.ts rename to frontend/src/core/constants/app.ts diff --git a/frontend/src/constants/automation.ts b/frontend/src/core/constants/automation.ts similarity index 100% rename from frontend/src/constants/automation.ts rename to frontend/src/core/constants/automation.ts diff --git a/frontend/src/constants/convertConstants.ts b/frontend/src/core/constants/convertConstants.ts similarity index 100% rename from frontend/src/constants/convertConstants.ts rename to frontend/src/core/constants/convertConstants.ts diff --git a/frontend/src/constants/convertSupportedFornats.ts b/frontend/src/core/constants/convertSupportedFornats.ts similarity index 100% rename from frontend/src/constants/convertSupportedFornats.ts rename to frontend/src/core/constants/convertSupportedFornats.ts diff --git a/frontend/src/constants/cropConstants.ts b/frontend/src/core/constants/cropConstants.ts similarity index 80% rename from frontend/src/constants/cropConstants.ts rename to frontend/src/core/constants/cropConstants.ts index 50352ae070..deff3cfe4f 100644 --- a/frontend/src/constants/cropConstants.ts +++ b/frontend/src/core/constants/cropConstants.ts @@ -1,4 +1,4 @@ -import { PAGE_SIZES } from "./pageSizeConstants"; +import { PAGE_SIZES } from "@app/constants/pageSizeConstants"; // Default crop area (covers entire page) export const DEFAULT_CROP_AREA = { diff --git a/frontend/src/constants/pageSizeConstants.ts b/frontend/src/core/constants/pageSizeConstants.ts similarity index 100% rename from frontend/src/constants/pageSizeConstants.ts rename to frontend/src/core/constants/pageSizeConstants.ts diff --git a/frontend/src/constants/splitConstants.ts b/frontend/src/core/constants/splitConstants.ts similarity index 97% rename from frontend/src/constants/splitConstants.ts rename to frontend/src/core/constants/splitConstants.ts index 9f849203e2..63a8ba4e3b 100644 --- a/frontend/src/constants/splitConstants.ts +++ b/frontend/src/core/constants/splitConstants.ts @@ -24,7 +24,7 @@ export const isSplitMethod = (value: string | null): value is SplitMethod => { return Object.values(SPLIT_METHODS).includes(value as SplitMethod); }; -import { CardOption } from '../components/shared/CardSelector'; +import { CardOption } from '@app/components/shared/CardSelector'; export interface MethodOption extends CardOption { tooltipKey: string; diff --git a/frontend/src/constants/theme.ts b/frontend/src/core/constants/theme.ts similarity index 100% rename from frontend/src/constants/theme.ts rename to frontend/src/core/constants/theme.ts diff --git a/frontend/src/constants/toolPanel.ts b/frontend/src/core/constants/toolPanel.ts similarity index 100% rename from frontend/src/constants/toolPanel.ts rename to frontend/src/core/constants/toolPanel.ts diff --git a/frontend/src/contexts/AppConfigContext.tsx b/frontend/src/core/contexts/AppConfigContext.tsx similarity index 90% rename from frontend/src/contexts/AppConfigContext.tsx rename to frontend/src/core/contexts/AppConfigContext.tsx index 089f938cf6..3f8399cad9 100644 --- a/frontend/src/contexts/AppConfigContext.tsx +++ b/frontend/src/core/contexts/AppConfigContext.tsx @@ -1,10 +1,5 @@ import React, { createContext, useContext, useState, useEffect } from 'react'; - -// Helper to get JWT from localStorage for Authorization header -function getAuthHeaders(): HeadersInit { - const token = localStorage.getItem('stirling_jwt'); - return token ? { 'Authorization': `Bearer ${token}` } : {}; -} +import { useRequestHeaders } from '@app/hooks/useRequestHeaders'; export interface AppConfig { baseUrl?: string; @@ -52,16 +47,17 @@ export const AppConfigProvider: React.FC<{ children: React.ReactNode }> = ({ chi const [config, setConfig] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const headers = useRequestHeaders(); const fetchConfig = async () => { try { setLoading(true); setError(null); - + const response = await fetch('/api/v1/config/app-config', { - headers: getAuthHeaders(), + headers, }); - + if (!response.ok) { throw new Error(`Failed to fetch config: ${response.status} ${response.statusText}`); } diff --git a/frontend/src/contexts/FileContext.tsx b/frontend/src/core/contexts/FileContext.tsx similarity index 94% rename from frontend/src/contexts/FileContext.tsx rename to frontend/src/core/contexts/FileContext.tsx index 824c87268d..60d95b6767 100644 --- a/frontend/src/contexts/FileContext.tsx +++ b/frontend/src/core/contexts/FileContext.tsx @@ -22,15 +22,15 @@ import { FileId, StirlingFileStub, StirlingFile, -} from '../types/fileContext'; +} from '@app/types/fileContext'; // Import modular components -import { fileContextReducer, initialFileContextState } from './file/FileReducer'; -import { createFileSelectors } from './file/fileSelectors'; -import { addFiles, addStirlingFileStubs, consumeFiles, undoConsumeFiles, createFileActions } from './file/fileActions'; -import { FileLifecycleManager } from './file/lifecycle'; -import { FileStateContext, FileActionsContext } from './file/contexts'; -import { IndexedDBProvider, useIndexedDB } from './IndexedDBContext'; +import { fileContextReducer, initialFileContextState } from '@app/contexts/file/FileReducer'; +import { createFileSelectors } from '@app/contexts/file/fileSelectors'; +import { addFiles, addStirlingFileStubs, consumeFiles, undoConsumeFiles, createFileActions } from '@app/contexts/file/fileActions'; +import { FileLifecycleManager } from '@app/contexts/file/lifecycle'; +import { FileStateContext, FileActionsContext } from '@app/contexts/file/contexts'; +import { IndexedDBProvider, useIndexedDB } from '@app/contexts/IndexedDBContext'; const DEBUG = process.env.NODE_ENV === 'development'; @@ -284,4 +284,4 @@ export { useSelectedFiles, // Primary API hooks for tools useFileContext -} from './file/fileHooks'; +} from '@app/contexts/file/fileHooks'; diff --git a/frontend/src/contexts/FileManagerContext.tsx b/frontend/src/core/contexts/FileManagerContext.tsx similarity index 98% rename from frontend/src/contexts/FileManagerContext.tsx rename to frontend/src/core/contexts/FileManagerContext.tsx index 8c7f6182d0..75c6d9276a 100644 --- a/frontend/src/contexts/FileManagerContext.tsx +++ b/frontend/src/core/contexts/FileManagerContext.tsx @@ -1,10 +1,10 @@ import React, { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react'; -import { fileStorage } from '../services/fileStorage'; -import { zipFileService } from '../services/zipFileService'; -import { StirlingFileStub } from '../types/fileContext'; -import { downloadFiles } from '../utils/downloadUtils'; -import { FileId } from '../types/file'; -import { groupFilesByOriginal } from '../utils/fileHistoryUtils'; +import { fileStorage } from '@app/services/fileStorage'; +import { zipFileService } from '@app/services/zipFileService'; +import { StirlingFileStub } from '@app/types/fileContext'; +import { downloadFiles } from '@app/utils/downloadUtils'; +import { FileId } from '@app/types/file'; +import { groupFilesByOriginal } from '@app/utils/fileHistoryUtils'; // Type for the context value - now contains everything directly interface FileManagerContextValue { diff --git a/frontend/src/contexts/FilesModalContext.tsx b/frontend/src/core/contexts/FilesModalContext.tsx similarity index 94% rename from frontend/src/contexts/FilesModalContext.tsx rename to frontend/src/core/contexts/FilesModalContext.tsx index e850fa4dd8..468609f7d9 100644 --- a/frontend/src/contexts/FilesModalContext.tsx +++ b/frontend/src/core/contexts/FilesModalContext.tsx @@ -1,8 +1,8 @@ import React, { createContext, useContext, useState, useCallback, useMemo } from 'react'; -import { useFileHandler } from '../hooks/useFileHandler'; -import { useFileActions } from './FileContext'; -import { StirlingFileStub } from '../types/fileContext'; -import { fileStorage } from '../services/fileStorage'; +import { useFileHandler } from '@app/hooks/useFileHandler'; +import { useFileActions } from '@app/contexts/FileContext'; +import { StirlingFileStub } from '@app/types/fileContext'; +import { fileStorage } from '@app/services/fileStorage'; interface FilesModalContextType { isFilesModalOpen: boolean; diff --git a/frontend/src/contexts/HotkeyContext.tsx b/frontend/src/core/contexts/HotkeyContext.tsx similarity index 96% rename from frontend/src/contexts/HotkeyContext.tsx rename to frontend/src/core/contexts/HotkeyContext.tsx index c5a0f26497..c7d353c410 100644 --- a/frontend/src/contexts/HotkeyContext.tsx +++ b/frontend/src/core/contexts/HotkeyContext.tsx @@ -1,8 +1,8 @@ import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; -import { HotkeyBinding, bindingEquals, bindingMatchesEvent, deserializeBindings, getDisplayParts, isMacLike, normalizeBinding, serializeBindings } from '../utils/hotkeys'; -import { useToolWorkflow } from './ToolWorkflowContext'; -import { ToolId } from '../types/toolId'; -import { ToolCategoryId, ToolRegistryEntry } from '../data/toolsTaxonomy'; +import { HotkeyBinding, bindingEquals, bindingMatchesEvent, deserializeBindings, getDisplayParts, isMacLike, normalizeBinding, serializeBindings } from '@app/utils/hotkeys'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { ToolId } from '@app/types/toolId'; +import { ToolCategoryId, ToolRegistryEntry } from '@app/data/toolsTaxonomy'; type Bindings = Partial>; diff --git a/frontend/src/contexts/IndexedDBContext.tsx b/frontend/src/core/contexts/IndexedDBContext.tsx similarity index 97% rename from frontend/src/contexts/IndexedDBContext.tsx rename to frontend/src/core/contexts/IndexedDBContext.tsx index 6c9130f000..4a29cd97ed 100644 --- a/frontend/src/contexts/IndexedDBContext.tsx +++ b/frontend/src/core/contexts/IndexedDBContext.tsx @@ -4,10 +4,10 @@ */ import React, { createContext, useContext, useCallback, useRef } from 'react'; -import { fileStorage } from '../services/fileStorage'; -import { FileId } from '../types/file'; -import { StirlingFileStub, createStirlingFile, createQuickKey } from '../types/fileContext'; -import { generateThumbnailForFile } from '../utils/thumbnailUtils'; +import { fileStorage } from '@app/services/fileStorage'; +import { FileId } from '@app/types/file'; +import { StirlingFileStub, createStirlingFile, createQuickKey } from '@app/types/fileContext'; +import { generateThumbnailForFile } from '@app/utils/thumbnailUtils'; const DEBUG = process.env.NODE_ENV === 'development'; diff --git a/frontend/src/contexts/NavigationContext.tsx b/frontend/src/core/contexts/NavigationContext.tsx similarity index 98% rename from frontend/src/contexts/NavigationContext.tsx rename to frontend/src/core/contexts/NavigationContext.tsx index b29a26d252..377ee43e6c 100644 --- a/frontend/src/contexts/NavigationContext.tsx +++ b/frontend/src/core/contexts/NavigationContext.tsx @@ -1,7 +1,7 @@ import React, { createContext, useContext, useReducer, useCallback } from 'react'; -import { WorkbenchType, getDefaultWorkbench } from '../types/workbench'; -import { ToolId, isValidToolId } from '../types/toolId'; -import { useToolRegistry } from './ToolRegistryContext'; +import { WorkbenchType, getDefaultWorkbench } from '@app/types/workbench'; +import { ToolId, isValidToolId } from '@app/types/toolId'; +import { useToolRegistry } from '@app/contexts/ToolRegistryContext'; /** * NavigationContext - Complete navigation management system diff --git a/frontend/src/contexts/OnboardingContext.tsx b/frontend/src/core/contexts/OnboardingContext.tsx similarity index 63% rename from frontend/src/contexts/OnboardingContext.tsx rename to frontend/src/core/contexts/OnboardingContext.tsx index d2898e46d5..21bdadc4d5 100644 --- a/frontend/src/contexts/OnboardingContext.tsx +++ b/frontend/src/core/contexts/OnboardingContext.tsx @@ -1,7 +1,6 @@ import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; -import { usePreferences } from './PreferencesContext'; -import { useMediaQuery } from '@mantine/hooks'; -import { useAuth } from '../auth/UseSession'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import { useShouldShowWelcomeModal } from '@app/hooks/useShouldShowWelcomeModal'; interface OnboardingContextValue { isOpen: boolean; @@ -18,26 +17,18 @@ interface OnboardingContextValue { const OnboardingContext = createContext(undefined); export const OnboardingProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const { preferences, updatePreference } = usePreferences(); - const { session, loading } = useAuth(); + const { updatePreference } = usePreferences(); const [isOpen, setIsOpen] = useState(false); const [currentStep, setCurrentStep] = useState(0); const [showWelcomeModal, setShowWelcomeModal] = useState(false); - const isMobile = useMediaQuery("(max-width: 1024px)"); + const shouldShow = useShouldShowWelcomeModal(); - // Auto-show welcome modal for first-time users after preferences load - // Only show after user has seen the tool panel mode prompt - // Also, don't show tour on mobile devices because it feels clunky - // IMPORTANT: Only show welcome modal if user is authenticated or login is disabled + // Auto-show welcome modal for first-time users useEffect(() => { - if (!loading && !preferences.hasCompletedOnboarding && preferences.toolPanelModePromptSeen && !isMobile) { - // Only show welcome modal if user is authenticated (session exists) - // This prevents the modal from showing on login screens when security is enabled - if (session) { - setShowWelcomeModal(true); - } + if (shouldShow) { + setShowWelcomeModal(true); } - }, [preferences.hasCompletedOnboarding, preferences.toolPanelModePromptSeen, isMobile, session, loading]); + }, [shouldShow]); const startTour = useCallback(() => { setCurrentStep(0); diff --git a/frontend/src/contexts/PreferencesContext.tsx b/frontend/src/core/contexts/PreferencesContext.tsx similarity index 94% rename from frontend/src/contexts/PreferencesContext.tsx rename to frontend/src/core/contexts/PreferencesContext.tsx index e9c9cead7e..b28d1b35bf 100644 --- a/frontend/src/contexts/PreferencesContext.tsx +++ b/frontend/src/core/contexts/PreferencesContext.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext, useState, useCallback } from 'react'; -import { preferencesService, UserPreferences } from '../services/preferencesService'; +import { preferencesService, UserPreferences } from '@app/services/preferencesService'; interface PreferencesContextValue { preferences: UserPreferences; diff --git a/frontend/src/contexts/RightRailContext.tsx b/frontend/src/core/contexts/RightRailContext.tsx similarity index 97% rename from frontend/src/contexts/RightRailContext.tsx rename to frontend/src/core/contexts/RightRailContext.tsx index 6366545af1..5919a53e41 100644 --- a/frontend/src/contexts/RightRailContext.tsx +++ b/frontend/src/core/contexts/RightRailContext.tsx @@ -1,5 +1,5 @@ import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; -import { RightRailAction, RightRailButtonConfig } from '../types/rightRail'; +import { RightRailAction, RightRailButtonConfig } from '@app/types/rightRail'; interface RightRailContextValue { buttons: RightRailButtonConfig[]; diff --git a/frontend/src/contexts/SidebarContext.tsx b/frontend/src/core/contexts/SidebarContext.tsx similarity index 97% rename from frontend/src/contexts/SidebarContext.tsx rename to frontend/src/core/contexts/SidebarContext.tsx index edcbc07116..6568c9ff40 100644 --- a/frontend/src/contexts/SidebarContext.tsx +++ b/frontend/src/core/contexts/SidebarContext.tsx @@ -1,5 +1,5 @@ import { createContext, useContext, useState, useRef, useMemo } from 'react'; -import { SidebarState, SidebarRefs, SidebarContextValue, SidebarProviderProps } from '../types/sidebar'; +import { SidebarState, SidebarRefs, SidebarContextValue, SidebarProviderProps } from '@app/types/sidebar'; const SidebarContext = createContext(undefined); diff --git a/frontend/src/contexts/SignatureContext.tsx b/frontend/src/core/contexts/SignatureContext.tsx similarity index 97% rename from frontend/src/contexts/SignatureContext.tsx rename to frontend/src/core/contexts/SignatureContext.tsx index bbb1655644..753a524147 100644 --- a/frontend/src/contexts/SignatureContext.tsx +++ b/frontend/src/core/contexts/SignatureContext.tsx @@ -1,6 +1,6 @@ import React, { createContext, useContext, useState, ReactNode, useCallback, useRef } from 'react'; -import { SignParameters } from '../hooks/tools/sign/useSignParameters'; -import type { SignatureAPI, HistoryAPI } from '../components/viewer/viewerTypes'; +import { SignParameters } from '@app/hooks/tools/sign/useSignParameters'; +import type { SignatureAPI, HistoryAPI } from '@app/components/viewer/viewerTypes'; // Signature state interface interface SignatureState { diff --git a/frontend/src/contexts/ToolRegistryContext.tsx b/frontend/src/core/contexts/ToolRegistryContext.tsx similarity index 90% rename from frontend/src/contexts/ToolRegistryContext.tsx rename to frontend/src/core/contexts/ToolRegistryContext.tsx index 77dcf55679..6a131ebed2 100644 --- a/frontend/src/contexts/ToolRegistryContext.tsx +++ b/frontend/src/core/contexts/ToolRegistryContext.tsx @@ -6,8 +6,8 @@ import type { RegularToolRegistry, SuperToolRegistry, LinkToolRegistry, -} from '../data/toolsTaxonomy'; -import type { ToolId } from '../types/toolId'; +} from '@app/data/toolsTaxonomy'; +import type { ToolId } from '@app/types/toolId'; export interface ToolRegistryCatalog { regularTools: RegularToolRegistry; diff --git a/frontend/src/contexts/ToolRegistryProvider.tsx b/frontend/src/core/contexts/ToolRegistryProvider.tsx similarity index 75% rename from frontend/src/contexts/ToolRegistryProvider.tsx rename to frontend/src/core/contexts/ToolRegistryProvider.tsx index e7dc7f53b5..fb8e5e48f6 100644 --- a/frontend/src/contexts/ToolRegistryProvider.tsx +++ b/frontend/src/core/contexts/ToolRegistryProvider.tsx @@ -1,9 +1,9 @@ import { useMemo } from 'react'; -import type { ToolId } from '../types/toolId'; -import type { ToolRegistry } from '../data/toolsTaxonomy'; -import ToolRegistryContext, { ToolRegistryCatalog } from './ToolRegistryContext'; -import { useTranslatedToolCatalog } from '../data/useTranslatedToolRegistry'; +import type { ToolId } from '@app/types/toolId'; +import type { ToolRegistry } from '@app/data/toolsTaxonomy'; +import ToolRegistryContext, { ToolRegistryCatalog } from '@app/contexts/ToolRegistryContext'; +import { useTranslatedToolCatalog } from '@app/data/useTranslatedToolRegistry'; interface ToolRegistryProviderProps { children: React.ReactNode; diff --git a/frontend/src/contexts/ToolWorkflowContext.tsx b/frontend/src/core/contexts/ToolWorkflowContext.tsx similarity index 94% rename from frontend/src/contexts/ToolWorkflowContext.tsx rename to frontend/src/core/contexts/ToolWorkflowContext.tsx index 57e38b92d0..2c86700129 100644 --- a/frontend/src/contexts/ToolWorkflowContext.tsx +++ b/frontend/src/core/contexts/ToolWorkflowContext.tsx @@ -4,23 +4,23 @@ */ import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'; -import { useToolManagement } from '../hooks/useToolManagement'; -import { PageEditorFunctions } from '../types/pageEditor'; -import { ToolRegistryEntry, ToolRegistry } from '../data/toolsTaxonomy'; -import { useNavigationActions, useNavigationState } from './NavigationContext'; -import { ToolId, isValidToolId } from '../types/toolId'; -import { WorkbenchType, getDefaultWorkbench, isBaseWorkbench } from '../types/workbench'; -import { useNavigationUrlSync } from '../hooks/useUrlSync'; -import { filterToolRegistryByQuery } from '../utils/toolSearch'; -import { useToolHistory } from '../hooks/tools/useUserToolActivity'; +import { useToolManagement } from '@app/hooks/useToolManagement'; +import { PageEditorFunctions } from '@app/types/pageEditor'; +import { ToolRegistryEntry, ToolRegistry } from '@app/data/toolsTaxonomy'; +import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext'; +import { ToolId, isValidToolId } from '@app/types/toolId'; +import { WorkbenchType, getDefaultWorkbench, isBaseWorkbench } from '@app/types/workbench'; +import { useNavigationUrlSync } from '@app/hooks/useUrlSync'; +import { filterToolRegistryByQuery } from '@app/utils/toolSearch'; +import { useToolHistory } from '@app/hooks/tools/useUserToolActivity'; import { ToolWorkflowState, createInitialState, toolWorkflowReducer, -} from './toolWorkflow/toolWorkflowState'; -import type { ToolPanelMode } from '../constants/toolPanel'; -import { usePreferences } from './PreferencesContext'; -import { useToolRegistry } from './ToolRegistryContext'; +} from '@app/contexts/toolWorkflow/toolWorkflowState'; +import type { ToolPanelMode } from '@app/constants/toolPanel'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import { useToolRegistry } from '@app/contexts/ToolRegistryContext'; // State interface // Types and reducer/state moved to './toolWorkflow/state' diff --git a/frontend/src/contexts/TourOrchestrationContext.tsx b/frontend/src/core/contexts/TourOrchestrationContext.tsx similarity index 93% rename from frontend/src/contexts/TourOrchestrationContext.tsx rename to frontend/src/core/contexts/TourOrchestrationContext.tsx index 8c6c0c05bf..3c55fd394d 100644 --- a/frontend/src/contexts/TourOrchestrationContext.tsx +++ b/frontend/src/core/contexts/TourOrchestrationContext.tsx @@ -1,11 +1,11 @@ import React, { createContext, useContext, useCallback, useRef } from 'react'; -import { useFileHandler } from '../hooks/useFileHandler'; -import { useFilesModalContext } from './FilesModalContext'; -import { useNavigationActions } from './NavigationContext'; -import { useToolWorkflow } from './ToolWorkflowContext'; -import { useAllFiles, useFileManagement } from './FileContext'; -import { StirlingFile } from '../types/fileContext'; -import { fileStorage } from '../services/fileStorage'; +import { useFileHandler } from '@app/hooks/useFileHandler'; +import { useFilesModalContext } from '@app/contexts/FilesModalContext'; +import { useNavigationActions } from '@app/contexts/NavigationContext'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useAllFiles, useFileManagement } from '@app/contexts/FileContext'; +import { StirlingFile } from '@app/types/fileContext'; +import { fileStorage } from '@app/services/fileStorage'; interface TourOrchestrationContextType { // State management diff --git a/frontend/src/contexts/ViewerContext.tsx b/frontend/src/core/contexts/ViewerContext.tsx similarity index 99% rename from frontend/src/contexts/ViewerContext.tsx rename to frontend/src/core/contexts/ViewerContext.tsx index e3aa94487d..8e0bea44a2 100644 --- a/frontend/src/contexts/ViewerContext.tsx +++ b/frontend/src/core/contexts/ViewerContext.tsx @@ -1,6 +1,6 @@ import React, { createContext, useContext, useState, ReactNode, useRef } from 'react'; import { SpreadMode } from '@embedpdf/plugin-spread/react'; -import { useNavigation } from './NavigationContext'; +import { useNavigation } from '@app/contexts/NavigationContext'; // Bridge API interfaces - these match what the bridges provide interface ScrollAPIWrapper { diff --git a/frontend/src/contexts/file/FileReducer.ts b/frontend/src/core/contexts/file/FileReducer.ts similarity index 98% rename from frontend/src/contexts/file/FileReducer.ts rename to frontend/src/core/contexts/file/FileReducer.ts index 3811572c0f..2baa22a861 100644 --- a/frontend/src/contexts/file/FileReducer.ts +++ b/frontend/src/core/contexts/file/FileReducer.ts @@ -2,12 +2,12 @@ * FileContext reducer - Pure state management for file operations */ -import { FileId } from '../../types/file'; +import { FileId } from '@app/types/file'; import { FileContextState, FileContextAction, StirlingFileStub -} from '../../types/fileContext'; +} from '@app/types/fileContext'; // Initial state export const initialFileContextState: FileContextState = { diff --git a/frontend/src/contexts/file/contexts.ts b/frontend/src/core/contexts/file/contexts.ts similarity index 94% rename from frontend/src/contexts/file/contexts.ts rename to frontend/src/core/contexts/file/contexts.ts index 2474f10947..c37da46bbc 100644 --- a/frontend/src/contexts/file/contexts.ts +++ b/frontend/src/core/contexts/file/contexts.ts @@ -3,7 +3,7 @@ */ import { createContext } from 'react'; -import { FileContextStateValue, FileContextActionsValue } from '../../types/fileContext'; +import { FileContextStateValue, FileContextActionsValue } from '@app/types/fileContext'; // Split contexts for performance export const FileStateContext = createContext(undefined); diff --git a/frontend/src/contexts/file/fileActions.ts b/frontend/src/core/contexts/file/fileActions.ts similarity index 97% rename from frontend/src/contexts/file/fileActions.ts rename to frontend/src/core/contexts/file/fileActions.ts index c1b23d4085..5b4d1d2d96 100644 --- a/frontend/src/contexts/file/fileActions.ts +++ b/frontend/src/core/contexts/file/fileActions.ts @@ -11,14 +11,14 @@ import { createQuickKey, createStirlingFile, ProcessedFileMetadata, -} from '../../types/fileContext'; -import { FileId, ToolOperation } from '../../types/file'; -import { generateThumbnailWithMetadata } from '../../utils/thumbnailUtils'; -import { FileLifecycleManager } from './lifecycle'; -import { buildQuickKeySet } from './fileSelectors'; -import { StirlingFile } from '../../types/fileContext'; -import { fileStorage } from '../../services/fileStorage'; -import { zipFileService } from '../../services/zipFileService'; +} from '@app/types/fileContext'; +import { FileId, ToolOperation } from '@app/types/file'; +import { generateThumbnailWithMetadata } from '@app/utils/thumbnailUtils'; +import { FileLifecycleManager } from '@app/contexts/file/lifecycle'; +import { buildQuickKeySet } from '@app/contexts/file/fileSelectors'; +import { StirlingFile } from '@app/types/fileContext'; +import { fileStorage } from '@app/services/fileStorage'; +import { zipFileService } from '@app/services/zipFileService'; const DEBUG = process.env.NODE_ENV === 'development'; /** @@ -281,7 +281,7 @@ export async function addFiles( // Non-PDF files: simple thumbnail generation, no processedFile metadata try { if (DEBUG) console.log(`📄 Generating simple thumbnail for non-PDF file ${file.name}`); - const { generateThumbnailForFile } = await import('../../utils/thumbnailUtils'); + const { generateThumbnailForFile } = await import('@app/utils/thumbnailUtils'); thumbnail = await generateThumbnailForFile(file); if (DEBUG) console.log(`📄 Generated simple thumbnail for ${file.name}: no page count, thumbnail: SUCCESS`); } catch (error) { diff --git a/frontend/src/contexts/file/fileHooks.ts b/frontend/src/core/contexts/file/fileHooks.ts similarity index 97% rename from frontend/src/contexts/file/fileHooks.ts rename to frontend/src/core/contexts/file/fileHooks.ts index e428605627..d046fe87d5 100644 --- a/frontend/src/contexts/file/fileHooks.ts +++ b/frontend/src/core/contexts/file/fileHooks.ts @@ -8,9 +8,9 @@ import { FileActionsContext, FileContextStateValue, FileContextActionsValue -} from './contexts'; -import { StirlingFileStub, StirlingFile } from '../../types/fileContext'; -import { FileId } from '../../types/file'; +} from '@app/contexts/file/contexts'; +import { StirlingFileStub, StirlingFile } from '@app/types/fileContext'; +import { FileId } from '@app/types/file'; /** * Hook for accessing file state (will re-render on any state change) diff --git a/frontend/src/contexts/file/fileSelectors.ts b/frontend/src/core/contexts/file/fileSelectors.ts similarity index 98% rename from frontend/src/contexts/file/fileSelectors.ts rename to frontend/src/core/contexts/file/fileSelectors.ts index a004831cc7..5fa54f33c5 100644 --- a/frontend/src/contexts/file/fileSelectors.ts +++ b/frontend/src/core/contexts/file/fileSelectors.ts @@ -2,14 +2,14 @@ * File selectors - Pure functions for accessing file state */ -import { FileId } from '../../types/file'; +import { FileId } from '@app/types/file'; import { StirlingFileStub, FileContextState, FileContextSelectors, StirlingFile, createStirlingFile -} from '../../types/fileContext'; +} from '@app/types/fileContext'; /** * Create stable selectors using stateRef and filesRef diff --git a/frontend/src/contexts/file/lifecycle.ts b/frontend/src/core/contexts/file/lifecycle.ts similarity index 98% rename from frontend/src/contexts/file/lifecycle.ts rename to frontend/src/core/contexts/file/lifecycle.ts index c65fec127b..93feac3754 100644 --- a/frontend/src/contexts/file/lifecycle.ts +++ b/frontend/src/core/contexts/file/lifecycle.ts @@ -2,8 +2,8 @@ * File lifecycle management - Resource cleanup and memory management */ -import { FileId } from '../../types/file'; -import { FileContextAction, StirlingFileStub, ProcessedFilePage } from '../../types/fileContext'; +import { FileId } from '@app/types/file'; +import { FileContextAction, StirlingFileStub, ProcessedFilePage } from '@app/types/fileContext'; const DEBUG = process.env.NODE_ENV === 'development'; diff --git a/frontend/src/contexts/toolWorkflow/toolWorkflowState.ts b/frontend/src/core/contexts/toolWorkflow/toolWorkflowState.ts similarity index 93% rename from frontend/src/contexts/toolWorkflow/toolWorkflowState.ts rename to frontend/src/core/contexts/toolWorkflow/toolWorkflowState.ts index 5d19b36741..42fdd6f159 100644 --- a/frontend/src/contexts/toolWorkflow/toolWorkflowState.ts +++ b/frontend/src/core/contexts/toolWorkflow/toolWorkflowState.ts @@ -1,5 +1,5 @@ -import { PageEditorFunctions } from '../../types/pageEditor'; -import { type ToolPanelMode, DEFAULT_TOOL_PANEL_MODE } from '../../constants/toolPanel'; +import { PageEditorFunctions } from '@app/types/pageEditor'; +import { type ToolPanelMode, DEFAULT_TOOL_PANEL_MODE } from '@app/constants/toolPanel'; export interface ToolWorkflowState { // UI State diff --git a/frontend/src/data/toolsTaxonomy.ts b/frontend/src/core/data/toolsTaxonomy.ts similarity index 95% rename from frontend/src/data/toolsTaxonomy.ts rename to frontend/src/core/data/toolsTaxonomy.ts index a0204f1ca6..0733d9fcc6 100644 --- a/frontend/src/data/toolsTaxonomy.ts +++ b/frontend/src/core/data/toolsTaxonomy.ts @@ -1,9 +1,9 @@ import { type TFunction } from 'i18next'; import React from 'react'; -import { ToolOperationConfig } from '../hooks/tools/shared/useToolOperation'; -import { BaseToolProps } from '../types/tool'; -import { WorkbenchType } from '../types/workbench'; -import { LinkToolId, RegularToolId, SuperToolId, ToolId, ToolKind } from '../types/toolId'; +import { ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { BaseToolProps } from '@app/types/tool'; +import { WorkbenchType } from '@app/types/workbench'; +import { LinkToolId, RegularToolId, SuperToolId, ToolId, ToolKind } from '@app/types/toolId'; import DrawRoundedIcon from '@mui/icons-material/DrawRounded'; import SecurityRoundedIcon from '@mui/icons-material/SecurityRounded'; import VerifiedUserRoundedIcon from '@mui/icons-material/VerifiedUserRounded'; @@ -15,6 +15,7 @@ import SmartToyRoundedIcon from '@mui/icons-material/SmartToyRounded'; import BuildRoundedIcon from '@mui/icons-material/BuildRounded'; import TuneRoundedIcon from '@mui/icons-material/TuneRounded'; import CodeRoundedIcon from '@mui/icons-material/CodeRounded'; +import { ProprietaryToolId } from '@app/types/proprietaryToolId'; export enum SubcategoryId { SIGNING = 'signing', @@ -64,6 +65,7 @@ export type RegularToolRegistry = Record; export type SuperToolRegistry = Record; export type LinkToolRegistry = Record; export type ToolRegistry = Record; +export type ProprietaryToolRegistry = Record; export const SUBCATEGORY_ORDER: SubcategoryId[] = [ SubcategoryId.SIGNING, diff --git a/frontend/src/core/data/useProprietaryToolRegistry.tsx b/frontend/src/core/data/useProprietaryToolRegistry.tsx new file mode 100644 index 0000000000..d0a64efa58 --- /dev/null +++ b/frontend/src/core/data/useProprietaryToolRegistry.tsx @@ -0,0 +1,15 @@ +import { useMemo } from "react"; +import { type ProprietaryToolRegistry } from "@app/data/toolsTaxonomy"; + +/** + * Proprietary tool registry extension. + * This file is overridden in src/proprietary/data/useProprietaryToolRegistry.tsx + * to add proprietary-specific tools. + * + * No tools should be defined in this file. + */ + +// Empty hook that returns empty registry (overridden in proprietary version) +export function useProprietaryToolRegistry(): ProprietaryToolRegistry { + return useMemo(() => ({} as ProprietaryToolRegistry), []); +} diff --git a/frontend/src/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx similarity index 78% rename from frontend/src/data/useTranslatedToolRegistry.tsx rename to frontend/src/core/data/useTranslatedToolRegistry.tsx index f3b22dcc4e..0860b5d965 100644 --- a/frontend/src/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -1,18 +1,18 @@ import { useMemo } from "react"; -import LocalIcon from "../components/shared/LocalIcon"; +import LocalIcon from "@app/components/shared/LocalIcon"; import { useTranslation } from "react-i18next"; -import SplitPdfPanel from "../tools/Split"; -import CompressPdfPanel from "../tools/Compress"; -import OCRPanel from "../tools/OCR"; -import ConvertPanel from "../tools/Convert"; -import Sanitize from "../tools/Sanitize"; -import AddPassword from "../tools/AddPassword"; -import ChangePermissions from "../tools/ChangePermissions"; -import RemoveBlanks from "../tools/RemoveBlanks"; -import RemovePages from "../tools/RemovePages"; -import ReorganizePages from "../tools/ReorganizePages"; -import { reorganizePagesOperationConfig } from "../hooks/tools/reorganizePages/useReorganizePagesOperation"; -import RemovePassword from "../tools/RemovePassword"; +import SplitPdfPanel from "@app/tools/Split"; +import CompressPdfPanel from "@app/tools/Compress"; +import OCRPanel from "@app/tools/OCR"; +import ConvertPanel from "@app/tools/Convert"; +import Sanitize from "@app/tools/Sanitize"; +import AddPassword from "@app/tools/AddPassword"; +import ChangePermissions from "@app/tools/ChangePermissions"; +import RemoveBlanks from "@app/tools/RemoveBlanks"; +import RemovePages from "@app/tools/RemovePages"; +import ReorganizePages from "@app/tools/ReorganizePages"; +import { reorganizePagesOperationConfig } from "@app/hooks/tools/reorganizePages/useReorganizePagesOperation"; +import RemovePassword from "@app/tools/RemovePassword"; import { SubcategoryId, ToolCategoryId, @@ -20,105 +20,106 @@ import { RegularToolRegistry, SuperToolRegistry, LinkToolRegistry, -} from "./toolsTaxonomy"; -import { isSuperToolId, isLinkToolId } from '../types/toolId'; -import AdjustContrast from "../tools/AdjustContrast"; -import AdjustContrastSingleStepSettings from "../components/tools/adjustContrast/AdjustContrastSingleStepSettings"; -import { adjustContrastOperationConfig } from "../hooks/tools/adjustContrast/useAdjustContrastOperation"; -import { getSynonyms } from "../utils/toolSynonyms"; -import AddWatermark from "../tools/AddWatermark"; -import AddStamp from "../tools/AddStamp"; -import AddAttachments from "../tools/AddAttachments"; -import Merge from '../tools/Merge'; -import Repair from "../tools/Repair"; -import AutoRename from "../tools/AutoRename"; -import SingleLargePage from "../tools/SingleLargePage"; -import PageLayout from "../tools/PageLayout"; -import UnlockPdfForms from "../tools/UnlockPdfForms"; -import RemoveCertificateSign from "../tools/RemoveCertificateSign"; -import RemoveImage from "../tools/RemoveImage"; -import CertSign from "../tools/CertSign"; -import BookletImposition from "../tools/BookletImposition"; -import Flatten from "../tools/Flatten"; -import Rotate from "../tools/Rotate"; -import ChangeMetadata from "../tools/ChangeMetadata"; -import Crop from "../tools/Crop"; -import Sign from "../tools/Sign"; -import { compressOperationConfig } from "../hooks/tools/compress/useCompressOperation"; -import { splitOperationConfig } from "../hooks/tools/split/useSplitOperation"; -import { addPasswordOperationConfig } from "../hooks/tools/addPassword/useAddPasswordOperation"; -import { removePasswordOperationConfig } from "../hooks/tools/removePassword/useRemovePasswordOperation"; -import { sanitizeOperationConfig } from "../hooks/tools/sanitize/useSanitizeOperation"; -import { repairOperationConfig } from "../hooks/tools/repair/useRepairOperation"; -import { addWatermarkOperationConfig } from "../hooks/tools/addWatermark/useAddWatermarkOperation"; -import { addStampOperationConfig } from "../components/tools/addStamp/useAddStampOperation"; -import { addAttachmentsOperationConfig } from "../hooks/tools/addAttachments/useAddAttachmentsOperation"; -import { unlockPdfFormsOperationConfig } from "../hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation"; -import { singleLargePageOperationConfig } from "../hooks/tools/singleLargePage/useSingleLargePageOperation"; -import { ocrOperationConfig } from "../hooks/tools/ocr/useOCROperation"; -import { convertOperationConfig } from "../hooks/tools/convert/useConvertOperation"; -import { removeCertificateSignOperationConfig } from "../hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation"; -import { changePermissionsOperationConfig } from "../hooks/tools/changePermissions/useChangePermissionsOperation"; -import { certSignOperationConfig } from "../hooks/tools/certSign/useCertSignOperation"; -import { bookletImpositionOperationConfig } from "../hooks/tools/bookletImposition/useBookletImpositionOperation"; -import { mergeOperationConfig } from '../hooks/tools/merge/useMergeOperation'; -import { autoRenameOperationConfig } from "../hooks/tools/autoRename/useAutoRenameOperation"; -import { flattenOperationConfig } from "../hooks/tools/flatten/useFlattenOperation"; -import { redactOperationConfig } from "../hooks/tools/redact/useRedactOperation"; -import { rotateOperationConfig } from "../hooks/tools/rotate/useRotateOperation"; -import { changeMetadataOperationConfig } from "../hooks/tools/changeMetadata/useChangeMetadataOperation"; -import { signOperationConfig } from "../hooks/tools/sign/useSignOperation"; -import { cropOperationConfig } from "../hooks/tools/crop/useCropOperation"; -import { removeAnnotationsOperationConfig } from "../hooks/tools/removeAnnotations/useRemoveAnnotationsOperation"; -import { extractImagesOperationConfig } from "../hooks/tools/extractImages/useExtractImagesOperation"; -import { replaceColorOperationConfig } from "../hooks/tools/replaceColor/useReplaceColorOperation"; -import { removePagesOperationConfig } from "../hooks/tools/removePages/useRemovePagesOperation"; -import { removeBlanksOperationConfig } from "../hooks/tools/removeBlanks/useRemoveBlanksOperation"; -import { overlayPdfsOperationConfig } from "../hooks/tools/overlayPdfs/useOverlayPdfsOperation"; -import { adjustPageScaleOperationConfig } from "../hooks/tools/adjustPageScale/useAdjustPageScaleOperation"; -import { scannerImageSplitOperationConfig } from "../hooks/tools/scannerImageSplit/useScannerImageSplitOperation"; -import { addPageNumbersOperationConfig } from "../components/tools/addPageNumbers/useAddPageNumbersOperation"; -import CompressSettings from "../components/tools/compress/CompressSettings"; -import AddPasswordSettings from "../components/tools/addPassword/AddPasswordSettings"; -import RemovePasswordSettings from "../components/tools/removePassword/RemovePasswordSettings"; -import SanitizeSettings from "../components/tools/sanitize/SanitizeSettings"; -import AddWatermarkSingleStepSettings from "../components/tools/addWatermark/AddWatermarkSingleStepSettings"; -import OCRSettings from "../components/tools/ocr/OCRSettings"; -import ConvertSettings from "../components/tools/convert/ConvertSettings"; -import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings"; -import BookletImpositionSettings from "../components/tools/bookletImposition/BookletImpositionSettings"; -import FlattenSettings from "../components/tools/flatten/FlattenSettings"; -import RedactSingleStepSettings from "../components/tools/redact/RedactSingleStepSettings"; -import Redact from "../tools/Redact"; -import AdjustPageScale from "../tools/AdjustPageScale"; -import ReplaceColor from "../tools/ReplaceColor"; -import ScannerImageSplit from "../tools/ScannerImageSplit"; -import OverlayPdfs from "../tools/OverlayPdfs"; -import { ToolId } from "../types/toolId"; -import MergeSettings from '../components/tools/merge/MergeSettings'; -import AdjustPageScaleSettings from "../components/tools/adjustPageScale/AdjustPageScaleSettings"; -import ScannerImageSplitSettings from "../components/tools/scannerImageSplit/ScannerImageSplitSettings"; -import ChangeMetadataSingleStep from "../components/tools/changeMetadata/ChangeMetadataSingleStep"; -import SignSettings from "../components/tools/sign/SignSettings"; -import AddPageNumbers from "../tools/AddPageNumbers"; -import RemoveAnnotations from "../tools/RemoveAnnotations"; -import PageLayoutSettings from "../components/tools/pageLayout/PageLayoutSettings"; -import ExtractImages from "../tools/ExtractImages"; -import ExtractImagesSettings from "../components/tools/extractImages/ExtractImagesSettings"; -import ReplaceColorSettings from "../components/tools/replaceColor/ReplaceColorSettings"; -import AddStampAutomationSettings from "../components/tools/addStamp/AddStampAutomationSettings"; -import CertSignAutomationSettings from "../components/tools/certSign/CertSignAutomationSettings"; -import CropAutomationSettings from "../components/tools/crop/CropAutomationSettings"; -import RotateAutomationSettings from "../components/tools/rotate/RotateAutomationSettings"; -import SplitAutomationSettings from "../components/tools/split/SplitAutomationSettings"; -import AddAttachmentsSettings from "../components/tools/addAttachments/AddAttachmentsSettings"; -import RemovePagesSettings from "../components/tools/removePages/RemovePagesSettings"; -import RemoveBlanksSettings from "../components/tools/removeBlanks/RemoveBlanksSettings"; -import AddPageNumbersAutomationSettings from "../components/tools/addPageNumbers/AddPageNumbersAutomationSettings"; -import OverlayPdfsSettings from "../components/tools/overlayPdfs/OverlayPdfsSettings"; -import ValidateSignature from "../tools/ValidateSignature"; -import Automate from "../tools/Automate"; -import { CONVERT_SUPPORTED_FORMATS } from "../constants/convertSupportedFornats"; +} from "@app/data/toolsTaxonomy"; +import { isSuperToolId, isLinkToolId } from '@app/types/toolId'; +import AdjustContrast from "@app/tools/AdjustContrast"; +import AdjustContrastSingleStepSettings from "@app/components/tools/adjustContrast/AdjustContrastSingleStepSettings"; +import { adjustContrastOperationConfig } from "@app/hooks/tools/adjustContrast/useAdjustContrastOperation"; +import { getSynonyms } from "@app/utils/toolSynonyms"; +import { useProprietaryToolRegistry } from "@app/data/useProprietaryToolRegistry"; +import AddWatermark from "@app/tools/AddWatermark"; +import AddStamp from "@app/tools/AddStamp"; +import AddAttachments from "@app/tools/AddAttachments"; +import Merge from '@app/tools/Merge'; +import Repair from "@app/tools/Repair"; +import AutoRename from "@app/tools/AutoRename"; +import SingleLargePage from "@app/tools/SingleLargePage"; +import PageLayout from "@app/tools/PageLayout"; +import UnlockPdfForms from "@app/tools/UnlockPdfForms"; +import RemoveCertificateSign from "@app/tools/RemoveCertificateSign"; +import RemoveImage from "@app/tools/RemoveImage"; +import CertSign from "@app/tools/CertSign"; +import BookletImposition from "@app/tools/BookletImposition"; +import Flatten from "@app/tools/Flatten"; +import Rotate from "@app/tools/Rotate"; +import ChangeMetadata from "@app/tools/ChangeMetadata"; +import Crop from "@app/tools/Crop"; +import Sign from "@app/tools/Sign"; +import { compressOperationConfig } from "@app/hooks/tools/compress/useCompressOperation"; +import { splitOperationConfig } from "@app/hooks/tools/split/useSplitOperation"; +import { addPasswordOperationConfig } from "@app/hooks/tools/addPassword/useAddPasswordOperation"; +import { removePasswordOperationConfig } from "@app/hooks/tools/removePassword/useRemovePasswordOperation"; +import { sanitizeOperationConfig } from "@app/hooks/tools/sanitize/useSanitizeOperation"; +import { repairOperationConfig } from "@app/hooks/tools/repair/useRepairOperation"; +import { addWatermarkOperationConfig } from "@app/hooks/tools/addWatermark/useAddWatermarkOperation"; +import { addStampOperationConfig } from "@app/components/tools/addStamp/useAddStampOperation"; +import { addAttachmentsOperationConfig } from "@app/hooks/tools/addAttachments/useAddAttachmentsOperation"; +import { unlockPdfFormsOperationConfig } from "@app/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation"; +import { singleLargePageOperationConfig } from "@app/hooks/tools/singleLargePage/useSingleLargePageOperation"; +import { ocrOperationConfig } from "@app/hooks/tools/ocr/useOCROperation"; +import { convertOperationConfig } from "@app/hooks/tools/convert/useConvertOperation"; +import { removeCertificateSignOperationConfig } from "@app/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation"; +import { changePermissionsOperationConfig } from "@app/hooks/tools/changePermissions/useChangePermissionsOperation"; +import { certSignOperationConfig } from "@app/hooks/tools/certSign/useCertSignOperation"; +import { bookletImpositionOperationConfig } from "@app/hooks/tools/bookletImposition/useBookletImpositionOperation"; +import { mergeOperationConfig } from '@app/hooks/tools/merge/useMergeOperation'; +import { autoRenameOperationConfig } from "@app/hooks/tools/autoRename/useAutoRenameOperation"; +import { flattenOperationConfig } from "@app/hooks/tools/flatten/useFlattenOperation"; +import { redactOperationConfig } from "@app/hooks/tools/redact/useRedactOperation"; +import { rotateOperationConfig } from "@app/hooks/tools/rotate/useRotateOperation"; +import { changeMetadataOperationConfig } from "@app/hooks/tools/changeMetadata/useChangeMetadataOperation"; +import { signOperationConfig } from "@app/hooks/tools/sign/useSignOperation"; +import { cropOperationConfig } from "@app/hooks/tools/crop/useCropOperation"; +import { removeAnnotationsOperationConfig } from "@app/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation"; +import { extractImagesOperationConfig } from "@app/hooks/tools/extractImages/useExtractImagesOperation"; +import { replaceColorOperationConfig } from "@app/hooks/tools/replaceColor/useReplaceColorOperation"; +import { removePagesOperationConfig } from "@app/hooks/tools/removePages/useRemovePagesOperation"; +import { removeBlanksOperationConfig } from "@app/hooks/tools/removeBlanks/useRemoveBlanksOperation"; +import { overlayPdfsOperationConfig } from "@app/hooks/tools/overlayPdfs/useOverlayPdfsOperation"; +import { adjustPageScaleOperationConfig } from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleOperation"; +import { scannerImageSplitOperationConfig } from "@app/hooks/tools/scannerImageSplit/useScannerImageSplitOperation"; +import { addPageNumbersOperationConfig } from "@app/components/tools/addPageNumbers/useAddPageNumbersOperation"; +import CompressSettings from "@app/components/tools/compress/CompressSettings"; +import AddPasswordSettings from "@app/components/tools/addPassword/AddPasswordSettings"; +import RemovePasswordSettings from "@app/components/tools/removePassword/RemovePasswordSettings"; +import SanitizeSettings from "@app/components/tools/sanitize/SanitizeSettings"; +import AddWatermarkSingleStepSettings from "@app/components/tools/addWatermark/AddWatermarkSingleStepSettings"; +import OCRSettings from "@app/components/tools/ocr/OCRSettings"; +import ConvertSettings from "@app/components/tools/convert/ConvertSettings"; +import ChangePermissionsSettings from "@app/components/tools/changePermissions/ChangePermissionsSettings"; +import BookletImpositionSettings from "@app/components/tools/bookletImposition/BookletImpositionSettings"; +import FlattenSettings from "@app/components/tools/flatten/FlattenSettings"; +import RedactSingleStepSettings from "@app/components/tools/redact/RedactSingleStepSettings"; +import Redact from "@app/tools/Redact"; +import AdjustPageScale from "@app/tools/AdjustPageScale"; +import ReplaceColor from "@app/tools/ReplaceColor"; +import ScannerImageSplit from "@app/tools/ScannerImageSplit"; +import OverlayPdfs from "@app/tools/OverlayPdfs"; +import { ToolId } from "@app/types/toolId"; +import MergeSettings from '@app/components/tools/merge/MergeSettings'; +import AdjustPageScaleSettings from "@app/components/tools/adjustPageScale/AdjustPageScaleSettings"; +import ScannerImageSplitSettings from "@app/components/tools/scannerImageSplit/ScannerImageSplitSettings"; +import ChangeMetadataSingleStep from "@app/components/tools/changeMetadata/ChangeMetadataSingleStep"; +import SignSettings from "@app/components/tools/sign/SignSettings"; +import AddPageNumbers from "@app/tools/AddPageNumbers"; +import RemoveAnnotations from "@app/tools/RemoveAnnotations"; +import PageLayoutSettings from "@app/components/tools/pageLayout/PageLayoutSettings"; +import ExtractImages from "@app/tools/ExtractImages"; +import ExtractImagesSettings from "@app/components/tools/extractImages/ExtractImagesSettings"; +import ReplaceColorSettings from "@app/components/tools/replaceColor/ReplaceColorSettings"; +import AddStampAutomationSettings from "@app/components/tools/addStamp/AddStampAutomationSettings"; +import CertSignAutomationSettings from "@app/components/tools/certSign/CertSignAutomationSettings"; +import CropAutomationSettings from "@app/components/tools/crop/CropAutomationSettings"; +import RotateAutomationSettings from "@app/components/tools/rotate/RotateAutomationSettings"; +import SplitAutomationSettings from "@app/components/tools/split/SplitAutomationSettings"; +import AddAttachmentsSettings from "@app/components/tools/addAttachments/AddAttachmentsSettings"; +import RemovePagesSettings from "@app/components/tools/removePages/RemovePagesSettings"; +import RemoveBlanksSettings from "@app/components/tools/removeBlanks/RemoveBlanksSettings"; +import AddPageNumbersAutomationSettings from "@app/components/tools/addPageNumbers/AddPageNumbersAutomationSettings"; +import OverlayPdfsSettings from "@app/components/tools/overlayPdfs/OverlayPdfsSettings"; +import ValidateSignature from "@app/tools/ValidateSignature"; +import Automate from "@app/tools/Automate"; +import { CONVERT_SUPPORTED_FORMATS } from "@app/constants/convertSupportedFornats"; export interface TranslatedToolCatalog { allTools: ToolRegistry; @@ -130,9 +131,12 @@ export interface TranslatedToolCatalog { // Hook to get the translated tool registry export function useTranslatedToolCatalog(): TranslatedToolCatalog { const { t } = useTranslation(); + const proprietaryTools = useProprietaryToolRegistry(); return useMemo(() => { const allTools: ToolRegistry = { + // Proprietary tools (if any) + ...proprietaryTools, // Recommended Tools in order multiTool: { icon: , @@ -862,5 +866,5 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { superTools, linkTools, }; - }, [t]); // Only re-compute when translations change + }, [t, proprietaryTools]); // Re-compute when translations or proprietary tools change } diff --git a/frontend/src/hooks/tools/addAttachments/useAddAttachmentsOperation.ts b/frontend/src/core/hooks/tools/addAttachments/useAddAttachmentsOperation.ts similarity index 83% rename from frontend/src/hooks/tools/addAttachments/useAddAttachmentsOperation.ts rename to frontend/src/core/hooks/tools/addAttachments/useAddAttachmentsOperation.ts index 91e216c188..9785fa9982 100644 --- a/frontend/src/hooks/tools/addAttachments/useAddAttachmentsOperation.ts +++ b/frontend/src/core/hooks/tools/addAttachments/useAddAttachmentsOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AddAttachmentsParameters } from './useAddAttachmentsParameters'; +import { useToolOperation, ToolOperationConfig, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AddAttachmentsParameters } from '@app/hooks/tools/addAttachments/useAddAttachmentsParameters'; const buildFormData = (parameters: AddAttachmentsParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/addAttachments/useAddAttachmentsParameters.ts b/frontend/src/core/hooks/tools/addAttachments/useAddAttachmentsParameters.ts similarity index 100% rename from frontend/src/hooks/tools/addAttachments/useAddAttachmentsParameters.ts rename to frontend/src/core/hooks/tools/addAttachments/useAddAttachmentsParameters.ts diff --git a/frontend/src/hooks/tools/addPassword/useAddPasswordOperation.test.ts b/frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.test.ts similarity index 93% rename from frontend/src/hooks/tools/addPassword/useAddPasswordOperation.test.ts rename to frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.test.ts index fe254aac5d..7a1b1753ea 100644 --- a/frontend/src/hooks/tools/addPassword/useAddPasswordOperation.test.ts +++ b/frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { useAddPasswordOperation } from './useAddPasswordOperation'; -import type { AddPasswordFullParameters } from './useAddPasswordParameters'; +import { useAddPasswordOperation } from '@app/hooks/tools/addPassword/useAddPasswordOperation'; +import type { AddPasswordFullParameters } from '@app/hooks/tools/addPassword/useAddPasswordParameters'; // Mock the useToolOperation hook vi.mock('../shared/useToolOperation', async () => { @@ -24,7 +24,7 @@ vi.mock('../../../utils/toolErrorHandler', () => ({ })); // Import the mocked function -import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '../shared/useToolOperation'; +import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; describe('useAddPasswordOperation', () => { diff --git a/frontend/src/hooks/tools/addPassword/useAddPasswordOperation.ts b/frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.ts similarity index 73% rename from frontend/src/hooks/tools/addPassword/useAddPasswordOperation.ts rename to frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.ts index f271a5a5a0..7b8e003f78 100644 --- a/frontend/src/hooks/tools/addPassword/useAddPasswordOperation.ts +++ b/frontend/src/core/hooks/tools/addPassword/useAddPasswordOperation.ts @@ -1,9 +1,9 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AddPasswordFullParameters, defaultParameters } from './useAddPasswordParameters'; -import { defaultParameters as permissionsDefaults } from '../changePermissions/useChangePermissionsParameters'; -import { getFormData } from '../changePermissions/useChangePermissionsOperation'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AddPasswordFullParameters, defaultParameters } from '@app/hooks/tools/addPassword/useAddPasswordParameters'; +import { defaultParameters as permissionsDefaults } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; +import { getFormData } from '@app/hooks/tools/changePermissions/useChangePermissionsOperation'; // Static function that can be used by both the hook and automation executor export const buildAddPasswordFormData = (parameters: AddPasswordFullParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/addPassword/useAddPasswordParameters.test.ts b/frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.test.ts similarity index 96% rename from frontend/src/hooks/tools/addPassword/useAddPasswordParameters.test.ts rename to frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.test.ts index 92a8760871..7c09938c57 100644 --- a/frontend/src/hooks/tools/addPassword/useAddPasswordParameters.test.ts +++ b/frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useAddPasswordParameters, defaultParameters, AddPasswordParametersHook } from './useAddPasswordParameters'; -import { defaultParameters as defaultChangePermissionsParameters, ChangePermissionsParameters } from '../changePermissions/useChangePermissionsParameters'; +import { useAddPasswordParameters, defaultParameters, AddPasswordParametersHook } from '@app/hooks/tools/addPassword/useAddPasswordParameters'; +import { defaultParameters as defaultChangePermissionsParameters, ChangePermissionsParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; describe('useAddPasswordParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/addPassword/useAddPasswordParameters.ts b/frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.ts similarity index 83% rename from frontend/src/hooks/tools/addPassword/useAddPasswordParameters.ts rename to frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.ts index 50fe74d569..9c05e8f015 100644 --- a/frontend/src/hooks/tools/addPassword/useAddPasswordParameters.ts +++ b/frontend/src/core/hooks/tools/addPassword/useAddPasswordParameters.ts @@ -1,6 +1,6 @@ -import { ChangePermissionsParameters, ChangePermissionsParametersHook, useChangePermissionsParameters } from '../changePermissions/useChangePermissionsParameters'; -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { ChangePermissionsParameters, ChangePermissionsParametersHook, useChangePermissionsParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AddPasswordParameters extends BaseParameters { password: string; diff --git a/frontend/src/hooks/tools/addWatermark/useAddWatermarkOperation.ts b/frontend/src/core/hooks/tools/addWatermark/useAddWatermarkOperation.ts similarity index 87% rename from frontend/src/hooks/tools/addWatermark/useAddWatermarkOperation.ts rename to frontend/src/core/hooks/tools/addWatermark/useAddWatermarkOperation.ts index d718a17621..6dcdec4eb9 100644 --- a/frontend/src/hooks/tools/addWatermark/useAddWatermarkOperation.ts +++ b/frontend/src/core/hooks/tools/addWatermark/useAddWatermarkOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AddWatermarkParameters, defaultParameters } from './useAddWatermarkParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AddWatermarkParameters, defaultParameters } from '@app/hooks/tools/addWatermark/useAddWatermarkParameters'; // Static function that can be used by both the hook and automation executor export const buildAddWatermarkFormData = (parameters: AddWatermarkParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/addWatermark/useAddWatermarkParameters.ts b/frontend/src/core/hooks/tools/addWatermark/useAddWatermarkParameters.ts similarity index 88% rename from frontend/src/hooks/tools/addWatermark/useAddWatermarkParameters.ts rename to frontend/src/core/hooks/tools/addWatermark/useAddWatermarkParameters.ts index 5b9a25da66..53a89abb9b 100644 --- a/frontend/src/hooks/tools/addWatermark/useAddWatermarkParameters.ts +++ b/frontend/src/core/hooks/tools/addWatermark/useAddWatermarkParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AddWatermarkParameters extends BaseParameters { watermarkType?: 'text' | 'image'; diff --git a/frontend/src/hooks/tools/adjustContrast/useAdjustContrastOperation.ts b/frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastOperation.ts similarity index 89% rename from frontend/src/hooks/tools/adjustContrast/useAdjustContrastOperation.ts rename to frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastOperation.ts index c52ed98649..176ddd4b5f 100644 --- a/frontend/src/hooks/tools/adjustContrast/useAdjustContrastOperation.ts +++ b/frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastOperation.ts @@ -1,10 +1,10 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { AdjustContrastParameters, defaultParameters } from './useAdjustContrastParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { AdjustContrastParameters, defaultParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; import { PDFDocument as PDFLibDocument } from 'pdf-lib'; -import { applyAdjustmentsToCanvas } from '../../../components/tools/adjustContrast/utils'; -import { pdfWorkerManager } from '../../../services/pdfWorkerManager'; -import { createFileFromApiResponse } from '../../../utils/fileResponseUtils'; +import { applyAdjustmentsToCanvas } from '@app/components/tools/adjustContrast/utils'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { createFileFromApiResponse } from '@app/utils/fileResponseUtils'; async function renderPdfPageToCanvas(pdf: any, pageNumber: number, scale: number): Promise { const page = await pdf.getPage(pageNumber); diff --git a/frontend/src/hooks/tools/adjustContrast/useAdjustContrastParameters.ts b/frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastParameters.ts similarity index 88% rename from frontend/src/hooks/tools/adjustContrast/useAdjustContrastParameters.ts rename to frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastParameters.ts index 14dd543d88..9160c0ce74 100644 --- a/frontend/src/hooks/tools/adjustContrast/useAdjustContrastParameters.ts +++ b/frontend/src/core/hooks/tools/adjustContrast/useAdjustContrastParameters.ts @@ -1,4 +1,4 @@ -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AdjustContrastParameters { contrast: number; // 0-200 (%), 100 = neutral diff --git a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts similarity index 76% rename from frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts rename to frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts index 458e7fda1b..bf95b9854f 100644 --- a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts +++ b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AdjustPageScaleParameters, defaultParameters } from './useAdjustPageScaleParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AdjustPageScaleParameters, defaultParameters } from '@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters'; export const buildAdjustPageScaleFormData = (parameters: AdjustPageScaleParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts similarity index 97% rename from frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts rename to frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts index d68cdd861d..6fb9ef71e3 100644 --- a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts +++ b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useAdjustPageScaleParameters, defaultParameters, PageSize, AdjustPageScaleParametersHook } from './useAdjustPageScaleParameters'; +import { useAdjustPageScaleParameters, defaultParameters, PageSize, AdjustPageScaleParametersHook } from '@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters'; describe('useAdjustPageScaleParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts similarity index 82% rename from frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts rename to frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts index 108d7d3ead..07c6dff842 100644 --- a/frontend/src/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts +++ b/frontend/src/core/hooks/tools/adjustPageScale/useAdjustPageScaleParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export enum PageSize { KEEP = 'KEEP', diff --git a/frontend/src/hooks/tools/autoRename/useAutoRenameOperation.ts b/frontend/src/core/hooks/tools/autoRename/useAutoRenameOperation.ts similarity index 81% rename from frontend/src/hooks/tools/autoRename/useAutoRenameOperation.ts rename to frontend/src/core/hooks/tools/autoRename/useAutoRenameOperation.ts index 237cc7cf6e..60c7887ff7 100644 --- a/frontend/src/hooks/tools/autoRename/useAutoRenameOperation.ts +++ b/frontend/src/core/hooks/tools/autoRename/useAutoRenameOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { AutoRenameParameters, defaultParameters } from './useAutoRenameParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { AutoRenameParameters, defaultParameters } from '@app/hooks/tools/autoRename/useAutoRenameParameters'; export const getFormData = ((parameters: AutoRenameParameters) => Object.entries(parameters).map(([key, value]) => diff --git a/frontend/src/hooks/tools/autoRename/useAutoRenameParameters.ts b/frontend/src/core/hooks/tools/autoRename/useAutoRenameParameters.ts similarity index 74% rename from frontend/src/hooks/tools/autoRename/useAutoRenameParameters.ts rename to frontend/src/core/hooks/tools/autoRename/useAutoRenameParameters.ts index ede570c332..7e6e149ce3 100644 --- a/frontend/src/hooks/tools/autoRename/useAutoRenameParameters.ts +++ b/frontend/src/core/hooks/tools/autoRename/useAutoRenameParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface AutoRenameParameters extends BaseParameters { useFirstTextAsFallback: boolean; diff --git a/frontend/src/hooks/tools/automate/useAutomateOperation.ts b/frontend/src/core/hooks/tools/automate/useAutomateOperation.ts similarity index 84% rename from frontend/src/hooks/tools/automate/useAutomateOperation.ts rename to frontend/src/core/hooks/tools/automate/useAutomateOperation.ts index e7a2ea19ca..004f289027 100644 --- a/frontend/src/hooks/tools/automate/useAutomateOperation.ts +++ b/frontend/src/core/hooks/tools/automate/useAutomateOperation.ts @@ -1,8 +1,8 @@ -import { ToolType, useToolOperation } from '../shared/useToolOperation'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; import { useCallback } from 'react'; -import { executeAutomationSequence } from '../../../utils/automationExecutor'; -import { useToolRegistry } from '../../../contexts/ToolRegistryContext'; -import { AutomateParameters } from '../../../types/automation'; +import { executeAutomationSequence } from '@app/utils/automationExecutor'; +import { useToolRegistry } from '@app/contexts/ToolRegistryContext'; +import { AutomateParameters } from '@app/types/automation'; export function useAutomateOperation() { const { allTools } = useToolRegistry(); diff --git a/frontend/src/hooks/tools/automate/useAutomationForm.ts b/frontend/src/core/hooks/tools/automate/useAutomationForm.ts similarity index 95% rename from frontend/src/hooks/tools/automate/useAutomationForm.ts rename to frontend/src/core/hooks/tools/automate/useAutomationForm.ts index 91df79ac90..c86d112d64 100644 --- a/frontend/src/hooks/tools/automate/useAutomationForm.ts +++ b/frontend/src/core/hooks/tools/automate/useAutomationForm.ts @@ -1,9 +1,9 @@ import { useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { AutomationTool, AutomationConfig, AutomationMode } from '../../../types/automation'; -import { AUTOMATION_CONSTANTS } from '../../../constants/automation'; -import { ToolRegistry } from '../../../data/toolsTaxonomy'; -import { ToolId } from 'src/types/toolId'; +import { AutomationTool, AutomationConfig, AutomationMode } from '@app/types/automation'; +import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import { ToolId } from "@app/types/toolId"; interface UseAutomationFormProps { diff --git a/frontend/src/hooks/tools/automate/useSavedAutomations.ts b/frontend/src/core/hooks/tools/automate/useSavedAutomations.ts similarity index 87% rename from frontend/src/hooks/tools/automate/useSavedAutomations.ts rename to frontend/src/core/hooks/tools/automate/useSavedAutomations.ts index 8ad7a80b6f..a4bba4857a 100644 --- a/frontend/src/hooks/tools/automate/useSavedAutomations.ts +++ b/frontend/src/core/hooks/tools/automate/useSavedAutomations.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; -import { AutomationConfig } from '../../../services/automationStorage'; -import { SuggestedAutomation } from '../../../types/automation'; +import { AutomationConfig } from '@app/services/automationStorage'; +import { SuggestedAutomation } from '@app/types/automation'; export interface SavedAutomation extends AutomationConfig {} @@ -13,7 +13,7 @@ export function useSavedAutomations() { try { setLoading(true); setError(null); - const { automationStorage } = await import('../../../services/automationStorage'); + const { automationStorage } = await import('@app/services/automationStorage'); const automations = await automationStorage.getAllAutomations(); setSavedAutomations(automations); } catch (err) { @@ -31,7 +31,7 @@ export function useSavedAutomations() { const deleteAutomation = useCallback(async (id: string) => { try { - const { automationStorage } = await import('../../../services/automationStorage'); + const { automationStorage } = await import('@app/services/automationStorage'); await automationStorage.deleteAutomation(id); // Refresh the list after deletion refreshAutomations(); @@ -43,7 +43,7 @@ export function useSavedAutomations() { const copyFromSuggested = useCallback(async (suggestedAutomation: SuggestedAutomation) => { try { - const { automationStorage } = await import('../../../services/automationStorage'); + const { automationStorage } = await import('@app/services/automationStorage'); // Map suggested automation icons to MUI icon keys const getIconKey = (_suggestedIcon: {id: string}): string => { diff --git a/frontend/src/hooks/tools/automate/useSuggestedAutomations.ts b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts similarity index 97% rename from frontend/src/hooks/tools/automate/useSuggestedAutomations.ts rename to frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts index dfa2b79b57..3783800500 100644 --- a/frontend/src/hooks/tools/automate/useSuggestedAutomations.ts +++ b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts @@ -1,9 +1,9 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import React from 'react'; -import LocalIcon from '../../../components/shared/LocalIcon'; -import { SuggestedAutomation } from '../../../types/automation'; -import { SPLIT_METHODS } from '../../../constants/splitConstants'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { SuggestedAutomation } from '@app/types/automation'; +import { SPLIT_METHODS } from '@app/constants/splitConstants'; // Create icon components const CompressIcon = () => React.createElement(LocalIcon, { icon: 'compress', width: '1.5rem', height: '1.5rem' }); diff --git a/frontend/src/hooks/tools/bookletImposition/useBookletImpositionOperation.ts b/frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionOperation.ts similarity index 87% rename from frontend/src/hooks/tools/bookletImposition/useBookletImpositionOperation.ts rename to frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionOperation.ts index 5daed63c3a..c01fde036d 100644 --- a/frontend/src/hooks/tools/bookletImposition/useBookletImpositionOperation.ts +++ b/frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { BookletImpositionParameters, defaultParameters } from './useBookletImpositionParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { BookletImpositionParameters, defaultParameters } from '@app/hooks/tools/bookletImposition/useBookletImpositionParameters'; // Static configuration that can be used by both the hook and automation executor export const buildBookletImpositionFormData = (parameters: BookletImpositionParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/bookletImposition/useBookletImpositionParameters.ts b/frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionParameters.ts similarity index 85% rename from frontend/src/hooks/tools/bookletImposition/useBookletImpositionParameters.ts rename to frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionParameters.ts index fd794379b7..dd7442398d 100644 --- a/frontend/src/hooks/tools/bookletImposition/useBookletImpositionParameters.ts +++ b/frontend/src/core/hooks/tools/bookletImposition/useBookletImpositionParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface BookletImpositionParameters extends BaseParameters { pagesPerSheet: 2; diff --git a/frontend/src/hooks/tools/certSign/useCertSignOperation.ts b/frontend/src/core/hooks/tools/certSign/useCertSignOperation.ts similarity index 88% rename from frontend/src/hooks/tools/certSign/useCertSignOperation.ts rename to frontend/src/core/hooks/tools/certSign/useCertSignOperation.ts index 0422e7d56e..c81b73fea1 100644 --- a/frontend/src/hooks/tools/certSign/useCertSignOperation.ts +++ b/frontend/src/core/hooks/tools/certSign/useCertSignOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { CertSignParameters, defaultParameters } from './useCertSignParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { CertSignParameters, defaultParameters } from '@app/hooks/tools/certSign/useCertSignParameters'; // Build form data for signing export const buildCertSignFormData = (parameters: CertSignParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/certSign/useCertSignParameters.ts b/frontend/src/core/hooks/tools/certSign/useCertSignParameters.ts similarity index 91% rename from frontend/src/hooks/tools/certSign/useCertSignParameters.ts rename to frontend/src/core/hooks/tools/certSign/useCertSignParameters.ts index aa49cb31cd..374cffd2c3 100644 --- a/frontend/src/hooks/tools/certSign/useCertSignParameters.ts +++ b/frontend/src/core/hooks/tools/certSign/useCertSignParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface CertSignParameters extends BaseParameters { // Sign mode selection diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts similarity index 94% rename from frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts rename to frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts index 8836189ac5..cade2be5a6 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.test.ts @@ -1,6 +1,6 @@ -import { buildChangeMetadataFormData } from './useChangeMetadataOperation'; -import { ChangeMetadataParameters } from './useChangeMetadataParameters'; -import { TrappedStatus } from '../../../types/metadata'; +import { buildChangeMetadataFormData } from '@app/hooks/tools/changeMetadata/useChangeMetadataOperation'; +import { ChangeMetadataParameters } from '@app/hooks/tools/changeMetadata/useChangeMetadataParameters'; +import { TrappedStatus } from '@app/types/metadata'; import { describe, expect, test } from 'vitest'; describe('buildChangeMetadataFormData', () => { diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts similarity index 90% rename from frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts rename to frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts index 1f1c8695bc..828fa01ab5 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataOperation.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ChangeMetadataParameters, defaultParameters } from './useChangeMetadataParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ChangeMetadataParameters, defaultParameters } from '@app/hooks/tools/changeMetadata/useChangeMetadataParameters'; // Helper function to format Date object to string const formatDateForBackend = (date: Date | null): string => { diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts similarity index 98% rename from frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts rename to frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts index fb27ef7a5e..f932f658f1 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.test.ts @@ -1,6 +1,6 @@ import { renderHook, act } from '@testing-library/react'; -import { defaultParameters, useChangeMetadataParameters } from './useChangeMetadataParameters'; -import { TrappedStatus } from '../../../types/metadata'; +import { defaultParameters, useChangeMetadataParameters } from '@app/hooks/tools/changeMetadata/useChangeMetadataParameters'; +import { TrappedStatus } from '@app/types/metadata'; import { describe, expect, test } from 'vitest'; describe('useChangeMetadataParameters', () => { diff --git a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.ts similarity index 93% rename from frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts rename to frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.ts index 0523166de9..cbc07ed6c9 100644 --- a/frontend/src/hooks/tools/changeMetadata/useChangeMetadataParameters.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataParameters.ts @@ -1,6 +1,6 @@ -import { BaseParameters } from '../../../types/parameters'; -import { TrappedStatus, CustomMetadataEntry } from '../../../types/metadata'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { TrappedStatus, CustomMetadataEntry } from '@app/types/metadata'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface ChangeMetadataParameters extends BaseParameters { // Standard PDF metadata fields diff --git a/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts b/frontend/src/core/hooks/tools/changeMetadata/useMetadataExtraction.ts similarity index 90% rename from frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts rename to frontend/src/core/hooks/tools/changeMetadata/useMetadataExtraction.ts index 423e19d7e2..9df398b661 100644 --- a/frontend/src/hooks/tools/changeMetadata/useMetadataExtraction.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useMetadataExtraction.ts @@ -1,7 +1,7 @@ import { useState, useEffect, useRef } from "react"; -import { extractPDFMetadata } from "../../../services/pdfMetadataService"; -import { useSelectedFiles } from "../../../contexts/file/fileHooks"; -import { ChangeMetadataParameters } from "./useChangeMetadataParameters"; +import { extractPDFMetadata } from "@app/services/pdfMetadataService"; +import { useSelectedFiles } from "@app/contexts/file/fileHooks"; +import { ChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; interface MetadataExtractionParams { updateParameter: (key: K, value: ChangeMetadataParameters[K]) => void; diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts similarity index 92% rename from frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts rename to frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts index b85f5533f5..22cd5c67c5 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts +++ b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { useChangePermissionsOperation } from './useChangePermissionsOperation'; -import type { ChangePermissionsParameters } from './useChangePermissionsParameters'; +import { useChangePermissionsOperation } from '@app/hooks/tools/changePermissions/useChangePermissionsOperation'; +import type { ChangePermissionsParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; // Mock the useToolOperation hook vi.mock('../shared/useToolOperation', async () => { @@ -24,7 +24,7 @@ vi.mock('../../../utils/toolErrorHandler', () => ({ })); // Import the mocked function -import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '../shared/useToolOperation'; +import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; describe('useChangePermissionsOperation', () => { const mockUseToolOperation = vi.mocked(useToolOperation); diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.ts similarity index 85% rename from frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts rename to frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.ts index 89b6c07d8d..6e391f739e 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsOperation.ts +++ b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ChangePermissionsParameters, defaultParameters } from './useChangePermissionsParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ChangePermissionsParameters, defaultParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; export const getFormData = ((parameters: ChangePermissionsParameters) => Object.entries(parameters).map(([key, value]) => diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts similarity index 97% rename from frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts rename to frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts index fe85434a5e..585f1c1725 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts +++ b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useChangePermissionsParameters, defaultParameters, ChangePermissionsParameters } from './useChangePermissionsParameters'; +import { useChangePermissionsParameters, defaultParameters, ChangePermissionsParameters } from '@app/hooks/tools/changePermissions/useChangePermissionsParameters'; describe('useChangePermissionsParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.ts b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.ts similarity index 86% rename from frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.ts rename to frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.ts index 7092798b73..4a28df2a54 100644 --- a/frontend/src/hooks/tools/changePermissions/useChangePermissionsParameters.ts +++ b/frontend/src/core/hooks/tools/changePermissions/useChangePermissionsParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface ChangePermissionsParameters extends BaseParameters { preventAssembly: boolean; diff --git a/frontend/src/hooks/tools/compress/useCompressOperation.ts b/frontend/src/core/hooks/tools/compress/useCompressOperation.ts similarity index 82% rename from frontend/src/hooks/tools/compress/useCompressOperation.ts rename to frontend/src/core/hooks/tools/compress/useCompressOperation.ts index ef468032d4..5b1417b21f 100644 --- a/frontend/src/hooks/tools/compress/useCompressOperation.ts +++ b/frontend/src/core/hooks/tools/compress/useCompressOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { CompressParameters, defaultParameters } from './useCompressParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { CompressParameters, defaultParameters } from '@app/hooks/tools/compress/useCompressParameters'; // Static configuration that can be used by both the hook and automation executor export const buildCompressFormData = (parameters: CompressParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/compress/useCompressParameters.ts b/frontend/src/core/hooks/tools/compress/useCompressParameters.ts similarity index 85% rename from frontend/src/hooks/tools/compress/useCompressParameters.ts rename to frontend/src/core/hooks/tools/compress/useCompressParameters.ts index d551dc2925..1ae9298f5e 100644 --- a/frontend/src/hooks/tools/compress/useCompressParameters.ts +++ b/frontend/src/core/hooks/tools/compress/useCompressParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface CompressParameters extends BaseParameters { compressionLevel: number; diff --git a/frontend/src/hooks/tools/convert/useConvertOperation.ts b/frontend/src/core/hooks/tools/convert/useConvertOperation.ts similarity index 94% rename from frontend/src/hooks/tools/convert/useConvertOperation.ts rename to frontend/src/core/hooks/tools/convert/useConvertOperation.ts index 4aaed74ee6..28080407d6 100644 --- a/frontend/src/hooks/tools/convert/useConvertOperation.ts +++ b/frontend/src/core/hooks/tools/convert/useConvertOperation.ts @@ -1,10 +1,10 @@ import { useCallback } from 'react'; -import apiClient from '../../../services/apiClient'; +import apiClient from '@app/services/apiClient'; import { useTranslation } from 'react-i18next'; -import { ConvertParameters, defaultParameters } from './useConvertParameters'; -import { createFileFromApiResponse } from '../../../utils/fileResponseUtils'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { getEndpointUrl, isImageFormat, isWebFormat } from '../../../utils/convertUtils'; +import { ConvertParameters, defaultParameters } from '@app/hooks/tools/convert/useConvertParameters'; +import { createFileFromApiResponse } from '@app/utils/fileResponseUtils'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { getEndpointUrl, isImageFormat, isWebFormat } from '@app/utils/convertUtils'; // Static function that can be used by both the hook and automation executor export const shouldProcessFilesSeparately = ( diff --git a/frontend/src/hooks/tools/convert/useConvertParameters.test.ts b/frontend/src/core/hooks/tools/convert/useConvertParameters.test.ts similarity index 98% rename from frontend/src/hooks/tools/convert/useConvertParameters.test.ts rename to frontend/src/core/hooks/tools/convert/useConvertParameters.test.ts index 1c809c1908..340115a81b 100644 --- a/frontend/src/hooks/tools/convert/useConvertParameters.test.ts +++ b/frontend/src/core/hooks/tools/convert/useConvertParameters.test.ts @@ -4,8 +4,8 @@ import { describe, test, expect } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useConvertParameters } from './useConvertParameters'; -import { FIT_OPTIONS } from '../../../constants/convertConstants'; +import { useConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; +import { FIT_OPTIONS } from '@app/constants/convertConstants'; describe('useConvertParameters', () => { diff --git a/frontend/src/hooks/tools/convert/useConvertParameters.ts b/frontend/src/core/hooks/tools/convert/useConvertParameters.ts similarity index 97% rename from frontend/src/hooks/tools/convert/useConvertParameters.ts rename to frontend/src/core/hooks/tools/convert/useConvertParameters.ts index 74a1bd3a13..c9c19176e3 100644 --- a/frontend/src/hooks/tools/convert/useConvertParameters.ts +++ b/frontend/src/core/hooks/tools/convert/useConvertParameters.ts @@ -6,11 +6,11 @@ import { type ColorType, type OutputOption, type FitOption -} from '../../../constants/convertConstants'; -import { getEndpointName as getEndpointNameUtil, getEndpointUrl, isImageFormat, isWebFormat, getAvailableToExtensions as getAvailableToExtensionsUtil } from '../../../utils/convertUtils'; -import { detectFileExtension as detectFileExtensionUtil } from '../../../utils/fileUtils'; -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +} from '@app/constants/convertConstants'; +import { getEndpointName as getEndpointNameUtil, getEndpointUrl, isImageFormat, isWebFormat, getAvailableToExtensions as getAvailableToExtensionsUtil } from '@app/utils/convertUtils'; +import { detectFileExtension as detectFileExtensionUtil } from '@app/utils/fileUtils'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; import { useCallback, useMemo } from 'react'; export interface ConvertParameters extends BaseParameters { diff --git a/frontend/src/hooks/tools/convert/useConvertParametersAutoDetection.test.ts b/frontend/src/core/hooks/tools/convert/useConvertParametersAutoDetection.test.ts similarity index 99% rename from frontend/src/hooks/tools/convert/useConvertParametersAutoDetection.test.ts rename to frontend/src/core/hooks/tools/convert/useConvertParametersAutoDetection.test.ts index e208d44794..e626671f91 100644 --- a/frontend/src/hooks/tools/convert/useConvertParametersAutoDetection.test.ts +++ b/frontend/src/core/hooks/tools/convert/useConvertParametersAutoDetection.test.ts @@ -5,7 +5,7 @@ import { describe, test, expect } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useConvertParameters } from './useConvertParameters'; +import { useConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; describe('useConvertParameters - Auto Detection & Smart Conversion', () => { diff --git a/frontend/src/hooks/tools/crop/useCropOperation.ts b/frontend/src/core/hooks/tools/crop/useCropOperation.ts similarity index 81% rename from frontend/src/hooks/tools/crop/useCropOperation.ts rename to frontend/src/core/hooks/tools/crop/useCropOperation.ts index 452b3ddf11..85d1cc30d5 100644 --- a/frontend/src/hooks/tools/crop/useCropOperation.ts +++ b/frontend/src/core/hooks/tools/crop/useCropOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { CropParameters, defaultParameters } from './useCropParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { CropParameters, defaultParameters } from '@app/hooks/tools/crop/useCropParameters'; // Static configuration that can be used by both the hook and automation executor export const buildCropFormData = (parameters: CropParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/crop/useCropParameters.ts b/frontend/src/core/hooks/tools/crop/useCropParameters.ts similarity index 94% rename from frontend/src/hooks/tools/crop/useCropParameters.ts rename to frontend/src/core/hooks/tools/crop/useCropParameters.ts index d16cb5af5d..443d79a1c8 100644 --- a/frontend/src/hooks/tools/crop/useCropParameters.ts +++ b/frontend/src/core/hooks/tools/crop/useCropParameters.ts @@ -1,8 +1,8 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; import { useCallback } from 'react'; -import { Rectangle, PDFBounds, constrainCropAreaToPDF, createFullPDFCropArea, roundCropArea, isRectangle } from '../../../utils/cropCoordinates'; -import { DEFAULT_CROP_AREA } from '../../../constants/cropConstants'; +import { Rectangle, PDFBounds, constrainCropAreaToPDF, createFullPDFCropArea, roundCropArea, isRectangle } from '@app/utils/cropCoordinates'; +import { DEFAULT_CROP_AREA } from '@app/constants/cropConstants'; export interface CropParameters extends BaseParameters { cropArea: Rectangle; diff --git a/frontend/src/hooks/tools/extractImages/useExtractImagesOperation.ts b/frontend/src/core/hooks/tools/extractImages/useExtractImagesOperation.ts similarity index 80% rename from frontend/src/hooks/tools/extractImages/useExtractImagesOperation.ts rename to frontend/src/core/hooks/tools/extractImages/useExtractImagesOperation.ts index a5ef983573..317630317c 100644 --- a/frontend/src/hooks/tools/extractImages/useExtractImagesOperation.ts +++ b/frontend/src/core/hooks/tools/extractImages/useExtractImagesOperation.ts @@ -1,9 +1,9 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ExtractImagesParameters, defaultParameters } from './useExtractImagesParameters'; -import { useToolResources } from '../shared/useToolResources'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ExtractImagesParameters, defaultParameters } from '@app/hooks/tools/extractImages/useExtractImagesParameters'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; // Static configuration that can be used by both the hook and automation executor export const buildExtractImagesFormData = (parameters: ExtractImagesParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/extractImages/useExtractImagesParameters.ts b/frontend/src/core/hooks/tools/extractImages/useExtractImagesParameters.ts similarity index 85% rename from frontend/src/hooks/tools/extractImages/useExtractImagesParameters.ts rename to frontend/src/core/hooks/tools/extractImages/useExtractImagesParameters.ts index d5937b59ce..183fdd2a76 100644 --- a/frontend/src/hooks/tools/extractImages/useExtractImagesParameters.ts +++ b/frontend/src/core/hooks/tools/extractImages/useExtractImagesParameters.ts @@ -1,4 +1,4 @@ -import { useBaseParameters } from '../shared/useBaseParameters'; +import { useBaseParameters } from '@app/hooks/tools/shared/useBaseParameters'; export interface ExtractImagesParameters { format: 'png' | 'jpg' | 'gif'; diff --git a/frontend/src/hooks/tools/flatten/useFlattenOperation.ts b/frontend/src/core/hooks/tools/flatten/useFlattenOperation.ts similarity index 78% rename from frontend/src/hooks/tools/flatten/useFlattenOperation.ts rename to frontend/src/core/hooks/tools/flatten/useFlattenOperation.ts index e2b6874344..f36b9d078a 100644 --- a/frontend/src/hooks/tools/flatten/useFlattenOperation.ts +++ b/frontend/src/core/hooks/tools/flatten/useFlattenOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { FlattenParameters, defaultParameters } from './useFlattenParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { FlattenParameters, defaultParameters } from '@app/hooks/tools/flatten/useFlattenParameters'; // Static function that can be used by both the hook and automation executor export const buildFlattenFormData = (parameters: FlattenParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/flatten/useFlattenParameters.ts b/frontend/src/core/hooks/tools/flatten/useFlattenParameters.ts similarity index 72% rename from frontend/src/hooks/tools/flatten/useFlattenParameters.ts rename to frontend/src/core/hooks/tools/flatten/useFlattenParameters.ts index 98c5b96559..af47ab3e1d 100644 --- a/frontend/src/hooks/tools/flatten/useFlattenParameters.ts +++ b/frontend/src/core/hooks/tools/flatten/useFlattenParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface FlattenParameters extends BaseParameters { flattenOnlyForms: boolean; diff --git a/frontend/src/hooks/tools/merge/useMergeOperation.test.ts b/frontend/src/core/hooks/tools/merge/useMergeOperation.test.ts similarity index 94% rename from frontend/src/hooks/tools/merge/useMergeOperation.test.ts rename to frontend/src/core/hooks/tools/merge/useMergeOperation.test.ts index 4d41c51621..bcdd621679 100644 --- a/frontend/src/hooks/tools/merge/useMergeOperation.test.ts +++ b/frontend/src/core/hooks/tools/merge/useMergeOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { useMergeOperation } from './useMergeOperation'; -import type { MergeParameters } from './useMergeParameters'; +import { useMergeOperation } from '@app/hooks/tools/merge/useMergeOperation'; +import type { MergeParameters } from '@app/hooks/tools/merge/useMergeParameters'; // Mock the useToolOperation hook vi.mock('../shared/useToolOperation', async () => { @@ -24,7 +24,7 @@ vi.mock('../../../utils/toolErrorHandler', () => ({ })); // Import the mocked function -import { MultiFileToolOperationConfig, ToolOperationHook, useToolOperation } from '../shared/useToolOperation'; +import { MultiFileToolOperationConfig, ToolOperationHook, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; describe('useMergeOperation', () => { const mockUseToolOperation = vi.mocked(useToolOperation); diff --git a/frontend/src/hooks/tools/merge/useMergeOperation.ts b/frontend/src/core/hooks/tools/merge/useMergeOperation.ts similarity index 87% rename from frontend/src/hooks/tools/merge/useMergeOperation.ts rename to frontend/src/core/hooks/tools/merge/useMergeOperation.ts index a334babb60..e21814a4f0 100644 --- a/frontend/src/hooks/tools/merge/useMergeOperation.ts +++ b/frontend/src/core/hooks/tools/merge/useMergeOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { MergeParameters } from './useMergeParameters'; +import { useToolOperation, ToolOperationConfig, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { MergeParameters } from '@app/hooks/tools/merge/useMergeParameters'; const buildFormData = (parameters: MergeParameters, files: File[]): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/merge/useMergeParameters.test.ts b/frontend/src/core/hooks/tools/merge/useMergeParameters.test.ts similarity index 95% rename from frontend/src/hooks/tools/merge/useMergeParameters.test.ts rename to frontend/src/core/hooks/tools/merge/useMergeParameters.test.ts index 8294cdf6ea..d5fbf5ef91 100644 --- a/frontend/src/hooks/tools/merge/useMergeParameters.test.ts +++ b/frontend/src/core/hooks/tools/merge/useMergeParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useMergeParameters, defaultParameters } from './useMergeParameters'; +import { useMergeParameters, defaultParameters } from '@app/hooks/tools/merge/useMergeParameters'; describe('useMergeParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/merge/useMergeParameters.ts b/frontend/src/core/hooks/tools/merge/useMergeParameters.ts similarity index 75% rename from frontend/src/hooks/tools/merge/useMergeParameters.ts rename to frontend/src/core/hooks/tools/merge/useMergeParameters.ts index 2abc416cab..b9b0c3b7a9 100644 --- a/frontend/src/hooks/tools/merge/useMergeParameters.ts +++ b/frontend/src/core/hooks/tools/merge/useMergeParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { BaseParametersHook, useBaseParameters } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { BaseParametersHook, useBaseParameters } from '@app/hooks/tools/shared/useBaseParameters'; export interface MergeParameters extends BaseParameters { removeDigitalSignature: boolean; diff --git a/frontend/src/hooks/tools/ocr/useOCROperation.ts b/frontend/src/core/hooks/tools/ocr/useOCROperation.ts similarity index 94% rename from frontend/src/hooks/tools/ocr/useOCROperation.ts rename to frontend/src/core/hooks/tools/ocr/useOCROperation.ts index b2d3a434a6..6e86a083e5 100644 --- a/frontend/src/hooks/tools/ocr/useOCROperation.ts +++ b/frontend/src/core/hooks/tools/ocr/useOCROperation.ts @@ -1,9 +1,9 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { OCRParameters, defaultParameters } from './useOCRParameters'; -import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { useToolResources } from '../shared/useToolResources'; +import { OCRParameters, defaultParameters } from '@app/hooks/tools/ocr/useOCRParameters'; +import { useToolOperation, ToolOperationConfig, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; // Helper: get MIME type based on file extension function getMimeType(filename: string): string { diff --git a/frontend/src/hooks/tools/ocr/useOCRParameters.ts b/frontend/src/core/hooks/tools/ocr/useOCRParameters.ts similarity index 80% rename from frontend/src/hooks/tools/ocr/useOCRParameters.ts rename to frontend/src/core/hooks/tools/ocr/useOCRParameters.ts index a3fd546d27..a2b6870317 100644 --- a/frontend/src/hooks/tools/ocr/useOCRParameters.ts +++ b/frontend/src/core/hooks/tools/ocr/useOCRParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface OCRParameters extends BaseParameters { languages: string[]; diff --git a/frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts b/frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts similarity index 85% rename from frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts rename to frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts index 2689628832..a3499eb78f 100644 --- a/frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts +++ b/frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType, type ToolOperationConfig } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { type OverlayPdfsParameters } from './useOverlayPdfsParameters'; +import { useToolOperation, ToolType, type ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { type OverlayPdfsParameters } from '@app/hooks/tools/overlayPdfs/useOverlayPdfsParameters'; const buildFormData = (parameters: OverlayPdfsParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts b/frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts similarity index 87% rename from frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts rename to frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts index c401d7205d..056747e847 100644 --- a/frontend/src/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts +++ b/frontend/src/core/hooks/tools/overlayPdfs/useOverlayPdfsParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, type BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, type BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export type OverlayMode = 'SequentialOverlay' | 'InterleavedOverlay' | 'FixedRepeatOverlay'; diff --git a/frontend/src/hooks/tools/pageLayout/usePageLayoutOperation.ts b/frontend/src/core/hooks/tools/pageLayout/usePageLayoutOperation.ts similarity index 77% rename from frontend/src/hooks/tools/pageLayout/usePageLayoutOperation.ts rename to frontend/src/core/hooks/tools/pageLayout/usePageLayoutOperation.ts index b96aeaaf84..f2b684b7bf 100644 --- a/frontend/src/hooks/tools/pageLayout/usePageLayoutOperation.ts +++ b/frontend/src/core/hooks/tools/pageLayout/usePageLayoutOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { PageLayoutParameters, defaultParameters } from './usePageLayoutParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { PageLayoutParameters, defaultParameters } from '@app/hooks/tools/pageLayout/usePageLayoutParameters'; export const buildPageLayoutFormData = (parameters: PageLayoutParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/pageLayout/usePageLayoutParameters.ts b/frontend/src/core/hooks/tools/pageLayout/usePageLayoutParameters.ts similarity index 76% rename from frontend/src/hooks/tools/pageLayout/usePageLayoutParameters.ts rename to frontend/src/core/hooks/tools/pageLayout/usePageLayoutParameters.ts index 13cbc860c5..5c10700c7c 100644 --- a/frontend/src/hooks/tools/pageLayout/usePageLayoutParameters.ts +++ b/frontend/src/core/hooks/tools/pageLayout/usePageLayoutParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface PageLayoutParameters extends BaseParameters { pagesPerSheet: number; diff --git a/frontend/src/hooks/tools/redact/useRedactOperation.test.ts b/frontend/src/core/hooks/tools/redact/useRedactOperation.test.ts similarity index 92% rename from frontend/src/hooks/tools/redact/useRedactOperation.test.ts rename to frontend/src/core/hooks/tools/redact/useRedactOperation.test.ts index 8ca6cc84df..9e7460d85c 100644 --- a/frontend/src/hooks/tools/redact/useRedactOperation.test.ts +++ b/frontend/src/core/hooks/tools/redact/useRedactOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { buildRedactFormData, redactOperationConfig, useRedactOperation } from './useRedactOperation'; -import { defaultParameters, RedactParameters } from './useRedactParameters'; +import { buildRedactFormData, redactOperationConfig, useRedactOperation } from '@app/hooks/tools/redact/useRedactOperation'; +import { defaultParameters, RedactParameters } from '@app/hooks/tools/redact/useRedactParameters'; // Mock the useToolOperation hook vi.mock('../shared/useToolOperation', async () => { @@ -119,7 +119,7 @@ describe('useRedactOperation', () => { }); test('should call useToolOperation with correct configuration', async () => { - const { useToolOperation } = await import('../shared/useToolOperation'); + const { useToolOperation } = await import('@app/hooks/tools/shared/useToolOperation'); const mockUseToolOperation = vi.mocked(useToolOperation); renderHook(() => useRedactOperation()); @@ -131,7 +131,7 @@ describe('useRedactOperation', () => { }); test('should provide error handler to useToolOperation', async () => { - const { useToolOperation } = await import('../shared/useToolOperation'); + const { useToolOperation } = await import('@app/hooks/tools/shared/useToolOperation'); const mockUseToolOperation = vi.mocked(useToolOperation); renderHook(() => useRedactOperation()); diff --git a/frontend/src/hooks/tools/redact/useRedactOperation.ts b/frontend/src/core/hooks/tools/redact/useRedactOperation.ts similarity index 87% rename from frontend/src/hooks/tools/redact/useRedactOperation.ts rename to frontend/src/core/hooks/tools/redact/useRedactOperation.ts index 407716395b..bf2a051213 100644 --- a/frontend/src/hooks/tools/redact/useRedactOperation.ts +++ b/frontend/src/core/hooks/tools/redact/useRedactOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RedactParameters, defaultParameters } from './useRedactParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RedactParameters, defaultParameters } from '@app/hooks/tools/redact/useRedactParameters'; // Static configuration that can be used by both the hook and automation executor export const buildRedactFormData = (parameters: RedactParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/redact/useRedactParameters.test.ts b/frontend/src/core/hooks/tools/redact/useRedactParameters.test.ts similarity index 98% rename from frontend/src/hooks/tools/redact/useRedactParameters.test.ts rename to frontend/src/core/hooks/tools/redact/useRedactParameters.test.ts index b87719ad9f..40e350010e 100644 --- a/frontend/src/hooks/tools/redact/useRedactParameters.test.ts +++ b/frontend/src/core/hooks/tools/redact/useRedactParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useRedactParameters, defaultParameters } from './useRedactParameters'; +import { useRedactParameters, defaultParameters } from '@app/hooks/tools/redact/useRedactParameters'; describe('useRedactParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/redact/useRedactParameters.ts b/frontend/src/core/hooks/tools/redact/useRedactParameters.ts similarity index 89% rename from frontend/src/hooks/tools/redact/useRedactParameters.ts rename to frontend/src/core/hooks/tools/redact/useRedactParameters.ts index 33e95e93dc..f29f56f967 100644 --- a/frontend/src/hooks/tools/redact/useRedactParameters.ts +++ b/frontend/src/core/hooks/tools/redact/useRedactParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export type RedactMode = 'automatic' | 'manual'; diff --git a/frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts similarity index 93% rename from frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts rename to frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts index cdf16846e7..4078b2b073 100644 --- a/frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts +++ b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RemoveAnnotationsParameters, defaultParameters } from './useRemoveAnnotationsParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RemoveAnnotationsParameters, defaultParameters } from '@app/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters'; import { PDFDocument, PDFName, PDFRef, PDFDict } from 'pdf-lib'; // Client-side PDF processing using PDF-lib const removeAnnotationsProcessor = async (_parameters: RemoveAnnotationsParameters, files: File[]): Promise => { diff --git a/frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts similarity index 84% rename from frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts rename to frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts index b62e1da082..55a5c81f9a 100644 --- a/frontend/src/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts +++ b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters.ts @@ -1,4 +1,4 @@ -import { useBaseParameters } from '../shared/useBaseParameters'; +import { useBaseParameters } from '@app/hooks/tools/shared/useBaseParameters'; export type RemoveAnnotationsParameters = Record diff --git a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts b/frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts similarity index 82% rename from frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts rename to frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts index 15cfe1724e..ddb0ba2d24 100644 --- a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts +++ b/frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksOperation.ts @@ -1,9 +1,9 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation, ToolOperationConfig } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RemoveBlanksParameters, defaultParameters } from './useRemoveBlanksParameters'; -import { useToolResources } from '../shared/useToolResources'; +import { ToolType, useToolOperation, ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RemoveBlanksParameters, defaultParameters } from '@app/hooks/tools/removeBlanks/useRemoveBlanksParameters'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; export const buildRemoveBlanksFormData = (parameters: RemoveBlanksParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts b/frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts similarity index 82% rename from frontend/src/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts rename to frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts index b6716c681c..4a57f8bf84 100644 --- a/frontend/src/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts +++ b/frontend/src/core/hooks/tools/removeBlanks/useRemoveBlanksParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface RemoveBlanksParameters extends BaseParameters { threshold: number; // 0-255 diff --git a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts b/frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts similarity index 81% rename from frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts rename to frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts index 48ade39402..a2a1277b90 100644 --- a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts +++ b/frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RemoveCertificateSignParameters, defaultParameters } from './useRemoveCertificateSignParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RemoveCertificateSignParameters, defaultParameters } from '@app/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters'; // Static function that can be used by both the hook and automation executor export const buildRemoveCertificateSignFormData = (_parameters: RemoveCertificateSignParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts b/frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts similarity index 78% rename from frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts rename to frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts index 59903ccfca..67476734a8 100644 --- a/frontend/src/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts +++ b/frontend/src/core/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface RemoveCertificateSignParameters extends BaseParameters { // Extends BaseParameters - ready for future parameter additions if needed diff --git a/frontend/src/hooks/tools/removeImage/useRemoveImageOperation.ts b/frontend/src/core/hooks/tools/removeImage/useRemoveImageOperation.ts similarity index 79% rename from frontend/src/hooks/tools/removeImage/useRemoveImageOperation.ts rename to frontend/src/core/hooks/tools/removeImage/useRemoveImageOperation.ts index 0f66495985..e975cf8d5b 100644 --- a/frontend/src/hooks/tools/removeImage/useRemoveImageOperation.ts +++ b/frontend/src/core/hooks/tools/removeImage/useRemoveImageOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import type { RemoveImageParameters } from './useRemoveImageParameters'; +import { useToolOperation, ToolOperationConfig, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import type { RemoveImageParameters } from '@app/hooks/tools/removeImage/useRemoveImageParameters'; export const buildRemoveImageFormData = (_params: RemoveImageParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/removeImage/useRemoveImageParameters.ts b/frontend/src/core/hooks/tools/removeImage/useRemoveImageParameters.ts similarity index 69% rename from frontend/src/hooks/tools/removeImage/useRemoveImageParameters.ts rename to frontend/src/core/hooks/tools/removeImage/useRemoveImageParameters.ts index f57a9e93ea..5684bc003d 100644 --- a/frontend/src/hooks/tools/removeImage/useRemoveImageParameters.ts +++ b/frontend/src/core/hooks/tools/removeImage/useRemoveImageParameters.ts @@ -1,5 +1,5 @@ -import { useBaseParameters } from '../shared/useBaseParameters'; -import type { BaseParametersHook } from '../shared/useBaseParameters'; +import { useBaseParameters } from '@app/hooks/tools/shared/useBaseParameters'; +import type { BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export type RemoveImageParameters = Record; diff --git a/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts b/frontend/src/core/hooks/tools/removePages/useRemovePagesOperation.ts similarity index 76% rename from frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts rename to frontend/src/core/hooks/tools/removePages/useRemovePagesOperation.ts index aa9f5d5747..85ca86545a 100644 --- a/frontend/src/hooks/tools/removePages/useRemovePagesOperation.ts +++ b/frontend/src/core/hooks/tools/removePages/useRemovePagesOperation.ts @@ -1,8 +1,8 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation, ToolOperationConfig } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RemovePagesParameters, defaultParameters } from './useRemovePagesParameters'; -// import { useToolResources } from '../shared/useToolResources'; +import { ToolType, useToolOperation, ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RemovePagesParameters, defaultParameters } from '@app/hooks/tools/removePages/useRemovePagesParameters'; +// import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; export const buildRemovePagesFormData = (parameters: RemovePagesParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/removePages/useRemovePagesParameters.ts b/frontend/src/core/hooks/tools/removePages/useRemovePagesParameters.ts similarity index 71% rename from frontend/src/hooks/tools/removePages/useRemovePagesParameters.ts rename to frontend/src/core/hooks/tools/removePages/useRemovePagesParameters.ts index 31484f54e3..e2b0139098 100644 --- a/frontend/src/hooks/tools/removePages/useRemovePagesParameters.ts +++ b/frontend/src/core/hooks/tools/removePages/useRemovePagesParameters.ts @@ -1,6 +1,6 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; -import { validatePageNumbers } from '../../../utils/pageSelection'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; +import { validatePageNumbers } from '@app/utils/pageSelection'; export interface RemovePagesParameters extends BaseParameters { pageNumbers: string; // comma-separated page numbers or ranges (e.g., "1,3,5-8") diff --git a/frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.test.ts b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.test.ts similarity index 91% rename from frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.test.ts rename to frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.test.ts index d3dc93f7bc..f29ba15111 100644 --- a/frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.test.ts +++ b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { useRemovePasswordOperation } from './useRemovePasswordOperation'; -import type { RemovePasswordParameters } from './useRemovePasswordParameters'; +import { useRemovePasswordOperation } from '@app/hooks/tools/removePassword/useRemovePasswordOperation'; +import type { RemovePasswordParameters } from '@app/hooks/tools/removePassword/useRemovePasswordParameters'; vi.mock('../shared/useToolOperation', async () => { const actual = await vi.importActual('../shared/useToolOperation'); // Need to keep ToolType etc. @@ -23,7 +23,7 @@ vi.mock('../../../utils/toolErrorHandler', () => ({ })); // Import the mocked function -import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '../shared/useToolOperation'; +import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; describe('useRemovePasswordOperation', () => { const mockUseToolOperation = vi.mocked(useToolOperation); diff --git a/frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.ts b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.ts similarity index 77% rename from frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.ts rename to frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.ts index e2a76638bc..ce6140730e 100644 --- a/frontend/src/hooks/tools/removePassword/useRemovePasswordOperation.ts +++ b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RemovePasswordParameters, defaultParameters } from './useRemovePasswordParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RemovePasswordParameters, defaultParameters } from '@app/hooks/tools/removePassword/useRemovePasswordParameters'; // Static function that can be used by both the hook and automation executor export const buildRemovePasswordFormData = (parameters: RemovePasswordParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.test.ts b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.test.ts similarity index 97% rename from frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.test.ts rename to frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.test.ts index f7310847b5..d3d2a4c5cb 100644 --- a/frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.test.ts +++ b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useRemovePasswordParameters, defaultParameters } from './useRemovePasswordParameters'; +import { useRemovePasswordParameters, defaultParameters } from '@app/hooks/tools/removePassword/useRemovePasswordParameters'; describe('useRemovePasswordParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.ts b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.ts similarity index 76% rename from frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.ts rename to frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.ts index fc39db5461..9c2ad4981a 100644 --- a/frontend/src/hooks/tools/removePassword/useRemovePasswordParameters.ts +++ b/frontend/src/core/hooks/tools/removePassword/useRemovePasswordParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface RemovePasswordParameters extends BaseParameters { password: string; diff --git a/frontend/src/hooks/tools/reorganizePages/useReorganizePagesOperation.ts b/frontend/src/core/hooks/tools/reorganizePages/useReorganizePagesOperation.ts similarity index 82% rename from frontend/src/hooks/tools/reorganizePages/useReorganizePagesOperation.ts rename to frontend/src/core/hooks/tools/reorganizePages/useReorganizePagesOperation.ts index ca5af13271..de18207fbd 100644 --- a/frontend/src/hooks/tools/reorganizePages/useReorganizePagesOperation.ts +++ b/frontend/src/core/hooks/tools/reorganizePages/useReorganizePagesOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolOperationConfig, ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ReorganizePagesParameters } from './useReorganizePagesParameters'; +import { ToolOperationConfig, ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ReorganizePagesParameters } from '@app/hooks/tools/reorganizePages/useReorganizePagesParameters'; const buildFormData = (parameters: ReorganizePagesParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/reorganizePages/useReorganizePagesParameters.ts b/frontend/src/core/hooks/tools/reorganizePages/useReorganizePagesParameters.ts similarity index 100% rename from frontend/src/hooks/tools/reorganizePages/useReorganizePagesParameters.ts rename to frontend/src/core/hooks/tools/reorganizePages/useReorganizePagesParameters.ts diff --git a/frontend/src/hooks/tools/repair/useRepairOperation.ts b/frontend/src/core/hooks/tools/repair/useRepairOperation.ts similarity index 76% rename from frontend/src/hooks/tools/repair/useRepairOperation.ts rename to frontend/src/core/hooks/tools/repair/useRepairOperation.ts index ce5e93ec4b..59f8c9eeae 100644 --- a/frontend/src/hooks/tools/repair/useRepairOperation.ts +++ b/frontend/src/core/hooks/tools/repair/useRepairOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RepairParameters, defaultParameters } from './useRepairParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RepairParameters, defaultParameters } from '@app/hooks/tools/repair/useRepairParameters'; // Static function that can be used by both the hook and automation executor export const buildRepairFormData = (_parameters: RepairParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/repair/useRepairParameters.ts b/frontend/src/core/hooks/tools/repair/useRepairParameters.ts similarity index 76% rename from frontend/src/hooks/tools/repair/useRepairParameters.ts rename to frontend/src/core/hooks/tools/repair/useRepairParameters.ts index 5c924de938..9b613d764b 100644 --- a/frontend/src/hooks/tools/repair/useRepairParameters.ts +++ b/frontend/src/core/hooks/tools/repair/useRepairParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface RepairParameters extends BaseParameters { // Extends BaseParameters - ready for future parameter additions if needed diff --git a/frontend/src/hooks/tools/replaceColor/useReplaceColorOperation.ts b/frontend/src/core/hooks/tools/replaceColor/useReplaceColorOperation.ts similarity index 82% rename from frontend/src/hooks/tools/replaceColor/useReplaceColorOperation.ts rename to frontend/src/core/hooks/tools/replaceColor/useReplaceColorOperation.ts index 45eb8e8dd2..87713a5b4b 100644 --- a/frontend/src/hooks/tools/replaceColor/useReplaceColorOperation.ts +++ b/frontend/src/core/hooks/tools/replaceColor/useReplaceColorOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ReplaceColorParameters, defaultParameters } from './useReplaceColorParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ReplaceColorParameters, defaultParameters } from '@app/hooks/tools/replaceColor/useReplaceColorParameters'; export const buildReplaceColorFormData = (parameters: ReplaceColorParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/replaceColor/useReplaceColorParameters.ts b/frontend/src/core/hooks/tools/replaceColor/useReplaceColorParameters.ts similarity index 85% rename from frontend/src/hooks/tools/replaceColor/useReplaceColorParameters.ts rename to frontend/src/core/hooks/tools/replaceColor/useReplaceColorParameters.ts index 2b269aa1a7..a914597156 100644 --- a/frontend/src/hooks/tools/replaceColor/useReplaceColorParameters.ts +++ b/frontend/src/core/hooks/tools/replaceColor/useReplaceColorParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface ReplaceColorParameters extends BaseParameters { replaceAndInvertOption: 'HIGH_CONTRAST_COLOR' | 'CUSTOM_COLOR' | 'FULL_INVERSION'; diff --git a/frontend/src/hooks/tools/rotate/useRotateOperation.test.ts b/frontend/src/core/hooks/tools/rotate/useRotateOperation.test.ts similarity index 93% rename from frontend/src/hooks/tools/rotate/useRotateOperation.test.ts rename to frontend/src/core/hooks/tools/rotate/useRotateOperation.test.ts index 53370ca5a8..93dd6a5604 100644 --- a/frontend/src/hooks/tools/rotate/useRotateOperation.test.ts +++ b/frontend/src/core/hooks/tools/rotate/useRotateOperation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, vi, beforeEach } from 'vitest'; import { renderHook } from '@testing-library/react'; -import { useRotateOperation } from './useRotateOperation'; -import type { RotateParameters } from './useRotateParameters'; +import { useRotateOperation } from '@app/hooks/tools/rotate/useRotateOperation'; +import type { RotateParameters } from '@app/hooks/tools/rotate/useRotateParameters'; // Mock the useToolOperation hook vi.mock('../shared/useToolOperation', async () => { @@ -24,7 +24,7 @@ vi.mock('../../../utils/toolErrorHandler', () => ({ })); // Import the mocked function -import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '../shared/useToolOperation'; +import { SingleFileToolOperationConfig, ToolOperationHook, ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; describe('useRotateOperation', () => { const mockUseToolOperation = vi.mocked(useToolOperation); diff --git a/frontend/src/hooks/tools/rotate/useRotateOperation.ts b/frontend/src/core/hooks/tools/rotate/useRotateOperation.ts similarity index 82% rename from frontend/src/hooks/tools/rotate/useRotateOperation.ts rename to frontend/src/core/hooks/tools/rotate/useRotateOperation.ts index 3399d8b211..c7b1e1a5e7 100644 --- a/frontend/src/hooks/tools/rotate/useRotateOperation.ts +++ b/frontend/src/core/hooks/tools/rotate/useRotateOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolType } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { RotateParameters, defaultParameters, normalizeAngle } from './useRotateParameters'; +import { useToolOperation, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { RotateParameters, defaultParameters, normalizeAngle } from '@app/hooks/tools/rotate/useRotateParameters'; // Static configuration that can be used by both the hook and automation executor export const buildRotateFormData = (parameters: RotateParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/rotate/useRotateParameters.test.ts b/frontend/src/core/hooks/tools/rotate/useRotateParameters.test.ts similarity index 98% rename from frontend/src/hooks/tools/rotate/useRotateParameters.test.ts rename to frontend/src/core/hooks/tools/rotate/useRotateParameters.test.ts index 6d3393fcce..1c9233e9a5 100644 --- a/frontend/src/hooks/tools/rotate/useRotateParameters.test.ts +++ b/frontend/src/core/hooks/tools/rotate/useRotateParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useRotateParameters, defaultParameters, normalizeAngle } from './useRotateParameters'; +import { useRotateParameters, defaultParameters, normalizeAngle } from '@app/hooks/tools/rotate/useRotateParameters'; describe('useRotateParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/rotate/useRotateParameters.ts b/frontend/src/core/hooks/tools/rotate/useRotateParameters.ts similarity index 92% rename from frontend/src/hooks/tools/rotate/useRotateParameters.ts rename to frontend/src/core/hooks/tools/rotate/useRotateParameters.ts index dff87bb8a0..f69f98caf7 100644 --- a/frontend/src/hooks/tools/rotate/useRotateParameters.ts +++ b/frontend/src/core/hooks/tools/rotate/useRotateParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; import { useMemo, useCallback } from 'react'; // Normalize angle to number between 0 and 359 diff --git a/frontend/src/hooks/tools/sanitize/useSanitizeOperation.ts b/frontend/src/core/hooks/tools/sanitize/useSanitizeOperation.ts similarity index 83% rename from frontend/src/hooks/tools/sanitize/useSanitizeOperation.ts rename to frontend/src/core/hooks/tools/sanitize/useSanitizeOperation.ts index 97e539fcbf..580fabe312 100644 --- a/frontend/src/hooks/tools/sanitize/useSanitizeOperation.ts +++ b/frontend/src/core/hooks/tools/sanitize/useSanitizeOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { SanitizeParameters, defaultParameters } from './useSanitizeParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { SanitizeParameters, defaultParameters } from '@app/hooks/tools/sanitize/useSanitizeParameters'; // Static function that can be used by both the hook and automation executor export const buildSanitizeFormData = (parameters: SanitizeParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/sanitize/useSanitizeParameters.test.ts b/frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.test.ts similarity index 96% rename from frontend/src/hooks/tools/sanitize/useSanitizeParameters.test.ts rename to frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.test.ts index f86a6c81a8..60559e5487 100644 --- a/frontend/src/hooks/tools/sanitize/useSanitizeParameters.test.ts +++ b/frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { defaultParameters, useSanitizeParameters } from './useSanitizeParameters'; +import { defaultParameters, useSanitizeParameters } from '@app/hooks/tools/sanitize/useSanitizeParameters'; describe('useSanitizeParameters', () => { test('should initialize with default parameters', () => { diff --git a/frontend/src/hooks/tools/sanitize/useSanitizeParameters.ts b/frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.ts similarity index 83% rename from frontend/src/hooks/tools/sanitize/useSanitizeParameters.ts rename to frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.ts index 9e050a7e50..18978f9459 100644 --- a/frontend/src/hooks/tools/sanitize/useSanitizeParameters.ts +++ b/frontend/src/core/hooks/tools/sanitize/useSanitizeParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface SanitizeParameters extends BaseParameters { removeJavaScript: boolean; diff --git a/frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts b/frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts similarity index 90% rename from frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts rename to frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts index 65f7a4b58c..144a316785 100644 --- a/frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts +++ b/frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitOperation.ts @@ -1,9 +1,9 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation, ToolOperationConfig } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { ScannerImageSplitParameters, defaultParameters } from './useScannerImageSplitParameters'; -import { useToolResources } from '../shared/useToolResources'; +import { ToolType, useToolOperation, ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { ScannerImageSplitParameters, defaultParameters } from '@app/hooks/tools/scannerImageSplit/useScannerImageSplitParameters'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; export const buildScannerImageSplitFormData = (parameters: ScannerImageSplitParameters, file: File): FormData => { const formData = new FormData(); diff --git a/frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts b/frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts similarity index 83% rename from frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts rename to frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts index bb028c0e7d..ef4b89b94c 100644 --- a/frontend/src/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts +++ b/frontend/src/core/hooks/tools/scannerImageSplit/useScannerImageSplitParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface ScannerImageSplitParameters extends BaseParameters { angle_threshold: number; diff --git a/frontend/src/hooks/tools/shared/useAccordionSteps.ts b/frontend/src/core/hooks/tools/shared/useAccordionSteps.ts similarity index 100% rename from frontend/src/hooks/tools/shared/useAccordionSteps.ts rename to frontend/src/core/hooks/tools/shared/useAccordionSteps.ts diff --git a/frontend/src/hooks/tools/shared/useBaseParameters.ts b/frontend/src/core/hooks/tools/shared/useBaseParameters.ts similarity index 100% rename from frontend/src/hooks/tools/shared/useBaseParameters.ts rename to frontend/src/core/hooks/tools/shared/useBaseParameters.ts diff --git a/frontend/src/hooks/tools/shared/useBaseTool.ts b/frontend/src/core/hooks/tools/shared/useBaseTool.ts similarity index 90% rename from frontend/src/hooks/tools/shared/useBaseTool.ts rename to frontend/src/core/hooks/tools/shared/useBaseTool.ts index 56174a73ad..aad6556eaa 100644 --- a/frontend/src/hooks/tools/shared/useBaseTool.ts +++ b/frontend/src/core/hooks/tools/shared/useBaseTool.ts @@ -1,10 +1,10 @@ import { useEffect, useCallback, useRef } from 'react'; -import { useFileSelection } from '../../../contexts/FileContext'; -import { useEndpointEnabled } from '../../useEndpointConfig'; -import { BaseToolProps } from '../../../types/tool'; -import { ToolOperationHook } from './useToolOperation'; -import { BaseParametersHook } from './useBaseParameters'; -import { StirlingFile } from '../../../types/fileContext'; +import { useFileSelection } from '@app/contexts/FileContext'; +import { useEndpointEnabled } from '@app/hooks/useEndpointConfig'; +import { BaseToolProps } from '@app/types/tool'; +import { ToolOperationHook } from '@app/hooks/tools/shared/useToolOperation'; +import { BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; +import { StirlingFile } from '@app/types/fileContext'; interface BaseToolReturn> { // File management diff --git a/frontend/src/hooks/tools/shared/useOperationResults.ts b/frontend/src/core/hooks/tools/shared/useOperationResults.ts similarity index 100% rename from frontend/src/hooks/tools/shared/useOperationResults.ts rename to frontend/src/core/hooks/tools/shared/useOperationResults.ts diff --git a/frontend/src/hooks/tools/shared/useToolApiCalls.ts b/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts similarity index 93% rename from frontend/src/hooks/tools/shared/useToolApiCalls.ts rename to frontend/src/core/hooks/tools/shared/useToolApiCalls.ts index 5747ec2269..a8e6a88a02 100644 --- a/frontend/src/hooks/tools/shared/useToolApiCalls.ts +++ b/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts @@ -1,9 +1,9 @@ import { useCallback, useRef } from 'react'; import axios, {type CancelTokenSource} from 'axios'; // Real axios for static methods (CancelToken, isCancel) -import apiClient from '../../../services/apiClient'; // Our configured instance -import { processResponse, ResponseHandler } from '../../../utils/toolResponseProcessor'; -import { isEmptyOutput } from '../../../services/errorUtils'; -import type { ProcessingProgress } from './useToolState'; +import apiClient from '@app/services/apiClient'; // Our configured instance +import { processResponse, ResponseHandler } from '@app/utils/toolResponseProcessor'; +import { isEmptyOutput } from '@app/services/errorUtils'; +import type { ProcessingProgress } from '@app/hooks/tools/shared/useToolState'; export interface ApiCallsConfig { endpoint: string | ((params: TParams) => string); diff --git a/frontend/src/hooks/tools/shared/useToolOperation.ts b/frontend/src/core/hooks/tools/shared/useToolOperation.ts similarity index 96% rename from frontend/src/hooks/tools/shared/useToolOperation.ts rename to frontend/src/core/hooks/tools/shared/useToolOperation.ts index f5e575a147..3d8e1406ec 100644 --- a/frontend/src/hooks/tools/shared/useToolOperation.ts +++ b/frontend/src/core/hooks/tools/shared/useToolOperation.ts @@ -1,17 +1,17 @@ import { useCallback, useRef, useEffect } from 'react'; -import apiClient from '../../../services/apiClient'; +import apiClient from '@app/services/apiClient'; import { useTranslation } from 'react-i18next'; -import { useFileContext } from '../../../contexts/FileContext'; -import { useToolState, type ProcessingProgress } from './useToolState'; -import { useToolApiCalls, type ApiCallsConfig } from './useToolApiCalls'; -import { useToolResources } from './useToolResources'; -import { extractErrorMessage } from '../../../utils/toolErrorHandler'; -import { StirlingFile, extractFiles, FileId, StirlingFileStub, createStirlingFile } from '../../../types/fileContext'; -import { FILE_EVENTS } from '../../../services/errorUtils'; -import { ResponseHandler } from '../../../utils/toolResponseProcessor'; -import { createChildStub, generateProcessedFileMetadata } from '../../../contexts/file/fileActions'; -import { ToolOperation } from '../../../types/file'; -import { ToolId } from '../../../types/toolId'; +import { useFileContext } from '@app/contexts/FileContext'; +import { useToolState, type ProcessingProgress } from '@app/hooks/tools/shared/useToolState'; +import { useToolApiCalls, type ApiCallsConfig } from '@app/hooks/tools/shared/useToolApiCalls'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; +import { extractErrorMessage } from '@app/utils/toolErrorHandler'; +import { StirlingFile, extractFiles, FileId, StirlingFileStub, createStirlingFile } from '@app/types/fileContext'; +import { FILE_EVENTS } from '@app/services/errorUtils'; +import { ResponseHandler } from '@app/utils/toolResponseProcessor'; +import { createChildStub, generateProcessedFileMetadata } from '@app/contexts/file/fileActions'; +import { ToolOperation } from '@app/types/file'; +import { ToolId } from '@app/types/toolId'; // Re-export for backwards compatibility export type { ProcessingProgress, ResponseHandler }; @@ -127,7 +127,7 @@ export interface ToolOperationHook { } // Re-export for backwards compatibility -export { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; +export { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; /** * Shared hook for tool operations providing consistent error handling, progress tracking, diff --git a/frontend/src/hooks/tools/shared/useToolResources.ts b/frontend/src/core/hooks/tools/shared/useToolResources.ts similarity index 95% rename from frontend/src/hooks/tools/shared/useToolResources.ts rename to frontend/src/core/hooks/tools/shared/useToolResources.ts index eb5a3f37db..086a00f49c 100644 --- a/frontend/src/hooks/tools/shared/useToolResources.ts +++ b/frontend/src/core/hooks/tools/shared/useToolResources.ts @@ -1,7 +1,7 @@ import { useState, useCallback, useEffect, useRef } from 'react'; -import { generateThumbnailForFile, generateThumbnailWithMetadata, ThumbnailWithMetadata } from '../../../utils/thumbnailUtils'; -import { zipFileService } from '../../../services/zipFileService'; -import { usePreferences } from '../../../contexts/PreferencesContext'; +import { generateThumbnailForFile, generateThumbnailWithMetadata, ThumbnailWithMetadata } from '@app/utils/thumbnailUtils'; +import { zipFileService } from '@app/services/zipFileService'; +import { usePreferences } from '@app/contexts/PreferencesContext'; export const useToolResources = () => { diff --git a/frontend/src/hooks/tools/shared/useToolState.ts b/frontend/src/core/hooks/tools/shared/useToolState.ts similarity index 100% rename from frontend/src/hooks/tools/shared/useToolState.ts rename to frontend/src/core/hooks/tools/shared/useToolState.ts diff --git a/frontend/src/hooks/tools/sign/useSignOperation.ts b/frontend/src/core/hooks/tools/sign/useSignOperation.ts similarity index 86% rename from frontend/src/hooks/tools/sign/useSignOperation.ts rename to frontend/src/core/hooks/tools/sign/useSignOperation.ts index ba128c54d6..79bca1da83 100644 --- a/frontend/src/hooks/tools/sign/useSignOperation.ts +++ b/frontend/src/core/hooks/tools/sign/useSignOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { useToolOperation, ToolOperationHook, ToolType } from '../shared/useToolOperation'; -import { SignParameters, DEFAULT_PARAMETERS } from './useSignParameters'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; +import { useToolOperation, ToolOperationHook, ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { SignParameters, DEFAULT_PARAMETERS } from '@app/hooks/tools/sign/useSignParameters'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; // Static configuration that can be used by both the hook and automation executor export const buildSignFormData = (params: SignParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/sign/useSignParameters.ts b/frontend/src/core/hooks/tools/sign/useSignParameters.ts similarity index 95% rename from frontend/src/hooks/tools/sign/useSignParameters.ts rename to frontend/src/core/hooks/tools/sign/useSignParameters.ts index bc379a36da..f81097db61 100644 --- a/frontend/src/hooks/tools/sign/useSignParameters.ts +++ b/frontend/src/core/hooks/tools/sign/useSignParameters.ts @@ -1,4 +1,4 @@ -import { useBaseParameters } from '../shared/useBaseParameters'; +import { useBaseParameters } from '@app/hooks/tools/shared/useBaseParameters'; export interface SignaturePosition { x: number; diff --git a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts b/frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageOperation.ts similarity index 76% rename from frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts rename to frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageOperation.ts index ab51c0cc43..db34b93bdc 100644 --- a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageOperation.ts +++ b/frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { SingleLargePageParameters, defaultParameters } from './useSingleLargePageParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { SingleLargePageParameters, defaultParameters } from '@app/hooks/tools/singleLargePage/useSingleLargePageParameters'; // Static function that can be used by both the hook and automation executor export const buildSingleLargePageFormData = (_parameters: SingleLargePageParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageParameters.ts b/frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageParameters.ts similarity index 76% rename from frontend/src/hooks/tools/singleLargePage/useSingleLargePageParameters.ts rename to frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageParameters.ts index df401b1a4a..7005ae062d 100644 --- a/frontend/src/hooks/tools/singleLargePage/useSingleLargePageParameters.ts +++ b/frontend/src/core/hooks/tools/singleLargePage/useSingleLargePageParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface SingleLargePageParameters extends BaseParameters { // Extends BaseParameters - ready for future parameter additions if needed diff --git a/frontend/src/hooks/tools/split/useSplitOperation.ts b/frontend/src/core/hooks/tools/split/useSplitOperation.ts similarity index 90% rename from frontend/src/hooks/tools/split/useSplitOperation.ts rename to frontend/src/core/hooks/tools/split/useSplitOperation.ts index 9551498688..c2cfe02a55 100644 --- a/frontend/src/hooks/tools/split/useSplitOperation.ts +++ b/frontend/src/core/hooks/tools/split/useSplitOperation.ts @@ -1,10 +1,10 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation, ToolOperationConfig } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { SplitParameters, defaultParameters } from './useSplitParameters'; -import { SPLIT_METHODS } from '../../../constants/splitConstants'; -import { useToolResources } from '../shared/useToolResources'; +import { ToolType, useToolOperation, ToolOperationConfig } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { SplitParameters, defaultParameters } from '@app/hooks/tools/split/useSplitParameters'; +import { SPLIT_METHODS } from '@app/constants/splitConstants'; +import { useToolResources } from '@app/hooks/tools/shared/useToolResources'; // Static functions that can be used by both the hook and automation executor export const buildSplitFormData = (parameters: SplitParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/split/useSplitParameters.ts b/frontend/src/core/hooks/tools/split/useSplitParameters.ts similarity index 86% rename from frontend/src/hooks/tools/split/useSplitParameters.ts rename to frontend/src/core/hooks/tools/split/useSplitParameters.ts index 8d77604e58..ca3d556e24 100644 --- a/frontend/src/hooks/tools/split/useSplitParameters.ts +++ b/frontend/src/core/hooks/tools/split/useSplitParameters.ts @@ -1,6 +1,6 @@ -import { SPLIT_METHODS, ENDPOINTS, type SplitMethod } from '../../../constants/splitConstants'; -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { SPLIT_METHODS, ENDPOINTS, type SplitMethod } from '@app/constants/splitConstants'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface SplitParameters extends BaseParameters { method: SplitMethod | ''; diff --git a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts b/frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts similarity index 76% rename from frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts rename to frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts index c60375a949..b2a45cd744 100644 --- a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts +++ b/frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation.ts @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; -import { ToolType, useToolOperation } from '../shared/useToolOperation'; -import { createStandardErrorHandler } from '../../../utils/toolErrorHandler'; -import { UnlockPdfFormsParameters, defaultParameters } from './useUnlockPdfFormsParameters'; +import { ToolType, useToolOperation } from '@app/hooks/tools/shared/useToolOperation'; +import { createStandardErrorHandler } from '@app/utils/toolErrorHandler'; +import { UnlockPdfFormsParameters, defaultParameters } from '@app/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters'; // Static function that can be used by both the hook and automation executor export const buildUnlockPdfFormsFormData = (_parameters: UnlockPdfFormsParameters, file: File): FormData => { diff --git a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts b/frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts similarity index 76% rename from frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts rename to frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts index ad2536643c..e4624bafd1 100644 --- a/frontend/src/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts +++ b/frontend/src/core/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters.ts @@ -1,5 +1,5 @@ -import { BaseParameters } from '../../../types/parameters'; -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { BaseParameters } from '@app/types/parameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface UnlockPdfFormsParameters extends BaseParameters { // Extends BaseParameters - ready for future parameter additions if needed diff --git a/frontend/src/hooks/tools/useFavoriteToolItems.ts b/frontend/src/core/hooks/tools/useFavoriteToolItems.ts similarity index 85% rename from frontend/src/hooks/tools/useFavoriteToolItems.ts rename to frontend/src/core/hooks/tools/useFavoriteToolItems.ts index 9101e3e3e4..4678d44810 100644 --- a/frontend/src/hooks/tools/useFavoriteToolItems.ts +++ b/frontend/src/core/hooks/tools/useFavoriteToolItems.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { ToolId } from '../../types/toolId'; -import { ToolRegistryEntry } from '../../data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import { ToolRegistryEntry } from '@app/data/toolsTaxonomy'; export function useFavoriteToolItems( favoriteTools: ToolId[], diff --git a/frontend/src/hooks/tools/useToolPanelGeometry.ts b/frontend/src/core/hooks/tools/useToolPanelGeometry.ts similarity index 100% rename from frontend/src/hooks/tools/useToolPanelGeometry.ts rename to frontend/src/core/hooks/tools/useToolPanelGeometry.ts diff --git a/frontend/src/hooks/tools/useUserToolActivity.ts b/frontend/src/core/hooks/tools/useUserToolActivity.ts similarity index 97% rename from frontend/src/hooks/tools/useUserToolActivity.ts rename to frontend/src/core/hooks/tools/useUserToolActivity.ts index a1149c443c..c3b7cbea95 100644 --- a/frontend/src/hooks/tools/useUserToolActivity.ts +++ b/frontend/src/core/hooks/tools/useUserToolActivity.ts @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback } from 'react'; -import { ToolId } from '../../types/toolId'; +import { ToolId } from '@app/types/toolId'; const RECENT_TOOLS_KEY = 'stirlingpdf.recentTools'; const FAVORITE_TOOLS_KEY = 'stirlingpdf.favoriteTools'; diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts similarity index 90% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts index d17cb26848..9ae2ab43ef 100644 --- a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts +++ b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection.ts @@ -1,6 +1,6 @@ import { PDFFont, PDFPage, rgb } from 'pdf-lib'; -import { wrapText } from '../utils/pdfText'; -import { colorPalette } from '../utils/pdfPalette'; +import { wrapText } from '@app/hooks/tools/validateSignature/utils/pdfText'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; interface DrawCenteredMessageOptions { page: PDFPage; diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts similarity index 90% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts index 27402e5c37..78378f6d61 100644 --- a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts +++ b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection.ts @@ -1,6 +1,6 @@ import { PDFFont, PDFPage } from 'pdf-lib'; -import { wrapText } from '../utils/pdfText'; -import { colorPalette } from '../utils/pdfPalette'; +import { wrapText } from '@app/hooks/tools/validateSignature/utils/pdfText'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; interface FieldBoxOptions { page: PDFPage; diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts similarity index 89% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts index 0d8946e5f9..c055a80a7c 100644 --- a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts +++ b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection.ts @@ -1,11 +1,11 @@ import type { TFunction } from 'i18next'; import { PDFFont, PDFPage } from 'pdf-lib'; -import { SignatureValidationSignature } from '../../../../types/validateSignature'; -import { drawFieldBox } from './FieldBoxSection'; -import { drawStatusBadge } from './StatusBadgeSection'; -import { computeSignatureStatus, statusKindToPdfColor } from '../utils/signatureStatus'; -import { formatDate } from '../utils/pdfText'; -import { colorPalette } from '../utils/pdfPalette'; +import { SignatureValidationSignature } from '@app/types/validateSignature'; +import { drawFieldBox } from '@app/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection'; +import { drawStatusBadge } from '@app/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection'; +import { computeSignatureStatus, statusKindToPdfColor } from '@app/hooks/tools/validateSignature/utils/signatureStatus'; +import { formatDate } from '@app/hooks/tools/validateSignature/utils/pdfText'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; interface DrawSignatureSectionOptions { page: PDFPage; diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection.ts similarity index 100% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/StatusBadgeSection.ts diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts similarity index 89% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts index 820fc78cbc..5e5bf8fa33 100644 --- a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts +++ b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/SummarySection.ts @@ -1,10 +1,10 @@ import type { TFunction } from 'i18next'; import { PDFFont, PDFImage, PDFPage } from 'pdf-lib'; -import { SignatureValidationReportEntry } from '../../../../types/validateSignature'; -import { drawFieldBox } from './FieldBoxSection'; -import { drawThumbnailImage, drawThumbnailPlaceholder } from './ThumbnailSection'; -import { colorPalette } from '../utils/pdfPalette'; -import { formatFileSize } from '../utils/pdfText'; +import { SignatureValidationReportEntry } from '@app/types/validateSignature'; +import { drawFieldBox } from '@app/hooks/tools/validateSignature/outputtedPDFSections/FieldBoxSection'; +import { drawThumbnailImage, drawThumbnailPlaceholder } from '@app/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; +import { formatFileSize } from '@app/hooks/tools/validateSignature/utils/pdfText'; interface DrawSummarySectionOptions { page: PDFPage; diff --git a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts similarity index 93% rename from frontend/src/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts rename to frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts index f23ddbb121..4596a0fe7d 100644 --- a/frontend/src/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts +++ b/frontend/src/core/hooks/tools/validateSignature/outputtedPDFSections/ThumbnailSection.ts @@ -1,5 +1,5 @@ import { PDFFont, PDFPage, PDFImage } from 'pdf-lib'; -import { colorPalette } from '../utils/pdfPalette'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; export const drawThumbnailPlaceholder = ( page: PDFPage, diff --git a/frontend/src/hooks/tools/validateSignature/signatureReportPdf.ts b/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts similarity index 81% rename from frontend/src/hooks/tools/validateSignature/signatureReportPdf.ts rename to frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts index 5f026a89d7..b61e928d15 100644 --- a/frontend/src/hooks/tools/validateSignature/signatureReportPdf.ts +++ b/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts @@ -1,13 +1,13 @@ import { PDFDocument, PDFPage, StandardFonts } from 'pdf-lib'; import type { TFunction } from 'i18next'; -import { SignatureValidationReportEntry } from '../../../types/validateSignature'; -import { REPORT_PDF_FILENAME } from './utils/signatureUtils'; -import { colorPalette } from './utils/pdfPalette'; -import { startReportPage, createThumbnailLoader } from './utils/pdfPageHelpers'; -import { deriveEntryStatus } from './utils/reportStatus'; -import { drawCenteredMessage } from './outputtedPDFSections/CenteredMessageSection'; -import { drawSummarySection } from './outputtedPDFSections/SummarySection'; -import { drawSignatureSection } from './outputtedPDFSections/SignatureSection'; +import { SignatureValidationReportEntry } from '@app/types/validateSignature'; +import { REPORT_PDF_FILENAME } from '@app/hooks/tools/validateSignature/utils/signatureUtils'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; +import { startReportPage, createThumbnailLoader } from '@app/hooks/tools/validateSignature/utils/pdfPageHelpers'; +import { deriveEntryStatus } from '@app/hooks/tools/validateSignature/utils/reportStatus'; +import { drawCenteredMessage } from '@app/hooks/tools/validateSignature/outputtedPDFSections/CenteredMessageSection'; +import { drawSummarySection } from '@app/hooks/tools/validateSignature/outputtedPDFSections/SummarySection'; +import { drawSignatureSection } from '@app/hooks/tools/validateSignature/outputtedPDFSections/SignatureSection'; const PAGE_WIDTH = 612; const PAGE_HEIGHT = 792; diff --git a/frontend/src/hooks/tools/validateSignature/useValidateSignatureOperation.ts b/frontend/src/core/hooks/tools/validateSignature/useValidateSignatureOperation.ts similarity index 88% rename from frontend/src/hooks/tools/validateSignature/useValidateSignatureOperation.ts rename to frontend/src/core/hooks/tools/validateSignature/useValidateSignatureOperation.ts index 9f6e1c20c0..cac9b158ab 100644 --- a/frontend/src/hooks/tools/validateSignature/useValidateSignatureOperation.ts +++ b/frontend/src/core/hooks/tools/validateSignature/useValidateSignatureOperation.ts @@ -1,20 +1,20 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import apiClient from '../../../services/apiClient'; -import { useFileContext } from '../../../contexts/file/fileHooks'; -import { ToolOperationHook } from '../shared/useToolOperation'; -import type { StirlingFile } from '../../../types/fileContext'; -import { extractErrorMessage } from '../../../utils/toolErrorHandler'; +import apiClient from '@app/services/apiClient'; +import { useFileContext } from '@app/contexts/file/fileHooks'; +import { ToolOperationHook } from '@app/hooks/tools/shared/useToolOperation'; +import type { StirlingFile } from '@app/types/fileContext'; +import { extractErrorMessage } from '@app/utils/toolErrorHandler'; import { SignatureValidationBackendResult, SignatureValidationFileResult, SignatureValidationReportEntry, -} from '../../../types/validateSignature'; -import { ValidateSignatureParameters } from './useValidateSignatureParameters'; -import { buildReportEntries } from './utils/signatureReportBuilder'; -import { createReportPdf } from './signatureReportPdf'; -import { createCsvFile as buildCsvFile } from './utils/signatureCsv'; -import { normalizeBackendResult, RESULT_JSON_FILENAME } from './utils/signatureUtils'; +} from '@app/types/validateSignature'; +import { ValidateSignatureParameters } from '@app/hooks/tools/validateSignature/useValidateSignatureParameters'; +import { buildReportEntries } from '@app/hooks/tools/validateSignature/utils/signatureReportBuilder'; +import { createReportPdf } from '@app/hooks/tools/validateSignature/signatureReportPdf'; +import { createCsvFile as buildCsvFile } from '@app/hooks/tools/validateSignature/utils/signatureCsv'; +import { normalizeBackendResult, RESULT_JSON_FILENAME } from '@app/hooks/tools/validateSignature/utils/signatureUtils'; export interface ValidateSignatureOperationHook extends ToolOperationHook { results: SignatureValidationReportEntry[]; diff --git a/frontend/src/hooks/tools/validateSignature/useValidateSignatureParameters.ts b/frontend/src/core/hooks/tools/validateSignature/useValidateSignatureParameters.ts similarity index 81% rename from frontend/src/hooks/tools/validateSignature/useValidateSignatureParameters.ts rename to frontend/src/core/hooks/tools/validateSignature/useValidateSignatureParameters.ts index 7785f4c13c..864b08aea2 100644 --- a/frontend/src/hooks/tools/validateSignature/useValidateSignatureParameters.ts +++ b/frontend/src/core/hooks/tools/validateSignature/useValidateSignatureParameters.ts @@ -1,4 +1,4 @@ -import { useBaseParameters, BaseParametersHook } from '../shared/useBaseParameters'; +import { useBaseParameters, BaseParametersHook } from '@app/hooks/tools/shared/useBaseParameters'; export interface ValidateSignatureParameters { certFile: File | null; diff --git a/frontend/src/hooks/tools/validateSignature/utils/pdfPageHelpers.ts b/frontend/src/core/hooks/tools/validateSignature/utils/pdfPageHelpers.ts similarity index 96% rename from frontend/src/hooks/tools/validateSignature/utils/pdfPageHelpers.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/pdfPageHelpers.ts index 06a7d75300..b348f506f1 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/pdfPageHelpers.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/pdfPageHelpers.ts @@ -1,6 +1,6 @@ import { PDFDocument, PDFFont, PDFImage } from 'pdf-lib'; import type { TFunction } from 'i18next'; -import { colorPalette } from './pdfPalette'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; interface StartPageParams { doc: PDFDocument; diff --git a/frontend/src/hooks/tools/validateSignature/utils/pdfPalette.ts b/frontend/src/core/hooks/tools/validateSignature/utils/pdfPalette.ts similarity index 100% rename from frontend/src/hooks/tools/validateSignature/utils/pdfPalette.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/pdfPalette.ts diff --git a/frontend/src/hooks/tools/validateSignature/utils/pdfText.ts b/frontend/src/core/hooks/tools/validateSignature/utils/pdfText.ts similarity index 100% rename from frontend/src/hooks/tools/validateSignature/utils/pdfText.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/pdfText.ts diff --git a/frontend/src/hooks/tools/validateSignature/utils/reportStatus.ts b/frontend/src/core/hooks/tools/validateSignature/utils/reportStatus.ts similarity index 84% rename from frontend/src/hooks/tools/validateSignature/utils/reportStatus.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/reportStatus.ts index 9b4ed39509..25c0687e1c 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/reportStatus.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/reportStatus.ts @@ -1,6 +1,6 @@ import type { TFunction } from 'i18next'; -import { SignatureValidationReportEntry } from '../../../../types/validateSignature'; -import { colorPalette } from './pdfPalette'; +import { SignatureValidationReportEntry } from '@app/types/validateSignature'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; export const deriveEntryStatus = ( entry: Pick, diff --git a/frontend/src/hooks/tools/validateSignature/utils/signatureCsv.ts b/frontend/src/core/hooks/tools/validateSignature/utils/signatureCsv.ts similarity index 94% rename from frontend/src/hooks/tools/validateSignature/utils/signatureCsv.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/signatureCsv.ts index 8e0b48344f..1a485c37bb 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/signatureCsv.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/signatureCsv.ts @@ -1,5 +1,5 @@ -import { SignatureValidationReportEntry } from '../../../../types/validateSignature'; -import { CSV_FILENAME, booleanToString, escapeCsvValue, keyUsagesToString } from './signatureUtils'; +import { SignatureValidationReportEntry } from '@app/types/validateSignature'; +import { CSV_FILENAME, booleanToString, escapeCsvValue, keyUsagesToString } from '@app/hooks/tools/validateSignature/utils/signatureUtils'; const buildCsvRows = (entries: SignatureValidationReportEntry[]): string[][] => { const headers = [ diff --git a/frontend/src/hooks/tools/validateSignature/utils/signatureReportBuilder.ts b/frontend/src/core/hooks/tools/validateSignature/utils/signatureReportBuilder.ts similarity index 83% rename from frontend/src/hooks/tools/validateSignature/utils/signatureReportBuilder.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/signatureReportBuilder.ts index d4615b52fa..cdff64c43b 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/signatureReportBuilder.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/signatureReportBuilder.ts @@ -1,8 +1,8 @@ -import { SignatureValidationFileResult, SignatureValidationReportEntry } from '../../../../types/validateSignature'; -import { FileContextSelectors } from '../../../../types/fileContext'; -import type { FileId } from '../../../../types/file'; +import { SignatureValidationFileResult, SignatureValidationReportEntry } from '@app/types/validateSignature'; +import { FileContextSelectors } from '@app/types/fileContext'; +import type { FileId } from '@app/types/file'; import type { TFunction } from 'i18next'; -import { deriveEntryStatus } from './reportStatus'; +import { deriveEntryStatus } from '@app/hooks/tools/validateSignature/utils/reportStatus'; interface BuildReportEntriesOptions { results: SignatureValidationFileResult[]; diff --git a/frontend/src/hooks/tools/validateSignature/utils/signatureStatus.ts b/frontend/src/core/hooks/tools/validateSignature/utils/signatureStatus.ts similarity index 93% rename from frontend/src/hooks/tools/validateSignature/utils/signatureStatus.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/signatureStatus.ts index 6ee5310d7e..981fa02e37 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/signatureStatus.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/signatureStatus.ts @@ -1,6 +1,6 @@ import type { TFunction } from 'i18next'; -import type { SignatureValidationSignature } from '../../../../types/validateSignature'; -import { colorPalette } from './pdfPalette'; +import type { SignatureValidationSignature } from '@app/types/validateSignature'; +import { colorPalette } from '@app/hooks/tools/validateSignature/utils/pdfPalette'; export type SignatureStatusKind = 'valid' | 'warning' | 'invalid' | 'neutral'; diff --git a/frontend/src/hooks/tools/validateSignature/utils/signatureUtils.ts b/frontend/src/core/hooks/tools/validateSignature/utils/signatureUtils.ts similarity index 95% rename from frontend/src/hooks/tools/validateSignature/utils/signatureUtils.ts rename to frontend/src/core/hooks/tools/validateSignature/utils/signatureUtils.ts index 6ef96aea2d..bb98afc8cb 100644 --- a/frontend/src/hooks/tools/validateSignature/utils/signatureUtils.ts +++ b/frontend/src/core/hooks/tools/validateSignature/utils/signatureUtils.ts @@ -1,5 +1,5 @@ -import { SignatureValidationBackendResult, SignatureValidationSignature } from '../../../../types/validateSignature'; -import type { StirlingFile } from '../../../../types/fileContext'; +import { SignatureValidationBackendResult, SignatureValidationSignature } from '@app/types/validateSignature'; +import type { StirlingFile } from '@app/types/fileContext'; export const RESULT_JSON_FILENAME = 'signature-validation.json'; export const CSV_FILENAME = 'signature-validation.csv'; diff --git a/frontend/src/hooks/useBaseUrl.ts b/frontend/src/core/hooks/useBaseUrl.ts similarity index 69% rename from frontend/src/hooks/useBaseUrl.ts rename to frontend/src/core/hooks/useBaseUrl.ts index b71beee845..f8e237dc8b 100644 --- a/frontend/src/hooks/useBaseUrl.ts +++ b/frontend/src/core/hooks/useBaseUrl.ts @@ -1,4 +1,4 @@ -import { useAppConfig } from '../contexts/AppConfigContext' +import { useAppConfig } from '@app/contexts/AppConfigContext'; export const useBaseUrl = (): string => { const { config } = useAppConfig(); diff --git a/frontend/src/hooks/useCookieConsent.ts b/frontend/src/core/hooks/useCookieConsent.ts similarity index 98% rename from frontend/src/hooks/useCookieConsent.ts rename to frontend/src/core/hooks/useCookieConsent.ts index 88de503a0c..5c437d717b 100644 --- a/frontend/src/hooks/useCookieConsent.ts +++ b/frontend/src/core/hooks/useCookieConsent.ts @@ -1,7 +1,7 @@ import { useEffect, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { BASE_PATH } from '../constants/app'; -import { useAppConfig } from '../contexts/AppConfigContext'; +import { BASE_PATH } from '@app/constants/app'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; declare global { interface Window { diff --git a/frontend/src/hooks/useDocumentMeta.ts b/frontend/src/core/hooks/useDocumentMeta.ts similarity index 100% rename from frontend/src/hooks/useDocumentMeta.ts rename to frontend/src/core/hooks/useDocumentMeta.ts diff --git a/frontend/src/hooks/useEndpointConfig.ts b/frontend/src/core/hooks/useEndpointConfig.ts similarity index 91% rename from frontend/src/hooks/useEndpointConfig.ts rename to frontend/src/core/hooks/useEndpointConfig.ts index f87c0187aa..3c418aac20 100644 --- a/frontend/src/hooks/useEndpointConfig.ts +++ b/frontend/src/core/hooks/useEndpointConfig.ts @@ -1,10 +1,5 @@ import { useState, useEffect } from 'react'; - -// Helper to get JWT from localStorage for Authorization header -function getAuthHeaders(): HeadersInit { - const token = localStorage.getItem('stirling_jwt'); - return token ? { 'Authorization': `Bearer ${token}` } : {}; -} +import { useRequestHeaders } from '@app/hooks/useRequestHeaders'; /** * Hook to check if a specific endpoint is enabled @@ -18,6 +13,7 @@ export function useEndpointEnabled(endpoint: string): { const [enabled, setEnabled] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const headers = useRequestHeaders(); const fetchEndpointStatus = async () => { if (!endpoint) { @@ -31,7 +27,7 @@ export function useEndpointEnabled(endpoint: string): { setError(null); const response = await fetch(`/api/v1/config/endpoint-enabled?endpoint=${encodeURIComponent(endpoint)}`, { - headers: getAuthHeaders(), + headers, }); if (!response.ok) { @@ -73,6 +69,7 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): { const [endpointStatus, setEndpointStatus] = useState>({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const headers = useRequestHeaders(); const fetchAllEndpointStatuses = async () => { if (!endpoints || endpoints.length === 0) { @@ -89,7 +86,7 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): { const endpointsParam = endpoints.join(','); const response = await fetch(`/api/v1/config/endpoints-enabled?endpoints=${encodeURIComponent(endpointsParam)}`, { - headers: getAuthHeaders(), + headers, }); if (!response.ok) { diff --git a/frontend/src/hooks/useEnhancedProcessedFiles.ts b/frontend/src/core/hooks/useEnhancedProcessedFiles.ts similarity index 98% rename from frontend/src/hooks/useEnhancedProcessedFiles.ts rename to frontend/src/core/hooks/useEnhancedProcessedFiles.ts index 2f0ab923d0..932428dd0d 100644 --- a/frontend/src/hooks/useEnhancedProcessedFiles.ts +++ b/frontend/src/core/hooks/useEnhancedProcessedFiles.ts @@ -1,7 +1,7 @@ import { useState, useEffect, useRef } from 'react'; -import { ProcessedFile, ProcessingState, ProcessingConfig } from '../types/processing'; -import { enhancedPDFProcessingService } from '../services/enhancedPDFProcessingService'; -import { FileHasher } from '../utils/fileHash'; +import { ProcessedFile, ProcessingState, ProcessingConfig } from '@app/types/processing'; +import { enhancedPDFProcessingService } from '@app/services/enhancedPDFProcessingService'; +import { FileHasher } from '@app/utils/fileHash'; interface UseEnhancedProcessedFilesResult { processedFiles: Map; diff --git a/frontend/src/hooks/useFileHandler.ts b/frontend/src/core/hooks/useFileHandler.ts similarity index 90% rename from frontend/src/hooks/useFileHandler.ts rename to frontend/src/core/hooks/useFileHandler.ts index c29b5bd367..93c7fe2864 100644 --- a/frontend/src/hooks/useFileHandler.ts +++ b/frontend/src/core/hooks/useFileHandler.ts @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import { useFileActions } from '../contexts/FileContext'; +import { useFileActions } from '@app/contexts/FileContext'; export const useFileHandler = () => { const { actions } = useFileActions(); diff --git a/frontend/src/hooks/useFileManager.ts b/frontend/src/core/hooks/useFileManager.ts similarity index 95% rename from frontend/src/hooks/useFileManager.ts rename to frontend/src/core/hooks/useFileManager.ts index 0d583201cd..c07b235913 100644 --- a/frontend/src/hooks/useFileManager.ts +++ b/frontend/src/core/hooks/useFileManager.ts @@ -1,8 +1,8 @@ import { useState, useCallback } from 'react'; -import { useIndexedDB } from '../contexts/IndexedDBContext'; -import { fileStorage } from '../services/fileStorage'; -import { StirlingFileStub, StirlingFile } from '../types/fileContext'; -import { FileId } from '../types/fileContext'; +import { useIndexedDB } from '@app/contexts/IndexedDBContext'; +import { fileStorage } from '@app/services/fileStorage'; +import { StirlingFileStub, StirlingFile } from '@app/types/fileContext'; +import { FileId } from '@app/types/fileContext'; export const useFileManager = () => { const [loading, setLoading] = useState(false); diff --git a/frontend/src/hooks/useFileWithUrl.ts b/frontend/src/core/hooks/useFileWithUrl.ts similarity index 96% rename from frontend/src/hooks/useFileWithUrl.ts rename to frontend/src/core/hooks/useFileWithUrl.ts index 5176c1225e..ce0d5945e9 100644 --- a/frontend/src/hooks/useFileWithUrl.ts +++ b/frontend/src/core/hooks/useFileWithUrl.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { isFileObject } from '../types/fileContext'; +import { isFileObject } from '@app/types/fileContext'; /** * Hook to convert a File object to { file: File; url: string } format diff --git a/frontend/src/hooks/useFocusTrap.ts b/frontend/src/core/hooks/useFocusTrap.ts similarity index 100% rename from frontend/src/hooks/useFocusTrap.ts rename to frontend/src/core/hooks/useFocusTrap.ts diff --git a/frontend/src/hooks/useGoogleDrivePicker.ts b/frontend/src/core/hooks/useGoogleDrivePicker.ts similarity index 98% rename from frontend/src/hooks/useGoogleDrivePicker.ts rename to frontend/src/core/hooks/useGoogleDrivePicker.ts index 5c9ead5720..9e60c2357e 100644 --- a/frontend/src/hooks/useGoogleDrivePicker.ts +++ b/frontend/src/core/hooks/useGoogleDrivePicker.ts @@ -7,7 +7,7 @@ import { getGoogleDrivePickerService, isGoogleDriveConfigured, getGoogleDriveConfig, -} from '../services/googleDrivePickerService'; +} from '@app/services/googleDrivePickerService'; interface UseGoogleDrivePickerOptions { multiple?: boolean; diff --git a/frontend/src/hooks/useIndexedDBThumbnail.ts b/frontend/src/core/hooks/useIndexedDBThumbnail.ts similarity index 91% rename from frontend/src/hooks/useIndexedDBThumbnail.ts rename to frontend/src/core/hooks/useIndexedDBThumbnail.ts index c0431eef51..174946335f 100644 --- a/frontend/src/hooks/useIndexedDBThumbnail.ts +++ b/frontend/src/core/hooks/useIndexedDBThumbnail.ts @@ -1,8 +1,8 @@ import { useState, useEffect } from "react"; -import { StirlingFileStub } from "../types/fileContext"; -import { useIndexedDB } from "../contexts/IndexedDBContext"; -import { generateThumbnailForFile } from "../utils/thumbnailUtils"; -import { FileId } from "../types/fileContext"; +import { StirlingFileStub } from "@app/types/fileContext"; +import { useIndexedDB } from "@app/contexts/IndexedDBContext"; +import { generateThumbnailForFile } from "@app/utils/thumbnailUtils"; +import { FileId } from "@app/types/fileContext"; /** diff --git a/frontend/src/hooks/useIsOverflowing.ts b/frontend/src/core/hooks/useIsOverflowing.ts similarity index 100% rename from frontend/src/hooks/useIsOverflowing.ts rename to frontend/src/core/hooks/useIsOverflowing.ts diff --git a/frontend/src/hooks/usePDFProcessor.ts b/frontend/src/core/hooks/usePDFProcessor.ts similarity index 95% rename from frontend/src/hooks/usePDFProcessor.ts rename to frontend/src/core/hooks/usePDFProcessor.ts index 23b8f6d379..b116545e21 100644 --- a/frontend/src/hooks/usePDFProcessor.ts +++ b/frontend/src/core/hooks/usePDFProcessor.ts @@ -1,7 +1,7 @@ import { useState, useCallback } from 'react'; -import { PDFDocument, PDFPage } from '../types/pageEditor'; -import { pdfWorkerManager } from '../services/pdfWorkerManager'; -import { createQuickKey } from '../types/fileContext'; +import { PDFDocument, PDFPage } from '@app/types/pageEditor'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { createQuickKey } from '@app/types/fileContext'; export function usePDFProcessor() { const [loading, setLoading] = useState(false); diff --git a/frontend/src/hooks/usePdfSignatureDetection.ts b/frontend/src/core/hooks/usePdfSignatureDetection.ts similarity index 93% rename from frontend/src/hooks/usePdfSignatureDetection.ts rename to frontend/src/core/hooks/usePdfSignatureDetection.ts index 77b7f79aca..cabfbb83db 100644 --- a/frontend/src/hooks/usePdfSignatureDetection.ts +++ b/frontend/src/core/hooks/usePdfSignatureDetection.ts @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; -import { pdfWorkerManager } from '../services/pdfWorkerManager'; -import { StirlingFile } from '../types/fileContext'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { StirlingFile } from '@app/types/fileContext'; export interface PdfSignatureDetectionResult { hasDigitalSignatures: boolean; diff --git a/frontend/src/hooks/useProcessedFiles.ts b/frontend/src/core/hooks/useProcessedFiles.ts similarity index 96% rename from frontend/src/hooks/useProcessedFiles.ts rename to frontend/src/core/hooks/useProcessedFiles.ts index a7db9b07e4..9d01efc3e8 100644 --- a/frontend/src/hooks/useProcessedFiles.ts +++ b/frontend/src/core/hooks/useProcessedFiles.ts @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; -import { ProcessedFile, ProcessingState } from '../types/processing'; -import { pdfProcessingService } from '../services/pdfProcessingService'; +import { ProcessedFile, ProcessingState } from '@app/types/processing'; +import { pdfProcessingService } from '@app/services/pdfProcessingService'; interface UseProcessedFilesResult { processedFiles: Map; diff --git a/frontend/src/hooks/useRainbowTheme.ts b/frontend/src/core/hooks/useRainbowTheme.ts similarity index 97% rename from frontend/src/hooks/useRainbowTheme.ts rename to frontend/src/core/hooks/useRainbowTheme.ts index 5fc0490073..6e768c0b00 100644 --- a/frontend/src/hooks/useRainbowTheme.ts +++ b/frontend/src/core/hooks/useRainbowTheme.ts @@ -1,6 +1,6 @@ import { useCallback, useRef, useEffect } from 'react'; -import { usePreferences } from '../contexts/PreferencesContext'; -import type { ThemeMode } from '../constants/theme'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import type { ThemeMode } from '@app/constants/theme'; interface RainbowThemeHook { themeMode: ThemeMode; diff --git a/frontend/src/core/hooks/useRequestHeaders.ts b/frontend/src/core/hooks/useRequestHeaders.ts new file mode 100644 index 0000000000..ff0d09ddf7 --- /dev/null +++ b/frontend/src/core/hooks/useRequestHeaders.ts @@ -0,0 +1,3 @@ +export function useRequestHeaders(): HeadersInit { + return {}; +} diff --git a/frontend/src/hooks/useRightRailButtons.ts b/frontend/src/core/hooks/useRightRailButtons.ts similarity index 92% rename from frontend/src/hooks/useRightRailButtons.ts rename to frontend/src/core/hooks/useRightRailButtons.ts index c901017337..aa43b0189e 100644 --- a/frontend/src/hooks/useRightRailButtons.ts +++ b/frontend/src/core/hooks/useRightRailButtons.ts @@ -1,6 +1,6 @@ import { useEffect, useMemo } from 'react'; -import { useRightRail } from '../contexts/RightRailContext'; -import { RightRailAction, RightRailButtonConfig } from '../types/rightRail'; +import { useRightRail } from '@app/contexts/RightRailContext'; +import { RightRailAction, RightRailButtonConfig } from '@app/types/rightRail'; export interface RightRailButtonWithAction extends RightRailButtonConfig { onClick?: RightRailAction; diff --git a/frontend/src/hooks/useScarfTracking.ts b/frontend/src/core/hooks/useScarfTracking.ts similarity index 88% rename from frontend/src/hooks/useScarfTracking.ts rename to frontend/src/core/hooks/useScarfTracking.ts index 4db7dc4175..b0297d5102 100644 --- a/frontend/src/hooks/useScarfTracking.ts +++ b/frontend/src/core/hooks/useScarfTracking.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react'; -import { useAppConfig } from '../contexts/AppConfigContext'; -import { useCookieConsent } from './useCookieConsent'; -import { setScarfConfig, firePixel } from '../utils/scarfTracking'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import { useCookieConsent } from '@app/hooks/useCookieConsent'; +import { setScarfConfig, firePixel } from '@app/utils/scarfTracking'; /** * Hook for initializing Scarf tracking diff --git a/frontend/src/core/hooks/useShouldShowWelcomeModal.ts b/frontend/src/core/hooks/useShouldShowWelcomeModal.ts new file mode 100644 index 0000000000..7de00567a3 --- /dev/null +++ b/frontend/src/core/hooks/useShouldShowWelcomeModal.ts @@ -0,0 +1,11 @@ +import { useMediaQuery } from '@mantine/hooks'; +import { usePreferences } from '@app/contexts/PreferencesContext'; + +export function useShouldShowWelcomeModal(): boolean { + const { preferences } = usePreferences(); + const isMobile = useMediaQuery("(max-width: 1024px)"); + + return !preferences.hasCompletedOnboarding + && preferences.toolPanelModePromptSeen + && !isMobile; +} diff --git a/frontend/src/hooks/useSidebarNavigation.ts b/frontend/src/core/hooks/useSidebarNavigation.ts similarity index 87% rename from frontend/src/hooks/useSidebarNavigation.ts rename to frontend/src/core/hooks/useSidebarNavigation.ts index 42f92e0f17..50065b6cf7 100644 --- a/frontend/src/hooks/useSidebarNavigation.ts +++ b/frontend/src/core/hooks/useSidebarNavigation.ts @@ -1,8 +1,8 @@ import { useCallback } from 'react'; -import { useToolNavigation } from './useToolNavigation'; -import { useToolWorkflow } from '../contexts/ToolWorkflowContext'; -import { handleUnlessSpecialClick } from '../utils/clickHandlers'; -import { ToolId } from 'src/types/toolId'; +import { useToolNavigation } from '@app/hooks/useToolNavigation'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; +import { ToolId } from "@app/types/toolId"; export interface SidebarNavigationProps { /** Full URL for the navigation (for href attribute) */ diff --git a/frontend/src/hooks/useSuggestedTools.ts b/frontend/src/core/hooks/useSuggestedTools.ts similarity index 88% rename from frontend/src/hooks/useSuggestedTools.ts rename to frontend/src/core/hooks/useSuggestedTools.ts index 3cf6179bfd..857108ed45 100644 --- a/frontend/src/hooks/useSuggestedTools.ts +++ b/frontend/src/core/hooks/useSuggestedTools.ts @@ -1,8 +1,8 @@ import { useMemo } from 'react'; -import { useNavigationState } from '../contexts/NavigationContext'; -import { useToolNavigation } from './useToolNavigation'; -import { useToolWorkflow } from '../contexts/ToolWorkflowContext'; -import { ToolId } from '../types/toolId'; +import { useNavigationState } from '@app/contexts/NavigationContext'; +import { useToolNavigation } from '@app/hooks/useToolNavigation'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { ToolId } from '@app/types/toolId'; // Material UI Icons import CompressIcon from '@mui/icons-material/Compress'; diff --git a/frontend/src/hooks/useThumbnailGeneration.ts b/frontend/src/core/hooks/useThumbnailGeneration.ts similarity index 97% rename from frontend/src/hooks/useThumbnailGeneration.ts rename to frontend/src/core/hooks/useThumbnailGeneration.ts index 694fdeeb7b..48f7b241bd 100644 --- a/frontend/src/hooks/useThumbnailGeneration.ts +++ b/frontend/src/core/hooks/useThumbnailGeneration.ts @@ -1,7 +1,7 @@ import { useCallback } from 'react'; -import { thumbnailGenerationService } from '../services/thumbnailGenerationService'; -import { createQuickKey } from '../types/fileContext'; -import { FileId } from '../types/file'; +import { thumbnailGenerationService } from '@app/services/thumbnailGenerationService'; +import { createQuickKey } from '@app/types/fileContext'; +import { FileId } from '@app/types/file'; // Request queue to handle concurrent thumbnail requests interface ThumbnailRequest { diff --git a/frontend/src/hooks/useToolManagement.tsx b/frontend/src/core/hooks/useToolManagement.tsx similarity index 89% rename from frontend/src/hooks/useToolManagement.tsx rename to frontend/src/core/hooks/useToolManagement.tsx index 75d4c4c7ff..fcc543d27a 100644 --- a/frontend/src/hooks/useToolManagement.tsx +++ b/frontend/src/core/hooks/useToolManagement.tsx @@ -1,9 +1,9 @@ import { useState, useCallback, useMemo } from 'react'; -import { useToolRegistry } from "../contexts/ToolRegistryContext"; -import { getAllEndpoints, type ToolRegistryEntry, type ToolRegistry } from "../data/toolsTaxonomy"; -import { useMultipleEndpointsEnabled } from "./useEndpointConfig"; -import { FileId } from '../types/file'; -import { ToolId } from 'src/types/toolId'; +import { useToolRegistry } from "@app/contexts/ToolRegistryContext"; +import { getAllEndpoints, type ToolRegistryEntry, type ToolRegistry } from "@app/data/toolsTaxonomy"; +import { useMultipleEndpointsEnabled } from "@app/hooks/useEndpointConfig"; +import { FileId } from '@app/types/file'; +import { ToolId } from "@app/types/toolId"; interface ToolManagementResult { selectedTool: ToolRegistryEntry | null; diff --git a/frontend/src/hooks/useToolNavigation.ts b/frontend/src/core/hooks/useToolNavigation.ts similarity index 83% rename from frontend/src/hooks/useToolNavigation.ts rename to frontend/src/core/hooks/useToolNavigation.ts index 1fdc8f2c76..7b0c055a28 100644 --- a/frontend/src/hooks/useToolNavigation.ts +++ b/frontend/src/core/hooks/useToolNavigation.ts @@ -1,8 +1,8 @@ import { useCallback } from 'react'; -import { ToolRegistryEntry, getToolUrlPath } from '../data/toolsTaxonomy'; -import { useToolWorkflow } from '../contexts/ToolWorkflowContext'; -import { handleUnlessSpecialClick } from '../utils/clickHandlers'; -import { ToolId } from '../types/toolId'; +import { ToolRegistryEntry, getToolUrlPath } from '@app/data/toolsTaxonomy'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { handleUnlessSpecialClick } from '@app/utils/clickHandlers'; +import { ToolId } from '@app/types/toolId'; export interface ToolNavigationProps { /** Full URL for the tool (for href attribute) */ diff --git a/frontend/src/hooks/useToolParameters.ts b/frontend/src/core/hooks/useToolParameters.ts similarity index 100% rename from frontend/src/hooks/useToolParameters.ts rename to frontend/src/core/hooks/useToolParameters.ts diff --git a/frontend/src/hooks/useToolSections.ts b/frontend/src/core/hooks/useToolSections.ts similarity index 98% rename from frontend/src/hooks/useToolSections.ts rename to frontend/src/core/hooks/useToolSections.ts index 8bfe18a64e..79850f5598 100644 --- a/frontend/src/hooks/useToolSections.ts +++ b/frontend/src/core/hooks/useToolSections.ts @@ -1,8 +1,8 @@ import { useMemo } from 'react'; -import { SUBCATEGORY_ORDER, SubcategoryId, ToolCategoryId, ToolRegistryEntry } from '../data/toolsTaxonomy'; +import { SUBCATEGORY_ORDER, SubcategoryId, ToolCategoryId, ToolRegistryEntry } from '@app/data/toolsTaxonomy'; import { useTranslation } from 'react-i18next'; -import { ToolId } from 'src/types/toolId'; +import { ToolId } from "@app/types/toolId"; type SubcategoryIdMap = { [subcategoryId in SubcategoryId]: Array<{ id: ToolId; tool: ToolRegistryEntry }>; diff --git a/frontend/src/hooks/useTooltipPosition.ts b/frontend/src/core/hooks/useTooltipPosition.ts similarity index 96% rename from frontend/src/hooks/useTooltipPosition.ts rename to frontend/src/core/hooks/useTooltipPosition.ts index 51ef2e9c3e..7b7d9a9231 100644 --- a/frontend/src/hooks/useTooltipPosition.ts +++ b/frontend/src/core/hooks/useTooltipPosition.ts @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; -import { clamp } from '../utils/genericUtils'; -import { getSidebarInfo } from '../utils/sidebarUtils'; -import { SidebarRefs, SidebarState } from '../types/sidebar'; +import { clamp } from '@app/utils/genericUtils'; +import { getSidebarInfo } from '@app/utils/sidebarUtils'; +import { SidebarRefs, SidebarState } from '@app/types/sidebar'; type Position = 'right' | 'left' | 'top' | 'bottom'; diff --git a/frontend/src/hooks/useTranslation.ts b/frontend/src/core/hooks/useTranslation.ts similarity index 100% rename from frontend/src/hooks/useTranslation.ts rename to frontend/src/core/hooks/useTranslation.ts diff --git a/frontend/src/hooks/useUndoRedo.ts b/frontend/src/core/hooks/useUndoRedo.ts similarity index 100% rename from frontend/src/hooks/useUndoRedo.ts rename to frontend/src/core/hooks/useUndoRedo.ts diff --git a/frontend/src/hooks/useUrlSync.ts b/frontend/src/core/hooks/useUrlSync.ts similarity index 93% rename from frontend/src/hooks/useUrlSync.ts rename to frontend/src/core/hooks/useUrlSync.ts index 545285c5ea..577dfa5f26 100644 --- a/frontend/src/hooks/useUrlSync.ts +++ b/frontend/src/core/hooks/useUrlSync.ts @@ -3,11 +3,11 @@ */ import { useEffect, useCallback, useRef } from 'react'; -import { ToolId } from '../types/toolId'; -import { parseToolRoute, updateToolRoute, clearToolRoute } from '../utils/urlRouting'; -import { ToolRegistry } from '../data/toolsTaxonomy'; -import { firePixel } from '../utils/scarfTracking'; -import { withBasePath } from '../constants/app'; +import { ToolId } from '@app/types/toolId'; +import { parseToolRoute, updateToolRoute, clearToolRoute } from '@app/utils/urlRouting'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import { firePixel } from '@app/utils/scarfTracking'; +import { withBasePath } from '@app/constants/app'; /** * Hook to sync workbench and tool with URL using registry diff --git a/frontend/src/i18n.ts b/frontend/src/core/i18n.ts similarity index 100% rename from frontend/src/i18n.ts rename to frontend/src/core/i18n.ts diff --git a/frontend/src/i18n/config.ts b/frontend/src/core/i18n/config.ts similarity index 100% rename from frontend/src/i18n/config.ts rename to frontend/src/core/i18n/config.ts diff --git a/frontend/src/pages/HomePage.css b/frontend/src/core/pages/HomePage.css similarity index 100% rename from frontend/src/pages/HomePage.css rename to frontend/src/core/pages/HomePage.css diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/core/pages/HomePage.tsx similarity index 90% rename from frontend/src/pages/HomePage.tsx rename to frontend/src/core/pages/HomePage.tsx index 9f5ecf6bc1..1e37f5147f 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/core/pages/HomePage.tsx @@ -1,27 +1,27 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useToolWorkflow } from "../contexts/ToolWorkflowContext"; +import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext"; import { Group, useMantineColorScheme } from "@mantine/core"; -import { useSidebarContext } from "../contexts/SidebarContext"; -import { useDocumentMeta } from "../hooks/useDocumentMeta"; -import { BASE_PATH } from "../constants/app"; -import { useBaseUrl } from "../hooks/useBaseUrl"; +import { useSidebarContext } from "@app/contexts/SidebarContext"; +import { useDocumentMeta } from "@app/hooks/useDocumentMeta"; +import { BASE_PATH } from "@app/constants/app"; +import { useBaseUrl } from "@app/hooks/useBaseUrl"; import { useMediaQuery } from "@mantine/hooks"; -import { useAppConfig } from "../contexts/AppConfigContext"; +import { useAppConfig } from "@app/contexts/AppConfigContext"; import AppsIcon from '@mui/icons-material/AppsRounded'; -import ToolPanel from "../components/tools/ToolPanel"; -import Workbench from "../components/layout/Workbench"; -import QuickAccessBar from "../components/shared/QuickAccessBar"; -import RightRail from "../components/shared/RightRail"; -import FileManager from "../components/FileManager"; -import LocalIcon from "../components/shared/LocalIcon"; -import { useFilesModalContext } from "../contexts/FilesModalContext"; -import AppConfigModal from "../components/shared/AppConfigModal"; -import ToolPanelModePrompt from "../components/tools/ToolPanelModePrompt"; -import AdminAnalyticsChoiceModal from "../components/shared/AdminAnalyticsChoiceModal"; +import ToolPanel from "@app/components/tools/ToolPanel"; +import Workbench from "@app/components/layout/Workbench"; +import QuickAccessBar from "@app/components/shared/QuickAccessBar"; +import RightRail from "@app/components/shared/RightRail"; +import FileManager from "@app/components/FileManager"; +import LocalIcon from "@app/components/shared/LocalIcon"; +import { useFilesModalContext } from "@app/contexts/FilesModalContext"; +import AppConfigModal from "@app/components/shared/AppConfigModal"; +import ToolPanelModePrompt from "@app/components/tools/ToolPanelModePrompt"; +import AdminAnalyticsChoiceModal from "@app/components/shared/AdminAnalyticsChoiceModal"; -import "./HomePage.css"; +import "@app/pages/HomePage.css"; type MobileView = "tools" | "workbench"; diff --git a/frontend/src/core/services/apiClient.ts b/frontend/src/core/services/apiClient.ts new file mode 100644 index 0000000000..0b6a293ff2 --- /dev/null +++ b/frontend/src/core/services/apiClient.ts @@ -0,0 +1,25 @@ +import axios from 'axios'; +import { handleHttpError } from '@app/services/httpErrorHandler'; +import { setupApiInterceptors } from '@app/services/apiClientSetup'; + +// Create axios instance with default config +const apiClient = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL || '/', + responseType: 'json', +}); + +// Setup interceptors (core does nothing, proprietary adds JWT auth) +setupApiInterceptors(apiClient); + +// ---------- Install error interceptor ---------- +apiClient.interceptors.response.use( + (response) => response, + async (error) => { + await handleHttpError(error); // Handle error (shows toast unless suppressed) + return Promise.reject(error); + } +); + + +// ---------- Exports ---------- +export default apiClient; diff --git a/frontend/src/core/services/apiClientSetup.ts b/frontend/src/core/services/apiClientSetup.ts new file mode 100644 index 0000000000..f7de717a30 --- /dev/null +++ b/frontend/src/core/services/apiClientSetup.ts @@ -0,0 +1,5 @@ +import { AxiosInstance } from 'axios'; + +export function setupApiInterceptors(_client: AxiosInstance): void { + // Core version: no interceptors to add +} diff --git a/frontend/src/services/automationStorage.ts b/frontend/src/core/services/automationStorage.ts similarity index 100% rename from frontend/src/services/automationStorage.ts rename to frontend/src/core/services/automationStorage.ts diff --git a/frontend/src/services/documentManipulationService.ts b/frontend/src/core/services/documentManipulationService.ts similarity index 98% rename from frontend/src/services/documentManipulationService.ts rename to frontend/src/core/services/documentManipulationService.ts index 54a967509d..edcb2a5357 100644 --- a/frontend/src/services/documentManipulationService.ts +++ b/frontend/src/core/services/documentManipulationService.ts @@ -1,4 +1,4 @@ -import { PDFDocument, PDFPage } from '../types/pageEditor'; +import { PDFDocument, PDFPage } from '@app/types/pageEditor'; /** * Service for applying DOM changes to PDF document state diff --git a/frontend/src/services/enhancedPDFProcessingService.ts b/frontend/src/core/services/enhancedPDFProcessingService.ts similarity index 97% rename from frontend/src/services/enhancedPDFProcessingService.ts rename to frontend/src/core/services/enhancedPDFProcessingService.ts index be58d0a6ea..b084d2eb1d 100644 --- a/frontend/src/services/enhancedPDFProcessingService.ts +++ b/frontend/src/core/services/enhancedPDFProcessingService.ts @@ -1,10 +1,10 @@ -import { ProcessedFile, ProcessingState, PDFPage, ProcessingConfig, ProcessingMetrics } from '../types/processing'; -import { ProcessingCache } from './processingCache'; -import { FileHasher } from '../utils/fileHash'; -import { FileAnalyzer } from './fileAnalyzer'; -import { ProcessingErrorHandler } from './processingErrorHandler'; -import { pdfWorkerManager } from './pdfWorkerManager'; -import { createQuickKey } from '../types/fileContext'; +import { ProcessedFile, ProcessingState, PDFPage, ProcessingConfig, ProcessingMetrics } from '@app/types/processing'; +import { ProcessingCache } from '@app/services/processingCache'; +import { FileHasher } from '@app/utils/fileHash'; +import { FileAnalyzer } from '@app/services/fileAnalyzer'; +import { ProcessingErrorHandler } from '@app/services/processingErrorHandler'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { createQuickKey } from '@app/types/fileContext'; export class EnhancedPDFProcessingService { private static instance: EnhancedPDFProcessingService; diff --git a/frontend/src/services/errorUtils.ts b/frontend/src/core/services/errorUtils.ts similarity index 100% rename from frontend/src/services/errorUtils.ts rename to frontend/src/core/services/errorUtils.ts diff --git a/frontend/src/services/fileAnalyzer.ts b/frontend/src/core/services/fileAnalyzer.ts similarity index 98% rename from frontend/src/services/fileAnalyzer.ts rename to frontend/src/core/services/fileAnalyzer.ts index 5655902a04..e168e530bc 100644 --- a/frontend/src/services/fileAnalyzer.ts +++ b/frontend/src/core/services/fileAnalyzer.ts @@ -1,5 +1,5 @@ -import { FileAnalysis, ProcessingStrategy } from '../types/processing'; -import { pdfWorkerManager } from './pdfWorkerManager'; +import { FileAnalysis, ProcessingStrategy } from '@app/types/processing'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; export class FileAnalyzer { private static readonly SIZE_THRESHOLDS = { diff --git a/frontend/src/services/fileProcessingService.ts b/frontend/src/core/services/fileProcessingService.ts similarity index 97% rename from frontend/src/services/fileProcessingService.ts rename to frontend/src/core/services/fileProcessingService.ts index be822b846c..261adb6c0f 100644 --- a/frontend/src/services/fileProcessingService.ts +++ b/frontend/src/core/services/fileProcessingService.ts @@ -4,9 +4,9 @@ * Called when files are added to FileContext, before any view sees them */ -import { generateThumbnailForFile } from '../utils/thumbnailUtils'; -import { pdfWorkerManager } from './pdfWorkerManager'; -import { FileId } from '../types/file'; +import { generateThumbnailForFile } from '@app/utils/thumbnailUtils'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { FileId } from '@app/types/file'; export interface ProcessedFileMetadata { totalPages: number; diff --git a/frontend/src/services/fileStorage.ts b/frontend/src/core/services/fileStorage.ts similarity index 98% rename from frontend/src/services/fileStorage.ts rename to frontend/src/core/services/fileStorage.ts index b4b1281642..3668f5cf2d 100644 --- a/frontend/src/services/fileStorage.ts +++ b/frontend/src/core/services/fileStorage.ts @@ -4,9 +4,9 @@ * Forces correct usage patterns through service API design */ -import { FileId, BaseFileMetadata } from '../types/file'; -import { StirlingFile, StirlingFileStub, createStirlingFile } from '../types/fileContext'; -import { indexedDBManager, DATABASE_CONFIGS } from './indexedDBManager'; +import { FileId, BaseFileMetadata } from '@app/types/file'; +import { StirlingFile, StirlingFileStub, createStirlingFile } from '@app/types/fileContext'; +import { indexedDBManager, DATABASE_CONFIGS } from '@app/services/indexedDBManager'; /** * Storage record - single source of truth diff --git a/frontend/src/services/fileStubHelpers.ts b/frontend/src/core/services/fileStubHelpers.ts similarity index 81% rename from frontend/src/services/fileStubHelpers.ts rename to frontend/src/core/services/fileStubHelpers.ts index 5f5545e761..b3304aba63 100644 --- a/frontend/src/services/fileStubHelpers.ts +++ b/frontend/src/core/services/fileStubHelpers.ts @@ -1,7 +1,7 @@ -import { StirlingFile, StirlingFileStub } from '../types/fileContext'; -import { createChildStub, generateProcessedFileMetadata } from '../contexts/file/fileActions'; -import { createStirlingFile } from '../types/fileContext'; -import { ToolId } from '../types/toolId'; +import { StirlingFile, StirlingFileStub } from '@app/types/fileContext'; +import { createChildStub, generateProcessedFileMetadata } from '@app/contexts/file/fileActions'; +import { createStirlingFile } from '@app/types/fileContext'; +import { ToolId } from '@app/types/toolId'; /** * Create StirlingFiles and StirlingFileStubs from exported files diff --git a/frontend/src/services/googleDrivePickerService.ts b/frontend/src/core/services/googleDrivePickerService.ts similarity index 99% rename from frontend/src/services/googleDrivePickerService.ts rename to frontend/src/core/services/googleDrivePickerService.ts index cb5b02b87b..d2956c38a6 100644 --- a/frontend/src/services/googleDrivePickerService.ts +++ b/frontend/src/core/services/googleDrivePickerService.ts @@ -3,7 +3,7 @@ * Handles Google Drive file picker integration */ -import { loadScript } from '../utils/scriptLoader'; +import { loadScript } from '@app/utils/scriptLoader'; const SCOPES = 'https://www.googleapis.com/auth/drive.readonly'; const SESSION_STORAGE_ID = 'googleDrivePickerAccessToken'; diff --git a/frontend/src/services/httpErrorHandler.ts b/frontend/src/core/services/httpErrorHandler.ts similarity index 97% rename from frontend/src/services/httpErrorHandler.ts rename to frontend/src/core/services/httpErrorHandler.ts index aaea20036c..e9ad2bca90 100644 --- a/frontend/src/services/httpErrorHandler.ts +++ b/frontend/src/core/services/httpErrorHandler.ts @@ -1,8 +1,8 @@ // frontend/src/services/httpErrorHandler.ts import axios from 'axios'; -import { alert } from '../components/toast'; -import { broadcastErroredFiles, extractErrorFileIds, normalizeAxiosErrorData } from './errorUtils'; -import { showSpecialErrorToast } from './specialErrorToasts'; +import { alert } from '@app/components/toast'; +import { broadcastErroredFiles, extractErrorFileIds, normalizeAxiosErrorData } from '@app/services/errorUtils'; +import { showSpecialErrorToast } from '@app/services/specialErrorToasts'; const FRIENDLY_FALLBACK = 'There was an error processing your request.'; const MAX_TOAST_BODY_CHARS = 400; // avoid massive, unreadable toasts diff --git a/frontend/src/services/indexedDBManager.ts b/frontend/src/core/services/indexedDBManager.ts similarity index 100% rename from frontend/src/services/indexedDBManager.ts rename to frontend/src/core/services/indexedDBManager.ts diff --git a/frontend/src/services/pdfExportHelpers.ts b/frontend/src/core/services/pdfExportHelpers.ts similarity index 91% rename from frontend/src/services/pdfExportHelpers.ts rename to frontend/src/core/services/pdfExportHelpers.ts index fa6d4775f3..8c6fb90b10 100644 --- a/frontend/src/services/pdfExportHelpers.ts +++ b/frontend/src/core/services/pdfExportHelpers.ts @@ -1,6 +1,6 @@ -import { PDFDocument } from '../types/pageEditor'; -import { pdfExportService } from './pdfExportService'; -import { FileId } from '../types/file'; +import { PDFDocument } from '@app/types/pageEditor'; +import { pdfExportService } from '@app/services/pdfExportService'; +import { FileId } from '@app/types/file'; /** * Export processed documents to File objects diff --git a/frontend/src/services/pdfExportService.ts b/frontend/src/core/services/pdfExportService.ts similarity index 99% rename from frontend/src/services/pdfExportService.ts rename to frontend/src/core/services/pdfExportService.ts index d42eeeab2a..ebbd4d2b0e 100644 --- a/frontend/src/services/pdfExportService.ts +++ b/frontend/src/core/services/pdfExportService.ts @@ -1,5 +1,5 @@ import { PDFDocument as PDFLibDocument, degrees, PageSizes } from 'pdf-lib'; -import { PDFDocument, PDFPage } from '../types/pageEditor'; +import { PDFDocument, PDFPage } from '@app/types/pageEditor'; export interface ExportOptions { selectedOnly?: boolean; diff --git a/frontend/src/services/pdfMetadataService.ts b/frontend/src/core/services/pdfMetadataService.ts similarity index 97% rename from frontend/src/services/pdfMetadataService.ts rename to frontend/src/core/services/pdfMetadataService.ts index 74e2e94077..3c1dd2b380 100644 --- a/frontend/src/services/pdfMetadataService.ts +++ b/frontend/src/core/services/pdfMetadataService.ts @@ -1,6 +1,6 @@ -import { pdfWorkerManager } from './pdfWorkerManager'; -import { FileAnalyzer } from './fileAnalyzer'; -import { TrappedStatus, CustomMetadataEntry, ExtractedPDFMetadata } from '../types/metadata'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { FileAnalyzer } from '@app/services/fileAnalyzer'; +import { TrappedStatus, CustomMetadataEntry, ExtractedPDFMetadata } from '@app/types/metadata'; import { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'; export interface MetadataExtractionResult { diff --git a/frontend/src/services/pdfProcessingService.ts b/frontend/src/core/services/pdfProcessingService.ts similarity index 95% rename from frontend/src/services/pdfProcessingService.ts rename to frontend/src/core/services/pdfProcessingService.ts index abcd492acd..02d29898ca 100644 --- a/frontend/src/services/pdfProcessingService.ts +++ b/frontend/src/core/services/pdfProcessingService.ts @@ -1,7 +1,7 @@ -import { ProcessedFile, ProcessingState, PDFPage } from '../types/processing'; -import { ProcessingCache } from './processingCache'; -import { pdfWorkerManager } from './pdfWorkerManager'; -import { createQuickKey } from '../types/fileContext'; +import { ProcessedFile, ProcessingState, PDFPage } from '@app/types/processing'; +import { ProcessingCache } from '@app/services/processingCache'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { createQuickKey } from '@app/types/fileContext'; export class PDFProcessingService { private static instance: PDFProcessingService; diff --git a/frontend/src/services/pdfWorkerManager.ts b/frontend/src/core/services/pdfWorkerManager.ts similarity index 100% rename from frontend/src/services/pdfWorkerManager.ts rename to frontend/src/core/services/pdfWorkerManager.ts diff --git a/frontend/src/services/preferencesService.ts b/frontend/src/core/services/preferencesService.ts similarity index 93% rename from frontend/src/services/preferencesService.ts rename to frontend/src/core/services/preferencesService.ts index da5e4350be..5894eae506 100644 --- a/frontend/src/services/preferencesService.ts +++ b/frontend/src/core/services/preferencesService.ts @@ -1,5 +1,5 @@ -import { type ToolPanelMode, DEFAULT_TOOL_PANEL_MODE } from '../constants/toolPanel'; -import { type ThemeMode, getSystemTheme } from '../constants/theme'; +import { type ToolPanelMode, DEFAULT_TOOL_PANEL_MODE } from '@app/constants/toolPanel'; +import { type ThemeMode, getSystemTheme } from '@app/constants/theme'; export interface UserPreferences { autoUnzip: boolean; diff --git a/frontend/src/services/processingCache.ts b/frontend/src/core/services/processingCache.ts similarity index 99% rename from frontend/src/services/processingCache.ts rename to frontend/src/core/services/processingCache.ts index 820cfcbef2..53a4356be7 100644 --- a/frontend/src/services/processingCache.ts +++ b/frontend/src/core/services/processingCache.ts @@ -1,4 +1,4 @@ -import { ProcessedFile, CacheConfig, CacheEntry, CacheStats } from '../types/processing'; +import { ProcessedFile, CacheConfig, CacheEntry, CacheStats } from '@app/types/processing'; export class ProcessingCache { private cache = new Map(); diff --git a/frontend/src/services/processingErrorHandler.ts b/frontend/src/core/services/processingErrorHandler.ts similarity index 99% rename from frontend/src/services/processingErrorHandler.ts rename to frontend/src/core/services/processingErrorHandler.ts index f6871008da..2cc55cf395 100644 --- a/frontend/src/services/processingErrorHandler.ts +++ b/frontend/src/core/services/processingErrorHandler.ts @@ -1,4 +1,4 @@ -import { ProcessingError } from '../types/processing'; +import { ProcessingError } from '@app/types/processing'; export class ProcessingErrorHandler { private static readonly DEFAULT_MAX_RETRIES = 3; diff --git a/frontend/src/services/signatureDetectionService.ts b/frontend/src/core/services/signatureDetectionService.ts similarity index 100% rename from frontend/src/services/signatureDetectionService.ts rename to frontend/src/core/services/signatureDetectionService.ts diff --git a/frontend/src/services/specialErrorToasts.ts b/frontend/src/core/services/specialErrorToasts.ts similarity index 97% rename from frontend/src/services/specialErrorToasts.ts rename to frontend/src/core/services/specialErrorToasts.ts index cdcc725fed..1468b8dc47 100644 --- a/frontend/src/services/specialErrorToasts.ts +++ b/frontend/src/core/services/specialErrorToasts.ts @@ -1,4 +1,4 @@ -import { alert } from '../components/toast'; +import { alert } from '@app/components/toast'; interface ErrorToastMapping { regex: RegExp; diff --git a/frontend/src/services/thumbnailGenerationService.ts b/frontend/src/core/services/thumbnailGenerationService.ts similarity index 98% rename from frontend/src/services/thumbnailGenerationService.ts rename to frontend/src/core/services/thumbnailGenerationService.ts index 2d76a623f4..c20b7aa475 100644 --- a/frontend/src/services/thumbnailGenerationService.ts +++ b/frontend/src/core/services/thumbnailGenerationService.ts @@ -2,8 +2,9 @@ * High-performance thumbnail generation service using main thread processing */ -import { FileId } from '../types/file'; -import { pdfWorkerManager } from './pdfWorkerManager'; +import { FileId } from '@app/types/file'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; +import { PDFDocumentProxy } from 'pdfjs-dist'; interface ThumbnailResult { pageNumber: number; @@ -26,7 +27,7 @@ interface CachedThumbnail { } interface CachedPDFDocument { - pdf: any; // PDFDocumentProxy from pdfjs-dist + pdf: PDFDocumentProxy; lastUsed: number; refCount: number; } diff --git a/frontend/src/services/zipFileService.ts b/frontend/src/core/services/zipFileService.ts similarity index 99% rename from frontend/src/services/zipFileService.ts rename to frontend/src/core/services/zipFileService.ts index 2b5162cadb..f7f157283f 100644 --- a/frontend/src/services/zipFileService.ts +++ b/frontend/src/core/services/zipFileService.ts @@ -1,7 +1,7 @@ import JSZip, { JSZipObject } from 'jszip'; -import { StirlingFileStub, createStirlingFile } from '../types/fileContext'; -import { generateThumbnailForFile } from '../utils/thumbnailUtils'; -import { fileStorage } from './fileStorage'; +import { StirlingFileStub, createStirlingFile } from '@app/types/fileContext'; +import { generateThumbnailForFile } from '@app/utils/thumbnailUtils'; +import { fileStorage } from '@app/services/fileStorage'; // Undocumented interface in JSZip for JSZipObject._data interface CompressedObject { diff --git a/frontend/src/setupTests.js b/frontend/src/core/setupTests.js similarity index 100% rename from frontend/src/setupTests.js rename to frontend/src/core/setupTests.js diff --git a/frontend/src/setupTests.ts b/frontend/src/core/setupTests.ts similarity index 100% rename from frontend/src/setupTests.ts rename to frontend/src/core/setupTests.ts diff --git a/frontend/src/styles/cookieconsent.css b/frontend/src/core/styles/cookieconsent.css similarity index 100% rename from frontend/src/styles/cookieconsent.css rename to frontend/src/core/styles/cookieconsent.css diff --git a/frontend/src/index.css b/frontend/src/core/styles/index.css similarity index 100% rename from frontend/src/index.css rename to frontend/src/core/styles/index.css diff --git a/frontend/src/styles/rainbow.module.css b/frontend/src/core/styles/rainbow.module.css similarity index 100% rename from frontend/src/styles/rainbow.module.css rename to frontend/src/core/styles/rainbow.module.css diff --git a/frontend/src/styles/tailwind.css b/frontend/src/core/styles/tailwind.css similarity index 100% rename from frontend/src/styles/tailwind.css rename to frontend/src/core/styles/tailwind.css diff --git a/frontend/src/styles/theme.css b/frontend/src/core/styles/theme.css similarity index 95% rename from frontend/src/styles/theme.css rename to frontend/src/core/styles/theme.css index 6423728703..c69fcd3d3e 100644 --- a/frontend/src/styles/theme.css +++ b/frontend/src/core/styles/theme.css @@ -262,27 +262,6 @@ --modal-content-bg: #ffffff; --modal-header-border: rgba(0, 0, 0, 0.06); - /* Auth page colors (light mode only - auth pages force light mode) */ - --auth-bg-color-light-only: #f3f4f6; - --auth-card-bg: #ffffff; - --auth-card-bg-light-only: #ffffff; - --auth-label-text-light-only: #374151; - --auth-input-border-light-only: #d1d5db; - --auth-input-bg-light-only: #ffffff; - --auth-input-text-light-only: #111827; - --auth-border-focus-light-only: #3b82f6; - --auth-focus-ring-light-only: rgba(59, 130, 246, 0.1); - --auth-button-bg-light-only: #AF3434; - --auth-button-text-light-only: #ffffff; - --auth-magic-button-bg-light-only: #e5e7eb; - --auth-magic-button-text-light-only: #374151; - --auth-text-primary-light-only: #111827; - --auth-text-secondary-light-only: #6b7280; - --text-divider-rule-rgb-light: 229, 231, 235; - --text-divider-label-rgb-light: 156, 163, 175; - --tool-subcategory-rule-color-light: #e5e7eb; - --tool-subcategory-text-color-light: #9ca3af; - /* PDF Report Colors (always light) */ --pdf-light-header-bg: 239 246 255; --pdf-light-accent: 59 130 246; diff --git a/frontend/src/styles/zIndex.ts b/frontend/src/core/styles/zIndex.ts similarity index 100% rename from frontend/src/styles/zIndex.ts rename to frontend/src/core/styles/zIndex.ts diff --git a/frontend/src/tests/convert/ConvertE2E.spec.ts b/frontend/src/core/tests/convert/ConvertE2E.spec.ts similarity index 99% rename from frontend/src/tests/convert/ConvertE2E.spec.ts rename to frontend/src/core/tests/convert/ConvertE2E.spec.ts index 5e250030ec..2d2e387a27 100644 --- a/frontend/src/tests/convert/ConvertE2E.spec.ts +++ b/frontend/src/core/tests/convert/ConvertE2E.spec.ts @@ -11,7 +11,7 @@ import { test, expect, Page } from '@playwright/test'; import { conversionDiscovery, type ConversionEndpoint -} from '../helpers/conversionEndpointDiscovery'; +} from '@app/tests/helpers/conversionEndpointDiscovery'; import * as path from 'path'; import * as fs from 'fs'; diff --git a/frontend/src/tests/convert/ConvertIntegration.test.tsx b/frontend/src/core/tests/convert/ConvertIntegration.test.tsx similarity index 97% rename from frontend/src/tests/convert/ConvertIntegration.test.tsx rename to frontend/src/core/tests/convert/ConvertIntegration.test.tsx index 1b8c437f1a..5d0d899d7e 100644 --- a/frontend/src/tests/convert/ConvertIntegration.test.tsx +++ b/frontend/src/core/tests/convert/ConvertIntegration.test.tsx @@ -12,14 +12,14 @@ import React from 'react'; import { describe, test, expect, vi, beforeEach, afterEach, Mock } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useConvertOperation } from '../../hooks/tools/convert/useConvertOperation'; -import { ConvertParameters } from '../../hooks/tools/convert/useConvertParameters'; -import { FileContextProvider } from '../../contexts/FileContext'; -import { PreferencesProvider } from '../../contexts/PreferencesContext'; +import { useConvertOperation } from '@app/hooks/tools/convert/useConvertOperation'; +import { ConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; +import { FileContextProvider } from '@app/contexts/FileContext'; +import { PreferencesProvider } from '@app/contexts/PreferencesContext'; import { I18nextProvider } from 'react-i18next'; -import i18n from '../../i18n/config'; -import { createTestStirlingFile } from '../utils/testFileHelpers'; -import { StirlingFile } from '../../types/fileContext'; +import i18n from '@app/i18n/config'; +import { createTestStirlingFile } from '@app/tests/utils/testFileHelpers'; +import { StirlingFile } from '@app/types/fileContext'; // Mock axios (for static methods like CancelToken, isCancel) vi.mock('axios', () => ({ @@ -50,7 +50,7 @@ vi.mock('../../services/apiClient', () => ({ })); // Import the mocked apiClient -import apiClient from '../../services/apiClient'; +import apiClient from '@app/services/apiClient'; const mockedApiClient = vi.mocked(apiClient); // Mock only essential services that are actually called by the tests diff --git a/frontend/src/tests/convert/ConvertSmartDetectionIntegration.test.tsx b/frontend/src/core/tests/convert/ConvertSmartDetectionIntegration.test.tsx similarity index 96% rename from frontend/src/tests/convert/ConvertSmartDetectionIntegration.test.tsx rename to frontend/src/core/tests/convert/ConvertSmartDetectionIntegration.test.tsx index 45cd461e85..a47bb26fc5 100644 --- a/frontend/src/tests/convert/ConvertSmartDetectionIntegration.test.tsx +++ b/frontend/src/core/tests/convert/ConvertSmartDetectionIntegration.test.tsx @@ -6,15 +6,15 @@ import React from 'react'; import { describe, test, expect, vi, beforeEach, afterEach, Mock } from 'vitest'; import { renderHook, act, waitFor } from '@testing-library/react'; -import { useConvertOperation } from '../../hooks/tools/convert/useConvertOperation'; -import { useConvertParameters } from '../../hooks/tools/convert/useConvertParameters'; -import { FileContextProvider } from '../../contexts/FileContext'; -import { PreferencesProvider } from '../../contexts/PreferencesContext'; +import { useConvertOperation } from '@app/hooks/tools/convert/useConvertOperation'; +import { useConvertParameters } from '@app/hooks/tools/convert/useConvertParameters'; +import { FileContextProvider } from '@app/contexts/FileContext'; +import { PreferencesProvider } from '@app/contexts/PreferencesContext'; import { I18nextProvider } from 'react-i18next'; -import i18n from '../../i18n/config'; -import { detectFileExtension } from '../../utils/fileUtils'; -import { FIT_OPTIONS } from '../../constants/convertConstants'; -import { createTestStirlingFile, createTestFilesWithId } from '../utils/testFileHelpers'; +import i18n from '@app/i18n/config'; +import { detectFileExtension } from '@app/utils/fileUtils'; +import { FIT_OPTIONS } from '@app/constants/convertConstants'; +import { createTestStirlingFile, createTestFilesWithId } from '@app/tests/utils/testFileHelpers'; // Mock axios (for static methods like CancelToken, isCancel) vi.mock('axios', () => ({ @@ -45,7 +45,7 @@ vi.mock('../../services/apiClient', () => ({ })); // Import the mocked apiClient -import apiClient from '../../services/apiClient'; +import apiClient from '@app/services/apiClient'; const mockedApiClient = vi.mocked(apiClient); // Mock only essential services that are actually called by the tests diff --git a/frontend/src/tests/convert/README.md b/frontend/src/core/tests/convert/README.md similarity index 100% rename from frontend/src/tests/convert/README.md rename to frontend/src/core/tests/convert/README.md diff --git a/frontend/src/tests/helpers/conversionEndpointDiscovery.ts b/frontend/src/core/tests/helpers/conversionEndpointDiscovery.ts similarity index 99% rename from frontend/src/tests/helpers/conversionEndpointDiscovery.ts rename to frontend/src/core/tests/helpers/conversionEndpointDiscovery.ts index cf0474dac0..2fbb07b81e 100644 --- a/frontend/src/tests/helpers/conversionEndpointDiscovery.ts +++ b/frontend/src/core/tests/helpers/conversionEndpointDiscovery.ts @@ -4,7 +4,7 @@ * Uses the backend's endpoint configuration API to discover available conversions */ -import { useMultipleEndpointsEnabled } from '../../hooks/useEndpointConfig'; +import { useMultipleEndpointsEnabled } from '@app/hooks/useEndpointConfig'; export interface ConversionEndpoint { endpoint: string; diff --git a/frontend/src/tests/missingTranslations.test.ts b/frontend/src/core/tests/missingTranslations.test.ts similarity index 96% rename from frontend/src/tests/missingTranslations.test.ts rename to frontend/src/core/tests/missingTranslations.test.ts index 53d635e163..2991ecaadb 100644 --- a/frontend/src/tests/missingTranslations.test.ts +++ b/frontend/src/core/tests/missingTranslations.test.ts @@ -3,9 +3,9 @@ import path from 'path'; import ts from 'typescript'; import { describe, expect, test } from 'vitest'; -const REPO_ROOT = path.join(__dirname, '../../../'); -const SRC_ROOT = path.join(__dirname, '..'); -const EN_GB_FILE = path.join(__dirname, '../../public/locales/en-GB/translation.json'); +const REPO_ROOT = path.join(__dirname, '../../../..'); +const SRC_ROOT = path.join(__dirname, '../..'); +const EN_GB_FILE = path.join(__dirname, '../../../public/locales/en-GB/translation.json'); const IGNORED_DIRS = new Set([ 'tests', diff --git a/frontend/src/tests/test-fixtures/README.md b/frontend/src/core/tests/test-fixtures/README.md similarity index 100% rename from frontend/src/tests/test-fixtures/README.md rename to frontend/src/core/tests/test-fixtures/README.md diff --git a/frontend/src/tests/test-fixtures/corrupted.pdf b/frontend/src/core/tests/test-fixtures/corrupted.pdf similarity index 100% rename from frontend/src/tests/test-fixtures/corrupted.pdf rename to frontend/src/core/tests/test-fixtures/corrupted.pdf diff --git a/frontend/src/tests/test-fixtures/sample.csv b/frontend/src/core/tests/test-fixtures/sample.csv similarity index 100% rename from frontend/src/tests/test-fixtures/sample.csv rename to frontend/src/core/tests/test-fixtures/sample.csv diff --git a/frontend/src/tests/test-fixtures/sample.doc b/frontend/src/core/tests/test-fixtures/sample.doc similarity index 100% rename from frontend/src/tests/test-fixtures/sample.doc rename to frontend/src/core/tests/test-fixtures/sample.doc diff --git a/frontend/src/tests/test-fixtures/sample.docx b/frontend/src/core/tests/test-fixtures/sample.docx similarity index 100% rename from frontend/src/tests/test-fixtures/sample.docx rename to frontend/src/core/tests/test-fixtures/sample.docx diff --git a/frontend/src/tests/test-fixtures/sample.eml b/frontend/src/core/tests/test-fixtures/sample.eml similarity index 100% rename from frontend/src/tests/test-fixtures/sample.eml rename to frontend/src/core/tests/test-fixtures/sample.eml diff --git a/frontend/src/tests/test-fixtures/sample.htm b/frontend/src/core/tests/test-fixtures/sample.htm similarity index 100% rename from frontend/src/tests/test-fixtures/sample.htm rename to frontend/src/core/tests/test-fixtures/sample.htm diff --git a/frontend/src/tests/test-fixtures/sample.html b/frontend/src/core/tests/test-fixtures/sample.html similarity index 100% rename from frontend/src/tests/test-fixtures/sample.html rename to frontend/src/core/tests/test-fixtures/sample.html diff --git a/frontend/src/tests/test-fixtures/sample.jpg b/frontend/src/core/tests/test-fixtures/sample.jpg similarity index 100% rename from frontend/src/tests/test-fixtures/sample.jpg rename to frontend/src/core/tests/test-fixtures/sample.jpg diff --git a/frontend/src/tests/test-fixtures/sample.md b/frontend/src/core/tests/test-fixtures/sample.md similarity index 100% rename from frontend/src/tests/test-fixtures/sample.md rename to frontend/src/core/tests/test-fixtures/sample.md diff --git a/frontend/src/tests/test-fixtures/sample.pdf b/frontend/src/core/tests/test-fixtures/sample.pdf similarity index 100% rename from frontend/src/tests/test-fixtures/sample.pdf rename to frontend/src/core/tests/test-fixtures/sample.pdf diff --git a/frontend/src/tests/test-fixtures/sample.png b/frontend/src/core/tests/test-fixtures/sample.png similarity index 100% rename from frontend/src/tests/test-fixtures/sample.png rename to frontend/src/core/tests/test-fixtures/sample.png diff --git a/frontend/src/tests/test-fixtures/sample.pptx b/frontend/src/core/tests/test-fixtures/sample.pptx similarity index 100% rename from frontend/src/tests/test-fixtures/sample.pptx rename to frontend/src/core/tests/test-fixtures/sample.pptx diff --git a/frontend/src/tests/test-fixtures/sample.svg b/frontend/src/core/tests/test-fixtures/sample.svg similarity index 100% rename from frontend/src/tests/test-fixtures/sample.svg rename to frontend/src/core/tests/test-fixtures/sample.svg diff --git a/frontend/src/tests/test-fixtures/sample.txt b/frontend/src/core/tests/test-fixtures/sample.txt similarity index 100% rename from frontend/src/tests/test-fixtures/sample.txt rename to frontend/src/core/tests/test-fixtures/sample.txt diff --git a/frontend/src/tests/test-fixtures/sample.xlsx b/frontend/src/core/tests/test-fixtures/sample.xlsx similarity index 100% rename from frontend/src/tests/test-fixtures/sample.xlsx rename to frontend/src/core/tests/test-fixtures/sample.xlsx diff --git a/frontend/src/tests/test-fixtures/sample.xml b/frontend/src/core/tests/test-fixtures/sample.xml similarity index 100% rename from frontend/src/tests/test-fixtures/sample.xml rename to frontend/src/core/tests/test-fixtures/sample.xml diff --git a/frontend/src/tests/translation.test.ts b/frontend/src/core/tests/translation.test.ts similarity index 95% rename from frontend/src/tests/translation.test.ts rename to frontend/src/core/tests/translation.test.ts index 4251d31240..3e4caa8b8d 100644 --- a/frontend/src/tests/translation.test.ts +++ b/frontend/src/core/tests/translation.test.ts @@ -2,7 +2,7 @@ import { describe, test, expect } from 'vitest'; import fs from 'fs'; import path from 'path'; -const LOCALES_DIR = path.join(__dirname, '../../public/locales'); +const LOCALES_DIR = path.join(__dirname, '../../../public/locales'); // Get all locale directories for parameterized tests const getLocaleDirectories = () => { diff --git a/frontend/src/tests/utils/testFileHelpers.ts b/frontend/src/core/tests/utils/testFileHelpers.ts similarity index 90% rename from frontend/src/tests/utils/testFileHelpers.ts rename to frontend/src/core/tests/utils/testFileHelpers.ts index 80b3c74cf8..72f435e871 100644 --- a/frontend/src/tests/utils/testFileHelpers.ts +++ b/frontend/src/core/tests/utils/testFileHelpers.ts @@ -2,7 +2,7 @@ * Test utilities for creating StirlingFile objects in tests */ -import { StirlingFile, createStirlingFile } from '../../types/fileContext'; +import { StirlingFile, createStirlingFile } from '@app/types/fileContext'; /** * Create a StirlingFile object for testing purposes diff --git a/frontend/src/theme/mantineTheme.ts b/frontend/src/core/theme/mantineTheme.ts similarity index 100% rename from frontend/src/theme/mantineTheme.ts rename to frontend/src/core/theme/mantineTheme.ts diff --git a/frontend/src/tools/AddAttachments.tsx b/frontend/src/core/tools/AddAttachments.tsx similarity index 81% rename from frontend/src/tools/AddAttachments.tsx rename to frontend/src/core/tools/AddAttachments.tsx index 933e786118..c248eab961 100644 --- a/frontend/src/tools/AddAttachments.tsx +++ b/frontend/src/core/tools/AddAttachments.tsx @@ -1,13 +1,13 @@ import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { useFileSelection } from "../contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useAddAttachmentsParameters } from "../hooks/tools/addAttachments/useAddAttachmentsParameters"; -import { useAddAttachmentsOperation } from "../hooks/tools/addAttachments/useAddAttachmentsOperation"; -import { useAccordionSteps } from "../hooks/tools/shared/useAccordionSteps"; -import AddAttachmentsSettings from "../components/tools/addAttachments/AddAttachmentsSettings"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useAddAttachmentsParameters } from "@app/hooks/tools/addAttachments/useAddAttachmentsParameters"; +import { useAddAttachmentsOperation } from "@app/hooks/tools/addAttachments/useAddAttachmentsOperation"; +import { useAccordionSteps } from "@app/hooks/tools/shared/useAccordionSteps"; +import AddAttachmentsSettings from "@app/components/tools/addAttachments/AddAttachmentsSettings"; const AddAttachments = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AddPageNumbers.tsx b/frontend/src/core/tools/AddPageNumbers.tsx similarity index 81% rename from frontend/src/tools/AddPageNumbers.tsx rename to frontend/src/core/tools/AddPageNumbers.tsx index 57566750be..3740c5f222 100644 --- a/frontend/src/tools/AddPageNumbers.tsx +++ b/frontend/src/core/tools/AddPageNumbers.tsx @@ -1,14 +1,14 @@ import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { useFileSelection } from "../contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useAddPageNumbersParameters } from "../components/tools/addPageNumbers/useAddPageNumbersParameters"; -import { useAddPageNumbersOperation } from "../components/tools/addPageNumbers/useAddPageNumbersOperation"; -import { useAccordionSteps } from "../hooks/tools/shared/useAccordionSteps"; -import AddPageNumbersPositionSettings from "../components/tools/addPageNumbers/AddPageNumbersPositionSettings"; -import AddPageNumbersAppearanceSettings from "../components/tools/addPageNumbers/AddPageNumbersAppearanceSettings"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useAddPageNumbersParameters } from "@app/components/tools/addPageNumbers/useAddPageNumbersParameters"; +import { useAddPageNumbersOperation } from "@app/components/tools/addPageNumbers/useAddPageNumbersOperation"; +import { useAccordionSteps } from "@app/hooks/tools/shared/useAccordionSteps"; +import AddPageNumbersPositionSettings from "@app/components/tools/addPageNumbers/AddPageNumbersPositionSettings"; +import AddPageNumbersAppearanceSettings from "@app/components/tools/addPageNumbers/AddPageNumbersAppearanceSettings"; const AddPageNumbers = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AddPassword.tsx b/frontend/src/core/tools/AddPassword.tsx similarity index 81% rename from frontend/src/tools/AddPassword.tsx rename to frontend/src/core/tools/AddPassword.tsx index c29491437e..0986422ab6 100644 --- a/frontend/src/tools/AddPassword.tsx +++ b/frontend/src/core/tools/AddPassword.tsx @@ -1,18 +1,18 @@ import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useFileSelection } from "../contexts/FileContext"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useFileSelection } from "@app/contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; -import AddPasswordSettings from "../components/tools/addPassword/AddPasswordSettings"; -import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings"; +import AddPasswordSettings from "@app/components/tools/addPassword/AddPasswordSettings"; +import ChangePermissionsSettings from "@app/components/tools/changePermissions/ChangePermissionsSettings"; -import { useAddPasswordParameters } from "../hooks/tools/addPassword/useAddPasswordParameters"; -import { useAddPasswordOperation } from "../hooks/tools/addPassword/useAddPasswordOperation"; -import { useAddPasswordTips } from "../components/tooltips/useAddPasswordTips"; -import { useAddPasswordPermissionsTips } from "../components/tooltips/useAddPasswordPermissionsTips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { useAddPasswordParameters } from "@app/hooks/tools/addPassword/useAddPasswordParameters"; +import { useAddPasswordOperation } from "@app/hooks/tools/addPassword/useAddPasswordOperation"; +import { useAddPasswordTips } from "@app/components/tooltips/useAddPasswordTips"; +import { useAddPasswordPermissionsTips } from "@app/components/tooltips/useAddPasswordPermissionsTips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const AddPassword = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AddStamp.tsx b/frontend/src/core/tools/AddStamp.tsx similarity index 85% rename from frontend/src/tools/AddStamp.tsx rename to frontend/src/core/tools/AddStamp.tsx index 87b6c53cc4..efb99ee8ad 100644 --- a/frontend/src/tools/AddStamp.tsx +++ b/frontend/src/core/tools/AddStamp.tsx @@ -1,19 +1,19 @@ import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useFileSelection } from "../contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useAddStampParameters } from "../components/tools/addStamp/useAddStampParameters"; -import { useAddStampOperation } from "../components/tools/addStamp/useAddStampOperation"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useAddStampParameters } from "@app/components/tools/addStamp/useAddStampParameters"; +import { useAddStampOperation } from "@app/components/tools/addStamp/useAddStampOperation"; import { Stack, Text } from "@mantine/core"; -import StampPreview from "../components/tools/addStamp/StampPreview"; -import styles from "../components/tools/addStamp/StampPreview.module.css"; -import ButtonSelector from "../components/shared/ButtonSelector"; -import { useAccordionSteps } from "../hooks/tools/shared/useAccordionSteps"; -import ObscuredOverlay from "../components/shared/ObscuredOverlay"; -import StampSetupSettings from "../components/tools/addStamp/StampSetupSettings"; -import StampPositionFormattingSettings from "../components/tools/addStamp/StampPositionFormattingSettings"; +import StampPreview from "@app/components/tools/addStamp/StampPreview"; +import styles from "@app/components/tools/addStamp/StampPreview.module.css"; +import ButtonSelector from "@app/components/shared/ButtonSelector"; +import { useAccordionSteps } from "@app/hooks/tools/shared/useAccordionSteps"; +import ObscuredOverlay from "@app/components/shared/ObscuredOverlay"; +import StampSetupSettings from "@app/components/tools/addStamp/StampSetupSettings"; +import StampPositionFormattingSettings from "@app/components/tools/addStamp/StampPositionFormattingSettings"; const AddStamp = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AddWatermark.tsx b/frontend/src/core/tools/AddWatermark.tsx similarity index 87% rename from frontend/src/tools/AddWatermark.tsx rename to frontend/src/core/tools/AddWatermark.tsx index 3bafbd3292..c7c040f2b3 100644 --- a/frontend/src/tools/AddWatermark.tsx +++ b/frontend/src/core/tools/AddWatermark.tsx @@ -1,26 +1,26 @@ import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useFileSelection } from "../contexts/FileContext"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useFileSelection } from "@app/contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; -import WatermarkTypeSettings from "../components/tools/addWatermark/WatermarkTypeSettings"; -import WatermarkWording from "../components/tools/addWatermark/WatermarkWording"; -import WatermarkTextStyle from "../components/tools/addWatermark/WatermarkTextStyle"; -import WatermarkImageFile from "../components/tools/addWatermark/WatermarkImageFile"; -import WatermarkFormatting from "../components/tools/addWatermark/WatermarkFormatting"; +import WatermarkTypeSettings from "@app/components/tools/addWatermark/WatermarkTypeSettings"; +import WatermarkWording from "@app/components/tools/addWatermark/WatermarkWording"; +import WatermarkTextStyle from "@app/components/tools/addWatermark/WatermarkTextStyle"; +import WatermarkImageFile from "@app/components/tools/addWatermark/WatermarkImageFile"; +import WatermarkFormatting from "@app/components/tools/addWatermark/WatermarkFormatting"; -import { useAddWatermarkParameters } from "../hooks/tools/addWatermark/useAddWatermarkParameters"; -import { useAddWatermarkOperation } from "../hooks/tools/addWatermark/useAddWatermarkOperation"; +import { useAddWatermarkParameters } from "@app/hooks/tools/addWatermark/useAddWatermarkParameters"; +import { useAddWatermarkOperation } from "@app/hooks/tools/addWatermark/useAddWatermarkOperation"; import { useWatermarkTypeTips, useWatermarkWordingTips, useWatermarkTextStyleTips, useWatermarkFileTips, useWatermarkFormattingTips, -} from "../components/tooltips/useWatermarkTips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +} from "@app/components/tooltips/useWatermarkTips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AdjustContrast.tsx b/frontend/src/core/tools/AdjustContrast.tsx similarity index 79% rename from frontend/src/tools/AdjustContrast.tsx rename to frontend/src/core/tools/AdjustContrast.tsx index 7e92c05419..7acd606fab 100644 --- a/frontend/src/tools/AdjustContrast.tsx +++ b/frontend/src/core/tools/AdjustContrast.tsx @@ -1,15 +1,15 @@ import { useTranslation } from 'react-i18next'; import { useEffect, useMemo, useState } from 'react'; -import { createToolFlow } from '../components/tools/shared/createToolFlow'; -import { BaseToolProps, ToolComponent } from '../types/tool'; -import { useBaseTool } from '../hooks/tools/shared/useBaseTool'; -import { useAdjustContrastParameters } from '../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import { useAdjustContrastOperation } from '../hooks/tools/adjustContrast/useAdjustContrastOperation'; -import AdjustContrastBasicSettings from '../components/tools/adjustContrast/AdjustContrastBasicSettings'; -import AdjustContrastColorSettings from '../components/tools/adjustContrast/AdjustContrastColorSettings'; -import AdjustContrastPreview from '../components/tools/adjustContrast/AdjustContrastPreview'; -import { useAccordionSteps } from '../hooks/tools/shared/useAccordionSteps'; -import NavigationArrows from '../components/shared/filePreview/NavigationArrows'; +import { createToolFlow } from '@app/components/tools/shared/createToolFlow'; +import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool'; +import { useAdjustContrastParameters } from '@app/hooks/tools/adjustContrast/useAdjustContrastParameters'; +import { useAdjustContrastOperation } from '@app/hooks/tools/adjustContrast/useAdjustContrastOperation'; +import AdjustContrastBasicSettings from '@app/components/tools/adjustContrast/AdjustContrastBasicSettings'; +import AdjustContrastColorSettings from '@app/components/tools/adjustContrast/AdjustContrastColorSettings'; +import AdjustContrastPreview from '@app/components/tools/adjustContrast/AdjustContrastPreview'; +import { useAccordionSteps } from '@app/hooks/tools/shared/useAccordionSteps'; +import NavigationArrows from '@app/components/shared/filePreview/NavigationArrows'; const AdjustContrast = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AdjustPageScale.tsx b/frontend/src/core/tools/AdjustPageScale.tsx similarity index 70% rename from frontend/src/tools/AdjustPageScale.tsx rename to frontend/src/core/tools/AdjustPageScale.tsx index 1ae862e6a7..66b1ab2f74 100644 --- a/frontend/src/tools/AdjustPageScale.tsx +++ b/frontend/src/core/tools/AdjustPageScale.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import AdjustPageScaleSettings from "../components/tools/adjustPageScale/AdjustPageScaleSettings"; -import { useAdjustPageScaleParameters } from "../hooks/tools/adjustPageScale/useAdjustPageScaleParameters"; -import { useAdjustPageScaleOperation } from "../hooks/tools/adjustPageScale/useAdjustPageScaleOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useAdjustPageScaleTips } from "../components/tooltips/useAdjustPageScaleTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import AdjustPageScaleSettings from "@app/components/tools/adjustPageScale/AdjustPageScaleSettings"; +import { useAdjustPageScaleParameters } from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleParameters"; +import { useAdjustPageScaleOperation } from "@app/hooks/tools/adjustPageScale/useAdjustPageScaleOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useAdjustPageScaleTips } from "@app/components/tooltips/useAdjustPageScaleTips"; const AdjustPageScale = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/AutoRename.tsx b/frontend/src/core/tools/AutoRename.tsx similarity index 70% rename from frontend/src/tools/AutoRename.tsx rename to frontend/src/core/tools/AutoRename.tsx index c00f880b3a..73e91cc0d7 100644 --- a/frontend/src/tools/AutoRename.tsx +++ b/frontend/src/core/tools/AutoRename.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps } from "@app/types/tool"; -import { useAutoRenameParameters } from "../hooks/tools/autoRename/useAutoRenameParameters"; -import { useAutoRenameOperation } from "../hooks/tools/autoRename/useAutoRenameOperation"; -import { useAutoRenameTips } from "../components/tooltips/useAutoRenameTips"; +import { useAutoRenameParameters } from "@app/hooks/tools/autoRename/useAutoRenameParameters"; +import { useAutoRenameOperation } from "@app/hooks/tools/autoRename/useAutoRenameOperation"; +import { useAutoRenameTips } from "@app/components/tooltips/useAutoRenameTips"; const AutoRename =(props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Automate.tsx b/frontend/src/core/tools/Automate.tsx similarity index 88% rename from frontend/src/tools/Automate.tsx rename to frontend/src/core/tools/Automate.tsx index c91ad8825c..11e7166569 100644 --- a/frontend/src/tools/Automate.tsx +++ b/frontend/src/core/tools/Automate.tsx @@ -1,21 +1,21 @@ import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useFileSelection } from "../contexts/FileContext"; -import { useNavigationActions } from "../contexts/NavigationContext"; -import { useToolWorkflow } from "../contexts/ToolWorkflowContext"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { useNavigationActions } from "@app/contexts/NavigationContext"; +import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { createFilesToolStep } from "../components/tools/shared/FilesToolStep"; -import AutomationSelection from "../components/tools/automate/AutomationSelection"; -import AutomationCreation from "../components/tools/automate/AutomationCreation"; -import AutomationRun from "../components/tools/automate/AutomationRun"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { createFilesToolStep } from "@app/components/tools/shared/FilesToolStep"; +import AutomationSelection from "@app/components/tools/automate/AutomationSelection"; +import AutomationCreation from "@app/components/tools/automate/AutomationCreation"; +import AutomationRun from "@app/components/tools/automate/AutomationRun"; -import { useAutomateOperation } from "../hooks/tools/automate/useAutomateOperation"; -import { BaseToolProps } from "../types/tool"; -import { useToolRegistry } from "../contexts/ToolRegistryContext"; -import { useSavedAutomations } from "../hooks/tools/automate/useSavedAutomations"; -import { AutomationConfig, AutomationStepData, AutomationMode, AutomationStep } from "../types/automation"; -import { AUTOMATION_STEPS } from "../constants/automation"; +import { useAutomateOperation } from "@app/hooks/tools/automate/useAutomateOperation"; +import { BaseToolProps } from "@app/types/tool"; +import { useToolRegistry } from "@app/contexts/ToolRegistryContext"; +import { useSavedAutomations } from "@app/hooks/tools/automate/useSavedAutomations"; +import { AutomationConfig, AutomationStepData, AutomationMode, AutomationStep } from "@app/types/automation"; +import { AUTOMATION_STEPS } from "@app/constants/automation"; const Automate = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/BookletImposition.tsx b/frontend/src/core/tools/BookletImposition.tsx similarity index 70% rename from frontend/src/tools/BookletImposition.tsx rename to frontend/src/core/tools/BookletImposition.tsx index de38217109..6e89cdeeef 100644 --- a/frontend/src/tools/BookletImposition.tsx +++ b/frontend/src/core/tools/BookletImposition.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import BookletImpositionSettings from "../components/tools/bookletImposition/BookletImpositionSettings"; -import { useBookletImpositionParameters } from "../hooks/tools/bookletImposition/useBookletImpositionParameters"; -import { useBookletImpositionOperation } from "../hooks/tools/bookletImposition/useBookletImpositionOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useBookletImpositionTips } from "../components/tooltips/useBookletImpositionTips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import BookletImpositionSettings from "@app/components/tools/bookletImposition/BookletImpositionSettings"; +import { useBookletImpositionParameters } from "@app/hooks/tools/bookletImposition/useBookletImpositionParameters"; +import { useBookletImpositionOperation } from "@app/hooks/tools/bookletImposition/useBookletImpositionOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useBookletImpositionTips } from "@app/components/tooltips/useBookletImpositionTips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const BookletImposition = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/CertSign.tsx b/frontend/src/core/tools/CertSign.tsx similarity index 80% rename from frontend/src/tools/CertSign.tsx rename to frontend/src/core/tools/CertSign.tsx index fd8dabc9c5..10d6b491ec 100644 --- a/frontend/src/tools/CertSign.tsx +++ b/frontend/src/core/tools/CertSign.tsx @@ -1,16 +1,16 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import CertificateTypeSettings from "../components/tools/certSign/CertificateTypeSettings"; -import CertificateFormatSettings from "../components/tools/certSign/CertificateFormatSettings"; -import CertificateFilesSettings from "../components/tools/certSign/CertificateFilesSettings"; -import SignatureAppearanceSettings from "../components/tools/certSign/SignatureAppearanceSettings"; -import { useCertSignParameters } from "../hooks/tools/certSign/useCertSignParameters"; -import { useCertSignOperation } from "../hooks/tools/certSign/useCertSignOperation"; -import { useCertificateTypeTips } from "../components/tooltips/useCertificateTypeTips"; -import { useSignatureAppearanceTips } from "../components/tooltips/useSignatureAppearanceTips"; -import { useSignModeTips } from "../components/tooltips/useSignModeTips"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import CertificateTypeSettings from "@app/components/tools/certSign/CertificateTypeSettings"; +import CertificateFormatSettings from "@app/components/tools/certSign/CertificateFormatSettings"; +import CertificateFilesSettings from "@app/components/tools/certSign/CertificateFilesSettings"; +import SignatureAppearanceSettings from "@app/components/tools/certSign/SignatureAppearanceSettings"; +import { useCertSignParameters } from "@app/hooks/tools/certSign/useCertSignParameters"; +import { useCertSignOperation } from "@app/hooks/tools/certSign/useCertSignOperation"; +import { useCertificateTypeTips } from "@app/components/tooltips/useCertificateTypeTips"; +import { useSignatureAppearanceTips } from "@app/components/tooltips/useSignatureAppearanceTips"; +import { useSignModeTips } from "@app/components/tooltips/useSignModeTips"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const CertSign = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ChangeMetadata.tsx b/frontend/src/core/tools/ChangeMetadata.tsx similarity index 81% rename from frontend/src/tools/ChangeMetadata.tsx rename to frontend/src/core/tools/ChangeMetadata.tsx index 455828b7df..988667a974 100644 --- a/frontend/src/tools/ChangeMetadata.tsx +++ b/frontend/src/core/tools/ChangeMetadata.tsx @@ -1,21 +1,21 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useAccordionSteps } from "../hooks/tools/shared/useAccordionSteps"; -import DeleteAllStep from "../components/tools/changeMetadata/steps/DeleteAllStep"; -import StandardMetadataStep from "../components/tools/changeMetadata/steps/StandardMetadataStep"; -import DocumentDatesStep from "../components/tools/changeMetadata/steps/DocumentDatesStep"; -import AdvancedOptionsStep from "../components/tools/changeMetadata/steps/AdvancedOptionsStep"; -import { useChangeMetadataParameters } from "../hooks/tools/changeMetadata/useChangeMetadataParameters"; -import { useChangeMetadataOperation } from "../hooks/tools/changeMetadata/useChangeMetadataOperation"; -import { useMetadataExtraction } from "../hooks/tools/changeMetadata/useMetadataExtraction"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useAccordionSteps } from "@app/hooks/tools/shared/useAccordionSteps"; +import DeleteAllStep from "@app/components/tools/changeMetadata/steps/DeleteAllStep"; +import StandardMetadataStep from "@app/components/tools/changeMetadata/steps/StandardMetadataStep"; +import DocumentDatesStep from "@app/components/tools/changeMetadata/steps/DocumentDatesStep"; +import AdvancedOptionsStep from "@app/components/tools/changeMetadata/steps/AdvancedOptionsStep"; +import { useChangeMetadataParameters } from "@app/hooks/tools/changeMetadata/useChangeMetadataParameters"; +import { useChangeMetadataOperation } from "@app/hooks/tools/changeMetadata/useChangeMetadataOperation"; +import { useMetadataExtraction } from "@app/hooks/tools/changeMetadata/useMetadataExtraction"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; import { useDeleteAllTips, useStandardMetadataTips, useDocumentDatesTips, useAdvancedOptionsTips -} from "../components/tooltips/useChangeMetadataTips"; +} from "@app/components/tooltips/useChangeMetadataTips"; enum MetadataStep { NONE = 'none', diff --git a/frontend/src/tools/ChangePermissions.tsx b/frontend/src/core/tools/ChangePermissions.tsx similarity index 72% rename from frontend/src/tools/ChangePermissions.tsx rename to frontend/src/core/tools/ChangePermissions.tsx index 3982d15202..7035a52e3b 100644 --- a/frontend/src/tools/ChangePermissions.tsx +++ b/frontend/src/core/tools/ChangePermissions.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings"; -import { useChangePermissionsParameters } from "../hooks/tools/changePermissions/useChangePermissionsParameters"; -import { useChangePermissionsOperation } from "../hooks/tools/changePermissions/useChangePermissionsOperation"; -import { useChangePermissionsTips } from "../components/tooltips/useChangePermissionsTips"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import ChangePermissionsSettings from "@app/components/tools/changePermissions/ChangePermissionsSettings"; +import { useChangePermissionsParameters } from "@app/hooks/tools/changePermissions/useChangePermissionsParameters"; +import { useChangePermissionsOperation } from "@app/hooks/tools/changePermissions/useChangePermissionsOperation"; +import { useChangePermissionsTips } from "@app/components/tooltips/useChangePermissionsTips"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const ChangePermissions = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Compress.tsx b/frontend/src/core/tools/Compress.tsx similarity index 72% rename from frontend/src/tools/Compress.tsx rename to frontend/src/core/tools/Compress.tsx index 6fbc92b098..9b48153281 100644 --- a/frontend/src/tools/Compress.tsx +++ b/frontend/src/core/tools/Compress.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import CompressSettings from "../components/tools/compress/CompressSettings"; -import { useCompressParameters } from "../hooks/tools/compress/useCompressParameters"; -import { useCompressOperation } from "../hooks/tools/compress/useCompressOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useCompressTips } from "../components/tooltips/useCompressTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import CompressSettings from "@app/components/tools/compress/CompressSettings"; +import { useCompressParameters } from "@app/hooks/tools/compress/useCompressParameters"; +import { useCompressOperation } from "@app/hooks/tools/compress/useCompressOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useCompressTips } from "@app/components/tooltips/useCompressTips"; const Compress = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Convert.tsx b/frontend/src/core/tools/Convert.tsx similarity index 88% rename from frontend/src/tools/Convert.tsx rename to frontend/src/core/tools/Convert.tsx index 9019e6fc75..51353cad46 100644 --- a/frontend/src/tools/Convert.tsx +++ b/frontend/src/core/tools/Convert.tsx @@ -1,15 +1,15 @@ import { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useFileState, useFileSelection } from "../contexts/FileContext"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useFileState, useFileSelection } from "@app/contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; -import ConvertSettings from "../components/tools/convert/ConvertSettings"; +import ConvertSettings from "@app/components/tools/convert/ConvertSettings"; -import { useConvertParameters } from "../hooks/tools/convert/useConvertParameters"; -import { useConvertOperation } from "../hooks/tools/convert/useConvertOperation"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { useConvertParameters } from "@app/hooks/tools/convert/useConvertParameters"; +import { useConvertOperation } from "@app/hooks/tools/convert/useConvertOperation"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Crop.tsx b/frontend/src/core/tools/Crop.tsx similarity index 72% rename from frontend/src/tools/Crop.tsx rename to frontend/src/core/tools/Crop.tsx index 4cf6e6b6e0..57c8b30258 100644 --- a/frontend/src/tools/Crop.tsx +++ b/frontend/src/core/tools/Crop.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import CropSettings from "../components/tools/crop/CropSettings"; -import { useCropParameters } from "../hooks/tools/crop/useCropParameters"; -import { useCropOperation } from "../hooks/tools/crop/useCropOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useCropTooltips } from "../components/tooltips/useCropTooltips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import CropSettings from "@app/components/tools/crop/CropSettings"; +import { useCropParameters } from "@app/hooks/tools/crop/useCropParameters"; +import { useCropOperation } from "@app/hooks/tools/crop/useCropOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useCropTooltips } from "@app/components/tooltips/useCropTooltips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const Crop = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ExtractImages.tsx b/frontend/src/core/tools/ExtractImages.tsx similarity index 73% rename from frontend/src/tools/ExtractImages.tsx rename to frontend/src/core/tools/ExtractImages.tsx index de124d8b05..3aee009c99 100644 --- a/frontend/src/tools/ExtractImages.tsx +++ b/frontend/src/core/tools/ExtractImages.tsx @@ -1,10 +1,10 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import ExtractImagesSettings from "../components/tools/extractImages/ExtractImagesSettings"; -import { useExtractImagesParameters } from "../hooks/tools/extractImages/useExtractImagesParameters"; -import { useExtractImagesOperation } from "../hooks/tools/extractImages/useExtractImagesOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import ExtractImagesSettings from "@app/components/tools/extractImages/ExtractImagesSettings"; +import { useExtractImagesParameters } from "@app/hooks/tools/extractImages/useExtractImagesParameters"; +import { useExtractImagesOperation } from "@app/hooks/tools/extractImages/useExtractImagesOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const ExtractImages = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Flatten.tsx b/frontend/src/core/tools/Flatten.tsx similarity index 74% rename from frontend/src/tools/Flatten.tsx rename to frontend/src/core/tools/Flatten.tsx index 833757ecdd..6f80686cd0 100644 --- a/frontend/src/tools/Flatten.tsx +++ b/frontend/src/core/tools/Flatten.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import FlattenSettings from "../components/tools/flatten/FlattenSettings"; -import { useFlattenParameters } from "../hooks/tools/flatten/useFlattenParameters"; -import { useFlattenOperation } from "../hooks/tools/flatten/useFlattenOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useFlattenTips } from "../components/tooltips/useFlattenTips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import FlattenSettings from "@app/components/tools/flatten/FlattenSettings"; +import { useFlattenParameters } from "@app/hooks/tools/flatten/useFlattenParameters"; +import { useFlattenOperation } from "@app/hooks/tools/flatten/useFlattenOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useFlattenTips } from "@app/components/tooltips/useFlattenTips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const Flatten = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Merge.tsx b/frontend/src/core/tools/Merge.tsx similarity index 81% rename from frontend/src/tools/Merge.tsx rename to frontend/src/core/tools/Merge.tsx index ef9f8228af..e725291dbb 100644 --- a/frontend/src/tools/Merge.tsx +++ b/frontend/src/core/tools/Merge.tsx @@ -1,14 +1,14 @@ import { useCallback } from "react"; import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import MergeSettings from "../components/tools/merge/MergeSettings"; -import MergeFileSorter from "../components/tools/merge/MergeFileSorter"; -import { useMergeParameters } from "../hooks/tools/merge/useMergeParameters"; -import { useMergeOperation } from "../hooks/tools/merge/useMergeOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useMergeTips } from "../components/tooltips/useMergeTips"; -import { useFileManagement, useSelectedFiles, useAllFiles } from "../contexts/FileContext"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import MergeSettings from "@app/components/tools/merge/MergeSettings"; +import MergeFileSorter from "@app/components/tools/merge/MergeFileSorter"; +import { useMergeParameters } from "@app/hooks/tools/merge/useMergeParameters"; +import { useMergeOperation } from "@app/hooks/tools/merge/useMergeOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useMergeTips } from "@app/components/tooltips/useMergeTips"; +import { useFileManagement, useSelectedFiles, useAllFiles } from "@app/contexts/FileContext"; const Merge = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/OCR.tsx b/frontend/src/core/tools/OCR.tsx similarity index 85% rename from frontend/src/tools/OCR.tsx rename to frontend/src/core/tools/OCR.tsx index c480972ad9..d9ad71c7a1 100644 --- a/frontend/src/tools/OCR.tsx +++ b/frontend/src/core/tools/OCR.tsx @@ -1,18 +1,18 @@ import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useFileSelection } from "../contexts/FileContext"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useFileSelection } from "@app/contexts/FileContext"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; -import OCRSettings from "../components/tools/ocr/OCRSettings"; -import AdvancedOCRSettings from "../components/tools/ocr/AdvancedOCRSettings"; +import OCRSettings from "@app/components/tools/ocr/OCRSettings"; +import AdvancedOCRSettings from "@app/components/tools/ocr/AdvancedOCRSettings"; -import { useOCRParameters } from "../hooks/tools/ocr/useOCRParameters"; -import { useOCROperation } from "../hooks/tools/ocr/useOCROperation"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useOCRTips } from "../components/tooltips/useOCRTips"; -import { useAdvancedOCRTips } from "../components/tooltips/useAdvancedOCRTips"; +import { useOCRParameters } from "@app/hooks/tools/ocr/useOCRParameters"; +import { useOCROperation } from "@app/hooks/tools/ocr/useOCROperation"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useOCRTips } from "@app/components/tooltips/useOCRTips"; +import { useAdvancedOCRTips } from "@app/components/tooltips/useAdvancedOCRTips"; const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/OverlayPdfs.tsx b/frontend/src/core/tools/OverlayPdfs.tsx similarity index 72% rename from frontend/src/tools/OverlayPdfs.tsx rename to frontend/src/core/tools/OverlayPdfs.tsx index ffd83cdd58..adae6fffbb 100644 --- a/frontend/src/tools/OverlayPdfs.tsx +++ b/frontend/src/core/tools/OverlayPdfs.tsx @@ -1,11 +1,11 @@ import { useTranslation } from 'react-i18next'; -import { createToolFlow } from '../components/tools/shared/createToolFlow'; -import { useBaseTool } from '../hooks/tools/shared/useBaseTool'; -import { BaseToolProps, ToolComponent } from '../types/tool'; -import OverlayPdfsSettings from '../components/tools/overlayPdfs/OverlayPdfsSettings'; -import { useOverlayPdfsParameters } from '../hooks/tools/overlayPdfs/useOverlayPdfsParameters'; -import { useOverlayPdfsOperation } from '../hooks/tools/overlayPdfs/useOverlayPdfsOperation'; -import { useOverlayPdfsTips } from '../components/tooltips/useOverlayPdfsTips'; +import { createToolFlow } from '@app/components/tools/shared/createToolFlow'; +import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool'; +import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import OverlayPdfsSettings from '@app/components/tools/overlayPdfs/OverlayPdfsSettings'; +import { useOverlayPdfsParameters } from '@app/hooks/tools/overlayPdfs/useOverlayPdfsParameters'; +import { useOverlayPdfsOperation } from '@app/hooks/tools/overlayPdfs/useOverlayPdfsOperation'; +import { useOverlayPdfsTips } from '@app/components/tooltips/useOverlayPdfsTips'; const OverlayPdfs = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/PageLayout.tsx b/frontend/src/core/tools/PageLayout.tsx similarity index 73% rename from frontend/src/tools/PageLayout.tsx rename to frontend/src/core/tools/PageLayout.tsx index 57a99724af..1b8608dab1 100644 --- a/frontend/src/tools/PageLayout.tsx +++ b/frontend/src/core/tools/PageLayout.tsx @@ -1,10 +1,10 @@ import { useTranslation } from 'react-i18next'; -import { createToolFlow } from '../components/tools/shared/createToolFlow'; -import { useBaseTool } from '../hooks/tools/shared/useBaseTool'; -import { BaseToolProps, ToolComponent } from '../types/tool'; -import { usePageLayoutParameters } from '../hooks/tools/pageLayout/usePageLayoutParameters'; -import { usePageLayoutOperation } from '../hooks/tools/pageLayout/usePageLayoutOperation'; -import PageLayoutSettings from '../components/tools/pageLayout/PageLayoutSettings'; +import { createToolFlow } from '@app/components/tools/shared/createToolFlow'; +import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool'; +import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import { usePageLayoutParameters } from '@app/hooks/tools/pageLayout/usePageLayoutParameters'; +import { usePageLayoutOperation } from '@app/hooks/tools/pageLayout/usePageLayoutOperation'; +import PageLayoutSettings from '@app/components/tools/pageLayout/PageLayoutSettings'; const PageLayout = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Redact.tsx b/frontend/src/core/tools/Redact.tsx similarity index 85% rename from frontend/src/tools/Redact.tsx rename to frontend/src/core/tools/Redact.tsx index 3c15938b7c..27604da0b7 100644 --- a/frontend/src/tools/Redact.tsx +++ b/frontend/src/core/tools/Redact.tsx @@ -1,14 +1,14 @@ import { useTranslation } from "react-i18next"; import { useState } from "react"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import RedactModeSelector from "../components/tools/redact/RedactModeSelector"; -import { useRedactParameters } from "../hooks/tools/redact/useRedactParameters"; -import { useRedactOperation } from "../hooks/tools/redact/useRedactOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useRedactModeTips, useRedactWordsTips, useRedactAdvancedTips } from "../components/tooltips/useRedactTips"; -import RedactAdvancedSettings from "../components/tools/redact/RedactAdvancedSettings"; -import WordsToRedactInput from "../components/tools/redact/WordsToRedactInput"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import RedactModeSelector from "@app/components/tools/redact/RedactModeSelector"; +import { useRedactParameters } from "@app/hooks/tools/redact/useRedactParameters"; +import { useRedactOperation } from "@app/hooks/tools/redact/useRedactOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useRedactModeTips, useRedactWordsTips, useRedactAdvancedTips } from "@app/components/tooltips/useRedactTips"; +import RedactAdvancedSettings from "@app/components/tools/redact/RedactAdvancedSettings"; +import WordsToRedactInput from "@app/components/tools/redact/WordsToRedactInput"; const Redact = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemoveAnnotations.tsx b/frontend/src/core/tools/RemoveAnnotations.tsx similarity index 69% rename from frontend/src/tools/RemoveAnnotations.tsx rename to frontend/src/core/tools/RemoveAnnotations.tsx index 3c1518fcf1..82d2f47b8a 100644 --- a/frontend/src/tools/RemoveAnnotations.tsx +++ b/frontend/src/core/tools/RemoveAnnotations.tsx @@ -1,10 +1,10 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import RemoveAnnotationsSettings from "../components/tools/removeAnnotations/RemoveAnnotationsSettings"; -import { useRemoveAnnotationsParameters } from "../hooks/tools/removeAnnotations/useRemoveAnnotationsParameters"; -import { useRemoveAnnotationsOperation } from "../hooks/tools/removeAnnotations/useRemoveAnnotationsOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import RemoveAnnotationsSettings from "@app/components/tools/removeAnnotations/RemoveAnnotationsSettings"; +import { useRemoveAnnotationsParameters } from "@app/hooks/tools/removeAnnotations/useRemoveAnnotationsParameters"; +import { useRemoveAnnotationsOperation } from "@app/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const RemoveAnnotations = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemoveBlanks.tsx b/frontend/src/core/tools/RemoveBlanks.tsx similarity index 73% rename from frontend/src/tools/RemoveBlanks.tsx rename to frontend/src/core/tools/RemoveBlanks.tsx index d7478bdac4..f47a02f936 100644 --- a/frontend/src/tools/RemoveBlanks.tsx +++ b/frontend/src/core/tools/RemoveBlanks.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useRemoveBlanksParameters } from "../hooks/tools/removeBlanks/useRemoveBlanksParameters"; -import { useRemoveBlanksOperation } from "../hooks/tools/removeBlanks/useRemoveBlanksOperation"; -import RemoveBlanksSettings from "../components/tools/removeBlanks/RemoveBlanksSettings"; -import { useRemoveBlanksTips } from "../components/tooltips/useRemoveBlanksTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useRemoveBlanksParameters } from "@app/hooks/tools/removeBlanks/useRemoveBlanksParameters"; +import { useRemoveBlanksOperation } from "@app/hooks/tools/removeBlanks/useRemoveBlanksOperation"; +import RemoveBlanksSettings from "@app/components/tools/removeBlanks/RemoveBlanksSettings"; +import { useRemoveBlanksTips } from "@app/components/tooltips/useRemoveBlanksTips"; const RemoveBlanks = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemoveCertificateSign.tsx b/frontend/src/core/tools/RemoveCertificateSign.tsx similarity index 71% rename from frontend/src/tools/RemoveCertificateSign.tsx rename to frontend/src/core/tools/RemoveCertificateSign.tsx index 13a3068e60..c182d920ee 100644 --- a/frontend/src/tools/RemoveCertificateSign.tsx +++ b/frontend/src/core/tools/RemoveCertificateSign.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useRemoveCertificateSignParameters } from "../hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters"; -import { useRemoveCertificateSignOperation } from "../hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useRemoveCertificateSignParameters } from "@app/hooks/tools/removeCertificateSign/useRemoveCertificateSignParameters"; +import { useRemoveCertificateSignOperation } from "@app/hooks/tools/removeCertificateSign/useRemoveCertificateSignOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const RemoveCertificateSign = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemoveImage.tsx b/frontend/src/core/tools/RemoveImage.tsx similarity index 71% rename from frontend/src/tools/RemoveImage.tsx rename to frontend/src/core/tools/RemoveImage.tsx index f636f9f651..27b07a9a34 100644 --- a/frontend/src/tools/RemoveImage.tsx +++ b/frontend/src/core/tools/RemoveImage.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useRemoveImageParameters } from "../hooks/tools/removeImage/useRemoveImageParameters"; -import { useRemoveImageOperation } from "../hooks/tools/removeImage/useRemoveImageOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useRemoveImageParameters } from "@app/hooks/tools/removeImage/useRemoveImageParameters"; +import { useRemoveImageOperation } from "@app/hooks/tools/removeImage/useRemoveImageOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const RemoveImage = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemovePages.tsx b/frontend/src/core/tools/RemovePages.tsx similarity index 72% rename from frontend/src/tools/RemovePages.tsx rename to frontend/src/core/tools/RemovePages.tsx index ec3e9762d1..93b905f211 100644 --- a/frontend/src/tools/RemovePages.tsx +++ b/frontend/src/core/tools/RemovePages.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useRemovePagesParameters } from "../hooks/tools/removePages/useRemovePagesParameters"; -import { useRemovePagesOperation } from "../hooks/tools/removePages/useRemovePagesOperation"; -import RemovePagesSettings from "../components/tools/removePages/RemovePagesSettings"; -import { useRemovePagesTips } from "../components/tooltips/useRemovePagesTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useRemovePagesParameters } from "@app/hooks/tools/removePages/useRemovePagesParameters"; +import { useRemovePagesOperation } from "@app/hooks/tools/removePages/useRemovePagesOperation"; +import RemovePagesSettings from "@app/components/tools/removePages/RemovePagesSettings"; +import { useRemovePagesTips } from "@app/components/tooltips/useRemovePagesTips"; const RemovePages = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/RemovePassword.tsx b/frontend/src/core/tools/RemovePassword.tsx similarity index 72% rename from frontend/src/tools/RemovePassword.tsx rename to frontend/src/core/tools/RemovePassword.tsx index 970eb324b9..a39fc4efd9 100644 --- a/frontend/src/tools/RemovePassword.tsx +++ b/frontend/src/core/tools/RemovePassword.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import RemovePasswordSettings from "../components/tools/removePassword/RemovePasswordSettings"; -import { useRemovePasswordParameters } from "../hooks/tools/removePassword/useRemovePasswordParameters"; -import { useRemovePasswordOperation } from "../hooks/tools/removePassword/useRemovePasswordOperation"; -import { useRemovePasswordTips } from "../components/tooltips/useRemovePasswordTips"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import RemovePasswordSettings from "@app/components/tools/removePassword/RemovePasswordSettings"; +import { useRemovePasswordParameters } from "@app/hooks/tools/removePassword/useRemovePasswordParameters"; +import { useRemovePasswordOperation } from "@app/hooks/tools/removePassword/useRemovePasswordOperation"; +import { useRemovePasswordTips } from "@app/components/tooltips/useRemovePasswordTips"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const RemovePassword = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ReorganizePages.tsx b/frontend/src/core/tools/ReorganizePages.tsx similarity index 79% rename from frontend/src/tools/ReorganizePages.tsx rename to frontend/src/core/tools/ReorganizePages.tsx index e2a68e883f..9ce1ec2dad 100644 --- a/frontend/src/tools/ReorganizePages.tsx +++ b/frontend/src/core/tools/ReorganizePages.tsx @@ -1,13 +1,13 @@ import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useEndpointEnabled } from "../hooks/useEndpointConfig"; -import { useFileSelection } from "../contexts/FileContext"; -import { useAccordionSteps } from "../hooks/tools/shared/useAccordionSteps"; -import ReorganizePagesSettings from "../components/tools/reorganizePages/ReorganizePagesSettings"; -import { useReorganizePagesParameters } from "../hooks/tools/reorganizePages/useReorganizePagesParameters"; -import { useReorganizePagesOperation } from "../hooks/tools/reorganizePages/useReorganizePagesOperation"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useEndpointEnabled } from "@app/hooks/useEndpointConfig"; +import { useFileSelection } from "@app/contexts/FileContext"; +import { useAccordionSteps } from "@app/hooks/tools/shared/useAccordionSteps"; +import ReorganizePagesSettings from "@app/components/tools/reorganizePages/ReorganizePagesSettings"; +import { useReorganizePagesParameters } from "@app/hooks/tools/reorganizePages/useReorganizePagesParameters"; +import { useReorganizePagesOperation } from "@app/hooks/tools/reorganizePages/useReorganizePagesOperation"; const ReorganizePages = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Repair.tsx b/frontend/src/core/tools/Repair.tsx similarity index 73% rename from frontend/src/tools/Repair.tsx rename to frontend/src/core/tools/Repair.tsx index 88cf4eb281..22e2fff9f2 100644 --- a/frontend/src/tools/Repair.tsx +++ b/frontend/src/core/tools/Repair.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useRepairParameters } from "../hooks/tools/repair/useRepairParameters"; -import { useRepairOperation } from "../hooks/tools/repair/useRepairOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useRepairParameters } from "@app/hooks/tools/repair/useRepairParameters"; +import { useRepairOperation } from "@app/hooks/tools/repair/useRepairOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const Repair = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ReplaceColor.tsx b/frontend/src/core/tools/ReplaceColor.tsx similarity index 71% rename from frontend/src/tools/ReplaceColor.tsx rename to frontend/src/core/tools/ReplaceColor.tsx index 5486fc5916..a86512b09e 100644 --- a/frontend/src/tools/ReplaceColor.tsx +++ b/frontend/src/core/tools/ReplaceColor.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import ReplaceColorSettings from "../components/tools/replaceColor/ReplaceColorSettings"; -import { useReplaceColorParameters } from "../hooks/tools/replaceColor/useReplaceColorParameters"; -import { useReplaceColorOperation } from "../hooks/tools/replaceColor/useReplaceColorOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useReplaceColorTips } from "../components/tooltips/useReplaceColorTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import ReplaceColorSettings from "@app/components/tools/replaceColor/ReplaceColorSettings"; +import { useReplaceColorParameters } from "@app/hooks/tools/replaceColor/useReplaceColorParameters"; +import { useReplaceColorOperation } from "@app/hooks/tools/replaceColor/useReplaceColorOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useReplaceColorTips } from "@app/components/tooltips/useReplaceColorTips"; const ReplaceColor = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Rotate.tsx b/frontend/src/core/tools/Rotate.tsx similarity index 71% rename from frontend/src/tools/Rotate.tsx rename to frontend/src/core/tools/Rotate.tsx index 0b45d8d54b..78178055c3 100644 --- a/frontend/src/tools/Rotate.tsx +++ b/frontend/src/core/tools/Rotate.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import RotateSettings from "../components/tools/rotate/RotateSettings"; -import { useRotateParameters } from "../hooks/tools/rotate/useRotateParameters"; -import { useRotateOperation } from "../hooks/tools/rotate/useRotateOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useRotateTips } from "../components/tooltips/useRotateTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import RotateSettings from "@app/components/tools/rotate/RotateSettings"; +import { useRotateParameters } from "@app/hooks/tools/rotate/useRotateParameters"; +import { useRotateOperation } from "@app/hooks/tools/rotate/useRotateOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useRotateTips } from "@app/components/tooltips/useRotateTips"; const Rotate = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Sanitize.tsx b/frontend/src/core/tools/Sanitize.tsx similarity index 76% rename from frontend/src/tools/Sanitize.tsx rename to frontend/src/core/tools/Sanitize.tsx index 9e0c46db34..121c8a9ab5 100644 --- a/frontend/src/tools/Sanitize.tsx +++ b/frontend/src/core/tools/Sanitize.tsx @@ -1,10 +1,10 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import SanitizeSettings from "../components/tools/sanitize/SanitizeSettings"; -import { useSanitizeParameters } from "../hooks/tools/sanitize/useSanitizeParameters"; -import { useSanitizeOperation } from "../hooks/tools/sanitize/useSanitizeOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import SanitizeSettings from "@app/components/tools/sanitize/SanitizeSettings"; +import { useSanitizeParameters } from "@app/hooks/tools/sanitize/useSanitizeParameters"; +import { useSanitizeOperation } from "@app/hooks/tools/sanitize/useSanitizeOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const Sanitize = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ScannerImageSplit.tsx b/frontend/src/core/tools/ScannerImageSplit.tsx similarity index 70% rename from frontend/src/tools/ScannerImageSplit.tsx rename to frontend/src/core/tools/ScannerImageSplit.tsx index 2b0a12ff5b..1acf17d63b 100644 --- a/frontend/src/tools/ScannerImageSplit.tsx +++ b/frontend/src/core/tools/ScannerImageSplit.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import ScannerImageSplitSettings from "../components/tools/scannerImageSplit/ScannerImageSplitSettings"; -import { useScannerImageSplitParameters } from "../hooks/tools/scannerImageSplit/useScannerImageSplitParameters"; -import { useScannerImageSplitOperation } from "../hooks/tools/scannerImageSplit/useScannerImageSplitOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { useScannerImageSplitTips } from "../components/tooltips/useScannerImageSplitTips"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import ScannerImageSplitSettings from "@app/components/tools/scannerImageSplit/ScannerImageSplitSettings"; +import { useScannerImageSplitParameters } from "@app/hooks/tools/scannerImageSplit/useScannerImageSplitParameters"; +import { useScannerImageSplitOperation } from "@app/hooks/tools/scannerImageSplit/useScannerImageSplitOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { useScannerImageSplitTips } from "@app/components/tooltips/useScannerImageSplitTips"; const ScannerImageSplit = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Sign.tsx b/frontend/src/core/tools/Sign.tsx similarity index 88% rename from frontend/src/tools/Sign.tsx rename to frontend/src/core/tools/Sign.tsx index 64a3040427..d8999a9200 100644 --- a/frontend/src/tools/Sign.tsx +++ b/frontend/src/core/tools/Sign.tsx @@ -1,16 +1,16 @@ import { useEffect, useCallback, useRef } from "react"; import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useSignParameters } from "../hooks/tools/sign/useSignParameters"; -import { useSignOperation } from "../hooks/tools/sign/useSignOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import SignSettings from "../components/tools/sign/SignSettings"; -import { useNavigation } from "../contexts/NavigationContext"; -import { useSignature } from "../contexts/SignatureContext"; -import { useFileContext } from "../contexts/FileContext"; -import { useViewer } from "../contexts/ViewerContext"; -import { flattenSignatures } from "../utils/signatureFlattening"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useSignParameters } from "@app/hooks/tools/sign/useSignParameters"; +import { useSignOperation } from "@app/hooks/tools/sign/useSignOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import SignSettings from "@app/components/tools/sign/SignSettings"; +import { useNavigation } from "@app/contexts/NavigationContext"; +import { useSignature } from "@app/contexts/SignatureContext"; +import { useFileContext } from "@app/contexts/FileContext"; +import { useViewer } from "@app/contexts/ViewerContext"; +import { flattenSignatures } from "@app/utils/signatureFlattening"; const Sign = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/SingleLargePage.tsx b/frontend/src/core/tools/SingleLargePage.tsx similarity index 72% rename from frontend/src/tools/SingleLargePage.tsx rename to frontend/src/core/tools/SingleLargePage.tsx index d31836feb9..faa6e7932a 100644 --- a/frontend/src/tools/SingleLargePage.tsx +++ b/frontend/src/core/tools/SingleLargePage.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useSingleLargePageParameters } from "../hooks/tools/singleLargePage/useSingleLargePageParameters"; -import { useSingleLargePageOperation } from "../hooks/tools/singleLargePage/useSingleLargePageOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useSingleLargePageParameters } from "@app/hooks/tools/singleLargePage/useSingleLargePageParameters"; +import { useSingleLargePageOperation } from "@app/hooks/tools/singleLargePage/useSingleLargePageOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const SingleLargePage = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/Split.tsx b/frontend/src/core/tools/Split.tsx similarity index 80% rename from frontend/src/tools/Split.tsx rename to frontend/src/core/tools/Split.tsx index 96b335f5f3..769a25a089 100644 --- a/frontend/src/tools/Split.tsx +++ b/frontend/src/core/tools/Split.tsx @@ -1,14 +1,14 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import CardSelector from "../components/shared/CardSelector"; -import SplitSettings from "../components/tools/split/SplitSettings"; -import { useSplitParameters } from "../hooks/tools/split/useSplitParameters"; -import { useSplitOperation } from "../hooks/tools/split/useSplitOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { useSplitMethodTips } from "../components/tooltips/useSplitMethodTips"; -import { useSplitSettingsTips } from "../components/tooltips/useSplitSettingsTips"; -import { BaseToolProps, ToolComponent } from "../types/tool"; -import { type SplitMethod, METHOD_OPTIONS, type MethodOption } from "../constants/splitConstants"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import CardSelector from "@app/components/shared/CardSelector"; +import SplitSettings from "@app/components/tools/split/SplitSettings"; +import { useSplitParameters } from "@app/hooks/tools/split/useSplitParameters"; +import { useSplitOperation } from "@app/hooks/tools/split/useSplitOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { useSplitMethodTips } from "@app/components/tooltips/useSplitMethodTips"; +import { useSplitSettingsTips } from "@app/components/tooltips/useSplitSettingsTips"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; +import { type SplitMethod, METHOD_OPTIONS, type MethodOption } from "@app/constants/splitConstants"; const Split = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/SwaggerUI.tsx b/frontend/src/core/tools/SwaggerUI.tsx similarity index 85% rename from frontend/src/tools/SwaggerUI.tsx rename to frontend/src/core/tools/SwaggerUI.tsx index 32034def3c..c860ed93fb 100644 --- a/frontend/src/tools/SwaggerUI.tsx +++ b/frontend/src/core/tools/SwaggerUI.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from "react"; -import { BaseToolProps } from "../types/tool"; -import { withBasePath } from "../constants/app"; +import { BaseToolProps } from "@app/types/tool"; +import { withBasePath } from "@app/constants/app"; const SwaggerUI: React.FC = () => { useEffect(() => { diff --git a/frontend/src/tools/UnlockPdfForms.tsx b/frontend/src/core/tools/UnlockPdfForms.tsx similarity index 72% rename from frontend/src/tools/UnlockPdfForms.tsx rename to frontend/src/core/tools/UnlockPdfForms.tsx index 7dd4aeb186..e8ba292d5e 100644 --- a/frontend/src/tools/UnlockPdfForms.tsx +++ b/frontend/src/core/tools/UnlockPdfForms.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; -import { createToolFlow } from "../components/tools/shared/createToolFlow"; -import { useUnlockPdfFormsParameters } from "../hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters"; -import { useUnlockPdfFormsOperation } from "../hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation"; -import { useBaseTool } from "../hooks/tools/shared/useBaseTool"; -import { BaseToolProps, ToolComponent } from "../types/tool"; +import { createToolFlow } from "@app/components/tools/shared/createToolFlow"; +import { useUnlockPdfFormsParameters } from "@app/hooks/tools/unlockPdfForms/useUnlockPdfFormsParameters"; +import { useUnlockPdfFormsOperation } from "@app/hooks/tools/unlockPdfForms/useUnlockPdfFormsOperation"; +import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool"; +import { BaseToolProps, ToolComponent } from "@app/types/tool"; const UnlockPdfForms = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/tools/ValidateSignature.tsx b/frontend/src/core/tools/ValidateSignature.tsx similarity index 84% rename from frontend/src/tools/ValidateSignature.tsx rename to frontend/src/core/tools/ValidateSignature.tsx index 0932d85551..5ad21c83de 100644 --- a/frontend/src/tools/ValidateSignature.tsx +++ b/frontend/src/core/tools/ValidateSignature.tsx @@ -1,17 +1,17 @@ import { useEffect, useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; -import { createToolFlow } from '../components/tools/shared/createToolFlow'; -import { useBaseTool } from '../hooks/tools/shared/useBaseTool'; -import { BaseToolProps, ToolComponent } from '../types/tool'; -import { useValidateSignatureParameters, defaultParameters } from '../hooks/tools/validateSignature/useValidateSignatureParameters'; -import ValidateSignatureSettings from '../components/tools/validateSignature/ValidateSignatureSettings'; -import ValidateSignatureResults from '../components/tools/validateSignature/ValidateSignatureResults'; -import { useValidateSignatureOperation, ValidateSignatureOperationHook } from '../hooks/tools/validateSignature/useValidateSignatureOperation'; -import ValidateSignatureReportView from '../components/tools/validateSignature/ValidateSignatureReportView'; -import { useToolWorkflow } from '../contexts/ToolWorkflowContext'; -import { useNavigationActions, useNavigationState } from '../contexts/NavigationContext'; -import type { SignatureValidationReportData } from '../types/validateSignature'; +import { createToolFlow } from '@app/components/tools/shared/createToolFlow'; +import { useBaseTool } from '@app/hooks/tools/shared/useBaseTool'; +import { BaseToolProps, ToolComponent } from '@app/types/tool'; +import { useValidateSignatureParameters, defaultParameters } from '@app/hooks/tools/validateSignature/useValidateSignatureParameters'; +import ValidateSignatureSettings from '@app/components/tools/validateSignature/ValidateSignatureSettings'; +import ValidateSignatureResults from '@app/components/tools/validateSignature/ValidateSignatureResults'; +import { useValidateSignatureOperation, ValidateSignatureOperationHook } from '@app/hooks/tools/validateSignature/useValidateSignatureOperation'; +import ValidateSignatureReportView from '@app/components/tools/validateSignature/ValidateSignatureReportView'; +import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext'; +import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext'; +import type { SignatureValidationReportData } from '@app/types/validateSignature'; const ValidateSignature = (props: BaseToolProps) => { const { t } = useTranslation(); diff --git a/frontend/src/types/automation.ts b/frontend/src/core/types/automation.ts similarity index 90% rename from frontend/src/types/automation.ts rename to frontend/src/core/types/automation.ts index 78acc81b42..3dc2c41f54 100644 --- a/frontend/src/types/automation.ts +++ b/frontend/src/core/types/automation.ts @@ -25,7 +25,7 @@ export interface AutomationTool { parameters?: Record; } -export type AutomationStep = typeof import('../constants/automation').AUTOMATION_STEPS[keyof typeof import('../constants/automation').AUTOMATION_STEPS]; +export type AutomationStep = typeof import('@app/constants/automation').AUTOMATION_STEPS[keyof typeof import('@app/constants/automation').AUTOMATION_STEPS]; export interface AutomationStepData { step: AutomationStep; diff --git a/frontend/src/types/file.ts b/frontend/src/core/types/file.ts similarity index 96% rename from frontend/src/types/file.ts rename to frontend/src/core/types/file.ts index 7fb8d7132f..8375164876 100644 --- a/frontend/src/types/file.ts +++ b/frontend/src/core/types/file.ts @@ -3,7 +3,7 @@ * FileContext uses pure File objects with separate ID tracking */ -import { ToolId } from "./toolId"; +import { ToolId } from "@app/types/toolId"; declare const tag: unique symbol; export type FileId = string & { readonly [tag]: 'FileId' }; diff --git a/frontend/src/types/fileContext.ts b/frontend/src/core/types/fileContext.ts similarity index 99% rename from frontend/src/types/fileContext.ts rename to frontend/src/core/types/fileContext.ts index 7f62f945ab..fa8a5da455 100644 --- a/frontend/src/types/fileContext.ts +++ b/frontend/src/core/types/fileContext.ts @@ -2,8 +2,8 @@ * Types for global file context management across views and tools */ -import { PageOperation } from './pageEditor'; -import { FileId, BaseFileMetadata } from './file'; +import { PageOperation } from '@app/types/pageEditor'; +import { FileId, BaseFileMetadata } from '@app/types/file'; // Re-export FileId for convenience export type { FileId }; diff --git a/frontend/src/types/fileIdSafety.d.ts b/frontend/src/core/types/fileIdSafety.d.ts similarity index 96% rename from frontend/src/types/fileIdSafety.d.ts rename to frontend/src/core/types/fileIdSafety.d.ts index 13aac82ddc..0afbc7f931 100644 --- a/frontend/src/types/fileIdSafety.d.ts +++ b/frontend/src/core/types/fileIdSafety.d.ts @@ -2,7 +2,7 @@ * Type safety declarations to prevent file.name/UUID confusion */ -import { FileId, StirlingFile } from './fileContext'; +import { FileId, StirlingFile } from '@app/types/fileContext'; declare global { namespace FileIdSafety { diff --git a/frontend/src/types/metadata.ts b/frontend/src/core/types/metadata.ts similarity index 100% rename from frontend/src/types/metadata.ts rename to frontend/src/core/types/metadata.ts diff --git a/frontend/src/types/navigation.ts b/frontend/src/core/types/navigation.ts similarity index 74% rename from frontend/src/types/navigation.ts rename to frontend/src/core/types/navigation.ts index b66b3276db..996cd57920 100644 --- a/frontend/src/types/navigation.ts +++ b/frontend/src/core/types/navigation.ts @@ -2,8 +2,8 @@ * Navigation types for workbench and tool separation */ -import { WorkbenchType } from './workbench'; -import { ToolId } from './toolId'; +import { WorkbenchType } from '@app/types/workbench'; +import { ToolId } from '@app/types/toolId'; // Navigation state export interface NavigationState { diff --git a/frontend/src/types/navigationActions.ts b/frontend/src/core/types/navigationActions.ts similarity index 86% rename from frontend/src/types/navigationActions.ts rename to frontend/src/core/types/navigationActions.ts index d200ffdbc3..b2d7a5e896 100644 --- a/frontend/src/types/navigationActions.ts +++ b/frontend/src/core/types/navigationActions.ts @@ -2,8 +2,8 @@ * Navigation action interfaces to break circular dependencies */ -import { WorkbenchType } from './workbench'; -import { ToolId } from './toolId'; +import { WorkbenchType } from '@app/types/workbench'; +import { ToolId } from '@app/types/toolId'; export interface NavigationActions { setWorkbench: (workbench: WorkbenchType) => void; diff --git a/frontend/src/types/pageEditor.ts b/frontend/src/core/types/pageEditor.ts similarity index 97% rename from frontend/src/types/pageEditor.ts rename to frontend/src/core/types/pageEditor.ts index b8ee88f578..5c46ed0631 100644 --- a/frontend/src/types/pageEditor.ts +++ b/frontend/src/core/types/pageEditor.ts @@ -1,4 +1,4 @@ -import { FileId } from './file'; +import { FileId } from '@app/types/file'; export interface PDFPage { id: string; diff --git a/frontend/src/types/parameters.ts b/frontend/src/core/types/parameters.ts similarity index 100% rename from frontend/src/types/parameters.ts rename to frontend/src/core/types/parameters.ts diff --git a/frontend/src/types/processing.ts b/frontend/src/core/types/processing.ts similarity index 100% rename from frontend/src/types/processing.ts rename to frontend/src/core/types/processing.ts diff --git a/frontend/src/core/types/proprietaryToolId.ts b/frontend/src/core/types/proprietaryToolId.ts new file mode 100644 index 0000000000..295cd30624 --- /dev/null +++ b/frontend/src/core/types/proprietaryToolId.ts @@ -0,0 +1,16 @@ +/** + * Proprietary tool ID definitions. + * This file is overridden in src/proprietary/types/proprietaryToolId.ts + * to add proprietary-specific tool IDs. + * + * No tool IDs should be defined in this file. + */ + +export const PROPRIETARY_REGULAR_TOOL_IDS = [] as const; +export const PROPRIETARY_SUPER_TOOL_IDS = [] as const; +export const PROPRIETARY_LINK_TOOL_IDS = [] as const; + +export type ProprietaryRegularToolId = typeof PROPRIETARY_REGULAR_TOOL_IDS[number]; +export type ProprietarySuperToolId = typeof PROPRIETARY_SUPER_TOOL_IDS[number]; +export type ProprietaryLinkToolId = typeof PROPRIETARY_LINK_TOOL_IDS[number]; +export type ProprietaryToolId = ProprietaryRegularToolId | ProprietarySuperToolId | ProprietaryLinkToolId; diff --git a/frontend/src/types/rightRail.ts b/frontend/src/core/types/rightRail.ts similarity index 100% rename from frontend/src/types/rightRail.ts rename to frontend/src/core/types/rightRail.ts diff --git a/frontend/src/types/sidebar.ts b/frontend/src/core/types/sidebar.ts similarity index 100% rename from frontend/src/types/sidebar.ts rename to frontend/src/core/types/sidebar.ts diff --git a/frontend/src/types/tips.ts b/frontend/src/core/types/tips.ts similarity index 100% rename from frontend/src/types/tips.ts rename to frontend/src/core/types/tips.ts diff --git a/frontend/src/types/tool.ts b/frontend/src/core/types/tool.ts similarity index 96% rename from frontend/src/types/tool.ts rename to frontend/src/core/types/tool.ts index 0e1d489929..a6a41eefef 100644 --- a/frontend/src/types/tool.ts +++ b/frontend/src/core/types/tool.ts @@ -1,5 +1,5 @@ import React from 'react'; -import { ToolOperationHook } from '../hooks/tools/shared/useToolOperation'; +import { ToolOperationHook } from '@app/hooks/tools/shared/useToolOperation'; export type MaxFiles = number; // 1=single, >1=limited, -1=unlimited export type ToolCategory = 'manipulation' | 'conversion' | 'analysis' | 'utility' | 'optimization' | 'security'; diff --git a/frontend/src/types/toolId.ts b/frontend/src/core/types/toolId.ts similarity index 80% rename from frontend/src/types/toolId.ts rename to frontend/src/core/types/toolId.ts index d485cd2203..123bc6f4b2 100644 --- a/frontend/src/types/toolId.ts +++ b/frontend/src/core/types/toolId.ts @@ -1,6 +1,12 @@ +import { + PROPRIETARY_REGULAR_TOOL_IDS, + PROPRIETARY_SUPER_TOOL_IDS, + PROPRIETARY_LINK_TOOL_IDS, +} from '@app/types/proprietaryToolId'; + export type ToolKind = 'regular' | 'super' | 'link'; -export const REGULAR_TOOL_IDS = [ +export const CORE_REGULAR_TOOL_IDS = [ 'certSign', 'sign', 'addPassword', @@ -49,20 +55,35 @@ export const REGULAR_TOOL_IDS = [ 'bookletImposition', ] as const; -export const SUPER_TOOL_IDS = [ +export const CORE_SUPER_TOOL_IDS = [ 'multiTool', 'read', 'automate', ] as const; -const LINK_TOOL_IDS = [ +export const CORE_LINK_TOOL_IDS = [ 'devApi', 'devFolderScanning', 'devSsoGuide', 'devAirgapped', ] as const; -const TOOL_IDS = [ +export const REGULAR_TOOL_IDS = [ + ...CORE_REGULAR_TOOL_IDS, + ...PROPRIETARY_REGULAR_TOOL_IDS, +] as const; + +export const SUPER_TOOL_IDS = [ + ...CORE_SUPER_TOOL_IDS, + ...PROPRIETARY_SUPER_TOOL_IDS, +] as const; + +export const LINK_TOOL_IDS = [ + ...CORE_LINK_TOOL_IDS, + ...PROPRIETARY_LINK_TOOL_IDS, +] as const; + +export const TOOL_IDS = [ ...REGULAR_TOOL_IDS, ...SUPER_TOOL_IDS, ...LINK_TOOL_IDS, diff --git a/frontend/src/types/validateSignature.ts b/frontend/src/core/types/validateSignature.ts similarity index 100% rename from frontend/src/types/validateSignature.ts rename to frontend/src/core/types/validateSignature.ts diff --git a/frontend/src/types/workbench.ts b/frontend/src/core/types/workbench.ts similarity index 100% rename from frontend/src/types/workbench.ts rename to frontend/src/core/types/workbench.ts diff --git a/frontend/src/utils/automationExecutor.ts b/frontend/src/core/utils/automationExecutor.ts similarity index 94% rename from frontend/src/utils/automationExecutor.ts rename to frontend/src/core/utils/automationExecutor.ts index 8c59be9b15..760a86d7bb 100644 --- a/frontend/src/utils/automationExecutor.ts +++ b/frontend/src/core/utils/automationExecutor.ts @@ -1,10 +1,10 @@ import axios from 'axios'; -import { ToolRegistry } from '../data/toolsTaxonomy'; -import { ToolId } from '../types/toolId'; -import { AUTOMATION_CONSTANTS } from '../constants/automation'; -import { AutomationFileProcessor } from './automationFileProcessor'; -import { ToolType } from '../hooks/tools/shared/useToolOperation'; -import { processResponse } from './toolResponseProcessor'; +import { ToolRegistry } from '@app/data/toolsTaxonomy'; +import { ToolId } from '@app/types/toolId'; +import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; +import { AutomationFileProcessor } from '@app/utils/automationFileProcessor'; +import { ToolType } from '@app/hooks/tools/shared/useToolOperation'; +import { processResponse } from '@app/utils/toolResponseProcessor'; /** * Process multi-file tool response (handles ZIP or single PDF responses) diff --git a/frontend/src/utils/automationFileProcessor.ts b/frontend/src/core/utils/automationFileProcessor.ts similarity index 96% rename from frontend/src/utils/automationFileProcessor.ts rename to frontend/src/core/utils/automationFileProcessor.ts index 4b7417177e..b07fe961be 100644 --- a/frontend/src/utils/automationFileProcessor.ts +++ b/frontend/src/core/utils/automationFileProcessor.ts @@ -3,9 +3,9 @@ */ import axios from 'axios'; -import { zipFileService } from '../services/zipFileService'; -import { ResourceManager } from './resourceManager'; -import { AUTOMATION_CONSTANTS } from '../constants/automation'; +import { zipFileService } from '@app/services/zipFileService'; +import { ResourceManager } from '@app/utils/resourceManager'; +import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; export interface AutomationProcessingOptions { timeout?: number; diff --git a/frontend/src/utils/bulkselection/README.md b/frontend/src/core/utils/bulkselection/README.md similarity index 100% rename from frontend/src/utils/bulkselection/README.md rename to frontend/src/core/utils/bulkselection/README.md diff --git a/frontend/src/utils/bulkselection/parseSelection.test.ts b/frontend/src/core/utils/bulkselection/parseSelection.test.ts similarity index 99% rename from frontend/src/utils/bulkselection/parseSelection.test.ts rename to frontend/src/core/utils/bulkselection/parseSelection.test.ts index de674844c6..bc1319a7d4 100644 --- a/frontend/src/utils/bulkselection/parseSelection.test.ts +++ b/frontend/src/core/utils/bulkselection/parseSelection.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { parseSelection } from './parseSelection'; +import { parseSelection } from '@app/utils/bulkselection/parseSelection'; describe('parseSelection', () => { const max = 120; diff --git a/frontend/src/utils/bulkselection/parseSelection.ts b/frontend/src/core/utils/bulkselection/parseSelection.ts similarity index 100% rename from frontend/src/utils/bulkselection/parseSelection.ts rename to frontend/src/core/utils/bulkselection/parseSelection.ts diff --git a/frontend/src/utils/clickHandlers.ts b/frontend/src/core/utils/clickHandlers.ts similarity index 100% rename from frontend/src/utils/clickHandlers.ts rename to frontend/src/core/utils/clickHandlers.ts diff --git a/frontend/src/utils/convertUtils.test.ts b/frontend/src/core/utils/convertUtils.test.ts similarity index 99% rename from frontend/src/utils/convertUtils.test.ts rename to frontend/src/core/utils/convertUtils.test.ts index 4f44f949bb..7441bbcef6 100644 --- a/frontend/src/utils/convertUtils.test.ts +++ b/frontend/src/core/utils/convertUtils.test.ts @@ -8,7 +8,7 @@ import { getEndpointUrl, isConversionSupported, isImageFormat -} from './convertUtils'; +} from '@app/utils/convertUtils'; describe('convertUtils', () => { diff --git a/frontend/src/utils/convertUtils.ts b/frontend/src/core/utils/convertUtils.ts similarity index 98% rename from frontend/src/utils/convertUtils.ts rename to frontend/src/core/utils/convertUtils.ts index 63e00da463..ef2836058f 100644 --- a/frontend/src/utils/convertUtils.ts +++ b/frontend/src/core/utils/convertUtils.ts @@ -4,7 +4,7 @@ import { EXTENSION_TO_ENDPOINT, CONVERSION_MATRIX, TO_FORMAT_OPTIONS -} from '../constants/convertConstants'; +} from '@app/constants/convertConstants'; /** * Resolves the endpoint name for a given conversion diff --git a/frontend/src/utils/cropCoordinates.ts b/frontend/src/core/utils/cropCoordinates.ts similarity index 100% rename from frontend/src/utils/cropCoordinates.ts rename to frontend/src/core/utils/cropCoordinates.ts diff --git a/frontend/src/utils/downloadUtils.ts b/frontend/src/core/utils/downloadUtils.ts similarity index 96% rename from frontend/src/utils/downloadUtils.ts rename to frontend/src/core/utils/downloadUtils.ts index 41ee8715e7..4bf8223fba 100644 --- a/frontend/src/utils/downloadUtils.ts +++ b/frontend/src/core/utils/downloadUtils.ts @@ -1,6 +1,6 @@ -import { StirlingFileStub } from '../types/fileContext'; -import { fileStorage } from '../services/fileStorage'; -import { zipFileService } from '../services/zipFileService'; +import { StirlingFileStub } from '@app/types/fileContext'; +import { fileStorage } from '@app/services/fileStorage'; +import { zipFileService } from '@app/services/zipFileService'; /** * Downloads a blob as a file using browser download API diff --git a/frontend/src/utils/fileHash.ts b/frontend/src/core/utils/fileHash.ts similarity index 100% rename from frontend/src/utils/fileHash.ts rename to frontend/src/core/utils/fileHash.ts diff --git a/frontend/src/utils/fileHistoryUtils.ts b/frontend/src/core/utils/fileHistoryUtils.ts similarity index 98% rename from frontend/src/utils/fileHistoryUtils.ts rename to frontend/src/core/utils/fileHistoryUtils.ts index 2773ab39dd..a67d0f4f89 100644 --- a/frontend/src/utils/fileHistoryUtils.ts +++ b/frontend/src/core/utils/fileHistoryUtils.ts @@ -4,7 +4,7 @@ * Helper functions for IndexedDB-based file history management. * Handles file history operations and lineage tracking. */ -import { StirlingFileStub } from '../types/fileContext'; +import { StirlingFileStub } from '@app/types/fileContext'; /** * Group files by processing branches - each branch ends in a leaf file diff --git a/frontend/src/utils/fileIdSafety.ts b/frontend/src/core/utils/fileIdSafety.ts similarity index 87% rename from frontend/src/utils/fileIdSafety.ts rename to frontend/src/core/utils/fileIdSafety.ts index 3fda8a4a58..fac7b14cc8 100644 --- a/frontend/src/utils/fileIdSafety.ts +++ b/frontend/src/core/utils/fileIdSafety.ts @@ -2,7 +2,7 @@ * Runtime validation utilities for FileId safety */ -import { FileId } from '../types/fileContext'; +import { FileId } from '@app/types/fileContext'; // Validate that a string is a proper FileId (has UUID format) export function isValidFileId(id: string): id is FileId { diff --git a/frontend/src/utils/fileResponseUtils.test.ts b/frontend/src/core/utils/fileResponseUtils.test.ts similarity index 99% rename from frontend/src/utils/fileResponseUtils.test.ts rename to frontend/src/core/utils/fileResponseUtils.test.ts index 2f16a7c615..6aee7e707e 100644 --- a/frontend/src/utils/fileResponseUtils.test.ts +++ b/frontend/src/core/utils/fileResponseUtils.test.ts @@ -3,7 +3,7 @@ */ import { describe, test, expect } from 'vitest'; -import { getFilenameFromHeaders, createFileFromApiResponse } from './fileResponseUtils'; +import { getFilenameFromHeaders, createFileFromApiResponse } from '@app/utils/fileResponseUtils'; describe('fileResponseUtils', () => { diff --git a/frontend/src/utils/fileResponseUtils.ts b/frontend/src/core/utils/fileResponseUtils.ts similarity index 100% rename from frontend/src/utils/fileResponseUtils.ts rename to frontend/src/core/utils/fileResponseUtils.ts diff --git a/frontend/src/utils/fileUtils.ts b/frontend/src/core/utils/fileUtils.ts similarity index 100% rename from frontend/src/utils/fileUtils.ts rename to frontend/src/core/utils/fileUtils.ts diff --git a/frontend/src/utils/fuzzySearch.ts b/frontend/src/core/utils/fuzzySearch.ts similarity index 100% rename from frontend/src/utils/fuzzySearch.ts rename to frontend/src/core/utils/fuzzySearch.ts diff --git a/frontend/src/utils/genericUtils.ts b/frontend/src/core/utils/genericUtils.ts similarity index 100% rename from frontend/src/utils/genericUtils.ts rename to frontend/src/core/utils/genericUtils.ts diff --git a/frontend/src/utils/hotkeys.ts b/frontend/src/core/utils/hotkeys.ts similarity index 100% rename from frontend/src/utils/hotkeys.ts rename to frontend/src/core/utils/hotkeys.ts diff --git a/frontend/src/utils/languageMapping.ts b/frontend/src/core/utils/languageMapping.ts similarity index 100% rename from frontend/src/utils/languageMapping.ts rename to frontend/src/core/utils/languageMapping.ts diff --git a/frontend/src/utils/pageSelection.ts b/frontend/src/core/utils/pageSelection.ts similarity index 100% rename from frontend/src/utils/pageSelection.ts rename to frontend/src/core/utils/pageSelection.ts diff --git a/frontend/src/utils/resourceManager.ts b/frontend/src/core/utils/resourceManager.ts similarity index 96% rename from frontend/src/utils/resourceManager.ts rename to frontend/src/core/utils/resourceManager.ts index 4dae97e011..06ba74dfe2 100644 --- a/frontend/src/utils/resourceManager.ts +++ b/frontend/src/core/utils/resourceManager.ts @@ -3,7 +3,7 @@ */ import { useCallback } from 'react'; -import { AUTOMATION_CONSTANTS } from '../constants/automation'; +import { AUTOMATION_CONSTANTS } from '@app/constants/automation'; export class ResourceManager { private static blobUrls = new Set(); diff --git a/frontend/src/utils/scarfTracking.ts b/frontend/src/core/utils/scarfTracking.ts similarity index 100% rename from frontend/src/utils/scarfTracking.ts rename to frontend/src/core/utils/scarfTracking.ts diff --git a/frontend/src/utils/scriptLoader.ts b/frontend/src/core/utils/scriptLoader.ts similarity index 100% rename from frontend/src/utils/scriptLoader.ts rename to frontend/src/core/utils/scriptLoader.ts diff --git a/frontend/src/utils/sidebarUtils.ts b/frontend/src/core/utils/sidebarUtils.ts similarity index 93% rename from frontend/src/utils/sidebarUtils.ts rename to frontend/src/core/utils/sidebarUtils.ts index cef1449715..67b0a4123c 100644 --- a/frontend/src/utils/sidebarUtils.ts +++ b/frontend/src/core/utils/sidebarUtils.ts @@ -1,4 +1,4 @@ -import { SidebarRefs, SidebarState, SidebarInfo } from '../types/sidebar'; +import { SidebarRefs, SidebarState, SidebarInfo } from '@app/types/sidebar'; /** * Gets the All tools sidebar information using React refs and state diff --git a/frontend/src/utils/signatureFlattening.ts b/frontend/src/core/utils/signatureFlattening.ts similarity index 98% rename from frontend/src/utils/signatureFlattening.ts rename to frontend/src/core/utils/signatureFlattening.ts index 062313df53..2baf7586b6 100644 --- a/frontend/src/utils/signatureFlattening.ts +++ b/frontend/src/core/utils/signatureFlattening.ts @@ -1,8 +1,8 @@ import { PDFDocument, rgb } from 'pdf-lib'; -import { generateThumbnailWithMetadata } from './thumbnailUtils'; -import { createProcessedFile, createChildStub } from '../contexts/file/fileActions'; -import { createStirlingFile, StirlingFile, FileId, StirlingFileStub } from '../types/fileContext'; -import type { SignatureAPI } from '../components/viewer/viewerTypes'; +import { generateThumbnailWithMetadata } from '@app/utils/thumbnailUtils'; +import { createProcessedFile, createChildStub } from '@app/contexts/file/fileActions'; +import { createStirlingFile, StirlingFile, FileId, StirlingFileStub } from '@app/types/fileContext'; +import type { SignatureAPI } from '@app/components/viewer/viewerTypes'; interface MinimalFileContextSelectors { getAllFileIds: () => FileId[]; diff --git a/frontend/src/utils/storageUtils.ts b/frontend/src/core/utils/storageUtils.ts similarity index 96% rename from frontend/src/utils/storageUtils.ts rename to frontend/src/core/utils/storageUtils.ts index 14ae78feea..956e9843dc 100644 --- a/frontend/src/utils/storageUtils.ts +++ b/frontend/src/core/utils/storageUtils.ts @@ -1,4 +1,4 @@ -import { StorageStats } from "../services/fileStorage"; +import { StorageStats } from "@app/services/fileStorage"; /** * Storage operation types for incremental updates diff --git a/frontend/src/utils/textUtils.ts b/frontend/src/core/utils/textUtils.ts similarity index 100% rename from frontend/src/utils/textUtils.ts rename to frontend/src/core/utils/textUtils.ts diff --git a/frontend/src/utils/thumbnailUtils.ts b/frontend/src/core/utils/thumbnailUtils.ts similarity index 99% rename from frontend/src/utils/thumbnailUtils.ts rename to frontend/src/core/utils/thumbnailUtils.ts index 84dc64457c..8faec2644c 100644 --- a/frontend/src/utils/thumbnailUtils.ts +++ b/frontend/src/core/utils/thumbnailUtils.ts @@ -1,4 +1,4 @@ -import { pdfWorkerManager } from '../services/pdfWorkerManager'; +import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; export interface ThumbnailWithMetadata { thumbnail: string; // Always returns a thumbnail (placeholder if needed) diff --git a/frontend/src/utils/toolErrorHandler.ts b/frontend/src/core/utils/toolErrorHandler.ts similarity index 100% rename from frontend/src/utils/toolErrorHandler.ts rename to frontend/src/core/utils/toolErrorHandler.ts diff --git a/frontend/src/utils/toolResponseProcessor.ts b/frontend/src/core/utils/toolResponseProcessor.ts similarity index 96% rename from frontend/src/utils/toolResponseProcessor.ts rename to frontend/src/core/utils/toolResponseProcessor.ts index c57678c27c..1bff28b815 100644 --- a/frontend/src/utils/toolResponseProcessor.ts +++ b/frontend/src/core/utils/toolResponseProcessor.ts @@ -1,5 +1,5 @@ // Note: This utility should be used with useToolResources for ZIP operations -import { getFilenameFromHeaders } from './fileResponseUtils'; +import { getFilenameFromHeaders } from '@app/utils/fileResponseUtils'; export type ResponseHandler = (blob: Blob, originalFiles: File[]) => Promise | File[]; diff --git a/frontend/src/utils/toolSearch.ts b/frontend/src/core/utils/toolSearch.ts similarity index 95% rename from frontend/src/utils/toolSearch.ts rename to frontend/src/core/utils/toolSearch.ts index 595bf7c194..b915cdf4dd 100644 --- a/frontend/src/utils/toolSearch.ts +++ b/frontend/src/core/utils/toolSearch.ts @@ -1,6 +1,6 @@ -import { ToolId } from "src/types/toolId"; -import { ToolRegistryEntry, ToolRegistry } from "../data/toolsTaxonomy"; -import { scoreMatch, minScoreForQuery, normalizeForSearch } from "./fuzzySearch"; +import { ToolId } from "@app/types/toolId"; +import { ToolRegistryEntry, ToolRegistry } from "@app/data/toolsTaxonomy"; +import { scoreMatch, minScoreForQuery, normalizeForSearch } from "@app/utils/fuzzySearch"; export interface RankedToolItem { item: [ToolId, ToolRegistryEntry]; diff --git a/frontend/src/utils/toolSynonyms.ts b/frontend/src/core/utils/toolSynonyms.ts similarity index 100% rename from frontend/src/utils/toolSynonyms.ts rename to frontend/src/core/utils/toolSynonyms.ts diff --git a/frontend/src/utils/urlMapping.ts b/frontend/src/core/utils/urlMapping.ts similarity index 98% rename from frontend/src/utils/urlMapping.ts rename to frontend/src/core/utils/urlMapping.ts index 5fb0a86cec..c76adf856c 100644 --- a/frontend/src/utils/urlMapping.ts +++ b/frontend/src/core/utils/urlMapping.ts @@ -1,4 +1,4 @@ -import { ToolId } from '../types/toolId'; +import { ToolId } from '@app/types/toolId'; // Map URL paths to tool keys (multiple URLs can map to same tool) export const URL_TO_TOOL_MAP: Record = { diff --git a/frontend/src/utils/urlRouting.ts b/frontend/src/core/utils/urlRouting.ts similarity index 90% rename from frontend/src/utils/urlRouting.ts rename to frontend/src/core/utils/urlRouting.ts index 12abf2ae0c..6d04817be3 100644 --- a/frontend/src/utils/urlRouting.ts +++ b/frontend/src/core/utils/urlRouting.ts @@ -2,13 +2,13 @@ * URL routing utilities for tool navigation with registry support */ -import { ToolRoute } from '../types/navigation'; -import { ToolId, isValidToolId } from '../types/toolId'; -import { getDefaultWorkbench } from '../types/workbench'; -import { ToolRegistry, getToolWorkbench, getToolUrlPath } from '../data/toolsTaxonomy'; -import { firePixel } from './scarfTracking'; -import { URL_TO_TOOL_MAP } from './urlMapping'; -import { BASE_PATH, withBasePath } from '../constants/app'; +import { ToolRoute } from '@app/types/navigation'; +import { ToolId, isValidToolId } from '@app/types/toolId'; +import { getDefaultWorkbench } from '@app/types/workbench'; +import { ToolRegistry, getToolWorkbench, getToolUrlPath } from '@app/data/toolsTaxonomy'; +import { firePixel } from '@app/utils/scarfTracking'; +import { URL_TO_TOOL_MAP } from '@app/utils/urlMapping'; +import { BASE_PATH, withBasePath } from '@app/constants/app'; /** * Parse the current URL to extract tool routing information diff --git a/frontend/src/global.d.ts b/frontend/src/global.d.ts index c964da3c2f..96d969c979 100644 --- a/frontend/src/global.d.ts +++ b/frontend/src/global.d.ts @@ -1,13 +1,8 @@ -declare module "../tools/Split"; -declare module "../tools/Compress"; -declare module "../components/PageEditor"; -declare module "../components/Viewer"; declare module "*.js"; declare module '*.module.css'; -declare module 'pdfjs-dist'; // Auto-generated icon set JSON import -declare module '../assets/material-symbols-icons.json' { +declare module 'assets/material-symbols-icons.json' { const value: { prefix: string; icons: Record; @@ -17,6 +12,4 @@ declare module '../assets/material-symbols-icons.json' { export default value; } -declare module 'pdfjs-dist/legacy/build/pdf.mjs' - export {}; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 36977ac2f4..c8e9081c1b 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,16 +1,16 @@ import '@mantine/core/styles.css'; import '@mantine/dates/styles.css'; import '../vite-env.d.ts'; -import './index.css'; // Import Tailwind CSS +import '@app/styles/index.css'; // Import global styles import React from 'react'; import ReactDOM from 'react-dom/client'; import { ColorSchemeScript } from '@mantine/core'; import { BrowserRouter } from 'react-router-dom'; -import App from './App'; -import './i18n'; // Initialize i18next +import App from '@app/App'; +import '@app/i18n'; // Initialize i18next import posthog from 'posthog-js'; import { PostHogProvider } from 'posthog-js/react'; -import { BASE_PATH } from './constants/app'; +import { BASE_PATH } from '@app/constants/app'; posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, { api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST, diff --git a/frontend/src/proprietary/App.tsx b/frontend/src/proprietary/App.tsx new file mode 100644 index 0000000000..defb7c21ef --- /dev/null +++ b/frontend/src/proprietary/App.tsx @@ -0,0 +1,37 @@ +import { Suspense } from "react"; +import { Routes, Route } from "react-router-dom"; +import { AppProviders } from "@app/components/AppProviders"; +import { LoadingFallback } from "@app/components/shared/LoadingFallback"; +import Landing from "@app/routes/Landing"; +import Login from "@app/routes/Login"; +import Signup from "@app/routes/Signup"; +import AuthCallback from "@app/routes/AuthCallback"; +import OnboardingTour from "@app/components/onboarding/OnboardingTour"; + +// Import global styles +import "@app/styles/tailwind.css"; +import "@app/styles/cookieconsent.css"; +import "@app/styles/index.css"; +import "@app/styles/auth-theme.css"; + +// Import file ID debugging helpers (development only) +import "@app/utils/fileIdSafety"; + +export default function App() { + return ( + }> + + + {/* Auth routes - no nested providers needed */} + } /> + } /> + } /> + + {/* Main app routes - Landing handles auth logic */} + } /> + + + + + ); +} diff --git a/frontend/src/auth/UseSession.tsx b/frontend/src/proprietary/auth/UseSession.tsx similarity index 97% rename from frontend/src/auth/UseSession.tsx rename to frontend/src/proprietary/auth/UseSession.tsx index 7728627f12..0f3436b9a9 100644 --- a/frontend/src/auth/UseSession.tsx +++ b/frontend/src/proprietary/auth/UseSession.tsx @@ -1,6 +1,6 @@ import { createContext, useContext, useEffect, useState, ReactNode, useCallback } from 'react'; -import { springAuth } from './springAuthClient'; -import type { Session, User, AuthError } from './springAuthClient'; +import { springAuth } from '@app/auth/springAuthClient'; +import type { Session, User, AuthError } from '@app/auth/springAuthClient'; /** * Auth Context Type diff --git a/frontend/src/auth/springAuthClient.ts b/frontend/src/proprietary/auth/springAuthClient.ts similarity index 100% rename from frontend/src/auth/springAuthClient.ts rename to frontend/src/proprietary/auth/springAuthClient.ts diff --git a/frontend/src/proprietary/components/AppProviders.tsx b/frontend/src/proprietary/components/AppProviders.tsx new file mode 100644 index 0000000000..74a42f5733 --- /dev/null +++ b/frontend/src/proprietary/components/AppProviders.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from "react"; +import { AppProviders as CoreAppProviders } from "@core/components/AppProviders"; +import { AuthProvider } from "@app/auth/UseSession"; + +export function AppProviders({ children }: { children: ReactNode }) { + return ( + + + {children} + + + ); +} diff --git a/frontend/src/components/shared/DividerWithText.tsx b/frontend/src/proprietary/components/shared/DividerWithText.tsx similarity index 93% rename from frontend/src/components/shared/DividerWithText.tsx rename to frontend/src/proprietary/components/shared/DividerWithText.tsx index 86984969e3..888f4acfb7 100644 --- a/frontend/src/components/shared/DividerWithText.tsx +++ b/frontend/src/proprietary/components/shared/DividerWithText.tsx @@ -1,4 +1,4 @@ -import './dividerWithText/DividerWithText.css'; +import '@app/components/shared/dividerWithText/DividerWithText.css'; interface TextDividerProps { text?: string diff --git a/frontend/src/components/shared/LoginRightCarousel.tsx b/frontend/src/proprietary/components/shared/LoginRightCarousel.tsx similarity index 99% rename from frontend/src/components/shared/LoginRightCarousel.tsx rename to frontend/src/proprietary/components/shared/LoginRightCarousel.tsx index eb7e7ab734..00b5dac984 100644 --- a/frontend/src/components/shared/LoginRightCarousel.tsx +++ b/frontend/src/proprietary/components/shared/LoginRightCarousel.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useRef, useState } from 'react'; -import { BASE_PATH } from '../../constants/app'; +import { BASE_PATH } from '@app/constants/app'; type ImageSlide = { src: string; alt?: string; cornerModelUrl?: string; title?: string; subtitle?: string; followMouseTilt?: boolean; tiltMaxDeg?: number } diff --git a/frontend/src/proprietary/components/shared/config/OverviewHeader.tsx b/frontend/src/proprietary/components/shared/config/OverviewHeader.tsx new file mode 100644 index 0000000000..2361fce970 --- /dev/null +++ b/frontend/src/proprietary/components/shared/config/OverviewHeader.tsx @@ -0,0 +1,42 @@ +import { Text, Button } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import { useAuth } from '@app/auth/UseSession'; +import { useNavigate } from 'react-router-dom'; + +export function OverviewHeader() { + const { t } = useTranslation(); + const { signOut, user } = useAuth(); + const navigate = useNavigate(); + + const handleLogout = async () => { + try { + await signOut(); + navigate('/login'); + } catch (error) { + console.error('Logout error:', error); + } + }; + + return ( +
+
+
+ {t('config.overview.title', 'Application Configuration')} + + {t('config.overview.description', 'Current application settings and configuration details.')} + + {user?.email && ( + + Signed in as: {user.email} + + )} +
+ {user && ( + + )} +
+
+ ); +} diff --git a/frontend/src/components/shared/dividerWithText/DividerWithText.css b/frontend/src/proprietary/components/shared/dividerWithText/DividerWithText.css similarity index 100% rename from frontend/src/components/shared/dividerWithText/DividerWithText.css rename to frontend/src/proprietary/components/shared/dividerWithText/DividerWithText.css diff --git a/frontend/src/components/shared/loginSlides.ts b/frontend/src/proprietary/components/shared/loginSlides.ts similarity index 96% rename from frontend/src/components/shared/loginSlides.ts rename to frontend/src/proprietary/components/shared/loginSlides.ts index 690f84f6c9..167b2e6c57 100644 --- a/frontend/src/components/shared/loginSlides.ts +++ b/frontend/src/proprietary/components/shared/loginSlides.ts @@ -1,4 +1,4 @@ -import { BASE_PATH } from '../../constants/app'; +import { BASE_PATH } from '@app/constants/app'; export type LoginCarouselSlide = { src: string diff --git a/frontend/src/proprietary/data/useProprietaryToolRegistry.tsx b/frontend/src/proprietary/data/useProprietaryToolRegistry.tsx new file mode 100644 index 0000000000..e6d62693b1 --- /dev/null +++ b/frontend/src/proprietary/data/useProprietaryToolRegistry.tsx @@ -0,0 +1,13 @@ +import { useMemo } from "react"; +import { type ProprietaryToolRegistry } from "@app/data/toolsTaxonomy"; + +/** + * Hook that provides the proprietary tool registry. + * + * This is the definition of all proprietary tools, + * and will be included in the main tool registry. + */ +export function useProprietaryToolRegistry(): ProprietaryToolRegistry { + return useMemo(() => ({ + }), []); +} diff --git a/frontend/src/proprietary/hooks/useRequestHeaders.ts b/frontend/src/proprietary/hooks/useRequestHeaders.ts new file mode 100644 index 0000000000..79795a9206 --- /dev/null +++ b/frontend/src/proprietary/hooks/useRequestHeaders.ts @@ -0,0 +1,4 @@ +export function useRequestHeaders(): HeadersInit { + const token = localStorage.getItem('stirling_jwt'); + return token ? { 'Authorization': `Bearer ${token}` } : {}; +} diff --git a/frontend/src/proprietary/hooks/useShouldShowWelcomeModal.ts b/frontend/src/proprietary/hooks/useShouldShowWelcomeModal.ts new file mode 100644 index 0000000000..270188bc8b --- /dev/null +++ b/frontend/src/proprietary/hooks/useShouldShowWelcomeModal.ts @@ -0,0 +1,17 @@ +import { useMediaQuery } from '@mantine/hooks'; +import { usePreferences } from '@app/contexts/PreferencesContext'; +import { useAuth } from '@app/auth/UseSession'; + +export function useShouldShowWelcomeModal(): boolean { + const { preferences } = usePreferences(); + const { session, loading } = useAuth(); + const isMobile = useMediaQuery("(max-width: 1024px)"); + + // Only show welcome modal if user is authenticated (session exists) + // This prevents the modal from showing on login screens when security is enabled + return !loading + && !preferences.hasCompletedOnboarding + && preferences.toolPanelModePromptSeen + && !isMobile + && !!session; +} diff --git a/frontend/src/routes/AuthCallback.tsx b/frontend/src/proprietary/routes/AuthCallback.tsx similarity index 97% rename from frontend/src/routes/AuthCallback.tsx rename to frontend/src/proprietary/routes/AuthCallback.tsx index be4cd54244..9c7a11ba76 100644 --- a/frontend/src/routes/AuthCallback.tsx +++ b/frontend/src/proprietary/routes/AuthCallback.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useAuth } from '../auth/UseSession'; +import { useAuth } from '@app/auth/UseSession'; /** * OAuth Callback Handler diff --git a/frontend/src/routes/Landing.tsx b/frontend/src/proprietary/routes/Landing.tsx similarity index 90% rename from frontend/src/routes/Landing.tsx rename to frontend/src/proprietary/routes/Landing.tsx index c4e4df79a6..fc311ff94f 100644 --- a/frontend/src/routes/Landing.tsx +++ b/frontend/src/proprietary/routes/Landing.tsx @@ -1,8 +1,8 @@ import { Navigate, useLocation } from 'react-router-dom' -import { useAuth } from '../auth/UseSession' -import { useAppConfig } from '../contexts/AppConfigContext' -import HomePage from '../pages/HomePage' -import Login from './Login' +import { useAuth } from '@app/auth/UseSession' +import { useAppConfig } from '@app/contexts/AppConfigContext' +import HomePage from '@app/pages/HomePage' +import Login from '@app/routes/Login' /** * Landing component - Smart router based on authentication status diff --git a/frontend/src/routes/Login.tsx b/frontend/src/proprietary/routes/Login.tsx similarity index 89% rename from frontend/src/routes/Login.tsx rename to frontend/src/proprietary/routes/Login.tsx index 04c3459364..5133bd207e 100644 --- a/frontend/src/routes/Login.tsx +++ b/frontend/src/proprietary/routes/Login.tsx @@ -1,19 +1,19 @@ import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { springAuth } from '../auth/springAuthClient'; -import { useAuth } from '../auth/UseSession'; +import { springAuth } from '@app/auth/springAuthClient'; +import { useAuth } from '@app/auth/UseSession'; import { useTranslation } from 'react-i18next'; -import { useDocumentMeta } from '../hooks/useDocumentMeta'; -import AuthLayout from './authShared/AuthLayout'; +import { useDocumentMeta } from '@app/hooks/useDocumentMeta'; +import AuthLayout from '@app/routes/authShared/AuthLayout'; // Import login components -import LoginHeader from './login/LoginHeader'; -import ErrorMessage from './login/ErrorMessage'; -import EmailPasswordForm from './login/EmailPasswordForm'; -import OAuthButtons from './login/OAuthButtons'; -import DividerWithText from '../components/shared/DividerWithText'; -import LoggedInState from './login/LoggedInState'; -import { BASE_PATH } from '../constants/app'; +import LoginHeader from '@app/routes/login/LoginHeader'; +import ErrorMessage from '@app/routes/login/ErrorMessage'; +import EmailPasswordForm from '@app/routes/login/EmailPasswordForm'; +import OAuthButtons from '@app/routes/login/OAuthButtons'; +import DividerWithText from '@app/components/shared/DividerWithText'; +import LoggedInState from '@app/routes/login/LoggedInState'; +import { BASE_PATH } from '@app/constants/app'; export default function Login() { const navigate = useNavigate(); diff --git a/frontend/src/routes/Signup.tsx b/frontend/src/proprietary/routes/Signup.tsx similarity index 83% rename from frontend/src/routes/Signup.tsx rename to frontend/src/proprietary/routes/Signup.tsx index 465ff338be..192a3a95a5 100644 --- a/frontend/src/routes/Signup.tsx +++ b/frontend/src/proprietary/routes/Signup.tsx @@ -1,18 +1,18 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { useDocumentMeta } from '../hooks/useDocumentMeta'; -import AuthLayout from './authShared/AuthLayout'; -import './authShared/auth.css'; -import { BASE_PATH } from '../constants/app'; +import { useDocumentMeta } from '@app/hooks/useDocumentMeta'; +import AuthLayout from '@app/routes/authShared/AuthLayout'; +import '@app/routes/authShared/auth.css'; +import { BASE_PATH } from '@app/constants/app'; // Import signup components -import LoginHeader from './login/LoginHeader'; -import ErrorMessage from './login/ErrorMessage'; -import DividerWithText from '../components/shared/DividerWithText'; -import SignupForm from './signup/SignupForm'; -import { useSignupFormValidation, SignupFieldErrors } from './signup/SignupFormValidation'; -import { useAuthService } from './signup/AuthService'; +import LoginHeader from '@app/routes/login/LoginHeader'; +import ErrorMessage from '@app/routes/login/ErrorMessage'; +import DividerWithText from '@app/components/shared/DividerWithText'; +import SignupForm from '@app/routes/signup/SignupForm'; +import { useSignupFormValidation, SignupFieldErrors } from '@app/routes/signup/SignupFormValidation'; +import { useAuthService } from '@app/routes/signup/AuthService'; export default function Signup() { const navigate = useNavigate(); diff --git a/frontend/src/routes/authShared/AuthLayout.module.css b/frontend/src/proprietary/routes/authShared/AuthLayout.module.css similarity index 100% rename from frontend/src/routes/authShared/AuthLayout.module.css rename to frontend/src/proprietary/routes/authShared/AuthLayout.module.css diff --git a/frontend/src/routes/authShared/AuthLayout.tsx b/frontend/src/proprietary/routes/authShared/AuthLayout.tsx similarity index 91% rename from frontend/src/routes/authShared/AuthLayout.tsx rename to frontend/src/proprietary/routes/authShared/AuthLayout.tsx index 99c4b69de2..ba7df3795f 100644 --- a/frontend/src/routes/authShared/AuthLayout.tsx +++ b/frontend/src/proprietary/routes/authShared/AuthLayout.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; -import LoginRightCarousel from '../../components/shared/LoginRightCarousel'; -import loginSlides from '../../components/shared/loginSlides'; -import styles from './AuthLayout.module.css'; +import LoginRightCarousel from '@app/components/shared/LoginRightCarousel'; +import loginSlides from '@app/components/shared/loginSlides'; +import styles from '@app/routes/authShared/AuthLayout.module.css'; interface AuthLayoutProps { children: React.ReactNode diff --git a/frontend/src/routes/authShared/auth.css b/frontend/src/proprietary/routes/authShared/auth.css similarity index 100% rename from frontend/src/routes/authShared/auth.css rename to frontend/src/proprietary/routes/authShared/auth.css diff --git a/frontend/src/routes/login/EmailPasswordForm.tsx b/frontend/src/proprietary/routes/login/EmailPasswordForm.tsx similarity index 98% rename from frontend/src/routes/login/EmailPasswordForm.tsx rename to frontend/src/proprietary/routes/login/EmailPasswordForm.tsx index dff38026fc..65dd6c5887 100644 --- a/frontend/src/routes/login/EmailPasswordForm.tsx +++ b/frontend/src/proprietary/routes/login/EmailPasswordForm.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import '../authShared/auth.css'; +import '@app/routes/authShared/auth.css'; interface EmailPasswordFormProps { email: string diff --git a/frontend/src/routes/login/ErrorMessage.tsx b/frontend/src/proprietary/routes/login/ErrorMessage.tsx similarity index 100% rename from frontend/src/routes/login/ErrorMessage.tsx rename to frontend/src/proprietary/routes/login/ErrorMessage.tsx diff --git a/frontend/src/routes/login/LoggedInState.tsx b/frontend/src/proprietary/routes/login/LoggedInState.tsx similarity index 96% rename from frontend/src/routes/login/LoggedInState.tsx rename to frontend/src/proprietary/routes/login/LoggedInState.tsx index 7caf92bcf1..e211e82af3 100644 --- a/frontend/src/routes/login/LoggedInState.tsx +++ b/frontend/src/proprietary/routes/login/LoggedInState.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useAuth } from '../../auth/UseSession'; +import { useAuth } from '@app/auth/UseSession'; import { useTranslation } from 'react-i18next'; export default function LoggedInState() { diff --git a/frontend/src/routes/login/LoginHeader.tsx b/frontend/src/proprietary/routes/login/LoginHeader.tsx similarity index 92% rename from frontend/src/routes/login/LoginHeader.tsx rename to frontend/src/proprietary/routes/login/LoginHeader.tsx index dde6867ab7..2ba4186354 100644 --- a/frontend/src/routes/login/LoginHeader.tsx +++ b/frontend/src/proprietary/routes/login/LoginHeader.tsx @@ -1,5 +1,5 @@ -import { BASE_PATH } from '../../constants/app'; +import { BASE_PATH } from '@app/constants/app'; interface LoginHeaderProps { title: string diff --git a/frontend/src/routes/login/NavigationLink.tsx b/frontend/src/proprietary/routes/login/NavigationLink.tsx similarity index 100% rename from frontend/src/routes/login/NavigationLink.tsx rename to frontend/src/proprietary/routes/login/NavigationLink.tsx diff --git a/frontend/src/routes/login/OAuthButtons.tsx b/frontend/src/proprietary/routes/login/OAuthButtons.tsx similarity index 98% rename from frontend/src/routes/login/OAuthButtons.tsx rename to frontend/src/proprietary/routes/login/OAuthButtons.tsx index b5d5ec54ca..e7fcb1b066 100644 --- a/frontend/src/routes/login/OAuthButtons.tsx +++ b/frontend/src/proprietary/routes/login/OAuthButtons.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { BASE_PATH } from '../../constants/app'; +import { BASE_PATH } from '@app/constants/app'; // OAuth provider configuration const oauthProviders = [ diff --git a/frontend/src/routes/signup/AuthService.ts b/frontend/src/proprietary/routes/signup/AuthService.ts similarity index 91% rename from frontend/src/routes/signup/AuthService.ts rename to frontend/src/proprietary/routes/signup/AuthService.ts index a68e72d245..d21bbc062d 100644 --- a/frontend/src/routes/signup/AuthService.ts +++ b/frontend/src/proprietary/routes/signup/AuthService.ts @@ -1,5 +1,5 @@ -import { springAuth } from '../../auth/springAuthClient'; -import { BASE_PATH } from '../../constants/app'; +import { springAuth } from '@app/auth/springAuthClient'; +import { BASE_PATH } from '@app/constants/app'; export const useAuthService = () => { @@ -51,4 +51,5 @@ export const useAuthService = () => { signUp, signInWithProvider }; -}; \ No newline at end of file +} +; diff --git a/frontend/src/routes/signup/SignupForm.tsx b/frontend/src/proprietary/routes/signup/SignupForm.tsx similarity index 97% rename from frontend/src/routes/signup/SignupForm.tsx rename to frontend/src/proprietary/routes/signup/SignupForm.tsx index 9ff7bc7f44..35caf77644 100644 --- a/frontend/src/routes/signup/SignupForm.tsx +++ b/frontend/src/proprietary/routes/signup/SignupForm.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; -import '../authShared/auth.css'; +import '@app/routes/authShared/auth.css'; import { useTranslation } from 'react-i18next'; -import { SignupFieldErrors } from './SignupFormValidation'; +import { SignupFieldErrors } from '@app/routes/signup/SignupFormValidation'; interface SignupFormProps { name?: string @@ -159,4 +159,4 @@ export default function SignupForm({ ); -} \ No newline at end of file +} diff --git a/frontend/src/routes/signup/SignupFormValidation.ts b/frontend/src/proprietary/routes/signup/SignupFormValidation.ts similarity index 100% rename from frontend/src/routes/signup/SignupFormValidation.ts rename to frontend/src/proprietary/routes/signup/SignupFormValidation.ts diff --git a/frontend/src/proprietary/services/apiClientSetup.ts b/frontend/src/proprietary/services/apiClientSetup.ts new file mode 100644 index 0000000000..be51b165c8 --- /dev/null +++ b/frontend/src/proprietary/services/apiClientSetup.ts @@ -0,0 +1,29 @@ +import { AxiosInstance } from 'axios'; + +function getJwtTokenFromStorage(): string | null { + try { + return localStorage.getItem('stirling_jwt'); + } catch (error) { + console.error('[API Client] Failed to read JWT from localStorage:', error); + return null; + } +} + +export function setupApiInterceptors(client: AxiosInstance): void { + // Install request interceptor to add JWT token + client.interceptors.request.use( + (config) => { + const jwtToken = getJwtTokenFromStorage(); + + if (jwtToken && !config.headers.Authorization) { + config.headers.Authorization = `Bearer ${jwtToken}`; + console.debug('[API Client] Added JWT token from localStorage to Authorization header'); + } + + return config; + }, + (error) => { + return Promise.reject(error); + } + ); +} diff --git a/frontend/src/proprietary/styles/auth-theme.css b/frontend/src/proprietary/styles/auth-theme.css new file mode 100644 index 0000000000..abc474d127 --- /dev/null +++ b/frontend/src/proprietary/styles/auth-theme.css @@ -0,0 +1,24 @@ +/* Auth-specific CSS variables for proprietary version */ + +:root { + /* Auth page colors (light mode only - auth pages force light mode) */ + --auth-bg-color-light-only: #f3f4f6; + --auth-card-bg: #ffffff; + --auth-card-bg-light-only: #ffffff; + --auth-label-text-light-only: #374151; + --auth-input-border-light-only: #d1d5db; + --auth-input-bg-light-only: #ffffff; + --auth-input-text-light-only: #111827; + --auth-border-focus-light-only: #3b82f6; + --auth-focus-ring-light-only: rgba(59, 130, 246, 0.1); + --auth-button-bg-light-only: #AF3434; + --auth-button-text-light-only: #ffffff; + --auth-magic-button-bg-light-only: #e5e7eb; + --auth-magic-button-text-light-only: #374151; + --auth-text-primary-light-only: #111827; + --auth-text-secondary-light-only: #6b7280; + --text-divider-rule-rgb-light: 229, 231, 235; + --text-divider-label-rgb-light: 156, 163, 175; + --tool-subcategory-rule-color-light: #e5e7eb; + --tool-subcategory-text-color-light: #9ca3af; +} diff --git a/frontend/src/proprietary/types/proprietaryToolId.ts b/frontend/src/proprietary/types/proprietaryToolId.ts new file mode 100644 index 0000000000..084cffa29e --- /dev/null +++ b/frontend/src/proprietary/types/proprietaryToolId.ts @@ -0,0 +1,19 @@ +/** + * Proprietary tool ID definitions. + * This file overrides src/core/types/proprietaryToolId.ts + * to add proprietary-specific tool IDs. + */ + +export const PROPRIETARY_REGULAR_TOOL_IDS = [ +] as const; + +export const PROPRIETARY_SUPER_TOOL_IDS = [ +] as const; + +export const PROPRIETARY_LINK_TOOL_IDS = [ +] as const; + +export type ProprietaryRegularToolId = typeof PROPRIETARY_REGULAR_TOOL_IDS[number]; +export type ProprietarySuperToolId = typeof PROPRIETARY_SUPER_TOOL_IDS[number]; +export type ProprietaryLinkToolId = typeof PROPRIETARY_LINK_TOOL_IDS[number]; +export type ProprietaryToolId = ProprietaryRegularToolId | ProprietarySuperToolId | ProprietaryLinkToolId; diff --git a/frontend/src/services/apiClient.ts b/frontend/src/services/apiClient.ts deleted file mode 100644 index 906c3cefb8..0000000000 --- a/frontend/src/services/apiClient.ts +++ /dev/null @@ -1,51 +0,0 @@ -// frontend/src/services/http.ts -import axios from 'axios'; -import { handleHttpError } from './httpErrorHandler'; - -// Create axios instance with default config -const apiClient = axios.create({ - baseURL: import.meta.env.VITE_API_BASE_URL || '/', // Use env var or relative path (proxied by Vite in dev) - responseType: 'json', -}); - -// Helper function to get JWT token from localStorage -function getJwtTokenFromStorage(): string | null { - try { - return localStorage.getItem('stirling_jwt'); - } catch (error) { - console.error('[API Client] Failed to read JWT from localStorage:', error); - return null; - } -} - -// ---------- Install request interceptor to add JWT token ---------- -apiClient.interceptors.request.use( - (config) => { - // Get JWT token from localStorage - const jwtToken = getJwtTokenFromStorage(); - - // If token exists and Authorization header is not already set, add it - if (jwtToken && !config.headers.Authorization) { - config.headers.Authorization = `Bearer ${jwtToken}`; - console.debug('[API Client] Added JWT token from localStorage to Authorization header'); - } - - return config; - }, - (error) => { - return Promise.reject(error); - } -); - -// ---------- Install error interceptor ---------- -apiClient.interceptors.response.use( - (response) => response, - async (error) => { - await handleHttpError(error); // Handle error (shows toast unless suppressed) - return Promise.reject(error); - } -); - - -// ---------- Exports ---------- -export default apiClient; diff --git a/frontend/tsconfig.core.json b/frontend/tsconfig.core.json new file mode 100644 index 0000000000..a2491e09ca --- /dev/null +++ b/frontend/tsconfig.core.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "paths": { + "@app/*": [ + "src/core/*" + ], + "@core/*": ["src/core/*"] + } + }, + "exclude": [ + "src/proprietary", + "node_modules" + ] +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 3e4c6105d9..f0c859e078 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -31,6 +31,12 @@ "moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */ "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ "paths": { /* Specify a set of entries that re-map imports to additional lookup locations. */ + "@app/*": [ + "src/proprietary/*", + "src/core/*" + ], + "@core/*": ["src/core/*"], + "@proprietary/*": ["src/proprietary/*"] }, // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ diff --git a/frontend/tsconfig.proprietary.json b/frontend/tsconfig.proprietary.json new file mode 100644 index 0000000000..bcb363546f --- /dev/null +++ b/frontend/tsconfig.proprietary.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "paths": { + "@app/*": [ + "src/proprietary/*", + "src/core/*" + ], + "@proprietary/*": ["src/proprietary/*"], + "@core/*": ["src/core/*"] + } + } +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 05d5da57b6..e5f4ddc8ab 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,8 +1,19 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react-swc'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +// When DISABLE_ADDITIONAL_FEATURES is false (or unset), enable proprietary features +const isProprietary = process.env.DISABLE_ADDITIONAL_FEATURES !== 'true'; export default defineConfig({ - plugins: [react()], + plugins: [ + react(), + tsconfigPaths({ + projects: [ + isProprietary ? './tsconfig.proprietary.json' : './tsconfig.core.json', + ], + }), + ], server: { proxy: { '/api': { diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts index dd393c6bef..de759c5f8f 100644 --- a/frontend/vitest.config.ts +++ b/frontend/vitest.config.ts @@ -1,12 +1,23 @@ import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react-swc'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +// When DISABLE_ADDITIONAL_FEATURES is false (or unset), enable proprietary features +const isProprietary = process.env.DISABLE_ADDITIONAL_FEATURES !== 'true'; export default defineConfig({ - plugins: [react()], + plugins: [ + react(), + tsconfigPaths({ + projects: [ + isProprietary ? './tsconfig.proprietary.json' : './tsconfig.core.json', + ], + }), + ], test: { globals: true, environment: 'jsdom', - setupFiles: ['./src/setupTests.ts'], + setupFiles: ['./src/core/setupTests.ts'], css: false, // Disable CSS processing to speed up tests include: [ 'src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}' @@ -22,7 +33,7 @@ export default defineConfig({ reporter: ['text', 'json', 'html'], exclude: [ 'node_modules/', - 'src/setupTests.ts', + 'src/core/setupTests.ts', '**/*.d.ts', 'src/tests/test-fixtures/**', 'src/**/*.spec.ts' // Exclude Playwright files from coverage @@ -31,10 +42,5 @@ export default defineConfig({ }, esbuild: { target: 'es2020' // Use older target to avoid warnings - }, - resolve: { - alias: { - '@': '/src' - } } }); From d0c5d74471b6db261ddddec0f7ce394a92fa5920 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:47:41 +0000 Subject: [PATCH 2/4] settingsPage Init selfhost (#4734) # Description of Changes --- ## 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) ### 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. --------- Co-authored-by: James Brunton --- .../common/configuration/AppConfig.java | 14 +- .../common/model/ApplicationProperties.java | 13 +- .../common/service/PostHogService.java | 5 - .../common/service/UserServiceInterface.java | 2 + .../software/common/util/AppArgsCapture.java | 29 + .../software/common/util/JarPathUtil.java | 84 ++ .../model/ApplicationPropertiesLogicTest.java | 8 - .../controller/api/SettingsController.java | 391 +++++++++ .../controller/api/misc/ConfigController.java | 23 +- .../src/main/resources/settings.yml.template | 3 +- .../api/ProprietaryUIDataController.java | 2 +- .../configuration/SecurityConfiguration.java | 7 +- .../api/AdminSettingsController.java | 191 +++- .../controller/api/DatabaseController.java | 126 ++- .../controller/api/TeamController.java | 71 +- .../controller/api/UserController.java | 373 ++++++-- .../security/filter/FirstLoginFilter.java | 77 -- .../proprietary/security/model/User.java | 2 +- .../security/service/EmailService.java | 86 ++ .../security/service/UserService.java | 15 + .../service/ServerCertificateService.java | 35 +- build.gradle | 33 +- docker/backend/Dockerfile | 3 +- docker/backend/Dockerfile.fat | 3 +- docker/backend/Dockerfile.ultra-lite | 3 +- .../public/locales/en-GB/translation.json | 540 ++++++++++++ .../src/core/components/layout/Workbench.tsx | 9 +- .../components/shared/AppConfigLoader.tsx | 24 + .../core/components/shared/AppConfigModal.tsx | 10 +- .../shared/DismissAllErrorsButton.tsx | 3 +- .../components/shared/FirstLoginModal.tsx | 159 ++++ .../src/core/components/shared/Footer.tsx | 37 +- .../components/shared/config/PendingBadge.tsx | 22 + .../config/RestartConfirmationModal.tsx | 68 ++ .../shared/config/configNavSections.tsx | 99 +++ .../configSections/AdminAdvancedSection.tsx | 821 ++++++++++++++++++ .../AdminConnectionsSection.tsx | 409 +++++++++ .../configSections/AdminDatabaseSection.tsx | 272 ++++++ .../configSections/AdminEndpointsSection.tsx | 176 ++++ .../configSections/AdminFeaturesSection.tsx | 209 +++++ .../configSections/AdminGeneralSection.tsx | 526 +++++++++++ .../configSections/AdminLegalSection.tsx | 177 ++++ .../configSections/AdminMailSection.tsx | 195 +++++ .../configSections/AdminPremiumSection.tsx | 136 +++ .../configSections/AdminPrivacySection.tsx | 189 ++++ .../configSections/AdminSecuritySection.tsx | 618 +++++++++++++ .../shared/config/configSections/Overview.tsx | 1 - .../config/configSections/PeopleSection.tsx | 673 ++++++++++++++ .../config/configSections/ProviderCard.tsx | 190 ++++ .../configSections/TeamDetailsSection.tsx | 476 ++++++++++ .../config/configSections/TeamsSection.tsx | 456 ++++++++++ .../configSections/providerDefinitions.ts | 353 ++++++++ .../core/components/shared/config/types.ts | 12 +- .../shared/config/useRestartServer.ts | 60 ++ .../core/components/toast/ToastRenderer.css | 2 +- .../src/core/contexts/AppConfigContext.tsx | 4 +- frontend/src/core/hooks/useAdminSettings.ts | 191 ++++ frontend/src/core/i18n.ts | 30 + frontend/src/core/pages/HomePage.tsx | 5 +- frontend/src/core/services/accountService.ts | 34 + .../src/core/services/httpErrorHandler.ts | 4 + frontend/src/core/services/teamService.ts | 107 +++ .../core/services/userManagementService.ts | 166 ++++ frontend/src/core/styles/zIndex.ts | 6 + .../src/core/utils/settingsPendingHelper.ts | 166 ++++ .../src/proprietary/auth/springAuthClient.ts | 1 + frontend/src/proprietary/routes/Landing.tsx | 51 +- scripts/RestartHelper.java | 129 +++ 68 files changed, 9133 insertions(+), 282 deletions(-) create mode 100644 app/common/src/main/java/stirling/software/common/util/AppArgsCapture.java create mode 100644 app/common/src/main/java/stirling/software/common/util/JarPathUtil.java delete mode 100644 app/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java create mode 100644 frontend/src/core/components/shared/AppConfigLoader.tsx create mode 100644 frontend/src/core/components/shared/FirstLoginModal.tsx create mode 100644 frontend/src/core/components/shared/config/PendingBadge.tsx create mode 100644 frontend/src/core/components/shared/config/RestartConfirmationModal.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminAdvancedSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminConnectionsSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminDatabaseSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminEndpointsSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminFeaturesSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminGeneralSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminLegalSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminMailSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminPremiumSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminPrivacySection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/AdminSecuritySection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/PeopleSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/ProviderCard.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/TeamDetailsSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/TeamsSection.tsx create mode 100644 frontend/src/core/components/shared/config/configSections/providerDefinitions.ts create mode 100644 frontend/src/core/components/shared/config/useRestartServer.ts create mode 100644 frontend/src/core/hooks/useAdminSettings.ts create mode 100644 frontend/src/core/services/accountService.ts create mode 100644 frontend/src/core/services/teamService.ts create mode 100644 frontend/src/core/services/userManagementService.ts create mode 100644 frontend/src/core/utils/settingsPendingHelper.ts create mode 100644 scripts/RestartHelper.java diff --git a/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java index 3bcc48715b..272c0b35ce 100644 --- a/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java +++ b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java @@ -74,8 +74,7 @@ public class AppConfig { @Bean(name = "appName") public String appName() { - String homeTitle = applicationProperties.getUi().getAppName(); - return (homeTitle != null) ? homeTitle : "Stirling PDF"; + return "Stirling PDF"; } @Bean(name = "appVersion") @@ -93,9 +92,7 @@ public class AppConfig { @Bean(name = "homeText") public String homeText() { - return (applicationProperties.getUi().getHomeDescription() != null) - ? applicationProperties.getUi().getHomeDescription() - : "null"; + return "null"; } @Bean(name = "languages") @@ -110,11 +107,8 @@ public class AppConfig { @Bean(name = "navBarText") public String navBarText() { - String defaultNavBar = - applicationProperties.getUi().getAppNameNavbar() != null - ? applicationProperties.getUi().getAppNameNavbar() - : applicationProperties.getUi().getAppName(); - return (defaultNavBar != null) ? defaultNavBar : "Stirling PDF"; + String navBar = applicationProperties.getUi().getAppNameNavbar(); + return (navBar != null) ? navBar : "Stirling PDF"; } @Bean(name = "enableAlphaFunctionality") diff --git a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java index a8861fdd86..5a5ca77b8f 100644 --- a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java +++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java @@ -490,21 +490,9 @@ public class ApplicationProperties { @Data public static class Ui { - private String appName; - private String homeDescription; private String appNameNavbar; private List languages; - public String getAppName() { - return appName != null && appName.trim().length() > 0 ? appName : null; - } - - public String getHomeDescription() { - return homeDescription != null && homeDescription.trim().length() > 0 - ? homeDescription - : null; - } - public String getAppNameNavbar() { return appNameNavbar != null && appNameNavbar.trim().length() > 0 ? appNameNavbar @@ -560,6 +548,7 @@ public class ApplicationProperties { @Data public static class Mail { private boolean enabled; + private boolean enableInvites = false; private String host; private int port; private String username; diff --git a/app/common/src/main/java/stirling/software/common/service/PostHogService.java b/app/common/src/main/java/stirling/software/common/service/PostHogService.java index 0d6353b505..310fc43ab2 100644 --- a/app/common/src/main/java/stirling/software/common/service/PostHogService.java +++ b/app/common/src/main/java/stirling/software/common/service/PostHogService.java @@ -335,11 +335,6 @@ public class PostHogService { applicationProperties.getSystem().isScarfEnabled()); // Capture UI properties - addIfNotEmpty(properties, "ui_appName", applicationProperties.getUi().getAppName()); - addIfNotEmpty( - properties, - "ui_homeDescription", - applicationProperties.getUi().getHomeDescription()); addIfNotEmpty( properties, "ui_appNameNavbar", applicationProperties.getUi().getAppNameNavbar()); diff --git a/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java b/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java index d4cc25dc03..a833d4c848 100644 --- a/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java +++ b/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java @@ -6,4 +6,6 @@ public interface UserServiceInterface { String getCurrentUsername(); long getTotalUsersCount(); + + boolean isCurrentUserAdmin(); } diff --git a/app/common/src/main/java/stirling/software/common/util/AppArgsCapture.java b/app/common/src/main/java/stirling/software/common/util/AppArgsCapture.java new file mode 100644 index 0000000000..691785187f --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/util/AppArgsCapture.java @@ -0,0 +1,29 @@ +package stirling.software.common.util; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +/** + * Captures application command-line arguments at startup so they can be reused for restart + * operations. This allows the application to restart with the same configuration. + */ +@Slf4j +@Component +public class AppArgsCapture implements ApplicationRunner { + + public static final AtomicReference> APP_ARGS = new AtomicReference<>(List.of()); + + @Override + public void run(ApplicationArguments args) { + APP_ARGS.set(List.of(args.getSourceArgs())); + log.debug( + "Captured {} application arguments for restart capability", + args.getSourceArgs().length); + } +} diff --git a/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java b/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java new file mode 100644 index 0000000000..738cde8e6f --- /dev/null +++ b/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java @@ -0,0 +1,84 @@ +package stirling.software.common.util; + +import java.io.File; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import lombok.extern.slf4j.Slf4j; + +/** Utility class to locate JAR files at runtime for restart operations */ +@Slf4j +public class JarPathUtil { + + /** + * Gets the path to the currently running JAR file + * + * @return Path to the current JAR, or null if not running from a JAR + */ + public static Path currentJar() { + try { + Path jar = + Paths.get( + JarPathUtil.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI()) + .toAbsolutePath(); + + // Check if we're actually running from a JAR (not from IDE/classes directory) + if (jar.toString().endsWith(".jar")) { + log.debug("Current JAR located at: {}", jar); + return jar; + } else { + log.warn("Not running from JAR, current location: {}", jar); + return null; + } + } catch (URISyntaxException e) { + log.error("Failed to determine current JAR location", e); + return null; + } + } + + /** + * Gets the path to the restart-helper.jar file Expected to be in the same directory as the main + * JAR + * + * @return Path to restart-helper.jar, or null if not found + */ + public static Path restartHelperJar() { + Path appJar = currentJar(); + if (appJar == null) { + return null; + } + + Path helperJar = appJar.getParent().resolve("restart-helper.jar"); + + if (Files.isRegularFile(helperJar)) { + log.debug("Restart helper JAR located at: {}", helperJar); + return helperJar; + } else { + log.warn("Restart helper JAR not found at: {}", helperJar); + return null; + } + } + + /** + * Gets the java binary path for the current JVM + * + * @return Path to java executable + */ + public static String javaExecutable() { + String javaHome = System.getProperty("java.home"); + String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; + + // On Windows, add .exe extension + if (System.getProperty("os.name").toLowerCase().contains("win")) { + javaBin += ".exe"; + } + + return javaBin; + } +} diff --git a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java index 66078099fe..ba98bf0e1e 100644 --- a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java +++ b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java @@ -112,19 +112,11 @@ class ApplicationPropertiesLogicTest { @Test void ui_getters_return_null_for_blank() { ApplicationProperties.Ui ui = new ApplicationProperties.Ui(); - ui.setAppName(" "); - ui.setHomeDescription(""); ui.setAppNameNavbar(null); - assertNull(ui.getAppName()); - assertNull(ui.getHomeDescription()); assertNull(ui.getAppNameNavbar()); - ui.setAppName("Stirling-PDF"); - ui.setHomeDescription("Home"); ui.setAppNameNavbar("Nav"); - assertEquals("Stirling-PDF", ui.getAppName()); - assertEquals("Home", ui.getHomeDescription()); assertEquals("Nav", ui.getAppNameNavbar()); } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java index 48793a98bd..9657d8f150 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java @@ -1,11 +1,14 @@ package stirling.software.SPDF.controller.api; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import io.swagger.v3.oas.annotations.Hidden; @@ -46,4 +49,392 @@ public class SettingsController { public ResponseEntity> getDisabledEndpoints() { return ResponseEntity.ok(endpointConfiguration.getEndpointStatuses()); } + + // ========== GENERAL SETTINGS ========== + + @GetMapping("/admin/settings/general") + @Hidden + public ResponseEntity> getGeneralSettings() { + Map settings = new HashMap<>(); + settings.put("ui", applicationProperties.getUi()); + settings.put( + "system", + Map.of( + "defaultLocale", applicationProperties.getSystem().getDefaultLocale(), + "showUpdate", applicationProperties.getSystem().isShowUpdate(), + "showUpdateOnlyAdmin", + applicationProperties.getSystem().getShowUpdateOnlyAdmin(), + "customHTMLFiles", applicationProperties.getSystem().isCustomHTMLFiles(), + "fileUploadLimit", applicationProperties.getSystem().getFileUploadLimit())); + return ResponseEntity.ok(settings); + } + + @PostMapping("/admin/settings/general") + @Hidden + public ResponseEntity updateGeneralSettings(@RequestBody Map settings) + throws IOException { + // Update UI settings + if (settings.containsKey("ui")) { + Map ui = (Map) settings.get("ui"); + if (ui.containsKey("appNameNavbar")) { + GeneralUtils.saveKeyToSettings("ui.appNameNavbar", ui.get("appNameNavbar")); + applicationProperties.getUi().setAppNameNavbar(ui.get("appNameNavbar")); + } + } + + // Update System settings + if (settings.containsKey("system")) { + Map system = (Map) settings.get("system"); + if (system.containsKey("defaultLocale")) { + GeneralUtils.saveKeyToSettings("system.defaultLocale", system.get("defaultLocale")); + applicationProperties + .getSystem() + .setDefaultLocale((String) system.get("defaultLocale")); + } + if (system.containsKey("showUpdate")) { + GeneralUtils.saveKeyToSettings("system.showUpdate", system.get("showUpdate")); + applicationProperties.getSystem().setShowUpdate((Boolean) system.get("showUpdate")); + } + if (system.containsKey("showUpdateOnlyAdmin")) { + GeneralUtils.saveKeyToSettings( + "system.showUpdateOnlyAdmin", system.get("showUpdateOnlyAdmin")); + applicationProperties + .getSystem() + .setShowUpdateOnlyAdmin((Boolean) system.get("showUpdateOnlyAdmin")); + } + if (system.containsKey("fileUploadLimit")) { + GeneralUtils.saveKeyToSettings( + "system.fileUploadLimit", system.get("fileUploadLimit")); + applicationProperties + .getSystem() + .setFileUploadLimit((String) system.get("fileUploadLimit")); + } + } + + return ResponseEntity.ok( + "General settings updated. Restart required for changes to take effect."); + } + + // ========== SECURITY SETTINGS ========== + + @GetMapping("/admin/settings/security") + @Hidden + public ResponseEntity> getSecuritySettings() { + Map settings = new HashMap<>(); + ApplicationProperties.Security security = applicationProperties.getSecurity(); + + settings.put("enableLogin", security.getEnableLogin()); + settings.put("csrfDisabled", security.getCsrfDisabled()); + settings.put("loginMethod", security.getLoginMethod()); + settings.put("loginAttemptCount", security.getLoginAttemptCount()); + settings.put("loginResetTimeMinutes", security.getLoginResetTimeMinutes()); + settings.put( + "initialLogin", + Map.of( + "username", + security.getInitialLogin().getUsername() != null + ? security.getInitialLogin().getUsername() + : "")); + + // JWT settings + ApplicationProperties.Security.Jwt jwt = security.getJwt(); + settings.put( + "jwt", + Map.of( + "enableKeystore", jwt.isEnableKeystore(), + "enableKeyRotation", jwt.isEnableKeyRotation(), + "enableKeyCleanup", jwt.isEnableKeyCleanup(), + "keyRetentionDays", jwt.getKeyRetentionDays())); + + return ResponseEntity.ok(settings); + } + + @PostMapping("/admin/settings/security") + @Hidden + public ResponseEntity updateSecuritySettings(@RequestBody Map settings) + throws IOException { + if (settings.containsKey("enableLogin")) { + GeneralUtils.saveKeyToSettings("security.enableLogin", settings.get("enableLogin")); + applicationProperties + .getSecurity() + .setEnableLogin((Boolean) settings.get("enableLogin")); + } + if (settings.containsKey("csrfDisabled")) { + GeneralUtils.saveKeyToSettings("security.csrfDisabled", settings.get("csrfDisabled")); + applicationProperties + .getSecurity() + .setCsrfDisabled((Boolean) settings.get("csrfDisabled")); + } + if (settings.containsKey("loginMethod")) { + GeneralUtils.saveKeyToSettings("security.loginMethod", settings.get("loginMethod")); + applicationProperties + .getSecurity() + .setLoginMethod((String) settings.get("loginMethod")); + } + if (settings.containsKey("loginAttemptCount")) { + GeneralUtils.saveKeyToSettings( + "security.loginAttemptCount", settings.get("loginAttemptCount")); + applicationProperties + .getSecurity() + .setLoginAttemptCount((Integer) settings.get("loginAttemptCount")); + } + if (settings.containsKey("loginResetTimeMinutes")) { + GeneralUtils.saveKeyToSettings( + "security.loginResetTimeMinutes", settings.get("loginResetTimeMinutes")); + applicationProperties + .getSecurity() + .setLoginResetTimeMinutes( + ((Number) settings.get("loginResetTimeMinutes")).longValue()); + } + + // JWT settings + if (settings.containsKey("jwt")) { + Map jwt = (Map) settings.get("jwt"); + if (jwt.containsKey("keyRetentionDays")) { + GeneralUtils.saveKeyToSettings( + "security.jwt.keyRetentionDays", jwt.get("keyRetentionDays")); + applicationProperties + .getSecurity() + .getJwt() + .setKeyRetentionDays((Integer) jwt.get("keyRetentionDays")); + } + } + + return ResponseEntity.ok( + "Security settings updated. Restart required for changes to take effect."); + } + + // ========== CONNECTIONS SETTINGS (OAuth/SAML) ========== + + @GetMapping("/admin/settings/connections") + @Hidden + public ResponseEntity> getConnectionsSettings() { + Map settings = new HashMap<>(); + ApplicationProperties.Security security = applicationProperties.getSecurity(); + + // OAuth2 settings + ApplicationProperties.Security.OAUTH2 oauth2 = security.getOauth2(); + settings.put( + "oauth2", + Map.of( + "enabled", oauth2.getEnabled(), + "issuer", oauth2.getIssuer() != null ? oauth2.getIssuer() : "", + "clientId", oauth2.getClientId() != null ? oauth2.getClientId() : "", + "provider", oauth2.getProvider() != null ? oauth2.getProvider() : "", + "autoCreateUser", oauth2.getAutoCreateUser(), + "blockRegistration", oauth2.getBlockRegistration(), + "useAsUsername", + oauth2.getUseAsUsername() != null + ? oauth2.getUseAsUsername() + : "")); + + // SAML2 settings + ApplicationProperties.Security.SAML2 saml2 = security.getSaml2(); + settings.put( + "saml2", + Map.of( + "enabled", saml2.getEnabled(), + "provider", saml2.getProvider() != null ? saml2.getProvider() : "", + "autoCreateUser", saml2.getAutoCreateUser(), + "blockRegistration", saml2.getBlockRegistration(), + "registrationId", saml2.getRegistrationId())); + + return ResponseEntity.ok(settings); + } + + @PostMapping("/admin/settings/connections") + @Hidden + public ResponseEntity updateConnectionsSettings( + @RequestBody Map settings) throws IOException { + // OAuth2 settings + if (settings.containsKey("oauth2")) { + Map oauth2 = (Map) settings.get("oauth2"); + if (oauth2.containsKey("enabled")) { + GeneralUtils.saveKeyToSettings("security.oauth2.enabled", oauth2.get("enabled")); + applicationProperties + .getSecurity() + .getOauth2() + .setEnabled((Boolean) oauth2.get("enabled")); + } + if (oauth2.containsKey("issuer")) { + GeneralUtils.saveKeyToSettings("security.oauth2.issuer", oauth2.get("issuer")); + applicationProperties + .getSecurity() + .getOauth2() + .setIssuer((String) oauth2.get("issuer")); + } + if (oauth2.containsKey("clientId")) { + GeneralUtils.saveKeyToSettings("security.oauth2.clientId", oauth2.get("clientId")); + applicationProperties + .getSecurity() + .getOauth2() + .setClientId((String) oauth2.get("clientId")); + } + if (oauth2.containsKey("clientSecret")) { + GeneralUtils.saveKeyToSettings( + "security.oauth2.clientSecret", oauth2.get("clientSecret")); + applicationProperties + .getSecurity() + .getOauth2() + .setClientSecret((String) oauth2.get("clientSecret")); + } + if (oauth2.containsKey("provider")) { + GeneralUtils.saveKeyToSettings("security.oauth2.provider", oauth2.get("provider")); + applicationProperties + .getSecurity() + .getOauth2() + .setProvider((String) oauth2.get("provider")); + } + if (oauth2.containsKey("autoCreateUser")) { + GeneralUtils.saveKeyToSettings( + "security.oauth2.autoCreateUser", oauth2.get("autoCreateUser")); + applicationProperties + .getSecurity() + .getOauth2() + .setAutoCreateUser((Boolean) oauth2.get("autoCreateUser")); + } + if (oauth2.containsKey("blockRegistration")) { + GeneralUtils.saveKeyToSettings( + "security.oauth2.blockRegistration", oauth2.get("blockRegistration")); + applicationProperties + .getSecurity() + .getOauth2() + .setBlockRegistration((Boolean) oauth2.get("blockRegistration")); + } + if (oauth2.containsKey("useAsUsername")) { + GeneralUtils.saveKeyToSettings( + "security.oauth2.useAsUsername", oauth2.get("useAsUsername")); + applicationProperties + .getSecurity() + .getOauth2() + .setUseAsUsername((String) oauth2.get("useAsUsername")); + } + } + + // SAML2 settings + if (settings.containsKey("saml2")) { + Map saml2 = (Map) settings.get("saml2"); + if (saml2.containsKey("enabled")) { + GeneralUtils.saveKeyToSettings("security.saml2.enabled", saml2.get("enabled")); + applicationProperties + .getSecurity() + .getSaml2() + .setEnabled((Boolean) saml2.get("enabled")); + } + if (saml2.containsKey("provider")) { + GeneralUtils.saveKeyToSettings("security.saml2.provider", saml2.get("provider")); + applicationProperties + .getSecurity() + .getSaml2() + .setProvider((String) saml2.get("provider")); + } + if (saml2.containsKey("autoCreateUser")) { + GeneralUtils.saveKeyToSettings( + "security.saml2.autoCreateUser", saml2.get("autoCreateUser")); + applicationProperties + .getSecurity() + .getSaml2() + .setAutoCreateUser((Boolean) saml2.get("autoCreateUser")); + } + if (saml2.containsKey("blockRegistration")) { + GeneralUtils.saveKeyToSettings( + "security.saml2.blockRegistration", saml2.get("blockRegistration")); + applicationProperties + .getSecurity() + .getSaml2() + .setBlockRegistration((Boolean) saml2.get("blockRegistration")); + } + } + + return ResponseEntity.ok( + "Connection settings updated. Restart required for changes to take effect."); + } + + // ========== PRIVACY SETTINGS ========== + + @GetMapping("/admin/settings/privacy") + @Hidden + public ResponseEntity> getPrivacySettings() { + Map settings = new HashMap<>(); + + settings.put("enableAnalytics", applicationProperties.getSystem().getEnableAnalytics()); + settings.put("googleVisibility", applicationProperties.getSystem().getGooglevisibility()); + settings.put("metricsEnabled", applicationProperties.getMetrics().getEnabled()); + + return ResponseEntity.ok(settings); + } + + @PostMapping("/admin/settings/privacy") + @Hidden + public ResponseEntity updatePrivacySettings(@RequestBody Map settings) + throws IOException { + if (settings.containsKey("enableAnalytics")) { + GeneralUtils.saveKeyToSettings( + "system.enableAnalytics", settings.get("enableAnalytics")); + applicationProperties + .getSystem() + .setEnableAnalytics((Boolean) settings.get("enableAnalytics")); + } + if (settings.containsKey("googleVisibility")) { + GeneralUtils.saveKeyToSettings( + "system.googlevisibility", settings.get("googleVisibility")); + applicationProperties + .getSystem() + .setGooglevisibility((Boolean) settings.get("googleVisibility")); + } + if (settings.containsKey("metricsEnabled")) { + GeneralUtils.saveKeyToSettings("metrics.enabled", settings.get("metricsEnabled")); + applicationProperties.getMetrics().setEnabled((Boolean) settings.get("metricsEnabled")); + } + + return ResponseEntity.ok( + "Privacy settings updated. Restart required for changes to take effect."); + } + + // ========== ADVANCED SETTINGS ========== + + @GetMapping("/admin/settings/advanced") + @Hidden + public ResponseEntity> getAdvancedSettings() { + Map settings = new HashMap<>(); + + settings.put("endpoints", applicationProperties.getEndpoints()); + settings.put( + "enableAlphaFunctionality", + applicationProperties.getSystem().getEnableAlphaFunctionality()); + settings.put("maxDPI", applicationProperties.getSystem().getMaxDPI()); + settings.put("enableUrlToPDF", applicationProperties.getSystem().getEnableUrlToPDF()); + settings.put("customPaths", applicationProperties.getSystem().getCustomPaths()); + settings.put( + "tempFileManagement", applicationProperties.getSystem().getTempFileManagement()); + + return ResponseEntity.ok(settings); + } + + @PostMapping("/admin/settings/advanced") + @Hidden + public ResponseEntity updateAdvancedSettings(@RequestBody Map settings) + throws IOException { + if (settings.containsKey("enableAlphaFunctionality")) { + GeneralUtils.saveKeyToSettings( + "system.enableAlphaFunctionality", settings.get("enableAlphaFunctionality")); + applicationProperties + .getSystem() + .setEnableAlphaFunctionality( + (Boolean) settings.get("enableAlphaFunctionality")); + } + if (settings.containsKey("maxDPI")) { + GeneralUtils.saveKeyToSettings("system.maxDPI", settings.get("maxDPI")); + applicationProperties.getSystem().setMaxDPI((Integer) settings.get("maxDPI")); + } + if (settings.containsKey("enableUrlToPDF")) { + GeneralUtils.saveKeyToSettings("system.enableUrlToPDF", settings.get("enableUrlToPDF")); + applicationProperties + .getSystem() + .setEnableUrlToPDF((Boolean) settings.get("enableUrlToPDF")); + } + + return ResponseEntity.ok( + "Advanced settings updated. Restart required for changes to take effect."); + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java index 9d94c3ad4d..3fc6e3e024 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java @@ -15,6 +15,7 @@ import stirling.software.common.annotations.api.ConfigApi; import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.service.ServerCertificateServiceInterface; +import stirling.software.common.service.UserServiceInterface; @ConfigApi @Hidden @@ -24,17 +25,21 @@ public class ConfigController { private final ApplicationContext applicationContext; private final EndpointConfiguration endpointConfiguration; private final ServerCertificateServiceInterface serverCertificateService; + private final UserServiceInterface userService; public ConfigController( ApplicationProperties applicationProperties, ApplicationContext applicationContext, EndpointConfiguration endpointConfiguration, @org.springframework.beans.factory.annotation.Autowired(required = false) - ServerCertificateServiceInterface serverCertificateService) { + ServerCertificateServiceInterface serverCertificateService, + @org.springframework.beans.factory.annotation.Autowired(required = false) + UserServiceInterface userService) { this.applicationProperties = applicationProperties; this.applicationContext = applicationContext; this.endpointConfiguration = endpointConfiguration; this.serverCertificateService = serverCertificateService; + this.userService = userService; } @GetMapping("/app-config") @@ -51,14 +56,26 @@ public class ConfigController { configData.put("serverPort", appConfig.getServerPort()); // Extract values from ApplicationProperties - configData.put("appName", applicationProperties.getUi().getAppName()); configData.put("appNameNavbar", applicationProperties.getUi().getAppNameNavbar()); - configData.put("homeDescription", applicationProperties.getUi().getHomeDescription()); configData.put("languages", applicationProperties.getUi().getLanguages()); // Security settings configData.put("enableLogin", applicationProperties.getSecurity().getEnableLogin()); + // Mail settings + configData.put("enableEmailInvites", applicationProperties.getMail().isEnableInvites()); + + // Check if user is admin using UserServiceInterface + boolean isAdmin = false; + if (userService != null) { + try { + isAdmin = userService.isCurrentUserAdmin(); + } catch (Exception e) { + // If there's an error, isAdmin remains false + } + } + configData.put("isAdmin", isAdmin); + // System settings configData.put( "enableAlphaFunctionality", diff --git a/app/core/src/main/resources/settings.yml.template b/app/core/src/main/resources/settings.yml.template index a9055833a4..70417f65b5 100644 --- a/app/core/src/main/resources/settings.yml.template +++ b/app/core/src/main/resources/settings.yml.template @@ -99,6 +99,7 @@ premium: mail: enabled: false # set to 'true' to enable sending emails + enableInvites: false # set to 'true' to enable email invites for user management (requires mail.enabled and security.enableLogin) host: smtp.example.com # SMTP server hostname port: 587 # SMTP server port username: '' # SMTP server username @@ -171,8 +172,6 @@ system: cleanupSystemTemp: false # Whether to clean broader system temp directory ui: - appName: '' # application's visible name - homeDescription: '' # short description or tagline shown on the homepage appNameNavbar: '' # name displayed on the navigation bar languages: [] # If empty, all languages are enabled. To display only German and Polish ["de_DE", "pl_PL"]. British English is always enabled. diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java index 5f321a89e3..5735027f6f 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/ProprietaryUIDataController.java @@ -53,7 +53,6 @@ import stirling.software.proprietary.security.session.SessionPersistentRegistry; @Slf4j @ProprietaryUiDataApi -@EnterpriseEndpoint public class ProprietaryUIDataController { private final ApplicationProperties applicationProperties; @@ -89,6 +88,7 @@ public class ProprietaryUIDataController { @GetMapping("/audit-dashboard") @PreAuthorize("hasRole('ADMIN')") + @EnterpriseEndpoint @Operation(summary = "Get audit dashboard data") public ResponseEntity getAuditDashboardData() { AuditDashboardData data = new AuditDashboardData(); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index b7e51fe2cd..92def884fd 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -39,7 +39,6 @@ import stirling.software.proprietary.security.CustomLogoutSuccessHandler; import stirling.software.proprietary.security.JwtAuthenticationEntryPoint; import stirling.software.proprietary.security.database.repository.JPATokenRepositoryImpl; import stirling.software.proprietary.security.database.repository.PersistentLoginRepository; -import stirling.software.proprietary.security.filter.FirstLoginFilter; import stirling.software.proprietary.security.filter.IPRateLimitingFilter; import stirling.software.proprietary.security.filter.JwtAuthenticationFilter; import stirling.software.proprietary.security.filter.UserAuthenticationFilter; @@ -74,7 +73,6 @@ public class SecurityConfiguration { private final JwtServiceInterface jwtService; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private final LoginAttemptService loginAttemptService; - private final FirstLoginFilter firstLoginFilter; private final SessionPersistentRegistry sessionRegistry; private final PersistentLoginRepository persistentLoginRepository; private final GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper; @@ -93,7 +91,6 @@ public class SecurityConfiguration { JwtServiceInterface jwtService, JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint, LoginAttemptService loginAttemptService, - FirstLoginFilter firstLoginFilter, SessionPersistentRegistry sessionRegistry, @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, @Autowired(required = false) @@ -110,7 +107,6 @@ public class SecurityConfiguration { this.jwtService = jwtService; this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint; this.loginAttemptService = loginAttemptService; - this.firstLoginFilter = firstLoginFilter; this.sessionRegistry = sessionRegistry; this.persistentLoginRepository = persistentLoginRepository; this.oAuth2userAuthoritiesMapper = oAuth2userAuthoritiesMapper; @@ -135,8 +131,7 @@ public class SecurityConfiguration { http.addFilterBefore( userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) .addFilterBefore( - rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class) - .addFilterAfter(firstLoginFilter, IPRateLimitingFilter.class); + rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class); if (v2Enabled) { http.addFilterBefore(jwtAuthenticationFilter(), UserAuthenticationFilter.class); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java index 8282cf0732..90f23b295c 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java @@ -1,19 +1,27 @@ package stirling.software.proprietary.security.controller.api; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @@ -32,7 +40,9 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.annotations.api.AdminApi; import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.util.AppArgsCapture; import stirling.software.common.util.GeneralUtils; +import stirling.software.common.util.JarPathUtil; import stirling.software.proprietary.security.model.api.admin.SettingValueResponse; import stirling.software.proprietary.security.model.api.admin.UpdateSettingValueRequest; import stirling.software.proprietary.security.model.api.admin.UpdateSettingsRequest; @@ -45,6 +55,7 @@ public class AdminSettingsController { private final ApplicationProperties applicationProperties; private final ObjectMapper objectMapper; + private final ApplicationContext applicationContext; // Track settings that have been modified but not yet applied (require restart) private static final ConcurrentHashMap pendingChanges = @@ -195,7 +206,8 @@ public class AdminSettingsController { @Operation( summary = "Get specific settings section", description = - "Retrieve settings for a specific section (e.g., security, system, ui). Admin access required.") + "Retrieve settings for a specific section (e.g., security, system, ui). " + + "By default includes pending changes with awaitingRestart flags. Admin access required.") @ApiResponses( value = { @ApiResponse( @@ -206,7 +218,9 @@ public class AdminSettingsController { responseCode = "403", description = "Access denied - Admin role required") }) - public ResponseEntity getSettingsSection(@PathVariable String sectionName) { + public ResponseEntity getSettingsSection( + @PathVariable String sectionName, + @RequestParam(defaultValue = "true") boolean includePending) { try { Object sectionData = getSectionData(sectionName); if (sectionData == null) { @@ -217,8 +231,24 @@ public class AdminSettingsController { + ". Valid sections: " + String.join(", ", VALID_SECTION_NAMES)); } - log.debug("Admin requested settings section: {}", sectionName); - return ResponseEntity.ok(sectionData); + + // Convert to Map for manipulation + @SuppressWarnings("unchecked") + Map sectionMap = objectMapper.convertValue(sectionData, Map.class); + + if (includePending && !pendingChanges.isEmpty()) { + // Add pending changes block for this section + Map sectionPending = extractPendingForSection(sectionName); + if (!sectionPending.isEmpty()) { + sectionMap.put("_pending", sectionPending); + } + } + + log.debug( + "Admin requested settings section: {} (includePending={})", + sectionName, + includePending); + return ResponseEntity.ok(sectionMap); } catch (IllegalArgumentException e) { log.error("Invalid section name {}: {}", sectionName, e.getMessage(), e); return ResponseEntity.status(HttpStatus.BAD_REQUEST) @@ -388,6 +418,101 @@ public class AdminSettingsController { } } + @PostMapping("/restart") + @Operation( + summary = "Restart the application", + description = + "Triggers a graceful restart of the Spring Boot application to apply pending settings changes. Uses a restart helper to ensure proper restart. Admin access required.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "Restart initiated successfully"), + @ApiResponse( + responseCode = "403", + description = "Access denied - Admin role required"), + @ApiResponse(responseCode = "500", description = "Failed to initiate restart") + }) + public ResponseEntity restartApplication() { + try { + log.warn("Admin initiated application restart"); + + // Get paths to current JAR and restart helper + Path appJar = JarPathUtil.currentJar(); + Path helperJar = JarPathUtil.restartHelperJar(); + + if (appJar == null) { + log.error("Cannot restart: not running from JAR (likely development mode)"); + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .body( + "Restart not available in development mode. Please restart the application manually."); + } + + if (helperJar == null || !Files.isRegularFile(helperJar)) { + log.error("Cannot restart: restart-helper.jar not found at expected location"); + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .body("Restart helper not found. Please restart the application manually."); + } + + // Get current application arguments + List appArgs = AppArgsCapture.APP_ARGS.get(); + + // Write args to temp file to avoid command-line quoting issues + Path argsFile = Files.createTempFile("stirling-app-args-", ".txt"); + Files.write(argsFile, appArgs, StandardCharsets.UTF_8); + + // Get current process PID and java executable + long pid = ProcessHandle.current().pid(); + String javaBin = JarPathUtil.javaExecutable(); + + // Build command to launch restart helper + List cmd = new ArrayList<>(); + cmd.add(javaBin); + cmd.add("-jar"); + cmd.add(helperJar.toString()); + cmd.add("--pid"); + cmd.add(Long.toString(pid)); + cmd.add("--app"); + cmd.add(appJar.toString()); + cmd.add("--argsFile"); + cmd.add(argsFile.toString()); + cmd.add("--backoffMs"); + cmd.add("1000"); + + log.info("Launching restart helper: {}", String.join(" ", cmd)); + + // Launch restart helper process + new ProcessBuilder(cmd) + .directory(appJar.getParent().toFile()) + .inheritIO() // Forward logs + .start(); + + // Clear pending changes since we're restarting + pendingChanges.clear(); + + // Give the HTTP response time to complete, then exit + new Thread( + () -> { + try { + Thread.sleep(1000); + log.info("Shutting down for restart..."); + SpringApplication.exit(applicationContext, () -> 0); + System.exit(0); + } catch (InterruptedException e) { + log.error("Restart interrupted: {}", e.getMessage(), e); + Thread.currentThread().interrupt(); + } + }) + .start(); + + return ResponseEntity.ok( + "Application restart initiated. The server will be back online shortly."); + + } catch (Exception e) { + log.error("Failed to initiate restart: {}", e.getMessage(), e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Failed to initiate application restart: " + e.getMessage()); + } + } + private Object getSectionData(String sectionName) { if (sectionName == null || sectionName.trim().isEmpty()) { return null; @@ -626,4 +751,62 @@ public class AdminSettingsController { return mergedSettings; } + + /** + * Extract pending changes for a specific section + * + * @param sectionName The section name (e.g., "security", "system") + * @return Map of pending changes with nested structure for this section + */ + @SuppressWarnings("unchecked") + private Map extractPendingForSection(String sectionName) { + Map result = new HashMap<>(); + String sectionPrefix = sectionName.toLowerCase() + "."; + + // Find all pending changes for this section + for (Map.Entry entry : pendingChanges.entrySet()) { + String pendingKey = entry.getKey(); + + if (pendingKey.toLowerCase().startsWith(sectionPrefix)) { + // Extract the path within the section (e.g., "security.enableLogin" -> + // "enableLogin") + String pathInSection = pendingKey.substring(sectionPrefix.length()); + Object pendingValue = entry.getValue(); + + // Build nested structure from dot notation + setNestedValue(result, pathInSection, pendingValue); + } + } + + return result; + } + + /** + * Set a value in a nested map using dot notation + * + * @param map The root map + * @param dotPath The dot notation path (e.g., "oauth2.clientSecret") + * @param value The value to set + */ + @SuppressWarnings("unchecked") + private void setNestedValue(Map map, String dotPath, Object value) { + String[] parts = dotPath.split("\\."); + Map current = map; + + // Navigate/create nested maps for all parts except the last + for (int i = 0; i < parts.length - 1; i++) { + String part = parts[i]; + Object nested = current.get(part); + + if (!(nested instanceof Map)) { + nested = new HashMap(); + current.put(part, nested); + } + + current = (Map) nested; + } + + // Set the final value + current.put(parts[parts.length - 1], value); + } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java index 9a3bcf839a..9fe3529aee 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java @@ -2,21 +2,19 @@ package stirling.software.proprietary.security.controller.api; import java.io.IOException; import java.io.InputStream; -import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import org.eclipse.jetty.http.HttpStatus; import org.springframework.context.annotation.Conditional; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; @@ -42,15 +40,19 @@ public class DatabaseController { summary = "Import a database backup file", description = "Uploads and imports a database backup SQL file.") @PostMapping(consumes = "multipart/form-data", value = "import-database") - public String importDatabase( + public ResponseEntity importDatabase( @Parameter(description = "SQL file to import", required = true) @RequestParam("fileInput") - MultipartFile file, - RedirectAttributes redirectAttributes) + MultipartFile file) throws IOException { if (file == null || file.isEmpty()) { - redirectAttributes.addAttribute("error", "fileNullOrEmpty"); - return "redirect:/database"; + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + java.util.Map.of( + "error", + "fileNullOrEmpty", + "message", + "File is null or empty")); } log.info("Received file: {}", file.getOriginalFilename()); Path tempTemplatePath = Files.createTempFile("backup_", ".sql"); @@ -58,15 +60,31 @@ public class DatabaseController { Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING); boolean importSuccess = databaseService.importDatabaseFromUI(tempTemplatePath); if (importSuccess) { - redirectAttributes.addAttribute("infoMessage", "importIntoDatabaseSuccessed"); + return ResponseEntity.ok( + java.util.Map.of( + "message", + "importIntoDatabaseSuccessed", + "description", + "Database imported successfully")); } else { - redirectAttributes.addAttribute("error", "failedImportFile"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "failedImportFile", + "message", + "Failed to import database file")); } } catch (Exception e) { log.error("Error importing database: {}", e.getMessage()); - redirectAttributes.addAttribute("error", "failedImportFile"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "failedImportFile", + "message", + "Failed to import database: " + e.getMessage())); } - return "redirect:/database"; } @Hidden @@ -74,11 +92,17 @@ public class DatabaseController { summary = "Import database backup by filename", description = "Imports a database backup file from the server using its file name.") @GetMapping("/import-database-file/{fileName}") - public String importDatabaseFromBackupUI( + public ResponseEntity importDatabaseFromBackupUI( @Parameter(description = "Name of the file to import", required = true) @PathVariable String fileName) { if (fileName == null || fileName.isEmpty()) { - return "redirect:/database?error=fileNullOrEmpty"; + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + java.util.Map.of( + "error", + "fileNullOrEmpty", + "message", + "File name is null or empty")); } // Check if the file exists in the backup list boolean fileExists = @@ -86,14 +110,31 @@ public class DatabaseController { .anyMatch(backup -> backup.getFileName().equals(fileName)); if (!fileExists) { log.error("File {} not found in backup list", fileName); - return "redirect:/database?error=fileNotFound"; + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body( + java.util.Map.of( + "error", + "fileNotFound", + "message", + "File not found in backup list")); } log.info("Received file: {}", fileName); if (databaseService.importDatabaseFromUI(fileName)) { log.info("File {} imported to database", fileName); - return "redirect:/database?infoMessage=importIntoDatabaseSuccessed"; + return ResponseEntity.ok( + java.util.Map.of( + "message", + "importIntoDatabaseSuccessed", + "description", + "Database backup imported successfully")); } - return "redirect:/database?error=failedImportFile"; + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "failedImportFile", + "message", + "Failed to import database file")); } @Hidden @@ -101,24 +142,42 @@ public class DatabaseController { summary = "Delete a database backup file", description = "Deletes a specified database backup file from the server.") @GetMapping("/delete/{fileName}") - public String deleteFile( + public ResponseEntity deleteFile( @Parameter(description = "Name of the file to delete", required = true) @PathVariable String fileName) { if (fileName == null || fileName.isEmpty()) { - throw new IllegalArgumentException("File must not be null or empty"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + java.util.Map.of( + "error", + "invalidFileName", + "message", + "File must not be null or empty")); } try { if (databaseService.deleteBackupFile(fileName)) { log.info("Deleted file: {}", fileName); + return ResponseEntity.ok(java.util.Map.of("message", "File deleted successfully")); } else { log.error("Failed to delete file: {}", fileName); - return "redirect:/database?error=failedToDeleteFile"; + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "failedToDeleteFile", + "message", + "Failed to delete backup file")); } } catch (IOException e) { log.error("Error deleting file: {}", e.getMessage()); - return "redirect:/database?error=" + e.getMessage(); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "deleteError", + "message", + "Error deleting file: " + e.getMessage())); } - return "redirect:/database"; } @Hidden @@ -142,22 +201,29 @@ public class DatabaseController { .body(resource); } catch (IOException e) { log.error("Error downloading file: {}", e.getMessage()); - return ResponseEntity.status(HttpStatus.SEE_OTHER_303) - .location(URI.create("/database?error=downloadFailed")) - .build(); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body( + java.util.Map.of( + "error", + "downloadFailed", + "message", + "Failed to download file: " + e.getMessage())); } } @Operation( summary = "Create a database backup", - description = - "This endpoint triggers the creation of a database backup and redirects to the" - + " database management page.") + description = "This endpoint triggers the creation of a database backup.") @GetMapping("/createDatabaseBackup") - public String createDatabaseBackup() { + public ResponseEntity createDatabaseBackup() { log.info("Starting database backup creation..."); databaseService.exportDatabase(); log.info("Database backup successfully created."); - return "redirect:/database?infoMessage=backupCreated"; + return ResponseEntity.ok( + java.util.Map.of( + "message", + "backupCreated", + "description", + "Database backup created successfully")); } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java index 84066ec698..e4e9c1e87b 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/TeamController.java @@ -1,10 +1,12 @@ package stirling.software.proprietary.security.controller.api; +import java.util.Map; import java.util.Optional; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.view.RedirectView; import jakarta.transaction.Transactional; @@ -30,98 +32,113 @@ public class TeamController { @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/create") - public RedirectView createTeam(@RequestParam("name") String name) { + public ResponseEntity createTeam(@RequestParam("name") String name) { if (teamRepository.existsByNameIgnoreCase(name)) { - return new RedirectView("/teams?messageType=teamExists"); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "Team name already exists.")); } Team team = new Team(); team.setName(name); teamRepository.save(team); - return new RedirectView("/teams?messageType=teamCreated"); + return ResponseEntity.ok(Map.of("message", "Team created successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/rename") - public RedirectView renameTeam( + public ResponseEntity renameTeam( @RequestParam("teamId") Long teamId, @RequestParam("newName") String newName) { Optional existing = teamRepository.findById(teamId); if (existing.isEmpty()) { - return new RedirectView("/teams?messageType=teamNotFound"); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "Team not found.")); } if (teamRepository.existsByNameIgnoreCase(newName)) { - return new RedirectView("/teams?messageType=teamNameExists"); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "Team name already exists.")); } Team team = existing.get(); // Prevent renaming the Internal team if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) { - return new RedirectView("/teams?messageType=internalTeamNotAccessible"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot rename Internal team.")); } team.setName(newName); teamRepository.save(team); - return new RedirectView("/teams?messageType=teamRenamed"); + return ResponseEntity.ok(Map.of("message", "Team renamed successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/delete") @Transactional - public RedirectView deleteTeam(@RequestParam("teamId") Long teamId) { + public ResponseEntity deleteTeam(@RequestParam("teamId") Long teamId) { Optional teamOpt = teamRepository.findById(teamId); if (teamOpt.isEmpty()) { - return new RedirectView("/teams?messageType=teamNotFound"); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "Team not found.")); } Team team = teamOpt.get(); // Prevent deleting the Internal team if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) { - return new RedirectView("/teams?messageType=internalTeamNotAccessible"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot delete Internal team.")); } long memberCount = userRepository.countByTeam(team); if (memberCount > 0) { - return new RedirectView("/teams?messageType=teamHasUsers"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + Map.of( + "error", + "Team must be empty before deletion. Please remove all members first.")); } teamRepository.delete(team); - return new RedirectView("/teams?messageType=teamDeleted"); + return ResponseEntity.ok(Map.of("message", "Team deleted successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/addUser") @Transactional - public RedirectView addUserToTeam( + public ResponseEntity addUserToTeam( @RequestParam("teamId") Long teamId, @RequestParam("userId") Long userId) { // Find the team - Team team = - teamRepository - .findById(teamId) - .orElseThrow(() -> new RuntimeException("Team not found")); + Optional teamOpt = teamRepository.findById(teamId); + if (teamOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "Team not found.")); + } + Team team = teamOpt.get(); // Prevent adding users to the Internal team if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) { - return new RedirectView("/teams?error=internalTeamNotAccessible"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot add users to Internal team.")); } // Find the user - User user = - userRepository - .findById(userId) - .orElseThrow(() -> new RuntimeException("User not found")); + Optional userOpt = userRepository.findById(userId); + if (userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); + } + User user = userOpt.get(); // Check if user is in the Internal team - prevent moving them if (user.getTeam() != null && user.getTeam().getName().equals(TeamService.INTERNAL_TEAM_NAME)) { - return new RedirectView("/teams/" + teamId + "?error=cannotMoveInternalUsers"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot move users from Internal team.")); } // Assign user to team user.setTeam(team); userRepository.save(user); - // Redirect back to team details page - return new RedirectView("/teams/" + teamId + "?messageType=userAdded"); + return ResponseEntity.ok(Map.of("message", "User added to team successfully")); } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index 6d4b803c2a..6920f5beee 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -17,8 +17,6 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import org.springframework.web.servlet.view.RedirectView; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -38,6 +36,7 @@ import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.model.api.user.UsernameAndPass; import stirling.software.proprietary.security.repository.TeamRepository; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; +import stirling.software.proprietary.security.service.EmailService; import stirling.software.proprietary.security.service.TeamService; import stirling.software.proprietary.security.service.UserService; import stirling.software.proprietary.security.session.SessionPersistentRegistry; @@ -53,6 +52,7 @@ public class UserController { private final ApplicationProperties applicationProperties; private final TeamRepository teamRepository; private final UserRepository userRepository; + private final Optional emailService; @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/register") @@ -137,100 +137,130 @@ public class UserController { @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/change-username") - public RedirectView changeUsername( + public ResponseEntity changeUsername( Principal principal, @RequestParam(name = "currentPasswordChangeUsername") String currentPassword, @RequestParam(name = "newUsername") String newUsername, HttpServletRequest request, - HttpServletResponse response, - RedirectAttributes redirectAttributes) + HttpServletResponse response) throws IOException, SQLException, UnsupportedProviderException { if (!userService.isUsernameValid(newUsername)) { - return new RedirectView("/account?messageType=invalidUsername", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "invalidUsername", "message", "Invalid username format")); } if (principal == null) { - return new RedirectView("/account?messageType=notAuthenticated", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "notAuthenticated", "message", "User not authenticated")); } // The username MUST be unique when renaming Optional userOpt = userService.findByUsername(principal.getName()); if (userOpt == null || userOpt.isEmpty()) { - return new RedirectView("/account?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "userNotFound", "message", "User not found")); } User user = userOpt.get(); if (user.getUsername().equals(newUsername)) { - return new RedirectView("/account?messageType=usernameExists", true); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "usernameExists", "message", "Username already in use")); } if (!userService.isPasswordCorrect(user, currentPassword)) { - return new RedirectView("/account?messageType=incorrectPassword", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "incorrectPassword", "message", "Incorrect password")); } if (!user.getUsername().equals(newUsername) && userService.usernameExists(newUsername)) { - return new RedirectView("/account?messageType=usernameExists", true); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "usernameExists", "message", "Username already exists")); } if (newUsername != null && newUsername.length() > 0) { try { userService.changeUsername(user, newUsername); } catch (IllegalArgumentException e) { - return new RedirectView("/account?messageType=invalidUsername", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + Map.of( + "error", + "invalidUsername", + "message", + "Invalid username format")); } } // Logout using Spring's utility new SecurityContextLogoutHandler().logout(request, response, null); - return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true); + return ResponseEntity.ok( + Map.of( + "message", + "credsUpdated", + "description", + "Username changed successfully. Please log in again.")); } @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/change-password-on-login") - public RedirectView changePasswordOnLogin( + public ResponseEntity changePasswordOnLogin( Principal principal, @RequestParam(name = "currentPassword") String currentPassword, @RequestParam(name = "newPassword") String newPassword, HttpServletRequest request, - HttpServletResponse response, - RedirectAttributes redirectAttributes) + HttpServletResponse response) throws SQLException, UnsupportedProviderException { if (principal == null) { - return new RedirectView("/change-creds?messageType=notAuthenticated", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "notAuthenticated", "message", "User not authenticated")); } Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName()); if (userOpt.isEmpty()) { - return new RedirectView("/change-creds?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "userNotFound", "message", "User not found")); } User user = userOpt.get(); if (!userService.isPasswordCorrect(user, currentPassword)) { - return new RedirectView("/change-creds?messageType=incorrectPassword", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "incorrectPassword", "message", "Incorrect password")); } userService.changePassword(user, newPassword); userService.changeFirstUse(user, false); // Logout using Spring's utility new SecurityContextLogoutHandler().logout(request, response, null); - return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true); + return ResponseEntity.ok( + Map.of( + "message", + "credsUpdated", + "description", + "Password changed successfully. Please log in again.")); } @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/change-password") - public RedirectView changePassword( + public ResponseEntity changePassword( Principal principal, @RequestParam(name = "currentPassword") String currentPassword, @RequestParam(name = "newPassword") String newPassword, HttpServletRequest request, - HttpServletResponse response, - RedirectAttributes redirectAttributes) + HttpServletResponse response) throws SQLException, UnsupportedProviderException { if (principal == null) { - return new RedirectView("/account?messageType=notAuthenticated", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "notAuthenticated", "message", "User not authenticated")); } Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName()); if (userOpt.isEmpty()) { - return new RedirectView("/account?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "userNotFound", "message", "User not found")); } User user = userOpt.get(); if (!userService.isPasswordCorrect(user, currentPassword)) { - return new RedirectView("/account?messageType=incorrectPassword", true); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(Map.of("error", "incorrectPassword", "message", "Incorrect password")); } userService.changePassword(user, newPassword); // Logout using Spring's utility new SecurityContextLogoutHandler().logout(request, response, null); - return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true); + return ResponseEntity.ok( + Map.of( + "message", + "credsUpdated", + "description", + "Password changed successfully. Please log in again.")); } @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @@ -248,23 +278,23 @@ public class UserController { * * Keys not listed above will be ignored. * @param principal The currently authenticated user. - * @return A redirect string to the account page after updating the settings. + * @return A ResponseEntity with success or error information. * @throws SQLException If a database error occurs. * @throws UnsupportedProviderException If the operation is not supported for the user's * provider. */ - public String updateUserSettings(@RequestBody Map updates, Principal principal) + public ResponseEntity updateUserSettings( + @RequestBody Map updates, Principal principal) throws SQLException, UnsupportedProviderException { log.debug("Processed updates: {}", updates); // Assuming you have a method in userService to update the settings for a user userService.updateUserSettings(principal.getName(), updates); - // Redirect to a page of your choice after updating - return "redirect:/account"; + return ResponseEntity.ok(Map.of("message", "Settings updated successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/admin/saveUser") - public RedirectView saveUser( + public ResponseEntity saveUser( @RequestParam(name = "username", required = true) String username, @RequestParam(name = "password", required = false) String password, @RequestParam(name = "role") String role, @@ -274,33 +304,42 @@ public class UserController { boolean forceChange) throws IllegalArgumentException, SQLException, UnsupportedProviderException { if (!userService.isUsernameValid(username)) { - return new RedirectView("/adminSettings?messageType=invalidUsername", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + Map.of( + "error", + "Invalid username format. Username must be 3-50 characters.")); } if (applicationProperties.getPremium().isEnabled() && applicationProperties.getPremium().getMaxUsers() <= userService.getTotalUsersCount()) { - return new RedirectView("/adminSettings?messageType=maxUsersReached", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Maximum number of users reached for your license.")); } Optional userOpt = userService.findByUsernameIgnoreCase(username); if (userOpt.isPresent()) { User user = userOpt.get(); if (user.getUsername().equalsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=usernameExists", true); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "Username already exists.")); } } if (userService.usernameExistsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=usernameExists", true); + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(Map.of("error", "Username already exists.")); } try { // Validate the role Role roleEnum = Role.fromString(role); if (roleEnum == Role.INTERNAL_API_USER) { // If the role is INTERNAL_API_USER, reject the request - return new RedirectView("/adminSettings?messageType=invalidRole", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign INTERNAL_API_USER role.")); } } catch (IllegalArgumentException e) { - // If the role ID is not valid, redirect with an error message - return new RedirectView("/adminSettings?messageType=invalidRole", true); + // If the role ID is not valid, return error + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Invalid role specified.")); } // Use teamId if provided, otherwise use default team @@ -316,28 +355,144 @@ public class UserController { Team selectedTeam = teamRepository.findById(effectiveTeamId).orElse(null); if (selectedTeam != null && TeamService.INTERNAL_TEAM_NAME.equals(selectedTeam.getName())) { - return new RedirectView( - "/adminSettings?messageType=internalTeamNotAccessible", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign users to Internal team.")); } } if (authType.equalsIgnoreCase(AuthenticationType.SSO.toString())) { userService.saveUser(username, AuthenticationType.SSO, effectiveTeamId, role); } else { - if (password.isBlank()) { - return new RedirectView("/adminSettings?messageType=invalidPassword", true); + if (password == null || password.isBlank()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Password is required.")); + } + if (password.length() < 6) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Password must be at least 6 characters.")); } userService.saveUser(username, password, effectiveTeamId, role, forceChange); } - return new RedirectView( - "/adminSettings", // Redirect to account page after adding the user - true); + return ResponseEntity.ok(Map.of("message", "User created successfully")); + } + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @PostMapping("/admin/inviteUsers") + public ResponseEntity inviteUsers( + @RequestParam(name = "emails", required = true) String emails, + @RequestParam(name = "role", defaultValue = "ROLE_USER") String role, + @RequestParam(name = "teamId", required = false) Long teamId) + throws SQLException, UnsupportedProviderException { + + // Check if email invites are enabled + if (!applicationProperties.getMail().isEnableInvites()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Email invites are not enabled")); + } + + // Check if email service is available + if (!emailService.isPresent()) { + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .body( + Map.of( + "error", + "Email service is not configured. Please configure SMTP settings.")); + } + + // Parse comma-separated email addresses + String[] emailArray = emails.split(","); + if (emailArray.length == 0) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "At least one email address is required")); + } + + // Check license limits + if (applicationProperties.getPremium().isEnabled()) { + long currentUserCount = userService.getTotalUsersCount(); + int maxUsers = applicationProperties.getPremium().getMaxUsers(); + long availableSlots = maxUsers - currentUserCount; + if (availableSlots < emailArray.length) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + Map.of( + "error", + "Not enough user slots available. Available: " + + availableSlots + + ", Requested: " + + emailArray.length)); + } + } + + // Validate role + try { + Role roleEnum = Role.fromString(role); + if (roleEnum == Role.INTERNAL_API_USER) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign INTERNAL_API_USER role")); + } + } catch (IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Invalid role specified")); + } + + // Determine team + Long effectiveTeamId = teamId; + if (effectiveTeamId == null) { + Team defaultTeam = + teamRepository.findByName(TeamService.DEFAULT_TEAM_NAME).orElse(null); + if (defaultTeam != null) { + effectiveTeamId = defaultTeam.getId(); + } + } else { + Team selectedTeam = teamRepository.findById(effectiveTeamId).orElse(null); + if (selectedTeam != null + && TeamService.INTERNAL_TEAM_NAME.equals(selectedTeam.getName())) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign users to Internal team")); + } + } + + int successCount = 0; + int failureCount = 0; + StringBuilder errors = new StringBuilder(); + + // Process each email + for (String email : emailArray) { + email = email.trim(); + if (email.isEmpty()) { + continue; + } + + InviteResult result = processEmailInvite(email, effectiveTeamId, role); + if (result.isSuccess()) { + successCount++; + } else { + failureCount++; + errors.append(result.getErrorMessage()).append("; "); + } + } + + Map response = new HashMap<>(); + response.put("successCount", successCount); + response.put("failureCount", failureCount); + + if (failureCount > 0) { + response.put("errors", errors.toString()); + } + + if (successCount > 0) { + response.put("message", successCount + " user(s) invited successfully"); + return ResponseEntity.ok(response); + } else { + response.put("error", "Failed to invite any users"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); + } } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/admin/changeRole") @Transactional - public RedirectView changeRole( + public ResponseEntity changeRole( @RequestParam(name = "username") String username, @RequestParam(name = "role") String role, @RequestParam(name = "teamId", required = false) Long teamId, @@ -345,27 +500,32 @@ public class UserController { throws SQLException, UnsupportedProviderException { Optional userOpt = userService.findByUsernameIgnoreCase(username); if (!userOpt.isPresent()) { - return new RedirectView("/adminSettings?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); } if (!userService.usernameExistsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); } // Get the currently authenticated username String currentUsername = authentication.getName(); // Check if the provided username matches the current session's username if (currentUsername.equalsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=downgradeCurrentUser", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot change your own role.")); } try { // Validate the role Role roleEnum = Role.fromString(role); if (roleEnum == Role.INTERNAL_API_USER) { // If the role is INTERNAL_API_USER, reject the request - return new RedirectView("/adminSettings?messageType=invalidRole", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign INTERNAL_API_USER role.")); } } catch (IllegalArgumentException e) { - // If the role ID is not valid, redirect with an error message - return new RedirectView("/adminSettings?messageType=invalidRole", true); + // If the role ID is not valid, return error + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Invalid role specified.")); } User user = userOpt.get(); @@ -375,15 +535,15 @@ public class UserController { if (team != null) { // Prevent assigning to Internal team if (TeamService.INTERNAL_TEAM_NAME.equals(team.getName())) { - return new RedirectView( - "/adminSettings?messageType=internalTeamNotAccessible", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot assign users to Internal team.")); } // Prevent moving users from Internal team if (user.getTeam() != null && TeamService.INTERNAL_TEAM_NAME.equals(user.getTeam().getName())) { - return new RedirectView( - "/adminSettings?messageType=cannotMoveInternalUsers", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot move users from Internal team.")); } user.setTeam(team); @@ -392,30 +552,31 @@ public class UserController { } userService.changeRole(user, role); - return new RedirectView( - "/adminSettings", // Redirect to account page after adding the user - true); + return ResponseEntity.ok(Map.of("message", "User role updated successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/admin/changeUserEnabled/{username}") - public RedirectView changeUserEnabled( + public ResponseEntity changeUserEnabled( @PathVariable("username") String username, @RequestParam("enabled") boolean enabled, Authentication authentication) throws SQLException, UnsupportedProviderException { Optional userOpt = userService.findByUsernameIgnoreCase(username); if (userOpt.isEmpty()) { - return new RedirectView("/adminSettings?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); } if (!userService.usernameExistsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=userNotFound", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); } // Get the currently authenticated username String currentUsername = authentication.getName(); // Check if the provided username matches the current session's username if (currentUsername.equalsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=disabledCurrentUser", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot disable your own account.")); } User user = userOpt.get(); userService.changeUserEnabled(user, enabled); @@ -442,23 +603,24 @@ public class UserController { } } } - return new RedirectView( - "/adminSettings", // Redirect to account page after adding the user - true); + return ResponseEntity.ok( + Map.of("message", "User " + (enabled ? "enabled" : "disabled") + " successfully")); } @PreAuthorize("hasRole('ROLE_ADMIN')") @PostMapping("/admin/deleteUser/{username}") - public RedirectView deleteUser( + public ResponseEntity deleteUser( @PathVariable("username") String username, Authentication authentication) { if (!userService.usernameExistsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=deleteUsernameExists", true); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Map.of("error", "User not found.")); } // Get the currently authenticated username String currentUsername = authentication.getName(); // Check if the provided username matches the current session's username if (currentUsername.equalsIgnoreCase(username)) { - return new RedirectView("/adminSettings?messageType=deleteCurrentUser", true); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "Cannot delete your own account.")); } // Invalidate all sessions before deleting the user List sessionsInformations = @@ -468,7 +630,7 @@ public class UserController { sessionRegistry.removeSessionInformation(sessionsInformation.getSessionId()); } userService.deleteUser(username); - return new RedirectView("/adminSettings", true); + return ResponseEntity.ok(Map.of("message", "User deleted successfully")); } @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @@ -499,4 +661,73 @@ public class UserController { } return ResponseEntity.ok(apiKey); } + + /** + * Helper method to process a single email invitation. + * + * @param email The email address to invite + * @param teamId The team ID to assign the user to + * @param role The role to assign to the user + * @return InviteResult containing success status and optional error message + */ + private InviteResult processEmailInvite(String email, Long teamId, String role) { + try { + // Validate email format (basic check) + if (!email.contains("@") || !email.contains(".")) { + return InviteResult.failure(email + ": Invalid email format"); + } + + // Check if user already exists + if (userService.usernameExistsIgnoreCase(email)) { + return InviteResult.failure(email + ": User already exists"); + } + + // Generate random password + String temporaryPassword = java.util.UUID.randomUUID().toString().substring(0, 12); + + // Create user with forceChange=true + userService.saveUser(email, temporaryPassword, teamId, role, true); + + // Send invite email + try { + emailService.get().sendInviteEmail(email, email, temporaryPassword); + log.info("Sent invite email to: {}", email); + return InviteResult.success(); + } catch (Exception emailEx) { + log.error("Failed to send invite email to {}: {}", email, emailEx.getMessage()); + return InviteResult.failure(email + ": User created but email failed to send"); + } + + } catch (Exception e) { + log.error("Failed to invite user {}: {}", email, e.getMessage()); + return InviteResult.failure(email + ": " + e.getMessage()); + } + } + + /** Result object for individual email invite processing. */ + private static class InviteResult { + private final boolean success; + private final String errorMessage; + + private InviteResult(boolean success, String errorMessage) { + this.success = success; + this.errorMessage = errorMessage; + } + + static InviteResult success() { + return new InviteResult(true, null); + } + + static InviteResult failure(String errorMessage) { + return new InviteResult(false, errorMessage); + } + + boolean isSuccess() { + return success; + } + + String getErrorMessage() { + return errorMessage; + } + } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java deleted file mode 100644 index 3bae721957..0000000000 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java +++ /dev/null @@ -1,77 +0,0 @@ -package stirling.software.proprietary.security.filter; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Optional; - -import org.springframework.context.annotation.Lazy; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; - -import lombok.extern.slf4j.Slf4j; - -import stirling.software.common.util.RequestUriUtils; -import stirling.software.proprietary.security.model.User; -import stirling.software.proprietary.security.service.UserService; - -@Slf4j -@Component -public class FirstLoginFilter extends OncePerRequestFilter { - - @Lazy private final UserService userService; - - public FirstLoginFilter(@Lazy UserService userService) { - this.userService = userService; - } - - @Override - protected void doFilterInternal( - HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - String method = request.getMethod(); - String requestURI = request.getRequestURI(); - String contextPath = request.getContextPath(); - // Check if the request is for static resources - boolean isStaticResource = RequestUriUtils.isStaticResource(contextPath, requestURI); - // If it's a static resource, just continue the filter chain and skip the logic below - if (isStaticResource) { - filterChain.doFilter(request, response); - return; - } - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication != null && authentication.isAuthenticated()) { - Optional user = userService.findByUsernameIgnoreCase(authentication.getName()); - if ("GET".equalsIgnoreCase(method) - && user.isPresent() - && user.get().isFirstLogin() - && !(contextPath + "/change-creds").equals(requestURI)) { - response.sendRedirect(contextPath + "/change-creds"); - return; - } - } - if (log.isDebugEnabled()) { - HttpSession session = request.getSession(true); - SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); - String creationTime = timeFormat.format(new Date(session.getCreationTime())); - log.debug( - "Request Info - New: {}, creationTimeSession {}, ID: {}, IP: {}, User-Agent: {}, Referer: {}, Request URL: {}", - session.isNew(), - creationTime, - session.getId(), - request.getRemoteAddr(), - request.getHeader("User-Agent"), - request.getHeader("Referer"), - request.getRequestURL().toString()); - } - filterChain.doFilter(request, response); - } -} diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 1c342bf5be..02bd08a5bd 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -73,7 +73,6 @@ public class User implements UserDetails, Serializable { @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "team_id") - @JsonIgnore private Team team; @ElementCollection @@ -81,6 +80,7 @@ public class User implements UserDetails, Serializable { @Lob @Column(name = "setting_value", columnDefinition = "text") @CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id")) + @JsonIgnore private Map settings = new HashMap<>(); // Key-value pairs of settings. @CreationTimestamp diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java index 08860a3407..1b9fc19bdd 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java @@ -73,4 +73,90 @@ public class EmailService { // Sends the email via the configured mail sender mailSender.send(message); } + + /** + * Sends a plain text/HTML email without attachments asynchronously. + * + * @param to The recipient email address + * @param subject The email subject + * @param body The email body (can contain HTML) + * @param isHtml Whether the body contains HTML content + * @throws MessagingException If there is an issue with creating or sending the email. + */ + @Async + public void sendPlainEmail(String to, String subject, String body, boolean isHtml) + throws MessagingException { + // Validate recipient email address + if (to == null || to.trim().isEmpty()) { + throw new MessagingException("Invalid recipient email address"); + } + + ApplicationProperties.Mail mailProperties = applicationProperties.getMail(); + + // Creates a MimeMessage to represent the email + MimeMessage message = mailSender.createMimeMessage(); + + // Helper class to set up the message content + MimeMessageHelper helper = new MimeMessageHelper(message, false); + + // Sets the recipient, subject, body, and sender email + helper.addTo(to); + helper.setSubject(subject); + helper.setText(body, isHtml); + helper.setFrom(mailProperties.getFrom()); + + // Sends the email via the configured mail sender + mailSender.send(message); + } + + /** + * Sends an invitation email to a new user with their credentials. + * + * @param to The recipient email address + * @param username The username for the new account + * @param temporaryPassword The temporary password + * @throws MessagingException If there is an issue with creating or sending the email. + */ + @Async + public void sendInviteEmail(String to, String username, String temporaryPassword) + throws MessagingException { + String subject = "Welcome to Stirling PDF"; + + String body = + """ + +
+
+ +
+ Stirling PDF +
+ +
+

Welcome to Stirling PDF!

+

Hi there,

+

You have been invited to join the workspace. Below are your login credentials:

+ +
+

Username: %s

+

Temporary Password: %s

+
+
+

⚠️ Important: You will be required to change your password upon first login for security reasons.

+
+

Please keep these credentials secure and do not share them with anyone.

+

— The Stirling PDF Team

+
+ +
+ © 2025 Stirling PDF. All rights reserved. +
+
+
+ + """ + .formatted(username, temporaryPassword); + + sendPlainEmail(to, subject, body, true); + } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java index 80e48dbf63..dc1c8c1bf1 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java @@ -642,6 +642,21 @@ public class UserService implements UserServiceInterface { return null; } + public boolean isCurrentUserAdmin() { + try { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null + && authentication.isAuthenticated() + && !"anonymousUser".equals(authentication.getPrincipal())) { + return authentication.getAuthorities().stream() + .anyMatch(auth -> Role.ADMIN.getRoleId().equals(auth.getAuthority())); + } + } catch (Exception e) { + log.debug("Error checking admin status", e); + } + return false; + } + @Transactional public void syncCustomApiUser(String customApiKey) { if (customApiKey == null || customApiKey.trim().isBlank()) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java index a743b21fec..aca98eb75f 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java @@ -30,6 +30,8 @@ import lombok.extern.slf4j.Slf4j; import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.service.ServerCertificateServiceInterface; +import stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License; +import stirling.software.proprietary.security.configuration.ee.LicenseKeyChecker; @Service @Slf4j @@ -51,6 +53,12 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa @Value("${system.serverCertificate.regenerateOnStartup:false}") private boolean regenerateOnStartup; + private final LicenseKeyChecker licenseKeyChecker; + + public ServerCertificateService(LicenseKeyChecker licenseKeyChecker) { + this.licenseKeyChecker = licenseKeyChecker; + } + static { Security.addProvider(new BouncyCastleProvider()); } @@ -59,8 +67,13 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa return Paths.get(InstallationPathConfig.getConfigPath(), KEYSTORE_FILENAME); } + private boolean hasProOrEnterpriseAccess() { + License license = licenseKeyChecker.getPremiumLicenseEnabledResult(); + return license == License.PRO || license == License.ENTERPRISE; + } + public boolean isEnabled() { - return enabled; + return enabled && hasProOrEnterpriseAccess(); } public boolean hasServerCertificate() { @@ -73,6 +86,11 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa return; } + if (!hasProOrEnterpriseAccess()) { + log.info("Server certificate feature requires Pro or Enterprise license"); + return; + } + Path keystorePath = getKeystorePath(); if (!Files.exists(keystorePath) || regenerateOnStartup) { @@ -88,6 +106,11 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa } public KeyStore getServerKeyStore() throws Exception { + if (!hasProOrEnterpriseAccess()) { + throw new IllegalStateException( + "Server certificate feature requires Pro or Enterprise license"); + } + if (!enabled || !hasServerCertificate()) { throw new IllegalStateException("Server certificate is not available"); } @@ -114,6 +137,11 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa } public void uploadServerCertificate(InputStream p12Stream, String password) throws Exception { + if (!hasProOrEnterpriseAccess()) { + throw new IllegalStateException( + "Server certificate feature requires Pro or Enterprise license"); + } + // Validate the uploaded certificate KeyStore uploadedKeyStore = KeyStore.getInstance("PKCS12"); uploadedKeyStore.load(p12Stream, password.toCharArray()); @@ -174,6 +202,11 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa } private void generateServerCertificate() throws Exception { + if (!hasProOrEnterpriseAccess()) { + throw new IllegalStateException( + "Server certificate feature requires Pro or Enterprise license"); + } + // Generate key pair KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); keyPairGenerator.initialize(2048, new SecureRandom()); diff --git a/build.gradle b/build.gradle index c2980cb5ee..9f2dba488d 100644 --- a/build.gradle +++ b/build.gradle @@ -629,9 +629,40 @@ tasks.named('bootRun') { tasks.named('build') { group = 'build' description = 'Delegates to :stirling-pdf:bootJar' - dependsOn ':stirling-pdf:bootJar' + dependsOn ':stirling-pdf:bootJar', 'buildRestartHelper' doFirst { println "Delegating to :stirling-pdf:bootJar" } } + +// Task to compile RestartHelper.java +tasks.register('compileRestartHelper', JavaCompile) { + group = 'build' + description = 'Compiles the RestartHelper utility' + + source = fileTree(dir: 'scripts', include: 'RestartHelper.java') + classpath = files() + destinationDirectory = file("${buildDir}/restart-helper-classes") + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +// Task to create restart-helper.jar +tasks.register('buildRestartHelper', Jar) { + group = 'build' + description = 'Builds the restart-helper.jar' + dependsOn 'compileRestartHelper' + + from "${buildDir}/restart-helper-classes" + archiveFileName = 'restart-helper.jar' + destinationDirectory = file("${buildDir}/libs") + + manifest { + attributes 'Main-Class': 'RestartHelper' + } + + doLast { + println "restart-helper.jar created at: ${destinationDirectory.get()}/restart-helper.jar" + } +} diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index 58655dfdbf..666e18bd38 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -30,6 +30,7 @@ COPY scripts /scripts COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/ # first /app directory is for the build stage, second is for the final image COPY --from=build /app/app/core/build/libs/*.jar app.jar +COPY --from=build /app/build/libs/restart-helper.jar restart-helper.jar ARG VERSION_TAG @@ -113,7 +114,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a # User permissions addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \ chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /pipeline /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /tmp/stirling-pdf && \ - chown stirlingpdfuser:stirlingpdfgroup /app.jar + chown stirlingpdfuser:stirlingpdfgroup /app.jar /restart-helper.jar EXPOSE 8080/tcp diff --git a/docker/backend/Dockerfile.fat b/docker/backend/Dockerfile.fat index bd12e3063e..4e63393e8d 100644 --- a/docker/backend/Dockerfile.fat +++ b/docker/backend/Dockerfile.fat @@ -30,6 +30,7 @@ COPY scripts /scripts COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/ # first /app directory is for the build stage, second is for the final image COPY --from=build /app/app/core/build/libs/*.jar app.jar +COPY --from=build /app/build/libs/restart-helper.jar restart-helper.jar ARG VERSION_TAG @@ -104,7 +105,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a # User permissions addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \ chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /pipeline /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /tmp/stirling-pdf && \ - chown stirlingpdfuser:stirlingpdfgroup /app.jar + chown stirlingpdfuser:stirlingpdfgroup /app.jar /restart-helper.jar EXPOSE 8080/tcp # Set user and run command diff --git a/docker/backend/Dockerfile.ultra-lite b/docker/backend/Dockerfile.ultra-lite index 0b74e3b0a2..0b4b7a9391 100644 --- a/docker/backend/Dockerfile.ultra-lite +++ b/docker/backend/Dockerfile.ultra-lite @@ -45,6 +45,7 @@ ENV DISABLE_ADDITIONAL_FEATURES=true \ COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh COPY scripts/installFonts.sh /scripts/installFonts.sh COPY --from=build /app/app/core/build/libs/*.jar app.jar +COPY --from=build /app/build/libs/restart-helper.jar restart-helper.jar # Set up necessary directories and permissions RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \ @@ -65,7 +66,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et chmod +x /scripts/*.sh && \ addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \ chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /pipeline /configs /customFiles /pipeline /tmp/stirling-pdf && \ - chown stirlingpdfuser:stirlingpdfgroup /app.jar + chown stirlingpdfuser:stirlingpdfgroup /app.jar /restart-helper.jar # Set environment variables ENV ENDPOINTS_GROUPS_TO_REMOVE=CLI diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 92b41f96c6..b72f5cc546 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -3489,8 +3489,358 @@ "help": "Help", "account": "Account", "config": "Config", + "adminSettings": "Admin Settings", "allTools": "All Tools" }, + "admin": { + "error": "Error", + "success": "Success", + "expand": "Expand", + "close": "Close", + "status": { + "active": "Active", + "inactive": "Inactive" + }, + "settings": { + "title": "Admin Settings", + "workspace": "Workspace", + "fetchError": "Failed to load settings", + "saveError": "Failed to save settings", + "saved": "Settings saved successfully", + "saveSuccess": "Settings saved successfully", + "save": "Save Changes", + "restartRequired": "Restart Required", + "restart": { + "title": "Restart Required", + "message": "Settings have been saved successfully. A server restart is required for the changes to take effect.", + "question": "Would you like to restart the server now or later?", + "now": "Restart Now", + "later": "Restart Later" + }, + "restarting": "Restarting Server", + "restartingMessage": "The server is restarting. Please wait a moment...", + "restartError": "Failed to restart server. Please restart manually.", + "general": { + "title": "General", + "description": "Configure general application settings including branding and default behaviour.", + "ui": "User Interface", + "system": "System", + "appName": "Application Name", + "appName.description": "The name displayed in the browser tab and home page", + "appNameNavbar": "Navbar Brand", + "appNameNavbar.description": "The name displayed in the navigation bar", + "homeDescription": "Home Description", + "homeDescription.description": "The description text shown on the home page", + "defaultLocale": "Default Locale", + "defaultLocale.description": "The default language for new users (e.g., en_US, es_ES)", + "fileUploadLimit": "File Upload Limit", + "fileUploadLimit.description": "Maximum file upload size (e.g., 100MB, 1GB)", + "showUpdate": "Show Update Notifications", + "showUpdate.description": "Display notifications when a new version is available", + "showUpdateOnlyAdmin": "Show Updates to Admins Only", + "showUpdateOnlyAdmin.description": "Restrict update notifications to admin users only", + "customHTMLFiles": "Custom HTML Files", + "customHTMLFiles.description": "Allow serving custom HTML files from the customFiles directory", + "languages": "Available Languages", + "languages.description": "Languages that users can select from (leave empty to enable all languages)", + "customMetadata": "Custom Metadata", + "customMetadata.autoUpdate": "Auto Update Metadata", + "customMetadata.autoUpdate.description": "Automatically update PDF metadata on all processed documents", + "customMetadata.author": "Default Author", + "customMetadata.author.description": "Default author for PDF metadata (e.g., username)", + "customMetadata.creator": "Default Creator", + "customMetadata.creator.description": "Default creator for PDF metadata", + "customMetadata.producer": "Default Producer", + "customMetadata.producer.description": "Default producer for PDF metadata", + "customPaths": "Custom Paths", + "customPaths.description": "Configure custom file system paths for pipeline processing and external tools", + "customPaths.pipeline": "Pipeline Directories", + "customPaths.pipeline.watchedFoldersDir": "Watched Folders Directory", + "customPaths.pipeline.watchedFoldersDir.description": "Directory where pipeline monitors for incoming PDFs (leave empty for default: /pipeline/watchedFolders)", + "customPaths.pipeline.finishedFoldersDir": "Finished Folders Directory", + "customPaths.pipeline.finishedFoldersDir.description": "Directory where processed PDFs are outputted (leave empty for default: /pipeline/finishedFolders)", + "customPaths.operations": "External Tool Paths", + "customPaths.operations.weasyprint": "WeasyPrint Executable", + "customPaths.operations.weasyprint.description": "Path to WeasyPrint executable for HTML to PDF conversion (leave empty for default: /opt/venv/bin/weasyprint)", + "customPaths.operations.unoconvert": "Unoconvert Executable", + "customPaths.operations.unoconvert.description": "Path to LibreOffice unoconvert for document conversions (leave empty for default: /opt/venv/bin/unoconvert)" + }, + "security": { + "title": "Security", + "description": "Configure authentication, login behaviour, and security policies.", + "ssoNotice": { + "title": "Looking for SSO/SAML settings?", + "message": "OAuth2 and SAML2 authentication providers have been moved to the Connections menu for easier management." + }, + "authentication": "Authentication", + "enableLogin": "Enable Login", + "enableLogin.description": "Require users to log in before accessing the application", + "loginMethod": "Login Method", + "loginMethod.description": "The authentication method to use for user login", + "loginMethod.all": "All Methods", + "loginMethod.normal": "Username/Password Only", + "loginMethod.oauth2": "OAuth2 Only", + "loginMethod.saml2": "SAML2 Only", + "loginAttemptCount": "Login Attempt Limit", + "loginAttemptCount.description": "Maximum number of failed login attempts before account lockout", + "loginResetTimeMinutes": "Login Reset Time (minutes)", + "loginResetTimeMinutes.description": "Time before failed login attempts are reset", + "csrfDisabled": "Disable CSRF Protection", + "csrfDisabled.description": "Disable Cross-Site Request Forgery protection (not recommended)", + "initialLogin": "Initial Login", + "initialLogin.username": "Initial Username", + "initialLogin.username.description": "The username for the initial admin account", + "initialLogin.password": "Initial Password", + "initialLogin.password.description": "The password for the initial admin account", + "jwt": "JWT Configuration", + "jwt.secureCookie": "Secure Cookie", + "jwt.secureCookie.description": "Require HTTPS for JWT cookies (recommended for production)", + "jwt.keyRetentionDays": "Key Retention Days", + "jwt.keyRetentionDays.description": "Number of days to retain old JWT keys for verification", + "jwt.persistence": "Enable Key Persistence", + "jwt.persistence.description": "Store JWT keys persistently to survive server restarts", + "jwt.enableKeyRotation": "Enable Key Rotation", + "jwt.enableKeyRotation.description": "Automatically rotate JWT signing keys periodically", + "jwt.enableKeyCleanup": "Enable Key Cleanup", + "jwt.enableKeyCleanup.description": "Automatically remove expired JWT keys", + "audit": "Audit Logging", + "audit.enabled": "Enable Audit Logging", + "audit.enabled.description": "Track user actions and system events for compliance and security monitoring", + "audit.level": "Audit Level", + "audit.level.description": "0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE", + "audit.retentionDays": "Audit Retention (days)", + "audit.retentionDays.description": "Number of days to retain audit logs", + "htmlUrlSecurity": "HTML URL Security", + "htmlUrlSecurity.description": "Configure URL access restrictions for HTML processing to prevent SSRF attacks", + "htmlUrlSecurity.enabled": "Enable URL Security", + "htmlUrlSecurity.enabled.description": "Enable URL security restrictions for HTML to PDF conversions", + "htmlUrlSecurity.level": "Security Level", + "htmlUrlSecurity.level.description": "MAX: whitelist only, MEDIUM: block internal networks, OFF: no restrictions", + "htmlUrlSecurity.level.max": "Maximum (Whitelist Only)", + "htmlUrlSecurity.level.medium": "Medium (Block Internal)", + "htmlUrlSecurity.level.off": "Off (No Restrictions)", + "htmlUrlSecurity.advanced": "Advanced Settings", + "htmlUrlSecurity.allowedDomains": "Allowed Domains (Whitelist)", + "htmlUrlSecurity.allowedDomains.description": "One domain per line (e.g., cdn.example.com). Only these domains allowed when level is MAX", + "htmlUrlSecurity.blockedDomains": "Blocked Domains (Blacklist)", + "htmlUrlSecurity.blockedDomains.description": "One domain per line (e.g., malicious.com). Additional domains to block", + "htmlUrlSecurity.internalTlds": "Internal TLDs", + "htmlUrlSecurity.internalTlds.description": "One TLD per line (e.g., .local, .internal). Block domains with these TLD patterns", + "htmlUrlSecurity.networkBlocking": "Network Blocking", + "htmlUrlSecurity.blockPrivateNetworks": "Block Private Networks", + "htmlUrlSecurity.blockPrivateNetworks.description": "Block RFC 1918 private networks (10.x.x.x, 192.168.x.x, 172.16-31.x.x)", + "htmlUrlSecurity.blockLocalhost": "Block Localhost", + "htmlUrlSecurity.blockLocalhost.description": "Block localhost and loopback addresses (127.x.x.x, ::1)", + "htmlUrlSecurity.blockLinkLocal": "Block Link-Local Addresses", + "htmlUrlSecurity.blockLinkLocal.description": "Block link-local addresses (169.254.x.x, fe80::/10)", + "htmlUrlSecurity.blockCloudMetadata": "Block Cloud Metadata Endpoints", + "htmlUrlSecurity.blockCloudMetadata.description": "Block cloud provider metadata endpoints (169.254.169.254)" + }, + "connections": { + "title": "Connections", + "description": "Configure external authentication providers like OAuth2 and SAML.", + "linkedServices": "Linked Services", + "unlinkedServices": "Unlinked Services", + "connect": "Connect", + "disconnect": "Disconnect", + "disconnected": "Provider disconnected successfully", + "disconnectError": "Failed to disconnect provider", + "ssoAutoLogin": "SSO Auto Login", + "ssoAutoLogin.enable": "Enable SSO Auto Login", + "ssoAutoLogin.description": "Automatically redirect to SSO login when authentication is required", + "oauth2": "OAuth2", + "oauth2.enabled": "Enable OAuth2", + "oauth2.enabled.description": "Allow users to authenticate using OAuth2 providers", + "oauth2.provider": "Provider", + "oauth2.provider.description": "The OAuth2 provider to use for authentication", + "oauth2.issuer": "Issuer URL", + "oauth2.issuer.description": "The OAuth2 provider issuer URL", + "oauth2.clientId": "Client ID", + "oauth2.clientId.description": "The OAuth2 client ID from your provider", + "oauth2.clientSecret": "Client Secret", + "oauth2.clientSecret.description": "The OAuth2 client secret from your provider", + "oauth2.useAsUsername": "Use as Username", + "oauth2.useAsUsername.description": "The OAuth2 claim to use as the username (e.g., email, sub)", + "oauth2.autoCreateUser": "Auto Create Users", + "oauth2.autoCreateUser.description": "Automatically create user accounts on first OAuth2 login", + "oauth2.blockRegistration": "Block Registration", + "oauth2.blockRegistration.description": "Prevent new user registration via OAuth2", + "oauth2.scopes": "OAuth2 Scopes", + "oauth2.scopes.description": "Comma-separated list of OAuth2 scopes to request (e.g., openid, profile, email)", + "saml2": "SAML2", + "saml2.enabled": "Enable SAML2", + "saml2.enabled.description": "Allow users to authenticate using SAML2 providers", + "saml2.provider": "Provider", + "saml2.provider.description": "The SAML2 provider name", + "saml2.registrationId": "Registration ID", + "saml2.registrationId.description": "The SAML2 registration identifier", + "saml2.autoCreateUser": "Auto Create Users", + "saml2.autoCreateUser.description": "Automatically create user accounts on first SAML2 login", + "saml2.blockRegistration": "Block Registration", + "saml2.blockRegistration.description": "Prevent new user registration via SAML2" + }, + "database": { + "title": "Database", + "description": "Configure custom database connection settings for enterprise deployments.", + "configuration": "Database Configuration", + "enableCustom": "Enable Custom Database", + "enableCustom.description": "Use your own custom database configuration instead of the default embedded database", + "customUrl": "Custom Database URL", + "customUrl.description": "Full JDBC connection string (e.g., jdbc:postgresql://localhost:5432/postgres). If provided, individual connection settings below are not used.", + "type": "Database Type", + "type.description": "Type of database (not used if custom URL is provided)", + "hostName": "Host Name", + "hostName.description": "Database server hostname (not used if custom URL is provided)", + "port": "Port", + "port.description": "Database server port (not used if custom URL is provided)", + "name": "Database Name", + "name.description": "Name of the database (not used if custom URL is provided)", + "username": "Username", + "username.description": "Database authentication username", + "password": "Password", + "password.description": "Database authentication password" + }, + "privacy": { + "title": "Privacy", + "description": "Configure privacy and data collection settings.", + "analytics": "Analytics & Tracking", + "enableAnalytics": "Enable Analytics", + "enableAnalytics.description": "Collect anonymous usage analytics to help improve the application", + "metricsEnabled": "Enable Metrics", + "metricsEnabled.description": "Enable collection of performance and usage metrics", + "searchEngine": "Search Engine Visibility", + "googleVisibility": "Google Visibility", + "googleVisibility.description": "Allow search engines to index this application" + }, + "advanced": { + "title": "Advanced", + "description": "Configure advanced features and experimental functionality.", + "features": "Feature Flags", + "processing": "Processing", + "endpoints": "Endpoints", + "endpoints.manage": "Manage API Endpoints", + "endpoints.description": "Endpoint management is configured via YAML. See documentation for details on enabling/disabling specific endpoints.", + "enableAlphaFunctionality": "Enable Alpha Features", + "enableAlphaFunctionality.description": "Enable experimental and alpha-stage features (may be unstable)", + "enableUrlToPDF": "Enable URL to PDF", + "enableUrlToPDF.description": "Allow conversion of web pages to PDF documents", + "maxDPI": "Maximum DPI", + "maxDPI.description": "Maximum DPI for image processing (0 = unlimited)", + "tessdataDir": "Tessdata Directory", + "tessdataDir.description": "Path to the tessdata directory for OCR language files", + "disableSanitize": "Disable HTML Sanitization", + "disableSanitize.description": "WARNING: Security risk - disabling HTML sanitization can lead to XSS vulnerabilities", + "tempFileManagement": "Temp File Management", + "tempFileManagement.description": "Configure temporary file storage and cleanup behavior", + "tempFileManagement.baseTmpDir": "Base Temp Directory", + "tempFileManagement.baseTmpDir.description": "Base directory for temporary files (leave empty for default: java.io.tmpdir/stirling-pdf)", + "tempFileManagement.libreofficeDir": "LibreOffice Temp Directory", + "tempFileManagement.libreofficeDir.description": "Directory for LibreOffice temp files (leave empty for default: baseTmpDir/libreoffice)", + "tempFileManagement.systemTempDir": "System Temp Directory", + "tempFileManagement.systemTempDir.description": "System temp directory to clean (only used if cleanupSystemTemp is enabled)", + "tempFileManagement.prefix": "Temp File Prefix", + "tempFileManagement.prefix.description": "Prefix for temp file names", + "tempFileManagement.maxAgeHours": "Max Age (hours)", + "tempFileManagement.maxAgeHours.description": "Maximum age in hours before temp files are cleaned up", + "tempFileManagement.cleanupIntervalMinutes": "Cleanup Interval (minutes)", + "tempFileManagement.cleanupIntervalMinutes.description": "How often to run cleanup (in minutes)", + "tempFileManagement.startupCleanup": "Startup Cleanup", + "tempFileManagement.startupCleanup.description": "Clean up old temp files on application startup", + "tempFileManagement.cleanupSystemTemp": "Cleanup System Temp", + "tempFileManagement.cleanupSystemTemp.description": "Whether to clean broader system temp directory (use with caution)", + "processExecutor": "Process Executor Limits", + "processExecutor.description": "Configure session limits and timeouts for each process executor", + "processExecutor.sessionLimit": "Session Limit", + "processExecutor.sessionLimit.description": "Maximum concurrent instances", + "processExecutor.timeout": "Timeout (minutes)", + "processExecutor.timeout.description": "Maximum execution time", + "processExecutor.libreOffice": "LibreOffice", + "processExecutor.pdfToHtml": "PDF to HTML", + "processExecutor.qpdf": "QPDF", + "processExecutor.tesseract": "Tesseract OCR", + "processExecutor.pythonOpenCv": "Python OpenCV", + "processExecutor.weasyPrint": "WeasyPrint", + "processExecutor.installApp": "Install App", + "processExecutor.calibre": "Calibre", + "processExecutor.ghostscript": "Ghostscript", + "processExecutor.ocrMyPdf": "OCRmyPDF" + }, + "mail": { + "title": "Mail Server", + "description": "Configure SMTP settings for sending email notifications.", + "smtp": "SMTP Configuration", + "enabled": "Enable Mail", + "enabled.description": "Enable email notifications and SMTP functionality", + "host": "SMTP Host", + "host.description": "The hostname or IP address of your SMTP server", + "port": "SMTP Port", + "port.description": "The port number for SMTP connection (typically 25, 465, or 587)", + "username": "SMTP Username", + "username.description": "Username for SMTP authentication", + "password": "SMTP Password", + "password.description": "Password for SMTP authentication", + "from": "From Address", + "from.description": "The email address to use as the sender", + "enableInvites": "Enable Email Invites", + "enableInvites.description": "Allow admins to invite users via email with auto-generated passwords" + }, + "legal": { + "title": "Legal Documents", + "description": "Configure links to legal documents and policies.", + "disclaimer": { + "title": "Legal Responsibility Warning", + "message": "By customizing these legal documents, you assume full responsibility for ensuring compliance with all applicable laws and regulations, including but not limited to GDPR and other EU data protection requirements. Only modify these settings if: (1) you are operating a personal/private instance, (2) you are outside EU jurisdiction and understand your local legal obligations, or (3) you have obtained proper legal counsel and accept sole responsibility for all user data and legal compliance. Stirling-PDF and its developers assume no liability for your legal obligations." + }, + "termsAndConditions": "Terms and Conditions", + "termsAndConditions.description": "URL or filename to terms and conditions", + "privacyPolicy": "Privacy Policy", + "privacyPolicy.description": "URL or filename to privacy policy", + "accessibilityStatement": "Accessibility Statement", + "accessibilityStatement.description": "URL or filename to accessibility statement", + "cookiePolicy": "Cookie Policy", + "cookiePolicy.description": "URL or filename to cookie policy", + "impressum": "Impressum", + "impressum.description": "URL or filename to impressum (required in some jurisdictions)" + }, + "premium": { + "title": "Premium & Enterprise", + "description": "Configure your premium or enterprise license key.", + "license": "License Configuration", + "key": "License Key", + "key.description": "Enter your premium or enterprise license key", + "enabled": "Enable Premium Features", + "enabled.description": "Enable license key checks for pro/enterprise features", + "movedFeatures": { + "title": "Premium Features Distributed", + "message": "Premium and Enterprise features are now organized in their respective sections:" + } + }, + "features": { + "title": "Features", + "description": "Configure optional features and functionality.", + "serverCertificate": "Server Certificate", + "serverCertificate.description": "Configure server-side certificate generation for \"Sign with Stirling-PDF\" functionality", + "serverCertificate.enabled": "Enable Server Certificate", + "serverCertificate.enabled.description": "Enable server-side certificate for \"Sign with Stirling-PDF\" option", + "serverCertificate.organizationName": "Organization Name", + "serverCertificate.organizationName.description": "Organization name for generated certificates", + "serverCertificate.validity": "Certificate Validity (days)", + "serverCertificate.validity.description": "Number of days the certificate will be valid", + "serverCertificate.regenerateOnStartup": "Regenerate on Startup", + "serverCertificate.regenerateOnStartup.description": "Generate new certificate on each application startup" + }, + "endpoints": { + "title": "API Endpoints", + "description": "Control which API endpoints and endpoint groups are available.", + "management": "Endpoint Management", + "toRemove": "Disabled Endpoints", + "toRemove.description": "Select individual endpoints to disable", + "groupsToRemove": "Disabled Endpoint Groups", + "groupsToRemove.description": "Select endpoint groups to disable", + "note": "Note: Disabling endpoints restricts API access but does not remove UI components. Restart required for changes to take effect." + } + } + }, "fileUpload": { "selectFile": "Select a file", "selectFiles": "Select files", @@ -4052,5 +4402,195 @@ "finish": "Finish", "startTour": "Start Tour", "startTourDescription": "Take a guided tour of Stirling PDF's key features" + }, + "workspace": { + "title": "Workspace", + "people": { + "title": "People", + "description": "Manage workspace members and their permissions", + "loading": "Loading people...", + "searchMembers": "Search members...", + "addMembers": "Add Members", + "inviteMembers": "Invite Members", + "inviteMembers.subtitle": "Type or paste in emails below, separated by commas. Your workspace will be billed by members.", + "user": "User", + "role": "Role", + "team": "Team", + "status": "Status", + "actions": "Actions", + "noMembersFound": "No members found", + "active": "Active", + "disabled": "Disabled", + "activeSession": "Active session", + "member": "Member", + "admin": "Admin", + "roleDescriptions": { + "admin": "Can manage settings and invite members, with full administrative access.", + "member": "Can view and edit shared files, but cannot manage workspace settings or members." + }, + "editRole": "Edit Role", + "enable": "Enable", + "disable": "Disable", + "deleteUser": "Delete User", + "deleteUserSuccess": "User deleted successfully", + "deleteUserError": "Failed to delete user", + "confirmDelete": "Are you sure you want to delete this user? This action cannot be undone.", + "addMember": { + "title": "Add Member", + "username": "Username (Email)", + "usernamePlaceholder": "user@example.com", + "password": "Password", + "passwordPlaceholder": "Enter password", + "role": "Role", + "team": "Team (Optional)", + "teamPlaceholder": "Select a team", + "forcePasswordChange": "Force password change on first login", + "cancel": "Cancel", + "submit": "Add Member", + "usernameRequired": "Username and password are required", + "passwordTooShort": "Password must be at least 6 characters", + "success": "User created successfully", + "error": "Failed to create user" + }, + "editMember": { + "title": "Edit Member", + "editing": "Editing:", + "role": "Role", + "team": "Team (Optional)", + "teamPlaceholder": "Select a team", + "cancel": "Cancel", + "submit": "Update Member", + "success": "User updated successfully", + "error": "Failed to update user" + }, + "toggleEnabled": { + "success": "User status updated successfully", + "error": "Failed to update user status" + }, + "delete": { + "success": "User deleted successfully", + "error": "Failed to delete user" + }, + "emailInvite": { + "tab": "Email Invite", + "description": "Type or paste in emails below, separated by commas. Users will receive login credentials via email.", + "emails": "Email Addresses", + "emailsPlaceholder": "user1@example.com, user2@example.com", + "emailsRequired": "At least one email address is required", + "submit": "Send Invites", + "success": "user(s) invited successfully", + "partialSuccess": "Some invites failed", + "allFailed": "Failed to invite users", + "error": "Failed to send invites" + }, + "directInvite": { + "tab": "Direct Create" + }, + "inviteMode": { + "username": "Username", + "email": "Email", + "emailDisabled": "Email invites require SMTP configuration and mail.enableInvites=true in settings" + } + }, + "teams": { + "title": "Teams", + "description": "Manage teams and organize workspace members", + "loading": "Loading teams...", + "loadingDetails": "Loading team details...", + "createNewTeam": "Create New Team", + "teamName": "Team Name", + "totalMembers": "Total Members", + "actions": "Actions", + "noTeamsFound": "No teams found", + "noMembers": "No members in this team", + "system": "System", + "addMember": "Add Member", + "viewTeam": "View Team", + "removeMember": "Remove from team", + "cannotRemoveFromSystemTeam": "Cannot remove from system team", + "renameTeamLabel": "Rename Team", + "deleteTeamLabel": "Delete Team", + "cannotDeleteInternal": "Cannot delete the Internal team", + "confirmDelete": "Are you sure you want to delete this team? This team must be empty to delete.", + "confirmRemove": "Remove user from this team?", + "cannotRenameInternal": "Cannot rename the Internal team", + "cannotAddToInternal": "Cannot add members to the Internal team", + "teamNotFound": "Team not found", + "backToTeams": "Back to Teams", + "memberCount": "{{count}} members", + "removeMemberSuccess": "User removed from team", + "removeMemberError": "Failed to remove user from team", + "createTeam": { + "title": "Create New Team", + "teamName": "Team Name", + "teamNamePlaceholder": "Enter team name", + "cancel": "Cancel", + "submit": "Create Team", + "nameRequired": "Team name is required", + "success": "Team created successfully", + "error": "Failed to create team" + }, + "renameTeam": { + "title": "Rename Team", + "renaming": "Renaming:", + "newTeamName": "New Team Name", + "newTeamNamePlaceholder": "Enter new team name", + "cancel": "Cancel", + "submit": "Rename Team", + "nameRequired": "Team name is required", + "success": "Team renamed successfully", + "error": "Failed to rename team" + }, + "deleteTeam": { + "success": "Team deleted successfully", + "error": "Failed to delete team. Make sure the team is empty.", + "teamMustBeEmpty": "Team must be empty before deletion" + }, + "addMemberToTeam": { + "title": "Add Member to Team", + "addingTo": "Adding to", + "selectUser": "Select User", + "selectUserPlaceholder": "Choose a user", + "selectUserRequired": "Please select a user", + "currentlyIn": "currently in", + "willBeMoved": "Note: This user will be moved from their current team to this team.", + "cancel": "Cancel", + "submit": "Add Member", + "userRequired": "Please select a user", + "success": "Member added to team successfully", + "error": "Failed to add member to team" + }, + "changeTeam": { + "label": "Change Team", + "title": "Change Team", + "changing": "Moving", + "selectTeam": "Select Team", + "selectTeamPlaceholder": "Choose a team", + "selectTeamRequired": "Please select a team", + "success": "Team changed successfully", + "error": "Failed to change team", + "submit": "Change Team" + } + } + }, + "firstLogin": { + "title": "First Time Login", + "welcomeTitle": "Welcome!", + "welcomeMessage": "For security reasons, you must change your password on your first login.", + "loggedInAs": "Logged in as", + "error": "Error", + "currentPassword": "Current Password", + "enterCurrentPassword": "Enter your current password", + "newPassword": "New Password", + "enterNewPassword": "Enter new password (min 8 characters)", + "confirmPassword": "Confirm New Password", + "reEnterNewPassword": "Re-enter new password", + "changePassword": "Change Password", + "allFieldsRequired": "All fields are required", + "passwordsDoNotMatch": "New passwords do not match", + "passwordTooShort": "Password must be at least 8 characters", + "passwordMustBeDifferent": "New password must be different from current password", + "passwordChangedSuccess": "Password changed successfully! Please log in again.", + "passwordChangeFailed": "Failed to change password. Please check your current password." } } diff --git a/frontend/src/core/components/layout/Workbench.tsx b/frontend/src/core/components/layout/Workbench.tsx index 91595195dd..861e6a3656 100644 --- a/frontend/src/core/components/layout/Workbench.tsx +++ b/frontend/src/core/components/layout/Workbench.tsx @@ -190,7 +190,14 @@ export default function Workbench() { {renderMainContent()} -