diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b38abe5dc9..be04dbd64c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,10 +31,15 @@ jobs: project: ${{ steps.changes.outputs.project }} openapi: ${{ steps.changes.outputs.openapi }} steps: - - uses: actions/checkout@v4.3.0 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 + with: + egress-policy: audit + + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Check for file changes - uses: dorny/paths-filter@v3.0.2 + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: filters: .github/config/.files.yaml @@ -51,19 +56,19 @@ jobs: spring-security: [true, false] steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK ${{ matrix.jdk-version }} - uses: actions/setup-java@v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: ${{ matrix.jdk-version }} distribution: "temurin" - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4.4.2 + uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 with: gradle-version: 8.14 - name: Build with Gradle and spring security ${{ matrix.spring-security }} @@ -89,7 +94,7 @@ jobs: done - name: Upload Test Reports if: always() - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: test-reports-jdk-${{ matrix.jdk-version }}-spring-security-${{ matrix.spring-security }} path: | @@ -106,26 +111,26 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK 17 - uses: actions/setup-java@v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: "17" distribution: "temurin" - - uses: gradle/actions/setup-gradle@v4.4.2 + - uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 - name: Generate OpenAPI documentation run: ./gradlew :stirling-pdf:generateOpenApiDocs env: DISABLE_ADDITIONAL_FEATURES: true - name: Upload OpenAPI Documentation - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: openapi-docs path: ./SwaggerDoc.json @@ -134,19 +139,21 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@v2.12.2 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node.js - uses: actions/setup-node@v4.1.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: - node-version: '20' + node-version: '22' cache: 'npm' 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 @@ -154,7 +161,7 @@ jobs: - name: Run frontend tests run: cd frontend && npm run test -- --run - name: Upload frontend build artifacts - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: frontend-build path: frontend/dist/ @@ -166,13 +173,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK 17 - uses: actions/setup-java@v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: "17" distribution: "temurin" @@ -180,7 +187,7 @@ jobs: run: ./gradlew clean checkLicense - name: FAILED - check the licenses for compatibility if: failure() - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: dependencies-without-allowed-license.json path: build/reports/dependency-license/dependencies-without-allowed-license.json @@ -207,15 +214,15 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout Repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Java 17 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: "17" distribution: "temurin" @@ -225,11 +232,11 @@ jobs: - name: Install Docker Compose run: | - sudo curl -SL "https://github.com/docker/compose/releases/download/v2.37.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo curl -SL "https://github.com/docker/compose/releases/download/v2.39.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: "3.12" cache: 'pip' # caching pip dependencies @@ -256,21 +263,21 @@ jobs: docker-rev: ["Dockerfile", "Dockerfile.ultra-lite", "Dockerfile.fat"] steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit - name: Checkout Repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK 17 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: "17" distribution: "temurin" - name: Set up Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 with: gradle-version: 8.14 diff --git a/README.md b/README.md index 250f71abb3..f8058d9060 100644 --- a/README.md +++ b/README.md @@ -115,46 +115,46 @@ Stirling-PDF currently supports 40 languages! | Language | Progress | | -------------------------------------------- | -------------------------------------- | -| Arabic (العربية) (ar_AR) | ![95%](https://geps.dev/progress/95) | -| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![35%](https://geps.dev/progress/35) | -| Basque (Euskara) (eu_ES) | ![20%](https://geps.dev/progress/20) | -| Bulgarian (Български) (bg_BG) | ![39%](https://geps.dev/progress/39) | -| Catalan (Català) (ca_CA) | ![37%](https://geps.dev/progress/37) | -| Croatian (Hrvatski) (hr_HR) | ![34%](https://geps.dev/progress/34) | -| Czech (Česky) (cs_CZ) | ![38%](https://geps.dev/progress/38) | -| Danish (Dansk) (da_DK) | ![34%](https://geps.dev/progress/34) | -| Dutch (Nederlands) (nl_NL) | ![34%](https://geps.dev/progress/34) | +| Arabic (العربية) (ar_AR) | ![83%](https://geps.dev/progress/83) | +| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![32%](https://geps.dev/progress/32) | +| Basque (Euskara) (eu_ES) | ![18%](https://geps.dev/progress/18) | +| Bulgarian (Български) (bg_BG) | ![35%](https://geps.dev/progress/35) | +| Catalan (Català) (ca_CA) | ![34%](https://geps.dev/progress/34) | +| Croatian (Hrvatski) (hr_HR) | ![31%](https://geps.dev/progress/31) | +| Czech (Česky) (cs_CZ) | ![34%](https://geps.dev/progress/34) | +| Danish (Dansk) (da_DK) | ![30%](https://geps.dev/progress/30) | +| Dutch (Nederlands) (nl_NL) | ![30%](https://geps.dev/progress/30) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) | -| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) | -| German (Deutsch) (de_DE) | ![95%](https://geps.dev/progress/95) | -| Greek (Ελληνικά) (el_GR) | ![38%](https://geps.dev/progress/38) | -| Hindi (हिंदी) (hi_IN) | ![38%](https://geps.dev/progress/38) | -| Hungarian (Magyar) (hu_HU) | ![42%](https://geps.dev/progress/42) | -| Indonesian (Bahasa Indonesia) (id_ID) | ![34%](https://geps.dev/progress/34) | -| Irish (Gaeilge) (ga_IE) | ![38%](https://geps.dev/progress/38) | -| Italian (Italiano) (it_IT) | ![95%](https://geps.dev/progress/95) | -| Japanese (日本語) (ja_JP) | ![70%](https://geps.dev/progress/70) | -| Korean (한국어) (ko_KR) | ![38%](https://geps.dev/progress/38) | -| Norwegian (Norsk) (no_NB) | ![36%](https://geps.dev/progress/36) | -| Persian (فارسی) (fa_IR) | ![38%](https://geps.dev/progress/38) | -| Polish (Polski) (pl_PL) | ![40%](https://geps.dev/progress/40) | -| Portuguese (Português) (pt_PT) | ![38%](https://geps.dev/progress/38) | -| Portuguese Brazilian (Português) (pt_BR) | ![95%](https://geps.dev/progress/95) | -| Romanian (Română) (ro_RO) | ![32%](https://geps.dev/progress/32) | -| Russian (Русский) (ru_RU) | ![94%](https://geps.dev/progress/94) | -| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![42%](https://geps.dev/progress/42) | -| Simplified Chinese (简体中文) (zh_CN) | ![96%](https://geps.dev/progress/96) | -| Slovakian (Slovensky) (sk_SK) | ![28%](https://geps.dev/progress/28) | -| Slovenian (Slovenščina) (sl_SI) | ![40%](https://geps.dev/progress/40) | -| Spanish (Español) (es_ES) | ![95%](https://geps.dev/progress/95) | -| Swedish (Svenska) (sv_SE) | ![37%](https://geps.dev/progress/37) | -| Thai (ไทย) (th_TH) | ![34%](https://geps.dev/progress/34) | +| French (Français) (fr_FR) | ![82%](https://geps.dev/progress/82) | +| German (Deutsch) (de_DE) | ![84%](https://geps.dev/progress/84) | +| Greek (Ελληνικά) (el_GR) | ![34%](https://geps.dev/progress/34) | +| Hindi (हिंदी) (hi_IN) | ![34%](https://geps.dev/progress/34) | +| Hungarian (Magyar) (hu_HU) | ![38%](https://geps.dev/progress/38) | +| Indonesian (Bahasa Indonesia) (id_ID) | ![31%](https://geps.dev/progress/31) | +| Irish (Gaeilge) (ga_IE) | ![34%](https://geps.dev/progress/34) | +| Italian (Italiano) (it_IT) | ![84%](https://geps.dev/progress/84) | +| Japanese (日本語) (ja_JP) | ![62%](https://geps.dev/progress/62) | +| Korean (한국어) (ko_KR) | ![34%](https://geps.dev/progress/34) | +| Norwegian (Norsk) (no_NB) | ![32%](https://geps.dev/progress/32) | +| Persian (فارسی) (fa_IR) | ![34%](https://geps.dev/progress/34) | +| Polish (Polski) (pl_PL) | ![36%](https://geps.dev/progress/36) | +| Portuguese (Português) (pt_PT) | ![34%](https://geps.dev/progress/34) | +| Portuguese Brazilian (Português) (pt_BR) | ![83%](https://geps.dev/progress/83) | +| Romanian (Română) (ro_RO) | ![28%](https://geps.dev/progress/28) | +| Russian (Русский) (ru_RU) | ![83%](https://geps.dev/progress/83) | +| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![37%](https://geps.dev/progress/37) | +| Simplified Chinese (简体中文) (zh_CN) | ![85%](https://geps.dev/progress/85) | +| Slovakian (Slovensky) (sk_SK) | ![26%](https://geps.dev/progress/26) | +| Slovenian (Slovenščina) (sl_SI) | ![36%](https://geps.dev/progress/36) | +| Spanish (Español) (es_ES) | ![84%](https://geps.dev/progress/84) | +| Swedish (Svenska) (sv_SE) | ![33%](https://geps.dev/progress/33) | +| Thai (ไทย) (th_TH) | ![31%](https://geps.dev/progress/31) | | Tibetan (བོད་ཡིག་) (bo_CN) | ![65%](https://geps.dev/progress/65) | -| Traditional Chinese (繁體中文) (zh_TW) | ![42%](https://geps.dev/progress/42) | -| Turkish (Türkçe) (tr_TR) | ![41%](https://geps.dev/progress/41) | -| Ukrainian (Українська) (uk_UA) | ![40%](https://geps.dev/progress/40) | -| Vietnamese (Tiếng Việt) (vi_VN) | ![31%](https://geps.dev/progress/31) | +| Traditional Chinese (繁體中文) (zh_TW) | ![38%](https://geps.dev/progress/38) | +| Turkish (Türkçe) (tr_TR) | ![37%](https://geps.dev/progress/37) | +| Ukrainian (Українська) (uk_UA) | ![36%](https://geps.dev/progress/36) | +| Vietnamese (Tiếng Việt) (vi_VN) | ![28%](https://geps.dev/progress/28) | | Malayalam (മലയാളം) (ml_IN) | ![73%](https://geps.dev/progress/73) | ## Stirling PDF Enterprise 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 75c5dd8ad3..2cc988cfae 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 @@ -355,6 +355,8 @@ public class ApplicationProperties { private String tessdataDir; private Boolean enableAlphaFunctionality; private Boolean enableAnalytics; + private Boolean enablePosthog; + private Boolean enableScarf; private Datasource datasource; private Boolean disableSanitize; private int maxDPI; @@ -372,6 +374,18 @@ public class ApplicationProperties { public boolean isAnalyticsEnabled() { return this.getEnableAnalytics() != null && this.getEnableAnalytics(); } + + public boolean isPosthogEnabled() { + // Treat null as enabled when analytics is enabled + return this.isAnalyticsEnabled() + && (this.getEnablePosthog() == null || this.getEnablePosthog()); + } + + public boolean isScarfEnabled() { + // Treat null as enabled when analytics is enabled + return this.isAnalyticsEnabled() + && (this.getEnableScarf() == null || this.getEnableScarf()); + } } @Data 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 d9b8836f4d..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 @@ -56,7 +56,7 @@ public class PostHogService { } private void captureSystemInfo() { - if (!applicationProperties.getSystem().isAnalyticsEnabled()) { + if (!applicationProperties.getSystem().isPosthogEnabled()) { return; } try { @@ -67,7 +67,7 @@ public class PostHogService { } public void captureEvent(String eventName, Map properties) { - if (!applicationProperties.getSystem().isAnalyticsEnabled()) { + if (!applicationProperties.getSystem().isPosthogEnabled()) { return; } @@ -325,6 +325,14 @@ public class PostHogService { properties, "system_enableAnalytics", applicationProperties.getSystem().isAnalyticsEnabled()); + addIfNotEmpty( + properties, + "system_enablePosthog", + applicationProperties.getSystem().isPosthogEnabled()); + addIfNotEmpty( + properties, + "system_enableScarf", + applicationProperties.getSystem().isScarfEnabled()); // Capture UI properties addIfNotEmpty( 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 82daf89e74..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 @@ -9,6 +9,7 @@ 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; @@ -31,7 +32,7 @@ public class SettingsController { @AutoJobPostMapping("/update-enable-analytics") @Hidden - public ResponseEntity updateApiKey(@RequestBody Boolean enabled) throws IOException { + public ResponseEntity updateApiKey(@RequestParam Boolean enabled) throws IOException { if (applicationProperties.getSystem().getEnableAnalytics() != null) { return ResponseEntity.status(HttpStatus.ALREADY_REPORTED) .body( 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 4a2fef040c..b578d7c428 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 @@ -84,6 +84,8 @@ public class ConfigController { applicationProperties.getSystem().getEnableAlphaFunctionality()); configData.put( "enableAnalytics", applicationProperties.getSystem().getEnableAnalytics()); + configData.put("enablePosthog", applicationProperties.getSystem().getEnablePosthog()); + configData.put("enableScarf", applicationProperties.getSystem().getEnableScarf()); // Premium/Enterprise settings configData.put("premiumEnabled", applicationProperties.getPremium().isEnabled()); diff --git a/app/core/src/main/resources/settings.yml.template b/app/core/src/main/resources/settings.yml.template index 602116e4fc..70417f65b5 100644 --- a/app/core/src/main/resources/settings.yml.template +++ b/app/core/src/main/resources/settings.yml.template @@ -107,8 +107,8 @@ mail: from: '' # sender email address legal: - termsAndConditions: https://www.stirlingpdf.com/terms # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder - privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder + termsAndConditions: https://www.stirling.com/legal/terms-of-service # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder + privacyPolicy: https://www.stirling.com/legal/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum). Empty string to disable or filename to load from local file in static folder @@ -121,7 +121,9 @@ system: showUpdateOnlyAdmin: false # only admins can see when a new update is available, depending on showUpdate it must be set to 'true' customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template HTML files tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored. - enableAnalytics: null # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true + enableAnalytics: null # Master toggle for analytics: set to 'true' to enable all analytics, 'false' to disable all analytics, or leave as 'null' to prompt admin on first launch + enablePosthog: null # Enable PostHog analytics (open-source product analytics): set to 'true' to enable, 'false' to disable, or 'null' to enable by default when analytics is enabled + enableScarf: null # Enable Scarf tracking pixel: set to 'true' to enable, 'false' to disable, or 'null' to enable by default when analytics is enabled enableUrlToPDF: false # Set to 'true' to enable URL to PDF, INTERNAL ONLY, known security issues, should not be used externally disableSanitize: false # set to true to disable Sanitize HTML; (can lead to injections in HTML) maxDPI: 500 # Maximum allowed DPI for PDF to image conversion 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 322fd27092..bee8304301 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 @@ -366,6 +366,10 @@ public class UserController { 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 ResponseEntity.ok(Map.of("message", "User created successfully")); @@ -458,41 +462,12 @@ public class UserController { continue; } - try { - // Validate email format (basic check) - if (!email.contains("@") || !email.contains(".")) { - errors.append(email).append(": Invalid email format; "); - failureCount++; - continue; - } - - // Check if user already exists - if (userService.usernameExistsIgnoreCase(email)) { - errors.append(email).append(": User already exists; "); - failureCount++; - continue; - } - - // Generate random password - String temporaryPassword = java.util.UUID.randomUUID().toString().substring(0, 12); - - // Create user with forceChange=true - userService.saveUser(email, temporaryPassword, effectiveTeamId, role, true); - - // Send invite email - try { - emailService.get().sendInviteEmail(email, email, temporaryPassword); - successCount++; - log.info("Sent invite email to: {}", email); - } catch (Exception emailEx) { - log.error("Failed to send invite email to {}: {}", email, emailEx.getMessage()); - errors.append(email).append(": User created but email failed to send; "); - } - - } catch (Exception e) { - log.error("Failed to invite user {}: {}", email, e.getMessage()); - errors.append(email).append(": ").append(e.getMessage()).append("; "); + InviteResult result = processEmailInvite(email, effectiveTeamId, role); + if (result.isSuccess()) { + successCount++; + } else { failureCount++; + errors.append(result.getErrorMessage()).append("; "); } } @@ -685,4 +660,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/service/EmailService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/EmailService.java index 4668e9a389..870c96f230 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 @@ -123,38 +123,39 @@ public class EmailService { String subject = "Welcome to Stirling PDF"; String body = - String.format( - "" - + "
" - + "
" - + " " - + "
" - + " \"Stirling" - + "
" - + " " - + "
" - + "

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." - + "
" - + "
" - + "
" - + "", - username, temporaryPassword); + """ + +
+
+ +
+ 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); } @@ -173,41 +174,42 @@ public class EmailService { String subject = "You've been invited to Stirling PDF"; String body = - String.format( - "" - + "
" - + "
" - + " " - + "
" - + " \"Stirling" - + "
" - + " " - + "
" - + "

Welcome to Stirling PDF!

" - + "

Hi there,

" - + "

You have been invited to join the Stirling PDF workspace. Click the button below to set up your account:

" - + " " - + "
" - + " Accept Invitation" - + "
" - + "

Or copy and paste this link in your browser:

" - + "
" - + " %s" - + "
" - + "
" - + "

⚠️ Important: This invitation link will expire on %s. Please complete your registration before then.

" - + "
" - + "

If you didn't expect this invitation, you can safely ignore this email.

" - + "

— The Stirling PDF Team

" - + "
" - + " " - + "
" - + " © 2025 Stirling PDF. All rights reserved." - + "
" - + "
" - + "
" - + "", - inviteUrl, inviteUrl, expiresAt); + """ + +
+
+ +
+ Stirling PDF +
+ +
+

Welcome to Stirling PDF!

+

Hi there,

+

You have been invited to join the Stirling PDF workspace. Click the button below to set up your account:

+ + +

Or copy and paste this link in your browser:

+
+ %s +
+
+

⚠️ Important: This invitation link will expire on %s. Please complete your registration before then.

+
+

If you didn't expect this invitation, you can safely ignore this email.

+

— The Stirling PDF Team

+
+ +
+ © 2025 Stirling PDF. All rights reserved. +
+
+
+ + """ + .formatted(inviteUrl, inviteUrl, expiresAt); sendPlainEmail(to, subject, body, true); } diff --git a/docker/Dockerfile.unified b/docker/Dockerfile.unified new file mode 100644 index 0000000000..0f1c31cf87 --- /dev/null +++ b/docker/Dockerfile.unified @@ -0,0 +1,141 @@ +# Unified Dockerfile - Frontend + Backend in single container +# Supports MODE parameter: BOTH (default), FRONTEND, BACKEND + +# Stage 1: Build Frontend +FROM node:20-alpine AS frontend-build + +WORKDIR /app + +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci + +COPY frontend . +RUN npm run build + +# Stage 2: Build Backend +FROM gradle:8.14-jdk21 AS backend-build + +COPY build.gradle . +COPY settings.gradle . +COPY gradlew . +COPY gradle gradle/ +COPY app/core/build.gradle core/. +COPY app/common/build.gradle common/. +COPY app/proprietary/build.gradle proprietary/. +RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0 + +WORKDIR /app +COPY . . + +RUN DISABLE_ADDITIONAL_FEATURES=false \ + STIRLING_PDF_DESKTOP_UI=false \ + ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube + +# Stage 3: Final unified image +FROM alpine:3.22.1 + +ARG VERSION_TAG + +# Labels +LABEL org.opencontainers.image.title="Stirling-PDF Unified" +LABEL org.opencontainers.image.description="Unified container for Stirling-PDF - Frontend + Backend with MODE parameter" +LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF" +LABEL org.opencontainers.image.licenses="MIT" +LABEL org.opencontainers.image.vendor="Stirling-Tools" +LABEL org.opencontainers.image.url="https://www.stirlingpdf.com" +LABEL org.opencontainers.image.documentation="https://docs.stirlingpdf.com" +LABEL maintainer="Stirling-Tools" +LABEL org.opencontainers.image.authors="Stirling-Tools" +LABEL org.opencontainers.image.version="${VERSION_TAG}" +LABEL org.opencontainers.image.keywords="PDF, manipulation, unified, API, Spring Boot, React" + +# Copy backend files +COPY scripts /scripts +COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/ +COPY --from=backend-build /app/app/core/build/libs/*.jar app.jar + +# Copy frontend files +COPY --from=frontend-build /app/dist /usr/share/nginx/html + +# Copy nginx configuration +COPY docker/unified/nginx.conf /etc/nginx/nginx.conf +COPY docker/unified/entrypoint.sh /entrypoint.sh + +# Environment Variables +ENV DISABLE_ADDITIONAL_FEATURES=false \ + VERSION_TAG=$VERSION_TAG \ + JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ + JAVA_CUSTOM_OPTS="" \ + HOME=/home/stirlingpdfuser \ + PUID=1000 \ + PGID=1000 \ + UMASK=022 \ + PYTHONPATH=/usr/lib/libreoffice/program:/opt/venv/lib/python3.12/site-packages \ + UNO_PATH=/usr/lib/libreoffice/program \ + URE_BOOTSTRAP=file:///usr/lib/libreoffice/program/fundamentalrc \ + PATH=$PATH:/opt/venv/bin \ + STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \ + TMPDIR=/tmp/stirling-pdf \ + TEMP=/tmp/stirling-pdf \ + TMP=/tmp/stirling-pdf \ + MODE=BOTH \ + BACKEND_INTERNAL_PORT=8081 \ + VITE_API_BASE_URL=http://localhost:8080 + +# Install all dependencies +RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \ + echo "@community https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \ + echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \ + apk upgrade --no-cache -a && \ + apk add --no-cache \ + ca-certificates \ + tzdata \ + tini \ + bash \ + curl \ + shadow \ + su-exec \ + openssl \ + openssl-dev \ + openjdk21-jre \ + nginx \ + # Doc conversion + gcompat \ + libc6-compat \ + libreoffice \ + # pdftohtml + poppler-utils \ + # OCR MY PDF + unpaper \ + tesseract-ocr-data-eng \ + tesseract-ocr-data-chi_sim \ + tesseract-ocr-data-deu \ + tesseract-ocr-data-fra \ + tesseract-ocr-data-por \ + ocrmypdf \ + # CV + py3-opencv \ + python3 \ + py3-pip \ + py3-pillow@testing \ + py3-pdf2image@testing && \ + python3 -m venv /opt/venv && \ + /opt/venv/bin/pip install --upgrade pip setuptools && \ + /opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \ + ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \ + ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \ + ln -s /usr/lib/libreoffice/program /opt/venv/lib/python3.12/site-packages/LibreOffice && \ + mv /usr/share/tessdata /usr/share/tessdata-original && \ + mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders /tmp/stirling-pdf /pipeline/watchedFolders /pipeline/finishedFolders && \ + mkdir -p /var/lib/nginx/tmp /var/log/nginx && \ + fc-cache -f -v && \ + chmod +x /scripts/* && \ + chmod +x /entrypoint.sh && \ + # 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 /var/lib/nginx /var/log/nginx /usr/share/nginx && \ + chown stirlingpdfuser:stirlingpdfgroup /app.jar + +EXPOSE 8080/tcp + +ENTRYPOINT ["tini", "--", "/entrypoint.sh"] diff --git a/docker/compose/docker-compose-unified-backend.yml b/docker/compose/docker-compose-unified-backend.yml new file mode 100644 index 0000000000..b8ebfd42b3 --- /dev/null +++ b/docker/compose/docker-compose-unified-backend.yml @@ -0,0 +1,58 @@ +# Example Docker Compose for Unified Stirling-PDF Container +# MODE=BACKEND: Backend API only (no frontend) + +services: + stirling-pdf-backend-only: + container_name: Stirling-PDF-Backend-Only + build: + context: ../.. + dockerfile: docker/Dockerfile.unified + ports: + - "8080:8080" + volumes: + - ./stirling/data:/usr/share/tessdata:rw + - ./stirling/config:/configs:rw + - ./stirling/logs:/logs:rw + - ./stirling/customFiles:/customFiles:rw + - ./stirling/pipeline:/pipeline:rw + environment: + # MODE parameter: BACKEND only + MODE: BACKEND + + # Standard Stirling-PDF configuration + DISABLE_ADDITIONAL_FEATURES: "false" + DOCKER_ENABLE_SECURITY: "false" + PUID: 1000 + PGID: 1000 + UMASK: "022" + + # Application settings + SYSTEM_DEFAULTLOCALE: en-US + UI_APPNAME: Stirling-PDF + SYSTEM_MAXFILESIZE: "100" + METRICS_ENABLED: "true" + + # Optional: Add OCR languages (comma-separated) + # TESSERACT_LANGS: "deu,fra,spa" + + # Optional: Java memory settings + # JAVA_CUSTOM_OPTS: "-Xmx4g" + + restart: unless-stopped + + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + deploy: + resources: + limits: + memory: 4G + reservations: + memory: 2G + +# Access the API at: http://localhost:8080/api +# Swagger UI at: http://localhost:8080/swagger-ui/index.html diff --git a/docker/compose/docker-compose-unified-both.yml b/docker/compose/docker-compose-unified-both.yml new file mode 100644 index 0000000000..92e08e4aae --- /dev/null +++ b/docker/compose/docker-compose-unified-both.yml @@ -0,0 +1,59 @@ +# Example Docker Compose for Unified Stirling-PDF Container +# MODE=BOTH (default): Frontend + Backend in single container on port 8080 + +services: + stirling-pdf-unified: + container_name: Stirling-PDF-Unified-Both + build: + context: ../.. + dockerfile: docker/Dockerfile.unified + ports: + - "8080:8080" + volumes: + - ./stirling/data:/usr/share/tessdata:rw + - ./stirling/config:/configs:rw + - ./stirling/logs:/logs:rw + - ./stirling/customFiles:/customFiles:rw + - ./stirling/pipeline:/pipeline:rw + environment: + # MODE parameter: BOTH (default), FRONTEND, or BACKEND + MODE: BOTH + + # Backend runs internally on this port when MODE=BOTH + BACKEND_INTERNAL_PORT: 8081 + + # Standard Stirling-PDF configuration + DISABLE_ADDITIONAL_FEATURES: "false" + DOCKER_ENABLE_SECURITY: "false" + PUID: 1000 + PGID: 1000 + UMASK: "022" + + # Application settings + SYSTEM_DEFAULTLOCALE: en-US + UI_APPNAME: Stirling-PDF + UI_HOMEDESCRIPTION: Your locally hosted one-stop-shop for all your PDF needs + SYSTEM_MAXFILESIZE: "100" + METRICS_ENABLED: "true" + + # Optional: Add OCR languages (comma-separated) + # TESSERACT_LANGS: "deu,fra,spa" + + # Optional: Java memory settings + # JAVA_CUSTOM_OPTS: "-Xmx4g" + + restart: unless-stopped + + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + deploy: + resources: + limits: + memory: 4G + reservations: + memory: 2G diff --git a/docker/compose/docker-compose-unified-frontend.yml b/docker/compose/docker-compose-unified-frontend.yml new file mode 100644 index 0000000000..c7d217b34c --- /dev/null +++ b/docker/compose/docker-compose-unified-frontend.yml @@ -0,0 +1,63 @@ +# Example Docker Compose for Unified Stirling-PDF Container +# MODE=FRONTEND: Frontend only, connects to separate backend + +services: + stirling-pdf-backend: + container_name: Stirling-PDF-Backend + build: + context: ../.. + dockerfile: docker/Dockerfile.unified + ports: + - "8081:8080" + volumes: + - ./stirling/data:/usr/share/tessdata:rw + - ./stirling/config:/configs:rw + - ./stirling/logs:/logs:rw + - ./stirling/customFiles:/customFiles:rw + - ./stirling/pipeline:/pipeline:rw + environment: + MODE: BACKEND + DISABLE_ADDITIONAL_FEATURES: "false" + DOCKER_ENABLE_SECURITY: "false" + PUID: 1000 + PGID: 1000 + UMASK: "022" + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + deploy: + resources: + limits: + memory: 4G + + stirling-pdf-frontend: + container_name: Stirling-PDF-Frontend + build: + context: ../.. + dockerfile: docker/Dockerfile.unified + ports: + - "8080:8080" + environment: + MODE: FRONTEND + + # Point to the backend service + VITE_API_BASE_URL: http://stirling-pdf-backend:8080 + + # Minimal config needed for frontend + PUID: 1000 + PGID: 1000 + depends_on: + - stirling-pdf-backend + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/ || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + deploy: + resources: + limits: + memory: 512M diff --git a/docker/unified/README.md b/docker/unified/README.md new file mode 100644 index 0000000000..6f0488aa23 --- /dev/null +++ b/docker/unified/README.md @@ -0,0 +1,458 @@ +# Stirling-PDF Unified Container + +Single Docker container that can run as **frontend + backend**, **frontend only**, or **backend only** using the `MODE` environment variable. + +## Quick Start + +### MODE=BOTH (Default) +Single container with both frontend and backend on port 8080: + +```bash +docker run -p 8080:8080 \ + -e MODE=BOTH \ + stirlingtools/stirling-pdf:unified +``` + +Access at: `http://localhost:8080` + +### MODE=FRONTEND +Frontend only, connecting to separate backend: + +```bash +docker run -p 8080:8080 \ + -e MODE=FRONTEND \ + -e VITE_API_BASE_URL=http://backend:8080 \ + stirlingtools/stirling-pdf:unified +``` + +### MODE=BACKEND +Backend API only: + +```bash +docker run -p 8080:8080 \ + -e MODE=BACKEND \ + stirlingtools/stirling-pdf:unified +``` + +Access API at: `http://localhost:8080/api` +Swagger UI at: `http://localhost:8080/swagger-ui/index.html` + +--- + +## Architecture + +### MODE=BOTH (Default) +``` +┌─────────────────────────────────────┐ +│ Port 8080 (External) │ +│ ┌───────────────────────────────┐ │ +│ │ Nginx │ │ +│ │ • Serves frontend (/) │ │ +│ │ • Proxies /api/* → backend │ │ +│ └───────────┬───────────────────┘ │ +│ │ │ +│ ┌───────────▼───────────────────┐ │ +│ │ Backend (Internal 8081) │ │ +│ │ • Spring Boot │ │ +│ │ • PDF Processing │ │ +│ │ • UnoServer │ │ +│ └───────────────────────────────┘ │ +└─────────────────────────────────────┘ +``` + +### MODE=FRONTEND +``` +┌─────────────────────────────┐ ┌──────────────────┐ +│ Frontend Container │ │ Backend │ +│ Port 8080 │ │ (External) │ +│ ┌───────────────────────┐ │ │ │ +│ │ Nginx │ │──────▶ :8080/api │ +│ │ • Serves frontend │ │ │ │ +│ │ • Proxies to backend │ │ │ │ +│ └───────────────────────┘ │ └──────────────────┘ +└─────────────────────────────┘ +``` + +### MODE=BACKEND +``` +┌─────────────────────────────┐ +│ Backend Container │ +│ Port 8080 │ +│ ┌───────────────────────┐ │ +│ │ Spring Boot │ │ +│ │ • API Endpoints │ │ +│ │ • PDF Processing │ │ +│ │ • UnoServer │ │ +│ └───────────────────────┘ │ +└─────────────────────────────┘ +``` + +--- + +## Environment Variables + +### MODE Configuration + +| Variable | Values | Default | Description | +|----------|--------|---------|-------------| +| `MODE` | `BOTH`, `FRONTEND`, `BACKEND` | `BOTH` | Container operation mode | + +### MODE=BOTH Specific + +| Variable | Default | Description | +|----------|---------|-------------| +| `BACKEND_INTERNAL_PORT` | `8081` | Internal port for backend when MODE=BOTH | + +### MODE=FRONTEND Specific + +| Variable | Default | Description | +|----------|---------|-------------| +| `VITE_API_BASE_URL` | `http://backend:8080` | Backend URL for API proxying | + +### Standard Configuration + +All modes support standard Stirling-PDF environment variables: + +- `DISABLE_ADDITIONAL_FEATURES` - Enable/disable OCR and LibreOffice features +- `DOCKER_ENABLE_SECURITY` - Enable authentication +- `PUID` / `PGID` - User/Group IDs +- `SYSTEM_MAXFILESIZE` - Max upload size (MB) +- `TESSERACT_LANGS` - Comma-separated OCR language codes +- `JAVA_CUSTOM_OPTS` - Additional JVM options + +See full configuration docs at: https://docs.stirlingpdf.com + +--- + +## Docker Compose Examples + +### Example 1: All-in-One (MODE=BOTH) + +**File:** `docker/compose/docker-compose-unified-both.yml` + +```yaml +services: + stirling-pdf: + image: stirlingtools/stirling-pdf:unified + ports: + - "8080:8080" + volumes: + - ./data:/usr/share/tessdata:rw + - ./config:/configs:rw + environment: + MODE: BOTH + restart: unless-stopped +``` + +### Example 2: Separate Frontend & Backend + +**File:** `docker/compose/docker-compose-unified-frontend.yml` + +```yaml +services: + backend: + image: stirlingtools/stirling-pdf:unified + ports: + - "8081:8080" + environment: + MODE: BACKEND + volumes: + - ./data:/usr/share/tessdata:rw + - ./config:/configs:rw + + frontend: + image: stirlingtools/stirling-pdf:unified + ports: + - "8080:8080" + environment: + MODE: FRONTEND + VITE_API_BASE_URL: http://backend:8080 + depends_on: + - backend +``` + +### Example 3: Backend API Only + +**File:** `docker/compose/docker-compose-unified-backend.yml` + +```yaml +services: + stirling-pdf-api: + image: stirlingtools/stirling-pdf:unified + ports: + - "8080:8080" + environment: + MODE: BACKEND + volumes: + - ./data:/usr/share/tessdata:rw + - ./config:/configs:rw + restart: unless-stopped +``` + +--- + +## Building the Image + +```bash +# From repository root +docker build -t stirlingtools/stirling-pdf:unified -f docker/Dockerfile.unified . +``` + +### Build Arguments + +| Argument | Description | +|----------|-------------| +| `VERSION_TAG` | Version tag for the image | + +Example: +```bash +docker build \ + --build-arg VERSION_TAG=v1.0.0 \ + -t stirlingtools/stirling-pdf:unified \ + -f docker/Dockerfile.unified . +``` + +--- + +## Use Cases + +### 1. Simple Deployment (MODE=BOTH) +- **Best for:** Personal use, small teams, simple deployments +- **Pros:** Single container, easy setup, minimal configuration +- **Cons:** Frontend and backend scale together + +### 2. Scaled Frontend (MODE=FRONTEND + BACKEND) +- **Best for:** High traffic, need to scale frontend independently +- **Pros:** Scale frontend containers separately, CDN-friendly +- **Example:** + ```yaml + services: + backend: + image: stirlingtools/stirling-pdf:unified + environment: + MODE: BACKEND + deploy: + replicas: 1 + + frontend: + image: stirlingtools/stirling-pdf:unified + environment: + MODE: FRONTEND + VITE_API_BASE_URL: http://backend:8080 + deploy: + replicas: 5 # Scale frontend independently + ``` + +### 3. API-Only (MODE=BACKEND) +- **Best for:** Headless deployments, custom frontends, API integrations +- **Pros:** Minimal resources, no nginx overhead +- **Example:** Use with external frontend or API consumers + +### 4. Multi-Backend Setup +- **Best for:** Load balancing, high availability +- **Example:** + ```yaml + services: + backend-1: + image: stirlingtools/stirling-pdf:unified + environment: + MODE: BACKEND + + backend-2: + image: stirlingtools/stirling-pdf:unified + environment: + MODE: BACKEND + + frontend: + image: stirlingtools/stirling-pdf:unified + environment: + MODE: FRONTEND + VITE_API_BASE_URL: http://load-balancer:8080 + ``` + +--- + +## Port Configuration + +All modes use **port 8080** by default: + +- **MODE=BOTH**: Nginx listens on 8080, proxies to backend on internal 8081 +- **MODE=FRONTEND**: Nginx listens on 8080 +- **MODE=BACKEND**: Spring Boot listens on 8080 + +**Expose port 8080** in all configurations: +```yaml +ports: + - "8080:8080" +``` + +--- + +## Health Checks + +### MODE=BOTH and MODE=BACKEND +```yaml +healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"] + interval: 30s + timeout: 10s + retries: 3 +``` + +### MODE=FRONTEND +```yaml +healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/ || exit 1"] + interval: 30s + timeout: 10s + retries: 3 +``` + +--- + +## Troubleshooting + +### Check logs +```bash +docker logs stirling-pdf-container +``` + +Look for the startup banner: +``` +=================================== +Stirling-PDF Unified Container +MODE: BOTH +=================================== +``` + +### Invalid MODE error +``` +ERROR: Invalid MODE 'XYZ'. Must be BOTH, FRONTEND, or BACKEND +``` +**Fix:** Set `MODE` to one of the three valid values. + +### Frontend can't connect to backend (MODE=FRONTEND) +**Check:** +1. `VITE_API_BASE_URL` points to correct backend URL +2. Backend container is running and accessible +3. Network connectivity between containers + +### Backend not starting (MODE=BOTH or BACKEND) +**Check:** +1. Sufficient memory allocated (4GB recommended) +2. Java heap size (`JAVA_CUSTOM_OPTS`) +3. Volume permissions for `/tmp/stirling-pdf` + +--- + +## Migration Guide + +### From Separate Containers → MODE=BOTH + +**Before:** +```yaml +services: + frontend: + image: stirlingtools/stirling-pdf:frontend + ports: ["80:80"] + + backend: + image: stirlingtools/stirling-pdf:backend + ports: ["8080:8080"] +``` + +**After:** +```yaml +services: + stirling-pdf: + image: stirlingtools/stirling-pdf:unified + ports: ["8080:8080"] + environment: + MODE: BOTH +``` + +### From Legacy → MODE=BACKEND +```yaml +services: + stirling-pdf: + image: stirlingtools/stirling-pdf:latest + ports: ["8080:8080"] +``` + +**Becomes:** +```yaml +services: + stirling-pdf: + image: stirlingtools/stirling-pdf:unified + ports: ["8080:8080"] + environment: + MODE: BACKEND +``` + +--- + +## Performance Tuning + +### MODE=BOTH +```yaml +environment: + JAVA_CUSTOM_OPTS: "-Xmx4g -XX:MaxRAMPercentage=75" + BACKEND_INTERNAL_PORT: 8081 +deploy: + resources: + limits: + memory: 4G + reservations: + memory: 2G +``` + +### MODE=FRONTEND (Lightweight) +```yaml +deploy: + resources: + limits: + memory: 512M + reservations: + memory: 256M +``` + +### MODE=BACKEND (Heavy Processing) +```yaml +environment: + JAVA_CUSTOM_OPTS: "-Xmx8g" +deploy: + resources: + limits: + memory: 10G + reservations: + memory: 4G +``` + +--- + +## Security Considerations + +1. **MODE=BOTH**: Backend not exposed externally (runs on internal port) +2. **MODE=BACKEND**: API exposed directly - consider API authentication +3. **MODE=FRONTEND**: Only serves static files - minimal attack surface + +Enable security features: +```yaml +environment: + DOCKER_ENABLE_SECURITY: "true" + SECURITY_ENABLELOGIN: "true" +``` + +--- + +## Support + +- Documentation: https://docs.stirlingpdf.com +- GitHub Issues: https://github.com/Stirling-Tools/Stirling-PDF/issues +- Docker Hub: https://hub.docker.com/r/stirlingtools/stirling-pdf + +--- + +## License + +MIT License - See repository for full details diff --git a/docker/unified/build.sh b/docker/unified/build.sh new file mode 100644 index 0000000000..5dd59d668e --- /dev/null +++ b/docker/unified/build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Build script for Stirling-PDF Unified Container +# Usage: ./build.sh [version-tag] + +set -e + +VERSION_TAG=${1:-latest} +IMAGE_NAME="stirlingtools/stirling-pdf:unified-${VERSION_TAG}" + +echo "===================================" +echo "Building Stirling-PDF Unified Container" +echo "Version: $VERSION_TAG" +echo "Image: $IMAGE_NAME" +echo "===================================" + +# Navigate to repository root (assuming script is in docker/unified/) +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +REPO_ROOT="$SCRIPT_DIR/../.." + +cd "$REPO_ROOT" + +# Build the image +docker build \ + --build-arg VERSION_TAG="$VERSION_TAG" \ + -t "$IMAGE_NAME" \ + -f docker/Dockerfile.unified \ + . + +echo "===================================" +echo "✓ Build complete!" +echo "Image: $IMAGE_NAME" +echo "" +echo "Test the image:" +echo " MODE=BOTH: docker run -p 8080:8080 -e MODE=BOTH $IMAGE_NAME" +echo " MODE=FRONTEND: docker run -p 8080:8080 -e MODE=FRONTEND $IMAGE_NAME" +echo " MODE=BACKEND: docker run -p 8080:8080 -e MODE=BACKEND $IMAGE_NAME" +echo "===================================" diff --git a/docker/unified/entrypoint.sh b/docker/unified/entrypoint.sh new file mode 100644 index 0000000000..92075ff3a5 --- /dev/null +++ b/docker/unified/entrypoint.sh @@ -0,0 +1,176 @@ +#!/bin/bash + +set -e + +# Default MODE to BOTH if not set +MODE=${MODE:-BOTH} + +echo "===================================" +echo "Stirling-PDF Unified Container" +echo "MODE: $MODE" +echo "===================================" + +# Function to setup OCR (from init.sh) +setup_ocr() { + echo "Setting up OCR languages..." + + # Copy tessdata + mkdir -p /usr/share/tessdata + cp -rn /usr/share/tessdata-original/* /usr/share/tessdata 2>/dev/null || true + + if [ -d /usr/share/tesseract-ocr/4.00/tessdata ]; then + cp -r /usr/share/tesseract-ocr/4.00/tessdata/* /usr/share/tessdata 2>/dev/null || true + fi + + if [ -d /usr/share/tesseract-ocr/5/tessdata ]; then + cp -r /usr/share/tesseract-ocr/5/tessdata/* /usr/share/tessdata 2>/dev/null || true + fi + + # Install additional languages if specified + if [[ -n "$TESSERACT_LANGS" ]]; then + SPACE_SEPARATED_LANGS=$(echo $TESSERACT_LANGS | tr ',' ' ') + pattern='^[a-zA-Z]{2,4}(_[a-zA-Z]{2,4})?$' + for LANG in $SPACE_SEPARATED_LANGS; do + if [[ $LANG =~ $pattern ]]; then + apk add --no-cache "tesseract-ocr-data-$LANG" 2>/dev/null || true + fi + done + fi +} + +# Function to setup user permissions (from init-without-ocr.sh) +setup_permissions() { + echo "Setting up user permissions..." + + export JAVA_TOOL_OPTIONS="${JAVA_BASE_OPTS} ${JAVA_CUSTOM_OPTS}" + + # Update user and group IDs + if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then + usermod -o -u "$PUID" stirlingpdfuser || true + fi + + if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then + groupmod -o -g "$PGID" stirlingpdfgroup || true + fi + + umask "$UMASK" || true + + # Install fonts if needed + if [[ -n "$LANGS" ]]; then + /scripts/installFonts.sh $LANGS + fi + + # Ensure directories exist with correct permissions + mkdir -p /tmp/stirling-pdf || true + + # Set ownership and permissions + chown -R stirlingpdfuser:stirlingpdfgroup \ + $HOME /logs /scripts /usr/share/fonts/opentype/noto \ + /configs /customFiles /pipeline /tmp/stirling-pdf \ + /var/lib/nginx /var/log/nginx /usr/share/nginx \ + /app.jar 2>/dev/null || echo "[WARN] Some chown operations failed, may run as host user" + + chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto \ + /configs /customFiles /pipeline /tmp/stirling-pdf 2>/dev/null || true +} + +# Function to configure nginx +configure_nginx() { + local backend_url=$1 + echo "Configuring nginx with backend URL: $backend_url" + sed -i "s|\${BACKEND_URL}|${backend_url}|g" /etc/nginx/nginx.conf +} + +# Function to run as user or root depending on permissions +run_as_user() { + if [ "$(id -u)" = "0" ]; then + # Running as root, use su-exec + su-exec stirlingpdfuser "$@" + else + # Already running as non-root + exec "$@" + fi +} + +# Setup OCR and permissions +setup_ocr +setup_permissions + +# Handle different modes +case "$MODE" in + BOTH) + echo "Starting in BOTH mode: Frontend + Backend on port 8080" + + # Configure nginx to proxy to internal backend + configure_nginx "http://localhost:${BACKEND_INTERNAL_PORT:-8081}" + + # Start backend on internal port + echo "Starting backend on port ${BACKEND_INTERNAL_PORT:-8081}..." + run_as_user sh -c "java -Dfile.encoding=UTF-8 \ + -Djava.io.tmpdir=/tmp/stirling-pdf \ + -Dserver.port=${BACKEND_INTERNAL_PORT:-8081} \ + -jar /app.jar" & + BACKEND_PID=$! + + # Start unoserver for document conversion + run_as_user /opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1 & + UNO_PID=$! + + # Wait for backend to start + sleep 3 + + # Start nginx on port 8080 + echo "Starting nginx on port 8080..." + run_as_user nginx -g "daemon off;" & + NGINX_PID=$! + + echo "===================================" + echo "✓ Frontend available at: http://localhost:8080" + echo "✓ Backend API at: http://localhost:8080/api" + echo "✓ Backend running internally on port ${BACKEND_INTERNAL_PORT:-8081}" + echo "===================================" + ;; + + FRONTEND) + echo "Starting in FRONTEND mode: Frontend only on port 8080" + + # Configure nginx with external backend URL + BACKEND_URL=${VITE_API_BASE_URL:-http://backend:8080} + configure_nginx "$BACKEND_URL" + + # Start nginx on port 8080 + echo "Starting nginx on port 8080..." + run_as_user nginx -g "daemon off;" & + NGINX_PID=$! + + echo "===================================" + echo "✓ Frontend available at: http://localhost:8080" + echo "✓ Proxying API calls to: $BACKEND_URL" + echo "===================================" + ;; + + BACKEND) + echo "Starting in BACKEND mode: Backend only on port 8080" + + # Start backend on port 8080 + echo "Starting backend on port 8080..." + run_as_user sh -c "java -Dfile.encoding=UTF-8 \ + -Djava.io.tmpdir=/tmp/stirling-pdf \ + -Dserver.port=8080 \ + -jar /app.jar & /opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1" & + BACKEND_PID=$! + + echo "===================================" + echo "✓ Backend API available at: http://localhost:8080/api" + echo "✓ Swagger UI at: http://localhost:8080/swagger-ui/index.html" + echo "===================================" + ;; + + *) + echo "ERROR: Invalid MODE '$MODE'. Must be BOTH, FRONTEND, or BACKEND" + exit 1 + ;; +esac + +# Wait for all background processes +wait diff --git a/docker/unified/nginx.conf b/docker/unified/nginx.conf new file mode 100644 index 0000000000..77ee17f89c --- /dev/null +++ b/docker/unified/nginx.conf @@ -0,0 +1,118 @@ +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Add .mjs MIME type mapping + types { + text/javascript mjs; + } + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; + + server { + listen 8080; + server_name _; + root /usr/share/nginx/html; + index index.html index.htm; + + # Global settings for file uploads + client_max_body_size 100m; + + # Handle client-side routing - support subpaths + location / { + try_files $uri $uri/ /index.html; + } + + # Proxy API calls to backend + location /api/ { + proxy_pass ${BACKEND_URL}/api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # Additional headers for proper API proxying + proxy_set_header Connection ''; + proxy_http_version 1.1; + proxy_buffering off; + proxy_cache off; + + # Timeout settings for large file uploads + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Request size limits for file uploads + client_max_body_size 100m; + proxy_request_buffering off; + } + + # Proxy Swagger UI to backend (including versioned paths) + location ~ ^/swagger-ui(.*)$ { + proxy_pass ${BACKEND_URL}/swagger-ui$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + proxy_set_header Connection ''; + proxy_http_version 1.1; + proxy_buffering off; + proxy_cache off; + } + + # Proxy API docs to backend (with query parameters and sub-paths) + location ~ ^/v3/api-docs(.*)$ { + proxy_pass ${BACKEND_URL}/v3/api-docs$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + } + + # Proxy v1 API docs to backend (with query parameters and sub-paths) + location ~ ^/v1/api-docs(.*)$ { + proxy_pass ${BACKEND_URL}/v1/api-docs$1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + } + + # Serve .mjs files with correct MIME type (must come before general static assets) + location ~* \.mjs$ { + try_files $uri =404; + add_header Content-Type "text/javascript; charset=utf-8" always; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + } +} 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 7dd9e15cd5..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" } }, @@ -436,7 +437,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -483,7 +483,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -507,7 +506,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.3.14.tgz", "integrity": "sha512-lE/vfhA53CxamaCfGWEibrEPr+JeZT42QCF+cOELUwv4+Zt6b+IE6+4wsznx/8wjjJYwllXJ3GJ/un1UzTqARw==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/engines": "1.3.14", "@embedpdf/models": "1.3.14" @@ -588,7 +586,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-history/-/plugin-history-1.3.14.tgz", "integrity": "sha512-77hnNLp0W0FHw8lT7SeqzCgp8bOClfeOAPZdcInu/jPDhVASUGYbtE/0fkLhiaqPH7kyMirNCLif4sF6n4b5vg==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -605,7 +602,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-interaction-manager/-/plugin-interaction-manager-1.3.14.tgz", "integrity": "sha512-nR0ZxNoTQtGqOHhweFh6QJ+nUJ4S4Ag1wWur6vAUAi8U95HUOfZhOEa0polZo0zR9WmmblGqRWjFM+mVSOoi1w==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -622,7 +618,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-loader/-/plugin-loader-1.3.14.tgz", "integrity": "sha512-KoJX1MacEWE2DrO1OeZeG/Ehz76//u+ida/xb4r9BfwqAp5TfYlksq09cOvcF8LMW5FY4pbAL+AHKI1Hjz+HNA==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -657,7 +652,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-render/-/plugin-render-1.3.14.tgz", "integrity": "sha512-IPj7GCQXJBsY++JaU+z7y+FwX5NaDBj4YYV6hsHNtSGf42Y1AdlwJzDYetivG2bA84xmk7KgD1X2Y3eIFBhjwA==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -690,7 +684,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-scroll/-/plugin-scroll-1.3.14.tgz", "integrity": "sha512-fQbt7OlRMLQJMuZj/Bzh0qpRxMw1ld5Qe/OTw8N54b/plljnFA52joE7cITl3H03huWWyHS3NKOScbw7f34dog==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -725,7 +718,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-selection/-/plugin-selection-1.3.14.tgz", "integrity": "sha512-EXENuaAsse3rT6cjA1nYzyrNvoy62ojJl28wblCng6zcs3HSlGPemIQZAvaYKPUxoY608M+6nKlcMQ5neRnk/A==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -797,7 +789,6 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-viewport/-/plugin-viewport-1.3.14.tgz", "integrity": "sha512-mfJ7EbbU68eKk6oFvQ4ozGJNpxUxWbjQ5Gm3uuB+Gj5/tWgBocBOX36k/9LgivEEeX7g2S0tOgyErljApmH8Vg==", "license": "MIT", - "peer": true, "dependencies": { "@embedpdf/models": "1.3.14" }, @@ -951,7 +942,6 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -995,7 +985,6 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -2029,7 +2018,6 @@ "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.1.tgz", "integrity": "sha512-OYfxn9cTv+K6RZ8+Ozn/HDQXkB8Fmn+KJJt5lxyFDP9F09EHnC59Ldadv1LyUZVBGtNqz4sn6b3vBShbxwAmYw==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/react": "^0.27.16", "clsx": "^2.1.1", @@ -2080,7 +2068,6 @@ "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.1.tgz", "integrity": "sha512-lQutBS+Q0iz/cNFvdrsYassPWo3RtWcmDGJeOtKfHigLzFOhxUuLOkQgepDbMf3WcVMB/tist6Px1PQOv57JTw==", "license": "MIT", - "peer": true, "peerDependencies": { "react": "^18.x || ^19.x" } @@ -2148,7 +2135,6 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.2.tgz", "integrity": "sha512-qXvbnawQhqUVfH1LMgMaiytP+ZpGoYhnGl7yYq2x57GYzcFL/iPzSZ3L30tlbwEjSVKNYcbiKO8tANR1tadjUg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.28.3", "@mui/core-downloads-tracker": "^7.3.2", @@ -3591,7 +3577,6 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3915,7 +3900,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -3926,7 +3910,6 @@ "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -3987,7 +3970,6 @@ "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/types": "8.44.1", @@ -4701,6 +4683,7 @@ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", "license": "MIT", + "peer": true, "dependencies": { "@vue/shared": "3.5.21" } @@ -4710,6 +4693,7 @@ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", "license": "MIT", + "peer": true, "dependencies": { "@vue/reactivity": "3.5.21", "@vue/shared": "3.5.21" @@ -4720,6 +4704,7 @@ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", "license": "MIT", + "peer": true, "dependencies": { "@vue/reactivity": "3.5.21", "@vue/runtime-core": "3.5.21", @@ -4732,6 +4717,7 @@ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-ssr": "3.5.21", "@vue/shared": "3.5.21" @@ -4759,7 +4745,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5434,7 +5419,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001741", @@ -6438,8 +6422,7 @@ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1508733.tgz", "integrity": "sha512-QJ1R5gtck6nDcdM+nlsaJXcelPEI7ZxSMw1ujHpO1c4+9l+Nue5qlebi9xO1Z2MGr92bFOQTW7/rrheh5hHxDg==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/dezalgo": { "version": "1.0.4", @@ -6834,7 +6817,6 @@ "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7006,7 +6988,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -7997,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", @@ -8280,7 +8268,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.6" }, @@ -9077,7 +9064,6 @@ "integrity": "sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/dom-selector": "^6.5.4", "cssstyle": "^5.3.0", @@ -10866,7 +10852,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -11158,7 +11143,6 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz", "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -11531,7 +11515,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -11541,7 +11524,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -13179,7 +13161,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13325,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", @@ -13462,7 +13464,6 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13545,7 +13546,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -13765,7 +13765,6 @@ "integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -13858,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", @@ -13897,7 +13916,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13911,7 +13929,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", diff --git a/frontend/package.json b/frontend/package.json index c49b2297b2..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", - "build": "npm run typecheck && vite build", + "lint": "eslint --max-warnings=0", + "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 f5908b086a..7ca6ab9c87 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -250,6 +250,7 @@ "title": "Do you want make Stirling PDF better?", "paragraph1": "Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.", "paragraph2": "Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.", + "learnMore": "Learn more", "enable": "Enable analytics", "disable": "Disable analytics", "settings": "You can change the settings for analytics in the config/settings.yml file" @@ -3374,6 +3375,10 @@ "title": "Analytics", "description": "These cookies help us understand how our tools are being used, so we can focus on building the features our community values most. Rest assured—Stirling PDF cannot and will never track the content of the documents you work with." } + }, + "services": { + "posthog": "PostHog Analytics", + "scarf": "Scarf Pixel" } }, "removeMetadata": { @@ -4196,6 +4201,10 @@ "preview": "Preview" }, "config": { + "overview": { + "title": "Application Configuration", + "description": "Current application settings and configuration details." + }, "account": { "overview": { "title": "Account Settings", @@ -4504,7 +4513,7 @@ "inviteMode": { "username": "Username", "email": "Email", - "emailDisabled": "SMTP not configured" + "emailDisabled": "Email invites require SMTP configuration and mail.enableInvites=true in settings" } }, "teams": { 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 b42d14c9ae..0000000000 --- a/frontend/src/App.tsx +++ /dev/null @@ -1,119 +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 { OnboardingProvider } from "./contexts/OnboardingContext"; -import { TourOrchestrationProvider } from "./contexts/TourOrchestrationContext"; -import ErrorBoundary from "./components/shared/ErrorBoundary"; -import OnboardingTour from "./components/onboarding/OnboardingTour"; - -// 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 InviteAccept from "./routes/InviteAccept"; - -// Import global styles -import "./styles/tailwind.css"; -import "./index.css"; - -// Load cookieconsent.css optionally - won't block UI if ad blocker blocks it -const loadOptionalCSS = () => { - const link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = '/src/styles/cookieconsent.css'; - link.onerror = () => { - console.debug('Cookie consent styles blocked by ad blocker - continuing without them'); - }; - document.head.appendChild(link); -}; -// Load it once when app initializes -if (typeof document !== 'undefined') { - loadOptionalCSS(); -} -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... -
-); - -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 94% rename from frontend/src/components/fileEditor/FileEditor.tsx rename to frontend/src/core/components/fileEditor/FileEditor.tsx index 54901902c8..fbafa8b896 100644 --- a/frontend/src/components/fileEditor/FileEditor.tsx +++ b/frontend/src/core/components/fileEditor/FileEditor.tsx @@ -1,19 +1,19 @@ -import React, { useState, useCallback, useRef, useMemo, useEffect } from 'react'; +import { useState, useCallback, useRef, useMemo, useEffect } from 'react'; 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 93% rename from frontend/src/components/layout/Workbench.tsx rename to frontend/src/core/components/layout/Workbench.tsx index 0ad8a4137b..d27819a2b9 100644 --- a/frontend/src/components/layout/Workbench.tsx +++ b/frontend/src/core/components/layout/Workbench.tsx @@ -1,13 +1,13 @@ import React from 'react'; 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 '../../hooks/useAppConfig'; +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 './Workbench.css'; import TopControls from '../shared/TopControls'; 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/core/components/shared/AdminAnalyticsChoiceModal.tsx b/frontend/src/core/components/shared/AdminAnalyticsChoiceModal.tsx new file mode 100644 index 0000000000..7a8974a3aa --- /dev/null +++ b/frontend/src/core/components/shared/AdminAnalyticsChoiceModal.tsx @@ -0,0 +1,112 @@ +import { Modal, Stack, Button, Text, Title, Anchor } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import { useState } from 'react'; +import { Z_ANALYTICS_MODAL } from '@app/styles/zIndex'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import apiClient from '@app/services/apiClient'; + +interface AdminAnalyticsChoiceModalProps { + opened: boolean; + onClose: () => void; +} + +export default function AdminAnalyticsChoiceModal({ opened, onClose }: AdminAnalyticsChoiceModalProps) { + const { t } = useTranslation(); + const { refetch } = useAppConfig(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const handleChoice = async (enableAnalytics: boolean) => { + setLoading(true); + setError(null); + + try { + const formData = new FormData(); + formData.append('enabled', enableAnalytics.toString()); + + await apiClient.post('/api/v1/settings/update-enable-analytics', formData); + + // Refetch config to apply new settings without page reload + await refetch(); + + // Close the modal after successful save + onClose(); + } catch (err) { + setError(err instanceof Error ? err.message : 'Unknown error occurred'); + setLoading(false); + } + }; + + const handleEnable = () => { + handleChoice(true); + }; + + const handleDisable = () => { + handleChoice(false); + }; + + return ( + {}} // Prevent closing + closeOnClickOutside={false} + closeOnEscape={false} + withCloseButton={false} + size="lg" + centered + zIndex={Z_ANALYTICS_MODAL} + > + + {t('analytics.title', 'Do you want make Stirling PDF better?')} + + + {t('analytics.paragraph1', 'Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.')} + + + + {t('analytics.paragraph2', 'Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.')}{' '} + + {t('analytics.learnMore', 'Learn more')} + + + + {error && ( + + {error} + + )} + + + + + + + + + {t('analytics.settings', 'You can change the settings for analytics in the config/settings.yml file')} + + + + ); +} 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/AppConfigLoader.tsx b/frontend/src/core/components/shared/AppConfigLoader.tsx similarity index 84% rename from frontend/src/components/shared/AppConfigLoader.tsx rename to frontend/src/core/components/shared/AppConfigLoader.tsx index a710823e9a..45cd7ad1bb 100644 --- a/frontend/src/components/shared/AppConfigLoader.tsx +++ b/frontend/src/core/components/shared/AppConfigLoader.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; -import { useAppConfig } from '../../hooks/useAppConfig'; -import { updateSupportedLanguages } from '../../i18n'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import { updateSupportedLanguages } from '@app/i18n'; /** * Component that loads app configuration and applies it to the application. 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 91% rename from frontend/src/components/shared/AppConfigModal.tsx rename to frontend/src/core/components/shared/AppConfigModal.tsx index 4253ac46eb..09bcd20fe5 100644 --- a/frontend/src/components/shared/AppConfigModal.tsx +++ b/frontend/src/core/components/shared/AppConfigModal.tsx @@ -1,13 +1,13 @@ 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 { useAppConfig } from '../../hooks/useAppConfig'; -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 { useAppConfig } from '@app/contexts/AppConfigContext'; +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 87% rename from frontend/src/components/shared/DismissAllErrorsButton.tsx rename to frontend/src/core/components/shared/DismissAllErrorsButton.tsx index 853e341aa0..43333aff18 100644 --- a/frontend/src/components/shared/DismissAllErrorsButton.tsx +++ b/frontend/src/core/components/shared/DismissAllErrorsButton.tsx @@ -1,10 +1,10 @@ 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'; -import { Z_INDEX_TOAST } from '../../styles/zIndex'; +import { Z_INDEX_TOAST } from '@app/styles/zIndex'; interface DismissAllErrorsButtonProps { className?: string; 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/FirstLoginModal.tsx b/frontend/src/core/components/shared/FirstLoginModal.tsx similarity index 83% rename from frontend/src/components/shared/FirstLoginModal.tsx rename to frontend/src/core/components/shared/FirstLoginModal.tsx index 935fa4ac1a..fa3e42bae6 100644 --- a/frontend/src/components/shared/FirstLoginModal.tsx +++ b/frontend/src/core/components/shared/FirstLoginModal.tsx @@ -1,15 +1,14 @@ import { useState } from 'react'; import { Modal, Stack, Text, PasswordInput, Button, Alert } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; -import LocalIcon from './LocalIcon'; -import { accountService } from '../../services/accountService'; -import { alert } from '../toast'; -import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '../../styles/zIndex'; -import { useAuth } from '../../auth/UseSession'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { accountService } from '@app/services/accountService'; +import { alert } from '@app/components/toast'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; interface FirstLoginModalProps { opened: boolean; + onPasswordChanged: () => void; username: string; } @@ -19,10 +18,8 @@ interface FirstLoginModalProps { * Forces first-time users to change their password. * Cannot be dismissed until password is successfully changed. */ -export default function FirstLoginModal({ opened, username }: FirstLoginModalProps) { +export default function FirstLoginModal({ opened, onPasswordChanged, username }: FirstLoginModalProps) { const { t } = useTranslation(); - const navigate = useNavigate(); - const { signOut } = useAuth(); const [currentPassword, setCurrentPassword] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); @@ -41,6 +38,11 @@ export default function FirstLoginModal({ opened, username }: FirstLoginModalPro return; } + if (newPassword.length < 8) { + setError(t('firstLogin.passwordTooShort', 'Password must be at least 8 characters')); + return; + } + if (newPassword === currentPassword) { setError(t('firstLogin.passwordMustBeDifferent', 'New password must be different from current password')); return; @@ -50,8 +52,7 @@ export default function FirstLoginModal({ opened, username }: FirstLoginModalPro setLoading(true); setError(''); - // Use changePasswordOnLogin to clear the first-use flag - await accountService.changePasswordOnLogin(currentPassword, newPassword); + await accountService.changePassword(currentPassword, newPassword); alert({ alertType: 'success', @@ -63,9 +64,11 @@ export default function FirstLoginModal({ opened, username }: FirstLoginModalPro setNewPassword(''); setConfirmPassword(''); - // Backend has logged us out, so clear frontend auth state and redirect to login - await signOut(); - navigate('/login?messageType=passwordChanged'); + // Wait a moment for the user to see the success message + // Then the backend will have logged them out, and onPasswordChanged will handle redirect + setTimeout(() => { + onPasswordChanged(); + }, 1500); } catch (err: any) { console.error('Failed to change password:', err); setError( @@ -127,7 +130,7 @@ export default function FirstLoginModal({ opened, username }: FirstLoginModalPro setNewPassword(e.currentTarget.value)} required 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 98% rename from frontend/src/components/shared/Footer.tsx rename to frontend/src/core/components/shared/Footer.tsx index a82ed430d1..52ee4165b6 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 cbed210a2c..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 '../../hooks/useAppConfig'; -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 91% rename from frontend/src/components/shared/TextInput.tsx rename to frontend/src/core/components/shared/TextInput.tsx index 63c69bb08f..0203e83c07 100644 --- a/frontend/src/components/shared/TextInput.tsx +++ b/frontend/src/core/components/shared/TextInput.tsx @@ -1,12 +1,16 @@ 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 */ export interface TextInputProps { + /** The input ID (required) */ + id: string; + /** The input name (required) */ + name: string; /** The input value (required) */ value: string; /** Callback when input value changes (required) */ @@ -36,6 +40,8 @@ export interface TextInputProps { } export const TextInput = forwardRef(({ + id, + name, value, onChange, placeholder, @@ -76,6 +82,8 @@ export const TextInput = forwardRef(({ onChange(e.currentTarget.value)} 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/PendingBadge.tsx b/frontend/src/core/components/shared/config/PendingBadge.tsx similarity index 100% rename from frontend/src/components/shared/config/PendingBadge.tsx rename to frontend/src/core/components/shared/config/PendingBadge.tsx diff --git a/frontend/src/components/shared/config/RestartConfirmationModal.tsx b/frontend/src/core/components/shared/config/RestartConfirmationModal.tsx similarity index 96% rename from frontend/src/components/shared/config/RestartConfirmationModal.tsx rename to frontend/src/core/components/shared/config/RestartConfirmationModal.tsx index d52535aef6..b97b17a0c6 100644 --- a/frontend/src/components/shared/config/RestartConfirmationModal.tsx +++ b/frontend/src/core/components/shared/config/RestartConfirmationModal.tsx @@ -2,7 +2,7 @@ import { Modal, Text, Group, Button, Stack } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import RefreshIcon from '@mui/icons-material/Refresh'; import ScheduleIcon from '@mui/icons-material/Schedule'; -import { Z_INDEX_OVER_CONFIG_MODAL } from '../../../styles/zIndex'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; interface RestartConfirmationModalProps { opened: boolean; diff --git a/frontend/src/components/shared/config/configNavSections.tsx b/frontend/src/core/components/shared/config/configNavSections.tsx similarity index 70% rename from frontend/src/components/shared/config/configNavSections.tsx rename to frontend/src/core/components/shared/config/configNavSections.tsx index ac539368bc..cb967378b0 100644 --- a/frontend/src/components/shared/config/configNavSections.tsx +++ b/frontend/src/core/components/shared/config/configNavSections.tsx @@ -1,19 +1,19 @@ import React from 'react'; -import { NavKey } from './types'; -import HotkeysSection from './configSections/HotkeysSection'; -import GeneralSection from './configSections/GeneralSection'; -import PeopleSection from './configSections/PeopleSection'; -import TeamsSection from './configSections/TeamsSection'; -import AdminGeneralSection from './configSections/AdminGeneralSection'; -import AdminSecuritySection from './configSections/AdminSecuritySection'; -import AdminConnectionsSection from './configSections/AdminConnectionsSection'; -import AdminPrivacySection from './configSections/AdminPrivacySection'; -import AdminDatabaseSection from './configSections/AdminDatabaseSection'; -import AdminAdvancedSection from './configSections/AdminAdvancedSection'; -import AdminLegalSection from './configSections/AdminLegalSection'; -import AdminPremiumSection from './configSections/AdminPremiumSection'; -import AdminFeaturesSection from './configSections/AdminFeaturesSection'; -import AdminEndpointsSection from './configSections/AdminEndpointsSection'; +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'; +import PeopleSection from '@app/components/shared/config/configSections/PeopleSection'; +import TeamsSection from '@app/components/shared/config/configSections/TeamsSection'; +import AdminGeneralSection from '@app/components/shared/config/configSections/AdminGeneralSection'; +import AdminSecuritySection from '@app/components/shared/config/configSections/AdminSecuritySection'; +import AdminConnectionsSection from '@app/components/shared/config/configSections/AdminConnectionsSection'; +import AdminPrivacySection from '@app/components/shared/config/configSections/AdminPrivacySection'; +import AdminDatabaseSection from '@app/components/shared/config/configSections/AdminDatabaseSection'; +import AdminAdvancedSection from '@app/components/shared/config/configSections/AdminAdvancedSection'; +import AdminLegalSection from '@app/components/shared/config/configSections/AdminLegalSection'; +import AdminPremiumSection from '@app/components/shared/config/configSections/AdminPremiumSection'; +import AdminFeaturesSection from '@app/components/shared/config/configSections/AdminFeaturesSection'; +import AdminEndpointsSection from '@app/components/shared/config/configSections/AdminEndpointsSection'; export interface ConfigNavItem { key: NavKey; diff --git a/frontend/src/components/shared/config/configSections/AdminAdvancedSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminAdvancedSection.tsx similarity index 98% rename from frontend/src/components/shared/config/configSections/AdminAdvancedSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminAdvancedSection.tsx index 45963582e4..b979a22b1c 100644 --- a/frontend/src/components/shared/config/configSections/AdminAdvancedSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminAdvancedSection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { NumberInput, Switch, Button, Stack, Paper, Text, Loader, Group, Accordion, TextInput } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface AdvancedSettingsData { enableAlphaFunctionality?: boolean; diff --git a/frontend/src/components/shared/config/configSections/AdminConnectionsSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminConnectionsSection.tsx similarity index 95% rename from frontend/src/components/shared/config/configSections/AdminConnectionsSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminConnectionsSection.tsx index f2aed551d9..663295b386 100644 --- a/frontend/src/components/shared/config/configSections/AdminConnectionsSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminConnectionsSection.tsx @@ -1,17 +1,17 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Stack, Text, Loader, Group, Divider, Paper, Switch, Badge } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import ProviderCard from './ProviderCard'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import ProviderCard from '@app/components/shared/config/configSections/ProviderCard'; import { ALL_PROVIDERS, Provider, -} from './providerDefinitions'; -import apiClient from '../../../../services/apiClient'; +} from '@app/components/shared/config/configSections/providerDefinitions'; +import apiClient from '@app/services/apiClient'; interface ConnectionsSettingsData { oauth2?: { diff --git a/frontend/src/components/shared/config/configSections/AdminDatabaseSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminDatabaseSection.tsx similarity index 96% rename from frontend/src/components/shared/config/configSections/AdminDatabaseSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminDatabaseSection.tsx index a8f742fe23..647364f190 100644 --- a/frontend/src/components/shared/config/configSections/AdminDatabaseSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminDatabaseSection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { NumberInput, Switch, Button, Stack, Paper, Text, Loader, Group, TextInput, PasswordInput, Select, Badge } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface DatabaseSettingsData { enableCustomDatabase?: boolean; diff --git a/frontend/src/components/shared/config/configSections/AdminEndpointsSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminEndpointsSection.tsx similarity index 93% rename from frontend/src/components/shared/config/configSections/AdminEndpointsSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminEndpointsSection.tsx index b29b97fcee..bf04d89b35 100644 --- a/frontend/src/components/shared/config/configSections/AdminEndpointsSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminEndpointsSection.tsx @@ -1,11 +1,11 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Stack, Paper, Text, Loader, Group, MultiSelect } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; interface EndpointsSettingsData { toRemove?: string[]; diff --git a/frontend/src/components/shared/config/configSections/AdminFeaturesSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminFeaturesSection.tsx similarity index 94% rename from frontend/src/components/shared/config/configSections/AdminFeaturesSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminFeaturesSection.tsx index 7f61705294..cb90e502b4 100644 --- a/frontend/src/components/shared/config/configSections/AdminFeaturesSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminFeaturesSection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { TextInput, NumberInput, Switch, Button, Stack, Paper, Text, Loader, Group, Badge } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface FeaturesSettingsData { serverCertificate?: { diff --git a/frontend/src/components/shared/config/configSections/AdminGeneralSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminGeneralSection.tsx similarity index 98% rename from frontend/src/components/shared/config/configSections/AdminGeneralSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminGeneralSection.tsx index 4cf0f938f6..c17c88f6a8 100644 --- a/frontend/src/components/shared/config/configSections/AdminGeneralSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminGeneralSection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { TextInput, Switch, Button, Stack, Paper, Text, Loader, Group, MultiSelect, Badge } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface GeneralSettingsData { ui: { diff --git a/frontend/src/components/shared/config/configSections/AdminLegalSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminLegalSection.tsx similarity index 94% rename from frontend/src/components/shared/config/configSections/AdminLegalSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminLegalSection.tsx index ef19c44ccc..9ed833e9c3 100644 --- a/frontend/src/components/shared/config/configSections/AdminLegalSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminLegalSection.tsx @@ -2,11 +2,11 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { TextInput, Button, Stack, Paper, Text, Loader, Group, Alert } from '@mantine/core'; import WarningIcon from '@mui/icons-material/Warning'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; interface LegalSettingsData { termsAndConditions?: string; diff --git a/frontend/src/components/shared/config/configSections/AdminMailSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminMailSection.tsx similarity index 94% rename from frontend/src/components/shared/config/configSections/AdminMailSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminMailSection.tsx index 860f13bb69..fbbfeebbf6 100644 --- a/frontend/src/components/shared/config/configSections/AdminMailSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminMailSection.tsx @@ -1,11 +1,11 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { TextInput, NumberInput, Switch, Button, Stack, Paper, Text, Loader, Group, PasswordInput } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; interface MailSettingsData { enabled?: boolean; diff --git a/frontend/src/components/shared/config/configSections/AdminPremiumSection.tsx b/frontend/src/core/components/shared/config/configSections/AdminPremiumSection.tsx similarity index 91% rename from frontend/src/components/shared/config/configSections/AdminPremiumSection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminPremiumSection.tsx index 69a77a8f34..42f45cb641 100644 --- a/frontend/src/components/shared/config/configSections/AdminPremiumSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminPremiumSection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { TextInput, Switch, Button, Stack, Paper, Text, Loader, Group, Alert } from '@mantine/core'; -import { alert } from '../../../toast'; -import LocalIcon from '../../LocalIcon'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; +import { alert } from '@app/components/toast'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; interface PremiumSettingsData { key?: string; diff --git a/frontend/src/components/shared/config/configSections/AdminPrivacySection.tsx b/frontend/src/core/components/shared/config/configSections/AdminPrivacySection.tsx similarity index 93% rename from frontend/src/components/shared/config/configSections/AdminPrivacySection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminPrivacySection.tsx index fccc126052..efe1a46f17 100644 --- a/frontend/src/components/shared/config/configSections/AdminPrivacySection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminPrivacySection.tsx @@ -1,12 +1,12 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Switch, Button, Stack, Paper, Text, Loader, Group } from '@mantine/core'; -import { alert } from '../../../toast'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface PrivacySettingsData { enableAnalytics?: boolean; diff --git a/frontend/src/components/shared/config/configSections/AdminSecuritySection.tsx b/frontend/src/core/components/shared/config/configSections/AdminSecuritySection.tsx similarity index 98% rename from frontend/src/components/shared/config/configSections/AdminSecuritySection.tsx rename to frontend/src/core/components/shared/config/configSections/AdminSecuritySection.tsx index 6c489cd0f7..9d51ecc999 100644 --- a/frontend/src/components/shared/config/configSections/AdminSecuritySection.tsx +++ b/frontend/src/core/components/shared/config/configSections/AdminSecuritySection.tsx @@ -1,13 +1,13 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { NumberInput, Switch, Button, Stack, Paper, Text, Loader, Group, Select, Alert, Badge, Accordion, Textarea } from '@mantine/core'; -import { alert } from '../../../toast'; -import LocalIcon from '../../LocalIcon'; -import RestartConfirmationModal from '../RestartConfirmationModal'; -import { useRestartServer } from '../useRestartServer'; -import { useAdminSettings } from '../../../../hooks/useAdminSettings'; -import PendingBadge from '../PendingBadge'; -import apiClient from '../../../../services/apiClient'; +import { alert } from '@app/components/toast'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; +import { useRestartServer } from '@app/components/shared/config/useRestartServer'; +import { useAdminSettings } from '@app/hooks/useAdminSettings'; +import PendingBadge from '@app/components/shared/config/PendingBadge'; +import apiClient from '@app/services/apiClient'; interface SecuritySettingsData { enableLogin?: boolean; 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 66% rename from frontend/src/components/shared/config/configSections/Overview.tsx rename to frontend/src/core/components/shared/config/configSections/Overview.tsx index 762fb6eaae..4e552cec08 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 '../../../../hooks/useAppConfig'; -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; @@ -57,15 +54,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 ( @@ -85,26 +73,7 @@ const Overview: React.FC = () => { return ( -
-
-
- Application Configuration - - Current application settings and configuration details. - - {user?.email && ( - - Signed in as: {user.email} - - )} -
- {user && ( - - )} -
-
+ {config && ( <> @@ -124,4 +93,4 @@ const Overview: React.FC = () => { ); }; -export default Overview; \ No newline at end of file +export default Overview; diff --git a/frontend/src/components/shared/config/configSections/PeopleSection.tsx b/frontend/src/core/components/shared/config/configSections/PeopleSection.tsx similarity index 67% rename from frontend/src/components/shared/config/configSections/PeopleSection.tsx rename to frontend/src/core/components/shared/config/configSections/PeopleSection.tsx index 022bfea45a..3eb90db6ed 100644 --- a/frontend/src/components/shared/config/configSections/PeopleSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/PeopleSection.tsx @@ -14,18 +14,18 @@ import { Modal, Select, Paper, - Switch, + Checkbox, Textarea, SegmentedControl, Tooltip, CloseButton, } from '@mantine/core'; -import LocalIcon from '../../LocalIcon'; -import { alert } from '../../../toast'; -import { userManagementService, User } from '../../../../services/userManagementService'; -import { teamService, Team } from '../../../../services/teamService'; -import { Z_INDEX_OVER_CONFIG_MODAL } from '../../../../styles/zIndex'; -import { useAppConfig } from '../../../../hooks/useAppConfig'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert } from '@app/components/toast'; +import { userManagementService, User } from '@app/services/userManagementService'; +import { teamService, Team } from '@app/services/teamService'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; export default function PeopleSection() { const { t } = useTranslation(); @@ -38,7 +38,7 @@ export default function PeopleSection() { const [editUserModalOpened, setEditUserModalOpened] = useState(false); const [selectedUser, setSelectedUser] = useState(null); const [processing, setProcessing] = useState(false); - const [inviteMode, setInviteMode] = useState<'email' | 'direct' | 'link'>('direct'); + const [inviteMode, setInviteMode] = useState<'email' | 'direct'>('direct'); // Form state for direct invite const [inviteForm, setInviteForm] = useState({ @@ -56,17 +56,6 @@ export default function PeopleSection() { teamId: undefined as number | undefined, }); - // Form state for invite link - const [inviteLinkForm, setInviteLinkForm] = useState({ - email: '', - role: 'ROLE_USER', - teamId: undefined as number | undefined, - expiryHours: 72, - sendEmail: false, - }); - - const [generatedInviteLink, setGeneratedInviteLink] = useState(null); - // Form state for edit user modal const [editForm, setEditForm] = useState({ role: 'ROLE_USER', @@ -200,45 +189,6 @@ export default function PeopleSection() { } }; - const handleGenerateInviteLink = async () => { - // Email is optional - if provided, it will be pre-filled for the user - // If not provided, user will be asked to enter their email during signup - - try { - setProcessing(true); - const response = await userManagementService.generateInviteLink({ - email: inviteLinkForm.email.trim() || undefined, - role: inviteLinkForm.role, - teamId: inviteLinkForm.teamId, - expiryHours: inviteLinkForm.expiryHours, - sendEmail: inviteLinkForm.sendEmail, - }); - - // Construct invite URL using current frontend origin (not backend URL) - const frontendUrl = `${window.location.origin}/invite?token=${response.token}`; - setGeneratedInviteLink(frontendUrl); - - if (response.emailSent) { - alert({ alertType: 'success', title: t('workspace.people.inviteLink.successWithEmail', 'Invite link generated and sent via email') }); - } else { - alert({ alertType: 'success', title: t('workspace.people.inviteLink.success', 'Invite link generated successfully') }); - } - - if (response.emailError) { - alert({ alertType: 'warning', title: t('workspace.people.inviteLink.emailFailed', 'Email failed to send'), body: response.emailError }); - } - } catch (error: any) { - console.error('Failed to generate invite link:', error); - const errorMessage = error.response?.data?.message || - error.response?.data?.error || - error.message || - t('workspace.people.inviteLink.error', 'Failed to generate invite link'); - alert({ alertType: 'error', title: errorMessage }); - } finally { - setProcessing(false); - } - }; - const handleUpdateUserRole = async () => { if (!selectedUser) return; @@ -513,17 +463,7 @@ export default function PeopleSection() { {/* Add Member Modal */} { - setInviteModalOpened(false); - setGeneratedInviteLink(null); - setInviteLinkForm({ - email: '', - role: 'ROLE_USER', - teamId: undefined, - expiryHours: 72, - sendEmail: false, - }); - }} + onClose={() => setInviteModalOpened(false)} size="md" zIndex={Z_INDEX_OVER_CONFIG_MODAL} centered @@ -532,17 +472,7 @@ export default function PeopleSection() { >
{ - setInviteModalOpened(false); - setGeneratedInviteLink(null); - setInviteLinkForm({ - email: '', - role: 'ROLE_USER', - teamId: undefined, - expiryHours: 72, - sendEmail: false, - }); - }} + onClick={() => setInviteModalOpened(false)} size="lg" style={{ position: 'absolute', @@ -566,36 +496,32 @@ export default function PeopleSection() { {/* Mode Toggle */} - setInviteMode(value as 'email' | 'direct' | 'link')} - data={[ - { - label: t('workspace.people.directInvite.tab', 'Direct Create'), - value: 'direct', - }, - { - label: ( - - {t('workspace.people.emailInvite.tab', 'Email Invite')} - - ), - value: 'email', - disabled: !config?.enableEmailInvites, - }, - { - label: t('workspace.people.inviteLinkTab.tab', 'Invite Link'), - value: 'link', - }, - ]} - fullWidth - /> + +
+ setInviteMode(value as 'email' | 'direct')} + data={[ + { + label: t('workspace.people.inviteMode.username', 'Username'), + value: 'direct', + }, + { + label: t('workspace.people.inviteMode.email', 'Email'), + value: 'email', + disabled: !config?.enableEmailInvites, + }, + ]} + fullWidth + /> +
+
{/* Email Mode */} {inviteMode === 'email' && config?.enableEmailInvites && ( @@ -663,7 +589,7 @@ export default function PeopleSection() { clearable comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }} /> - setInviteForm({ ...inviteForm, forceChange: e.currentTarget.checked })} @@ -671,147 +597,16 @@ export default function PeopleSection() { )} - {/* Invite Link Mode */} - {inviteMode === 'link' && ( - <> - - {t('workspace.people.inviteLink.description', 'Generate a secure link that allows the user to set their own password')} - - - { - const newEmail = e.currentTarget.value; - const hasEmail = newEmail.trim().length > 0; - const smtpEnabled = config?.enableEmailInvites || false; - - setInviteLinkForm({ - ...inviteLinkForm, - email: newEmail, - // Auto-enable sendEmail when email is provided and SMTP is configured - // Disable when email is cleared - sendEmail: hasEmail && smtpEnabled ? true : false, - }); - }} - /> - - setInviteLinkForm({ ...inviteLinkForm, teamId: value ? parseInt(value) : undefined })} - clearable - comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }} - /> - - setInviteLinkForm({ ...inviteLinkForm, expiryHours: parseInt(e.currentTarget.value) || 72 })} - min={1} - max={720} - /> - - {inviteLinkForm.email.trim() && ( - -
- setInviteLinkForm({ ...inviteLinkForm, sendEmail: e.currentTarget.checked })} - /> -
-
- )} - - {generatedInviteLink && ( - - - - {t('workspace.people.inviteLink.generated', 'Invite Link Generated')} - - - - { - try { - // Try modern clipboard API first (requires HTTPS or localhost) - if (navigator.clipboard && navigator.clipboard.writeText) { - await navigator.clipboard.writeText(generatedInviteLink); - alert({ alertType: 'success', title: t('workspace.people.inviteLink.copied', 'Link copied to clipboard') }); - } else { - // Fallback for HTTP (non-secure contexts) - const textArea = document.createElement('textarea'); - textArea.value = generatedInviteLink; - textArea.style.position = 'fixed'; - textArea.style.left = '-9999px'; - document.body.appendChild(textArea); - textArea.select(); - const successful = document.execCommand('copy'); - document.body.removeChild(textArea); - - if (successful) { - alert({ alertType: 'success', title: t('workspace.people.inviteLink.copied', 'Link copied to clipboard') }); - } else { - throw new Error('Copy command failed'); - } - } - } catch (err) { - console.error('Failed to copy:', err); - alert({ alertType: 'error', title: 'Failed to copy to clipboard' }); - } - }} - > - - - - - - )} - - )} - {/* Action Button */} diff --git a/frontend/src/components/shared/config/configSections/ProviderCard.tsx b/frontend/src/core/components/shared/config/configSections/ProviderCard.tsx similarity index 97% rename from frontend/src/components/shared/config/configSections/ProviderCard.tsx rename to frontend/src/core/components/shared/config/configSections/ProviderCard.tsx index a44868a6ec..6209fb4b6d 100644 --- a/frontend/src/components/shared/config/configSections/ProviderCard.tsx +++ b/frontend/src/core/components/shared/config/configSections/ProviderCard.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; import { Paper, Group, Text, Button, Collapse, Stack, TextInput, Textarea, Switch, PasswordInput } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import LocalIcon from '../../LocalIcon'; -import { Provider, ProviderField } from './providerDefinitions'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { Provider, ProviderField } from '@app/components/shared/config/configSections/providerDefinitions'; interface ProviderCardProps { provider: Provider; diff --git a/frontend/src/components/shared/config/configSections/TeamDetailsSection.tsx b/frontend/src/core/components/shared/config/configSections/TeamDetailsSection.tsx similarity index 97% rename from frontend/src/components/shared/config/configSections/TeamDetailsSection.tsx rename to frontend/src/core/components/shared/config/configSections/TeamDetailsSection.tsx index 07e6510e64..61dfe2a844 100644 --- a/frontend/src/components/shared/config/configSections/TeamDetailsSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/TeamDetailsSection.tsx @@ -16,12 +16,11 @@ import { Tooltip, Menu, } from '@mantine/core'; -import LocalIcon from '../../LocalIcon'; -import { alert } from '../../../toast'; -import { teamService, Team } from '../../../../services/teamService'; -import { User } from '../../../../services/userManagementService'; -import { userManagementService } from '../../../../services/userManagementService'; -import { Z_INDEX_OVER_CONFIG_MODAL } from '../../../../styles/zIndex'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert } from '@app/components/toast'; +import { teamService, Team } from '@app/services/teamService'; +import { User, userManagementService } from '@app/services/userManagementService'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; interface TeamDetailsSectionProps { teamId: number; diff --git a/frontend/src/components/shared/config/configSections/TeamsSection.tsx b/frontend/src/core/components/shared/config/configSections/TeamsSection.tsx similarity index 97% rename from frontend/src/components/shared/config/configSections/TeamsSection.tsx rename to frontend/src/core/components/shared/config/configSections/TeamsSection.tsx index 48fff701e0..e8b3b5b416 100644 --- a/frontend/src/components/shared/config/configSections/TeamsSection.tsx +++ b/frontend/src/core/components/shared/config/configSections/TeamsSection.tsx @@ -16,12 +16,12 @@ import { Select, CloseButton, } from '@mantine/core'; -import LocalIcon from '../../LocalIcon'; -import { alert } from '../../../toast'; -import { teamService, Team } from '../../../../services/teamService'; -import { userManagementService, User } from '../../../../services/userManagementService'; -import { Z_INDEX_OVER_CONFIG_MODAL } from '../../../../styles/zIndex'; -import TeamDetailsSection from './TeamDetailsSection'; +import LocalIcon from '@app/components/shared/LocalIcon'; +import { alert } from '@app/components/toast'; +import { teamService, Team } from '@app/services/teamService'; +import { userManagementService, User } from '@app/services/userManagementService'; +import { Z_INDEX_OVER_CONFIG_MODAL } from '@app/styles/zIndex'; +import TeamDetailsSection from '@app/components/shared/config/configSections/TeamDetailsSection'; export default function TeamsSection() { const { t } = useTranslation(); diff --git a/frontend/src/components/shared/config/configSections/providerDefinitions.ts b/frontend/src/core/components/shared/config/configSections/providerDefinitions.ts similarity index 100% rename from frontend/src/components/shared/config/configSections/providerDefinitions.ts rename to frontend/src/core/components/shared/config/configSections/providerDefinitions.ts 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/config/useRestartServer.ts b/frontend/src/core/components/shared/config/useRestartServer.ts similarity index 74% rename from frontend/src/components/shared/config/useRestartServer.ts rename to frontend/src/core/components/shared/config/useRestartServer.ts index cf42457700..d57a77a5f6 100644 --- a/frontend/src/components/shared/config/useRestartServer.ts +++ b/frontend/src/core/components/shared/config/useRestartServer.ts @@ -1,7 +1,6 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { alert } from '../../toast'; -import apiClient from '../../../services/apiClient'; +import { alert } from '@app/components/toast'; export function useRestartServer() { const { t } = useTranslation(); @@ -28,12 +27,18 @@ export function useRestartServer() { ), }); - await apiClient.post('/api/v1/admin/settings/restart'); + const response = await fetch('/api/v1/admin/settings/restart', { + method: 'POST', + }); - // Wait a moment then reload the page - setTimeout(() => { - window.location.reload(); - }, 3000); + if (response.ok) { + // Wait a moment then reload the page + setTimeout(() => { + window.location.reload(); + }, 3000); + } else { + throw new Error('Failed to restart'); + } } catch (_error) { alert({ alertType: 'error', 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 97% rename from frontend/src/components/shared/sliderWithInput/SliderWithInput.tsx rename to frontend/src/core/components/shared/sliderWithInput/SliderWithInput.tsx index e8e504ded1..7a91cdbe39 100644 --- a/frontend/src/components/shared/sliderWithInput/SliderWithInput.tsx +++ b/frontend/src/core/components/shared/sliderWithInput/SliderWithInput.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Slider, Text, Group, NumberInput } from '@mantine/core'; interface Props { 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 92% rename from frontend/src/components/tools/FullscreenToolList.tsx rename to frontend/src/core/components/tools/FullscreenToolList.tsx index ce76b73751..4c01b492ba 100644 --- a/frontend/src/components/tools/FullscreenToolList.tsx +++ b/frontend/src/core/components/tools/FullscreenToolList.tsx @@ -1,18 +1,18 @@ -import React, { useMemo } from 'react'; +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 }>; @@ -104,7 +104,7 @@ const FullscreenToolList = ({ {showRecentFavorites && ( <> {favoriteToolItems.length > 0 && ( -
0 && ( -
; 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 86% rename from frontend/src/components/tools/ToolPanel.tsx rename to frontend/src/core/components/tools/ToolPanel.tsx index c2d94d2030..4b6ea3eb40 100644 --- a/frontend/src/components/tools/ToolPanel.tsx +++ b/frontend/src/core/components/tools/ToolPanel.tsx @@ -1,23 +1,23 @@ -import React, { 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 { useEffect, useMemo } from 'react'; +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 95% rename from frontend/src/components/tools/addPageNumbers/PageNumberPreview.tsx rename to frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx index 8a762278a4..830703f217 100644 --- a/frontend/src/components/tools/addPageNumbers/PageNumberPreview.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx @@ -1,9 +1,9 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +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 83% rename from frontend/src/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx index 6993186bb1..061eac659c 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastBasicSettings.tsx @@ -1,8 +1,7 @@ -import React from 'react'; 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 82% rename from frontend/src/components/tools/adjustContrast/AdjustContrastColorSettings.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastColorSettings.tsx index 0f2722873c..f713ca24bd 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastColorSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastColorSettings.tsx @@ -1,8 +1,7 @@ -import React from 'react'; 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 88% rename from frontend/src/components/tools/adjustContrast/AdjustContrastPreview.tsx rename to frontend/src/core/components/tools/adjustContrast/AdjustContrastPreview.tsx index a50fb98caa..3fb42b46c6 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastPreview.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastPreview.tsx @@ -1,10 +1,10 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters'; -import { useThumbnailGeneration } from '../../../hooks/useThumbnailGeneration'; -import ObscuredOverlay from '../../shared/ObscuredOverlay'; +import { useEffect, useRef, useState } from 'react'; +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 ce19b80121..5fc9fe10f1 100644 --- a/frontend/src/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx +++ b/frontend/src/core/components/tools/adjustContrast/AdjustContrastSingleStepSettings.tsx @@ -1,8 +1,7 @@ -import React from 'react'; 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 94% rename from frontend/src/components/tools/automate/AutomationRun.tsx rename to frontend/src/core/components/tools/automate/AutomationRun.tsx index 105a8981a4..41c56558f8 100644 --- a/frontend/src/components/tools/automate/AutomationRun.tsx +++ b/frontend/src/core/components/tools/automate/AutomationRun.tsx @@ -1,13 +1,13 @@ -import React, { useEffect, useState } from "react"; +import { useEffect, useState } from "react"; 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 92% rename from frontend/src/components/tools/certSign/CertificateTypeSettings.tsx rename to frontend/src/core/components/tools/certSign/CertificateTypeSettings.tsx index 2d514a1614..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 "../../../hooks/useAppConfig"; +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 84% rename from frontend/src/components/tools/toolPicker/ToolSearch.tsx rename to frontend/src/core/components/tools/toolPicker/ToolSearch.tsx index d94003d2c8..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; @@ -82,15 +82,17 @@ const ToolSearch = ({ }, [autoFocus]); const searchInput = ( - } - autoComplete="off" - onFocus={onFocus} - /> + } + autoComplete="off" + onFocus={onFocus} + /> ); if (mode === "filter") { 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 8d8f58e157..68b95e3b7a 100644 --- a/frontend/src/components/tools/validateSignature/reportView/FileSummaryHeader.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/FileSummaryHeader.tsx @@ -1,7 +1,6 @@ -import React from 'react'; 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 e534205fa5..c6bef701fb 100644 --- a/frontend/src/components/tools/validateSignature/reportView/SignatureSection.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/SignatureSection.tsx @@ -1,10 +1,9 @@ -import React from 'react'; 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 462710cf5b..342c6713e6 100644 --- a/frontend/src/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/SignatureStatusBadge.tsx @@ -1,9 +1,8 @@ -import React from 'react'; 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 3b8312b3d6..33d76144f3 100644 --- a/frontend/src/components/tools/validateSignature/reportView/ThumbnailPreview.tsx +++ b/frontend/src/core/components/tools/validateSignature/reportView/ThumbnailPreview.tsx @@ -1,6 +1,5 @@ -import React from 'react'; 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 92% rename from frontend/src/components/viewer/LocalEmbedPDFWithAnnotations.tsx rename to frontend/src/core/components/viewer/LocalEmbedPDFWithAnnotations.tsx index 25efcb7ddf..87a5d75143 100644 --- a/frontend/src/components/viewer/LocalEmbedPDFWithAnnotations.tsx +++ b/frontend/src/core/components/viewer/LocalEmbedPDFWithAnnotations.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { createPluginRegistration } from '@embedpdf/core'; import { EmbedPDF } from '@embedpdf/core/react'; import { usePdfiumEngine } from '@embedpdf/engines/react'; @@ -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; @@ -316,4 +316,4 @@ export function LocalEmbedPDFWithAnnotations({
); -} \ No newline at end of file +} 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/hooks/useAppConfig.ts b/frontend/src/core/contexts/AppConfigContext.tsx similarity index 56% rename from frontend/src/hooks/useAppConfig.ts rename to frontend/src/core/contexts/AppConfigContext.tsx index 27e977788d..0fdd64d9e7 100644 --- a/frontend/src/hooks/useAppConfig.ts +++ b/frontend/src/core/contexts/AppConfigContext.tsx @@ -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 React, { createContext, useContext, useState, useEffect } from 'react'; +import { useRequestHeaders } from '@app/hooks/useRequestHeaders'; export interface AppConfig { baseUrl?: string; @@ -16,7 +11,9 @@ export interface AppConfig { enableEmailInvites?: boolean; isAdmin?: boolean; enableAlphaFunctionality?: boolean; - enableAnalytics?: boolean; + enableAnalytics?: boolean | null; + enablePosthog?: boolean | null; + enableScarf?: boolean | null; premiumEnabled?: boolean; premiumKey?: string; termsAndConditions?: string; @@ -32,40 +29,45 @@ export interface AppConfig { error?: string; } -interface UseAppConfigReturn { +interface AppConfigContextValue { config: AppConfig | null; loading: boolean; error: string | null; refetch: () => Promise; } +// Create context +const AppConfigContext = createContext(undefined); + /** - * Custom hook to fetch and manage application configuration + * Provider component that fetches and provides app configuration + * Should be placed at the top level of the app, before any components that need config */ -export function useAppConfig(): UseAppConfigReturn { +export const AppConfigProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { 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}`); } - + const data: AppConfig = await response.json(); setConfig(data); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; setError(errorMessage); - console.error('Failed to fetch app config:', err); + console.error('[AppConfig] Failed to fetch app config:', err); } finally { setLoading(false); } @@ -75,11 +77,31 @@ export function useAppConfig(): UseAppConfigReturn { fetchConfig(); }, []); - return { + const value: AppConfigContextValue = { config, loading, error, refetch: fetchConfig, }; + + return ( + + {children} + + ); +}; + +/** + * Hook to access application configuration + * Must be used within AppConfigProvider + */ +export function useAppConfig(): AppConfigContextValue { + const context = useContext(AppConfigContext); + + if (context === undefined) { + throw new Error('useAppConfig must be used within AppConfigProvider'); + } + + return context; } 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 72% rename from frontend/src/contexts/ToolRegistryProvider.tsx rename to frontend/src/core/contexts/ToolRegistryProvider.tsx index 30a0205019..fb8e5e48f6 100644 --- a/frontend/src/contexts/ToolRegistryProvider.tsx +++ b/frontend/src/core/contexts/ToolRegistryProvider.tsx @@ -1,9 +1,9 @@ -import React, { useMemo } from 'react'; +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 f50b5ed55b..0860b5d965 100644 --- a/frontend/src/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -1,18 +1,18 @@ -import React, { useMemo } from "react"; -import LocalIcon from "../components/shared/LocalIcon"; +import { useMemo } from "react"; +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/useAdminSettings.ts b/frontend/src/core/hooks/useAdminSettings.ts similarity index 98% rename from frontend/src/hooks/useAdminSettings.ts rename to frontend/src/core/hooks/useAdminSettings.ts index d7321c1b30..00c3af4326 100644 --- a/frontend/src/hooks/useAdminSettings.ts +++ b/frontend/src/core/hooks/useAdminSettings.ts @@ -1,6 +1,6 @@ import { useState } from 'react'; -import apiClient from '../services/apiClient'; -import { mergePendingSettings, isFieldPending, hasPendingChanges } from '../utils/settingsPendingHelper'; +import apiClient from '@app/services/apiClient'; +import { mergePendingSettings, isFieldPending, hasPendingChanges } from '@app/utils/settingsPendingHelper'; interface UseAdminSettingsOptions { sectionName: string; 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 5db03705e2..f8e237dc8b 100644 --- a/frontend/src/hooks/useBaseUrl.ts +++ b/frontend/src/core/hooks/useBaseUrl.ts @@ -1,4 +1,4 @@ -import { useAppConfig } from './useAppConfig'; +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 83% rename from frontend/src/hooks/useCookieConsent.ts rename to frontend/src/core/hooks/useCookieConsent.ts index 1dd324ce70..5c437d717b 100644 --- a/frontend/src/hooks/useCookieConsent.ts +++ b/frontend/src/core/hooks/useCookieConsent.ts @@ -1,12 +1,15 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { BASE_PATH } from '../constants/app'; +import { BASE_PATH } from '@app/constants/app'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; declare global { interface Window { - CookieConsent: { + CookieConsent?: { run: (config: any) => void; show: (show?: boolean) => void; + acceptedCategory: (category: string) => boolean; + acceptedService: (serviceName: string, category: string) => boolean; }; } } @@ -15,8 +18,11 @@ interface CookieConsentConfig { analyticsEnabled?: boolean; } -export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConfig = {}) => { +export const useCookieConsent = ({ + analyticsEnabled = false +}: CookieConsentConfig = {}) => { const { t } = useTranslation(); + const { config } = useAppConfig(); const [isInitialized, setIsInitialized] = useState(false); useEffect(() => { @@ -30,7 +36,7 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf setIsInitialized(true); // Force show the modal if it exists but isn't visible setTimeout(() => { - window.CookieConsent.show(); + window.CookieConsent?.show(); }, 100); return; } @@ -130,7 +136,24 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf necessary: { readOnly: true }, - analytics: {} + analytics: { + services: { + ...(config?.enablePosthog !== false && { + posthog: { + label: t('cookieBanner.services.posthog', 'PostHog Analytics'), + onAccept: () => console.log('PostHog service accepted'), + onReject: () => console.log('PostHog service rejected') + } + }), + ...(config?.enableScarf !== false && { + scarf: { + label: t('cookieBanner.services.scarf', 'Scarf Pixel'), + onAccept: () => console.log('Scarf service accepted'), + onReject: () => console.log('Scarf service rejected') + } + }) + } + } }, language: { default: "en", @@ -184,7 +207,7 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf // Force show after initialization setTimeout(() => { - window.CookieConsent.show(); + window.CookieConsent?.show(); }, 200); } catch (error) { @@ -212,15 +235,23 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf document.head.removeChild(customCSS); } }; - }, [analyticsEnabled, t]); + }, [analyticsEnabled, config?.enablePosthog, config?.enableScarf, t]); const showCookiePreferences = () => { if (isInitialized && window.CookieConsent) { - window.CookieConsent.show(true); + window.CookieConsent?.show(true); } }; + const isServiceAccepted = useCallback((service: string, category: string): boolean => { + if (typeof window === 'undefined' || !window.CookieConsent) { + return false; + } + return window.CookieConsent.acceptedService(service, category); + }, []); + return { - showCookiePreferences + showCookiePreferences, + isServiceAccepted }; }; 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/core/hooks/useScarfTracking.ts b/frontend/src/core/hooks/useScarfTracking.ts new file mode 100644 index 0000000000..b0297d5102 --- /dev/null +++ b/frontend/src/core/hooks/useScarfTracking.ts @@ -0,0 +1,44 @@ +import { useEffect } from 'react'; +import { useAppConfig } from '@app/contexts/AppConfigContext'; +import { useCookieConsent } from '@app/hooks/useCookieConsent'; +import { setScarfConfig, firePixel } from '@app/utils/scarfTracking'; + +/** + * Hook for initializing Scarf tracking + * + * This hook should be mounted once during app initialization (e.g., in index.tsx). + * It configures the scarf tracking utility with current config and consent state, + * and sets up event listeners to auto-fire pixels when consent is granted. + * + * After initialization, firePixel() can be called from anywhere in the app, + * including non-React utility functions like urlRouting.ts. + */ +export function useScarfTracking() { + const { config } = useAppConfig(); + const { isServiceAccepted } = useCookieConsent({ analyticsEnabled: config?.enableAnalytics === true }); + + // Update scarf config whenever config or consent changes + useEffect(() => { + if (config && config.enableScarf !== undefined) { + setScarfConfig(config.enableScarf, isServiceAccepted); + } + }, [config?.enableScarf, isServiceAccepted]); + + // Listen to cookie consent changes and auto-fire pixel when consent is granted + useEffect(() => { + const handleConsentChange = () => { + console.warn('[useScarfTracking] Consent changed, checking scarf service acceptance'); + if (isServiceAccepted('scarf', 'analytics')) { + firePixel(window.location.pathname); + } + }; + + window.addEventListener('cc:onConsent', handleConsentChange); + window.addEventListener('cc:onChange', handleConsentChange); + + return () => { + window.removeEventListener('cc:onConsent', handleConsentChange); + window.removeEventListener('cc:onChange', handleConsentChange); + }; + }, [isServiceAccepted]); +} 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 86% rename from frontend/src/pages/HomePage.tsx rename to frontend/src/core/pages/HomePage.tsx index c4531346e7..283ccbc0ec 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/core/pages/HomePage.tsx @@ -1,26 +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 { useAppConfig } from "../hooks/useAppConfig"; -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 "@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 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"; @@ -50,6 +51,14 @@ export default function HomePage() { const [activeMobileView, setActiveMobileView] = useState("tools"); const isProgrammaticScroll = useRef(false); const [configModalOpen, setConfigModalOpen] = useState(false); + const [showAnalyticsModal, setShowAnalyticsModal] = useState(false); + + // Show admin analytics choice modal if analytics settings not configured + useEffect(() => { + if (config && config.enableAnalytics === null) { + setShowAnalyticsModal(true); + } + }, [config]); const brandAltText = t("home.mobile.brandAlt", "Stirling PDF logo"); const brandIconSrc = `${BASE_PATH}/branding/StirlingPDFLogoNoText${ @@ -155,6 +164,10 @@ export default function HomePage() { return (
+ setShowAnalyticsModal(false)} + /> {isMobile ? (
diff --git a/frontend/src/services/accountService.ts b/frontend/src/core/services/accountService.ts similarity index 63% rename from frontend/src/services/accountService.ts rename to frontend/src/core/services/accountService.ts index 475c5a25b1..f546ed8bf5 100644 --- a/frontend/src/services/accountService.ts +++ b/frontend/src/core/services/accountService.ts @@ -1,4 +1,4 @@ -import apiClient from './apiClient'; +import apiClient from '@app/services/apiClient'; export interface AccountData { username: string; @@ -23,7 +23,7 @@ export const accountService = { }, /** - * Change user password (for regular password changes) + * Change user password */ async changePassword(currentPassword: string, newPassword: string): Promise { const formData = new FormData(); @@ -31,14 +31,4 @@ export const accountService = { formData.append('newPassword', newPassword); await apiClient.post('/api/v1/user/change-password', formData); }, - - /** - * Change password on first login (clears the first-use flag) - */ - async changePasswordOnLogin(currentPassword: string, newPassword: string): Promise { - const formData = new FormData(); - formData.append('currentPassword', currentPassword); - formData.append('newPassword', newPassword); - await apiClient.post('/api/v1/user/change-password-on-login', formData); - }, }; 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 044af41990..fa5160adf2 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/teamService.ts b/frontend/src/core/services/teamService.ts similarity index 98% rename from frontend/src/services/teamService.ts rename to frontend/src/core/services/teamService.ts index 25b11cef0b..36434a2931 100644 --- a/frontend/src/services/teamService.ts +++ b/frontend/src/core/services/teamService.ts @@ -1,4 +1,4 @@ -import apiClient from './apiClient'; +import apiClient from '@app/services/apiClient'; export interface Team { id: number; 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/userManagementService.ts b/frontend/src/core/services/userManagementService.ts similarity index 67% rename from frontend/src/services/userManagementService.ts rename to frontend/src/core/services/userManagementService.ts index 656cc493bb..8e92cf350c 100644 --- a/frontend/src/services/userManagementService.ts +++ b/frontend/src/core/services/userManagementService.ts @@ -1,4 +1,4 @@ -import apiClient from './apiClient'; +import apiClient from '@app/services/apiClient'; export interface User { id: number; @@ -62,35 +62,6 @@ export interface InviteUsersResponse { error?: string; } -export interface InviteLinkRequest { - email?: string; - role: string; - teamId?: number; - expiryHours?: number; - sendEmail?: boolean; -} - -export interface InviteLinkResponse { - token: string; - inviteUrl: string; - email: string; - expiresAt: string; - expiryHours: number; - emailSent?: boolean; - emailError?: string; - error?: string; -} - -export interface InviteToken { - id: number; - email: string; - role: string; - teamId?: number; - createdBy: string; - createdAt: string; - expiresAt: string; -} - /** * User Management Service * Provides functions to interact with user management backend APIs @@ -192,60 +163,4 @@ export const userManagementService = { return response.data; }, - - /** - * Generate an invite link (admin only) - */ - async generateInviteLink(data: InviteLinkRequest): Promise { - const formData = new FormData(); - // Only append email if it's provided and not empty - if (data.email && data.email.trim()) { - formData.append('email', data.email); - } - formData.append('role', data.role); - if (data.teamId) { - formData.append('teamId', data.teamId.toString()); - } - if (data.expiryHours) { - formData.append('expiryHours', data.expiryHours.toString()); - } - if (data.sendEmail !== undefined) { - formData.append('sendEmail', data.sendEmail.toString()); - } - - const response = await apiClient.post( - '/api/v1/invite/generate', - formData, - { - suppressErrorToast: true, - } as any - ); - - return response.data; - }, - - /** - * Get list of active invite links (admin only) - */ - async getInviteLinks(): Promise { - const response = await apiClient.get<{ invites: InviteToken[] }>('/api/v1/invite/list'); - return response.data.invites; - }, - - /** - * Revoke an invite link (admin only) - */ - async revokeInviteLink(inviteId: number): Promise { - await apiClient.delete(`/api/v1/invite/revoke/${inviteId}`, { - suppressErrorToast: true, - } as any); - }, - - /** - * Clean up expired invite links (admin only) - */ - async cleanupExpiredInvites(): Promise<{ deletedCount: number }> { - const response = await apiClient.post<{ deletedCount: number }>('/api/v1/invite/cleanup'); - return response.data; - }, }; 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 94% rename from frontend/src/styles/zIndex.ts rename to frontend/src/core/styles/zIndex.ts index b24cd17d91..f1bc929dd3 100644 --- a/frontend/src/styles/zIndex.ts +++ b/frontend/src/core/styles/zIndex.ts @@ -3,6 +3,7 @@ export const Z_INDEX_FULLSCREEN_SURFACE = 1000; export const Z_INDEX_OVER_FULLSCREEN_SURFACE = 1300; +export const Z_ANALYTICS_MODAL = 1301; export const Z_INDEX_FILE_MANAGER_MODAL = 1200; export const Z_INDEX_OVER_FILE_MANAGER_MODAL = 1300; 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 908ab1504e..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 78% rename from frontend/src/tools/AdjustContrast.tsx rename to frontend/src/core/tools/AdjustContrast.tsx index 0de528a40a..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 React, { 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 { useEffect, useMemo, useState } from 'react'; +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/core/utils/scarfTracking.ts b/frontend/src/core/utils/scarfTracking.ts new file mode 100644 index 0000000000..9824d9b3be --- /dev/null +++ b/frontend/src/core/utils/scarfTracking.ts @@ -0,0 +1,95 @@ +/** + * Scarf analytics pixel tracking utility + * + * This module provides a firePixel function that can be called from anywhere, + * including non-React utility functions. Configuration and consent state are + * injected via setScarfConfig() which should be called from a React hook + * during app initialization. + * + * IMPORTANT: setScarfConfig() must be called before firePixel() will work. + * The initialization hook (useScarfTracking) is mounted in App.tsx. + * + * For testing: Use resetScarfConfig() to clear module state between tests. + */ + +// Module-level state +let configured: boolean = false; +let enableScarf: boolean | null = null; +let isServiceAccepted: ((service: string, category: string) => boolean) | null = null; +let lastFiredPathname: string | null = null; +let lastFiredTime = 0; + +/** + * Configure scarf tracking with app config and consent checker + * Should be called from a React hook during app initialization (see useScarfTracking) + * + * @param scarfEnabled - Whether scarf tracking is enabled globally + * @param consentChecker - Function to check if user has accepted scarf service + */ +export function setScarfConfig( + scarfEnabled: boolean | null, + consentChecker: (service: string, category: string) => boolean +): void { + configured = true; + enableScarf = scarfEnabled; + isServiceAccepted = consentChecker; +} + +/** + * Fire scarf pixel for analytics tracking + * Only fires if: + * - Scarf tracking has been initialized via setScarfConfig() + * - Scarf is globally enabled in config + * - User has accepted scarf service via cookie consent + * - Pathname has changed or enough time has passed since last fire + * + * @param pathname - The pathname to track (usually window.location.pathname) + */ +export function firePixel(pathname: string): void { + // Dev-mode warning if called before initialization + if (!configured) { + console.warn( + '[scarfTracking] firePixel() called before setScarfConfig(). ' + + 'Ensure useScarfTracking() hook is mounted in App.tsx.' + ); + return; + } + + // Check if Scarf is globally disabled + if (enableScarf === false) { + return; + } + + // Check if consent checker is available and scarf service is accepted + if (!isServiceAccepted || !isServiceAccepted('scarf', 'analytics')) { + return; + } + + const now = Date.now(); + + // Only fire if pathname changed or it's been at least 250ms since last fire + if (pathname === lastFiredPathname && now - lastFiredTime < 250) { + return; + } + + lastFiredPathname = pathname; + lastFiredTime = now; + + const url = 'https://static.scarf.sh/a.png?x-pxid=3c1d68de-8945-4e9f-873f-65320b6fabf7' + + '&path=' + encodeURIComponent(pathname); + + const img = new Image(); + img.referrerPolicy = "no-referrer-when-downgrade"; + img.src = url; +} + +/** + * Reset scarf tracking configuration and state + * Useful for testing to ensure clean state between test runs + */ +export function resetScarfConfig(): void { + enableScarf = null; + isServiceAccepted = null; + lastFiredPathname = null; + lastFiredTime = 0; +} 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/settingsPendingHelper.ts b/frontend/src/core/utils/settingsPendingHelper.ts similarity index 100% rename from frontend/src/utils/settingsPendingHelper.ts rename to frontend/src/core/utils/settingsPendingHelper.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 083d779a59..c8e9081c1b 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,38 +1,37 @@ 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, defaults: '2025-05-24', capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this debug: false, - opt_out_capturing_by_default: false, // We handle opt-out via cookie consent + opt_out_capturing_by_default: true, // Opt-out by default, controlled by cookie consent }); function updatePosthogConsent(){ - if(typeof(posthog) == "undefined") { - return; - } - const optIn = (window.CookieConsent as any).acceptedCategory('analytics'); - if (optIn) { - posthog.opt_in_capturing(); - } else { - posthog.opt_out_capturing(); - } - - console.log("Updated analytics consent: ", optIn? "opted in" : "opted out"); + if(typeof(posthog) == "undefined" || !posthog.__loaded) { + return; } + const optIn = (window.CookieConsent as any)?.acceptedService?.('posthog', 'analytics') || false; + if (optIn) { + posthog.opt_in_capturing(); + } else { + posthog.opt_out_capturing(); + } + console.log("Updated PostHog consent: ", optIn ? "opted in" : "opted out"); +} window.addEventListener("cc:onConsent", updatePosthogConsent); window.addEventListener("cc:onChange", updatePosthogConsent); 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 81% rename from frontend/src/components/shared/DividerWithText.tsx rename to frontend/src/proprietary/components/shared/DividerWithText.tsx index 9b82240a1f..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 @@ -10,9 +10,9 @@ interface TextDividerProps { } export default function DividerWithText({ text, className = '', style, variant = 'default', respondsToDarkMode = true, opacity }: TextDividerProps) { - const variantClass = variant === 'subcategory' ? 'subcategory' : '' - const themeClass = respondsToDarkMode ? '' : 'force-light' - const styleWithOpacity = opacity !== undefined ? { ...(style || {}), ['--text-divider-opacity' as any]: opacity } : style + const variantClass = variant === 'subcategory' ? 'subcategory' : ''; + const themeClass = respondsToDarkMode ? '' : 'force-light'; + const styleWithOpacity = opacity !== undefined ? { ...(style || {}), ['--text-divider-opacity' as any]: opacity } : style; if (text) { return ( @@ -24,7 +24,7 @@ export default function DividerWithText({ text, className = '', style, variant = {text}
- ) + ); } return ( @@ -32,5 +32,5 @@ export default function DividerWithText({ text, className = '', style, variant = className={`h-px my-2.5 ${themeClass} ${className}`} style={styleWithOpacity} /> - ) + ); } diff --git a/frontend/src/components/shared/LoginRightCarousel.tsx b/frontend/src/proprietary/components/shared/LoginRightCarousel.tsx similarity index 75% rename from frontend/src/components/shared/LoginRightCarousel.tsx rename to frontend/src/proprietary/components/shared/LoginRightCarousel.tsx index c2ebb29bfa..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 { useEffect, useMemo, useRef, useState } from 'react'; +import { BASE_PATH } from '@app/constants/app'; type ImageSlide = { src: string; alt?: string; cornerModelUrl?: string; title?: string; subtitle?: string; followMouseTilt?: boolean; tiltMaxDeg?: number } @@ -14,53 +14,53 @@ export default function LoginRightCarousel({ initialSeconds?: number slideSeconds?: number }) { - const totalSlides = imageSlides.length - const [index, setIndex] = useState(0) - const mouse = useRef({ x: 0, y: 0 }) + const totalSlides = imageSlides.length; + const [index, setIndex] = useState(0); + const mouse = useRef({ x: 0, y: 0 }); const durationsMs = useMemo(() => { - if (imageSlides.length === 0) return [] - return imageSlides.map((_, i) => (i === 0 ? (initialSeconds ?? slideSeconds) : slideSeconds) * 1000) - }, [imageSlides, initialSeconds, slideSeconds]) + if (imageSlides.length === 0) return []; + return imageSlides.map((_, i) => (i === 0 ? (initialSeconds ?? slideSeconds) : slideSeconds) * 1000); + }, [imageSlides, initialSeconds, slideSeconds]); useEffect(() => { - if (totalSlides <= 1) return + if (totalSlides <= 1) return; const timeout = setTimeout(() => { - setIndex((i) => (i + 1) % totalSlides) - }, durationsMs[index] ?? slideSeconds * 1000) - return () => clearTimeout(timeout) - }, [index, totalSlides, durationsMs, slideSeconds]) + setIndex((i) => (i + 1) % totalSlides); + }, durationsMs[index] ?? slideSeconds * 1000); + return () => clearTimeout(timeout); + }, [index, totalSlides, durationsMs, slideSeconds]); useEffect(() => { const onMove = (e: MouseEvent) => { - mouse.current.x = (e.clientX / window.innerWidth) * 2 - 1 - mouse.current.y = (e.clientY / window.innerHeight) * 2 - 1 - } - window.addEventListener('mousemove', onMove) - return () => window.removeEventListener('mousemove', onMove) - }, []) + mouse.current.x = (e.clientX / window.innerWidth) * 2 - 1; + mouse.current.y = (e.clientY / window.innerHeight) * 2 - 1; + }; + window.addEventListener('mousemove', onMove); + return () => window.removeEventListener('mousemove', onMove); + }, []); function TiltImage({ src, alt, enabled, maxDeg = 6 }: { src: string; alt?: string; enabled: boolean; maxDeg?: number }) { - const imgRef = useRef(null) + const imgRef = useRef(null); useEffect(() => { - const el = imgRef.current - if (!el) return + const el = imgRef.current; + if (!el) return; - let raf = 0 + let raf = 0; const tick = () => { if (enabled) { - const rotY = (mouse.current.x || 0) * maxDeg - const rotX = -(mouse.current.y || 0) * maxDeg - el.style.transform = `translateY(-2rem) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg)` + const rotY = (mouse.current.x || 0) * maxDeg; + const rotX = -(mouse.current.y || 0) * maxDeg; + el.style.transform = `translateY(-2rem) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg)`; } else { - el.style.transform = 'translateY(-2rem)' + el.style.transform = 'translateY(-2rem)'; } - raf = requestAnimationFrame(tick) - } - raf = requestAnimationFrame(tick) - return () => cancelAnimationFrame(raf) - }, [enabled, maxDeg]) + raf = requestAnimationFrame(tick); + }; + raf = requestAnimationFrame(tick); + return () => cancelAnimationFrame(raf); + }, [enabled, maxDeg]); return ( - ) + ); } return ( @@ -155,5 +155,5 @@ export default function LoginRightCarousel({ ))}
- ) + ); } 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 93% rename from frontend/src/components/shared/loginSlides.ts rename to frontend/src/proprietary/components/shared/loginSlides.ts index aa3d7f443b..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 @@ -38,6 +38,6 @@ export const loginSlides: LoginCarouselSlide[] = [ followMouseTilt: true, tiltMaxDeg: 5, }, -] +]; -export default loginSlides +export default loginSlides; 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 69% rename from frontend/src/routes/AuthCallback.tsx rename to frontend/src/proprietary/routes/AuthCallback.tsx index 285d582512..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 { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useAuth } from '@app/auth/UseSession'; /** * OAuth Callback Handler @@ -10,50 +10,50 @@ import { useAuth } from '../auth/UseSession' * We extract it, store in localStorage, and redirect to the home page. */ export default function AuthCallback() { - const navigate = useNavigate() - const { refreshSession } = useAuth() + const navigate = useNavigate(); + const { refreshSession } = useAuth(); useEffect(() => { const handleCallback = async () => { try { - console.log('[AuthCallback] Handling OAuth callback...') + console.log('[AuthCallback] Handling OAuth callback...'); // Extract JWT from URL fragment (#access_token=...) - const hash = window.location.hash.substring(1) // Remove '#' - const params = new URLSearchParams(hash) - const token = params.get('access_token') + const hash = window.location.hash.substring(1); // Remove '#' + const params = new URLSearchParams(hash); + const token = params.get('access_token'); if (!token) { - console.error('[AuthCallback] No access_token in URL fragment') + console.error('[AuthCallback] No access_token in URL fragment'); navigate('/login', { replace: true, state: { error: 'OAuth login failed - no token received.' } - }) - return + }); + return; } // Store JWT in localStorage - localStorage.setItem('stirling_jwt', token) - console.log('[AuthCallback] JWT stored in localStorage') + localStorage.setItem('stirling_jwt', token); + console.log('[AuthCallback] JWT stored in localStorage'); // Refresh session to load user info into state - await refreshSession() + await refreshSession(); - console.log('[AuthCallback] Session refreshed, redirecting to home') + console.log('[AuthCallback] Session refreshed, redirecting to home'); // Clear the hash from URL and redirect to home page - navigate('/', { replace: true }) + navigate('/', { replace: true }); } catch (error) { - console.error('[AuthCallback] Error:', error) + console.error('[AuthCallback] Error:', error); navigate('/login', { replace: true, state: { error: 'OAuth login failed. Please try again.' } - }) + }); } - } + }; - handleCallback() - }, [navigate, refreshSession]) + handleCallback(); + }, [navigate, refreshSession]); return (
- ) + ); } diff --git a/frontend/src/routes/InviteAccept.tsx b/frontend/src/proprietary/routes/InviteAccept.tsx similarity index 96% rename from frontend/src/routes/InviteAccept.tsx rename to frontend/src/proprietary/routes/InviteAccept.tsx index 641ad47855..f40290ab9b 100644 --- a/frontend/src/routes/InviteAccept.tsx +++ b/frontend/src/proprietary/routes/InviteAccept.tsx @@ -1,12 +1,12 @@ import { useState, useEffect } from 'react'; import { useSearchParams, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { useDocumentMeta } from '../hooks/useDocumentMeta'; -import AuthLayout from './authShared/AuthLayout'; -import LoginHeader from './login/LoginHeader'; -import ErrorMessage from './login/ErrorMessage'; -import { BASE_PATH } from '../constants/app'; -import apiClient from '../services/apiClient'; +import { useDocumentMeta } from '@app/hooks/useDocumentMeta'; +import AuthLayout from '@app/routes/authShared/AuthLayout'; +import LoginHeader from '@app/routes/login/LoginHeader'; +import ErrorMessage from '@app/routes/login/ErrorMessage'; +import { BASE_PATH } from '@app/constants/app'; +import apiClient from '@app/services/apiClient'; interface InviteData { email: string | null; diff --git a/frontend/src/routes/Landing.tsx b/frontend/src/proprietary/routes/Landing.tsx similarity index 69% rename from frontend/src/routes/Landing.tsx rename to frontend/src/proprietary/routes/Landing.tsx index 78d69e7418..73b07063b0 100644 --- a/frontend/src/routes/Landing.tsx +++ b/frontend/src/proprietary/routes/Landing.tsx @@ -1,11 +1,11 @@ import { useState, useEffect } from 'react' import { Navigate, useLocation } from 'react-router-dom' -import { useAuth } from '../auth/UseSession' -import { useAppConfig } from '../hooks/useAppConfig' -import HomePage from '../pages/HomePage' -import Login from './Login' -import FirstLoginModal from '../components/shared/FirstLoginModal' -import { accountService } from '../services/accountService' +import { useAuth } from '@app/auth/UseSession' +import { useAppConfig } from '@app/contexts/AppConfigContext' +import HomePage from '@app/pages/HomePage' +import Login from '@app/routes/Login' +import FirstLoginModal from '@app/components/shared/FirstLoginModal' +import { accountService } from '@app/services/accountService' /** * Landing component - Smart router based on authentication status @@ -15,14 +15,14 @@ import { accountService } from '../services/accountService' * If user is not authenticated: Show Login or redirect to /login */ export default function Landing() { - const { session, loading: authLoading } = useAuth() - const { config, loading: configLoading } = useAppConfig() - const location = useLocation() - const [isFirstLogin, setIsFirstLogin] = useState(false) - const [checkingFirstLogin, setCheckingFirstLogin] = useState(false) - const [username, setUsername] = useState('') + const { session, loading: authLoading, refreshSession } = useAuth(); + const { config, loading: configLoading } = useAppConfig(); + const location = useLocation(); + const [isFirstLogin, setIsFirstLogin] = useState(false); + const [checkingFirstLogin, setCheckingFirstLogin] = useState(false); + const [username, setUsername] = useState(''); - const loading = authLoading || configLoading + const loading = authLoading || configLoading; // Check if user needs to change password on first login useEffect(() => { @@ -46,13 +46,20 @@ export default function Landing() { checkFirstLogin() }, [session, config]) + const handlePasswordChanged = async () => { + // After password change, backend logs out the user + // Refresh session to detect logout and redirect to login + setIsFirstLogin(false) // Close modal first + await refreshSession() + // The auth system will automatically redirect to login when session is null + } console.log('[Landing] State:', { pathname: location.pathname, loading, hasSession: !!session, loginEnabled: config?.enableLogin, - }) + }); // Show loading while checking auth and config if (loading || checkingFirstLogin) { @@ -65,13 +72,13 @@ export default function Landing() { - ) + ); } // If login is disabled, show app directly (anonymous mode) if (config?.enableLogin === false) { - console.debug('[Landing] Login disabled - showing app in anonymous mode') - return + console.debug('[Landing] Login disabled - showing app in anonymous mode'); + return ; } // If we have a session, show the main app @@ -80,20 +87,21 @@ export default function Landing() { <> - ) + ); } // If we're at home route ("/"), show login directly (marketing/landing page) // Otherwise navigate to login (fixes URL mismatch for tool routes) - const isHome = location.pathname === '/' || location.pathname === '' + const isHome = location.pathname === '/' || location.pathname === ''; if (isHome) { - return + return ; } // For non-home routes without auth, navigate to login (preserves from location) - return + return ; } diff --git a/frontend/src/routes/Login.tsx b/frontend/src/proprietary/routes/Login.tsx similarity index 71% rename from frontend/src/routes/Login.tsx rename to frontend/src/proprietary/routes/Login.tsx index c8e0a68477..855793a93e 100644 --- a/frontend/src/routes/Login.tsx +++ b/frontend/src/proprietary/routes/Login.tsx @@ -1,38 +1,38 @@ -import { useEffect, useState } from 'react' -import { useNavigate, useSearchParams } from 'react-router-dom' -import { springAuth } from '../auth/springAuthClient' -import { useAuth } from '../auth/UseSession' -import { useTranslation } from 'react-i18next' -import { useDocumentMeta } from '../hooks/useDocumentMeta' -import AuthLayout from './authShared/AuthLayout' +import { useEffect, useState } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { springAuth } from '@app/auth/springAuthClient'; +import { useAuth } from '@app/auth/UseSession'; +import { useTranslation } from 'react-i18next'; +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() - const [searchParams] = useSearchParams() - const { session, loading } = useAuth() - const { t } = useTranslation() - const [isSigningIn, setIsSigningIn] = useState(false) - const [error, setError] = useState(null) - const [successMessage, setSuccessMessage] = useState(null) - const [showEmailForm, setShowEmailForm] = useState(false) - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const { session, loading } = useAuth(); + const { t } = useTranslation(); + const [isSigningIn, setIsSigningIn] = useState(false); + const [error, setError] = useState(null); + const [successMessage, setSuccessMessage] = useState(null); + const [showEmailForm, setShowEmailForm] = useState(false); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); // Handle query params (email prefill and success messages) useEffect(() => { try { - const emailFromQuery = searchParams.get('email') + const emailFromQuery = searchParams.get('email'); if (emailFromQuery) { - setEmail(emailFromQuery) + setEmail(emailFromQuery); } const messageType = searchParams.get('messageType') @@ -52,7 +52,7 @@ export default function Login() { } catch (_) { // ignore } - }, [searchParams, t]) + }, [searchParams, t]); const baseUrl = window.location.origin + BASE_PATH; @@ -64,74 +64,74 @@ export default function Login() { ogDescription: t('app.description', 'The Free Adobe Acrobat alternative (10M+ Downloads)'), ogImage: `${baseUrl}/og_images/home.png`, ogUrl: `${window.location.origin}${window.location.pathname}` - }) + }); // Show logged in state if authenticated if (session && !loading) { - return + return ; } const signInWithProvider = async (provider: 'github' | 'google' | 'apple' | 'azure') => { try { - setIsSigningIn(true) - setError(null) + setIsSigningIn(true); + setError(null); - console.log(`[Login] Signing in with ${provider}`) + console.log(`[Login] Signing in with ${provider}`); // Redirect to Spring OAuth2 endpoint const { error } = await springAuth.signInWithOAuth({ provider, options: { redirectTo: `${BASE_PATH}/auth/callback` } - }) + }); if (error) { - console.error(`[Login] ${provider} error:`, error) - setError(t('login.failedToSignIn', { provider, message: error.message }) || `Failed to sign in with ${provider}`) + console.error(`[Login] ${provider} error:`, error); + setError(t('login.failedToSignIn', { provider, message: error.message }) || `Failed to sign in with ${provider}`); } } catch (err) { - console.error(`[Login] Unexpected error:`, err) - setError(t('login.unexpectedError', { message: err instanceof Error ? err.message : 'Unknown error' }) || 'An unexpected error occurred') + console.error(`[Login] Unexpected error:`, err); + setError(t('login.unexpectedError', { message: err instanceof Error ? err.message : 'Unknown error' }) || 'An unexpected error occurred'); } finally { - setIsSigningIn(false) + setIsSigningIn(false); } - } + }; const signInWithEmail = async () => { if (!email || !password) { - setError(t('login.pleaseEnterBoth') || 'Please enter both email and password') - return + setError(t('login.pleaseEnterBoth') || 'Please enter both email and password'); + return; } try { - setIsSigningIn(true) - setError(null) + setIsSigningIn(true); + setError(null); - console.log('[Login] Signing in with email:', email) + console.log('[Login] Signing in with email:', email); const { user, session, error } = await springAuth.signInWithPassword({ email: email.trim(), password: password - }) + }); if (error) { - console.error('[Login] Email sign in error:', error) - setError(error.message) + console.error('[Login] Email sign in error:', error); + setError(error.message); } else if (user && session) { - console.log('[Login] Email sign in successful') + console.log('[Login] Email sign in successful'); // Auth state will update automatically and Landing will redirect to home // No need to navigate manually here } } catch (err) { - console.error('[Login] Unexpected error:', err) - setError(t('login.unexpectedError', { message: err instanceof Error ? err.message : 'Unknown error' }) || 'An unexpected error occurred') + console.error('[Login] Unexpected error:', err); + setError(t('login.unexpectedError', { message: err instanceof Error ? err.message : 'Unknown error' }) || 'An unexpected error occurred'); } finally { - setIsSigningIn(false) + setIsSigningIn(false); } - } + }; const handleForgotPassword = () => { - navigate('/auth/reset') - } + navigate('/auth/reset'); + }; return ( @@ -217,5 +217,5 @@ export default function Login() { - ) + ); } diff --git a/frontend/src/routes/Signup.tsx b/frontend/src/proprietary/routes/Signup.tsx similarity index 55% rename from frontend/src/routes/Signup.tsx rename to frontend/src/proprietary/routes/Signup.tsx index 0a5ee32ac7..192a3a95a5 100644 --- a/frontend/src/routes/Signup.tsx +++ b/frontend/src/proprietary/routes/Signup.tsx @@ -1,28 +1,28 @@ -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 { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +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() - const { t } = useTranslation() - const [isSigningUp, setIsSigningUp] = useState(false) - const [error, setError] = useState(null) - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - const [confirmPassword, setConfirmPassword] = useState('') - const [fieldErrors, setFieldErrors] = useState({}) + const navigate = useNavigate(); + const { t } = useTranslation(); + const [isSigningUp, setIsSigningUp] = useState(false); + const [error, setError] = useState(null); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [confirmPassword, setConfirmPassword] = useState(''); + const [fieldErrors, setFieldErrors] = useState({}); const baseUrl = window.location.origin + BASE_PATH; @@ -34,38 +34,38 @@ export default function Signup() { ogDescription: t('app.description', 'The Free Adobe Acrobat alternative (10M+ Downloads)'), ogImage: `${baseUrl}/og_images/home.png`, ogUrl: `${window.location.origin}${window.location.pathname}` - }) + }); - const { validateSignupForm } = useSignupFormValidation() - const { signUp } = useAuthService() + const { validateSignupForm } = useSignupFormValidation(); + const { signUp } = useAuthService(); const handleSignUp = async () => { - const validation = validateSignupForm(email, password, confirmPassword) + const validation = validateSignupForm(email, password, confirmPassword); if (!validation.isValid) { - setError(validation.error) - setFieldErrors(validation.fieldErrors || {}) - return + setError(validation.error); + setFieldErrors(validation.fieldErrors || {}); + return; } try { - setIsSigningUp(true) - setError(null) - setFieldErrors({}) + setIsSigningUp(true); + setError(null); + setFieldErrors({}); - const result = await signUp(email, password, '') + const result = await signUp(email, password, ''); if (result.user) { // Show success message and redirect to login - setError(null) - setTimeout(() => navigate('/login'), 2000) + setError(null); + setTimeout(() => navigate('/login'), 2000); } } catch (err) { - console.error('[Signup] Unexpected error:', err) - setError(err instanceof Error ? err.message : t('signup.unexpectedError', { message: 'Unknown error' })) + console.error('[Signup] Unexpected error:', err); + setError(err instanceof Error ? err.message : t('signup.unexpectedError', { message: 'Unknown error' })); } finally { - setIsSigningUp(false) + setIsSigningUp(false); } - } + }; return ( @@ -101,5 +101,5 @@ export default function Signup() { - ) + ); } 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 54% rename from frontend/src/routes/authShared/AuthLayout.tsx rename to frontend/src/proprietary/routes/authShared/AuthLayout.tsx index e32f629e07..ba7df3795f 100644 --- a/frontend/src/routes/authShared/AuthLayout.tsx +++ b/frontend/src/proprietary/routes/authShared/AuthLayout.tsx @@ -1,51 +1,51 @@ -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 React, { useEffect, useRef, useState } from 'react'; +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 } export default function AuthLayout({ children }: AuthLayoutProps) { - const cardRef = useRef(null) - const [hideRightPanel, setHideRightPanel] = useState(false) + const cardRef = useRef(null); + const [hideRightPanel, setHideRightPanel] = useState(false); // Force light mode on auth pages useEffect(() => { - const htmlElement = document.documentElement - const previousColorScheme = htmlElement.getAttribute('data-mantine-color-scheme') + const htmlElement = document.documentElement; + const previousColorScheme = htmlElement.getAttribute('data-mantine-color-scheme'); // Set light mode - htmlElement.setAttribute('data-mantine-color-scheme', 'light') + htmlElement.setAttribute('data-mantine-color-scheme', 'light'); // Cleanup: restore previous theme when leaving auth pages return () => { if (previousColorScheme) { - htmlElement.setAttribute('data-mantine-color-scheme', previousColorScheme) + htmlElement.setAttribute('data-mantine-color-scheme', previousColorScheme); } - } - }, []) + }; + }, []); useEffect(() => { const update = () => { // Use viewport to avoid hysteresis when the card is already in single-column mode - const viewportWidth = window.innerWidth - const viewportHeight = window.innerHeight - const cardWidthIfTwoCols = Math.min(1180, viewportWidth * 0.96) // matches min(73.75rem, 96vw) - const columnWidth = cardWidthIfTwoCols / 2 - const tooNarrow = columnWidth < 470 - const tooShort = viewportHeight < 740 - setHideRightPanel(tooNarrow || tooShort) - } - update() - window.addEventListener('resize', update) - window.addEventListener('orientationchange', update) + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const cardWidthIfTwoCols = Math.min(1180, viewportWidth * 0.96); // matches min(73.75rem, 96vw) + const columnWidth = cardWidthIfTwoCols / 2; + const tooNarrow = columnWidth < 470; + const tooShort = viewportHeight < 740; + setHideRightPanel(tooNarrow || tooShort); + }; + update(); + window.addEventListener('resize', update); + window.addEventListener('orientationchange', update); return () => { - window.removeEventListener('resize', update) - window.removeEventListener('orientationchange', update) - } - }, []) + window.removeEventListener('resize', update); + window.removeEventListener('orientationchange', update); + }; + }, []); return (
@@ -64,5 +64,5 @@ export default function AuthLayout({ children }: AuthLayoutProps) { )}
- ) + ); } 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 92% rename from frontend/src/routes/login/EmailPasswordForm.tsx rename to frontend/src/proprietary/routes/login/EmailPasswordForm.tsx index 7036e24cf5..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 { useTranslation } from 'react-i18next'; +import '@app/routes/authShared/auth.css'; interface EmailPasswordFormProps { email: string @@ -27,12 +27,12 @@ export default function EmailPasswordForm({ showPasswordField = true, fieldErrors = {} }: EmailPasswordFormProps) { - const { t } = useTranslation() + const { t } = useTranslation(); const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - onSubmit() - } + e.preventDefault(); + onSubmit(); + }; return (
@@ -82,5 +82,5 @@ export default function EmailPasswordForm({ {submitButtonText}
- ) + ); } diff --git a/frontend/src/routes/login/ErrorMessage.tsx b/frontend/src/proprietary/routes/login/ErrorMessage.tsx similarity index 88% rename from frontend/src/routes/login/ErrorMessage.tsx rename to frontend/src/proprietary/routes/login/ErrorMessage.tsx index 4f237b77c8..4563a24505 100644 --- a/frontend/src/routes/login/ErrorMessage.tsx +++ b/frontend/src/proprietary/routes/login/ErrorMessage.tsx @@ -3,11 +3,11 @@ interface ErrorMessageProps { } export default function ErrorMessage({ error }: ErrorMessageProps) { - if (!error) return null + if (!error) return null; return (

{error}

- ) + ); } diff --git a/frontend/src/routes/login/LoggedInState.tsx b/frontend/src/proprietary/routes/login/LoggedInState.tsx similarity index 76% rename from frontend/src/routes/login/LoggedInState.tsx rename to frontend/src/proprietary/routes/login/LoggedInState.tsx index 19483b8bc7..e211e82af3 100644 --- a/frontend/src/routes/login/LoggedInState.tsx +++ b/frontend/src/proprietary/routes/login/LoggedInState.tsx @@ -1,20 +1,20 @@ -import { useEffect } from 'react' -import { useNavigate } from 'react-router-dom' -import { useAuth } from '../../auth/UseSession' -import { useTranslation } from 'react-i18next' +import { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useAuth } from '@app/auth/UseSession'; +import { useTranslation } from 'react-i18next'; export default function LoggedInState() { - const navigate = useNavigate() - const { user } = useAuth() - const { t } = useTranslation() + const navigate = useNavigate(); + const { user } = useAuth(); + const { t } = useTranslation(); useEffect(() => { const timer = setTimeout(() => { - navigate('/') - }, 2000) + navigate('/'); + }, 2000); - return () => clearTimeout(timer) - }, [navigate]) + return () => clearTimeout(timer); + }, [navigate]); return (
- ) + ); } diff --git a/frontend/src/routes/login/LoginHeader.tsx b/frontend/src/proprietary/routes/login/LoginHeader.tsx similarity index 91% rename from frontend/src/routes/login/LoginHeader.tsx rename to frontend/src/proprietary/routes/login/LoginHeader.tsx index 093100574b..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 @@ -18,5 +18,5 @@ export default function LoginHeader({ title, subtitle }: LoginHeaderProps) {

{subtitle}

)} - ) + ); } diff --git a/frontend/src/routes/login/NavigationLink.tsx b/frontend/src/proprietary/routes/login/NavigationLink.tsx similarity index 98% rename from frontend/src/routes/login/NavigationLink.tsx rename to frontend/src/proprietary/routes/login/NavigationLink.tsx index 965a659b92..935654381b 100644 --- a/frontend/src/routes/login/NavigationLink.tsx +++ b/frontend/src/proprietary/routes/login/NavigationLink.tsx @@ -15,5 +15,5 @@ export default function NavigationLink({ onClick, text, isDisabled = false }: Na {text} - ) + ); } diff --git a/frontend/src/routes/login/OAuthButtons.tsx b/frontend/src/proprietary/routes/login/OAuthButtons.tsx similarity index 94% rename from frontend/src/routes/login/OAuthButtons.tsx rename to frontend/src/proprietary/routes/login/OAuthButtons.tsx index 0de8f3179d..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 { useTranslation } from 'react-i18next'; +import { BASE_PATH } from '@app/constants/app'; // OAuth provider configuration const oauthProviders = [ @@ -7,7 +7,7 @@ const oauthProviders = [ { id: 'github', label: 'GitHub', file: 'github.svg', isDisabled: false }, { id: 'apple', label: 'Apple', file: 'apple.svg', isDisabled: true }, { id: 'azure', label: 'Microsoft', file: 'microsoft.svg', isDisabled: true } -] +]; interface OAuthButtonsProps { onProviderClick: (provider: 'github' | 'google' | 'apple' | 'azure') => void @@ -16,10 +16,10 @@ interface OAuthButtonsProps { } export default function OAuthButtons({ onProviderClick, isSubmitting, layout = 'vertical' }: OAuthButtonsProps) { - const { t } = useTranslation() + const { t } = useTranslation(); // Filter out disabled providers - don't show them at all - const enabledProviders = oauthProviders.filter(p => !p.isDisabled) + const enabledProviders = oauthProviders.filter(p => !p.isDisabled); if (layout === 'icons') { return ( @@ -37,7 +37,7 @@ export default function OAuthButtons({ onProviderClick, isSubmitting, layout = ' ))} - ) + ); } if (layout === 'grid') { @@ -56,7 +56,7 @@ export default function OAuthButtons({ onProviderClick, isSubmitting, layout = ' ))} - ) + ); } return ( @@ -74,5 +74,5 @@ export default function OAuthButtons({ onProviderClick, isSubmitting, layout = ' ))} - ) + ); } diff --git a/frontend/src/routes/signup/AuthService.ts b/frontend/src/proprietary/routes/signup/AuthService.ts similarity index 64% rename from frontend/src/routes/signup/AuthService.ts rename to frontend/src/proprietary/routes/signup/AuthService.ts index ce2426fa2a..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 = () => { @@ -8,7 +8,7 @@ export const useAuthService = () => { password: string, name: string ) => { - console.log('[Signup] Creating account for:', email) + console.log('[Signup] Creating account for:', email); const { user, session, error } = await springAuth.signUp({ email: email.trim(), @@ -17,38 +17,39 @@ export const useAuthService = () => { data: { full_name: name }, emailRedirectTo: `${BASE_PATH}/auth/callback` } - }) + }); if (error) { - console.error('[Signup] Sign up error:', error) - throw new Error(error.message) + console.error('[Signup] Sign up error:', error); + throw new Error(error.message); } if (user) { - console.log('[Signup] Sign up successful:', user) + console.log('[Signup] Sign up successful:', user); return { user: user, session: session, requiresEmailConfirmation: user && !session - } + }; } - throw new Error('Unknown error occurred during signup') - } + throw new Error('Unknown error occurred during signup'); + }; const signInWithProvider = async (provider: 'github' | 'google' | 'apple' | 'azure') => { const { error } = await springAuth.signInWithOAuth({ provider, options: { redirectTo: `${BASE_PATH}/auth/callback` } - }) + }); if (error) { - throw new Error(error.message) + throw new Error(error.message); } - } + }; return { 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 92% rename from frontend/src/routes/signup/SignupForm.tsx rename to frontend/src/proprietary/routes/signup/SignupForm.tsx index 2ae809467c..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 { useTranslation } from 'react-i18next' -import { SignupFieldErrors } from './SignupFormValidation' +import { useEffect } from 'react'; +import '@app/routes/authShared/auth.css'; +import { useTranslation } from 'react-i18next'; +import { SignupFieldErrors } from '@app/routes/signup/SignupFormValidation'; interface SignupFormProps { name?: string @@ -38,14 +38,14 @@ export default function SignupForm({ showName = false, showTerms = false }: SignupFormProps) { - const { t } = useTranslation() - const showConfirm = password.length >= 4 + const { t } = useTranslation(); + const showConfirm = password.length >= 4; useEffect(() => { if (!showConfirm && confirmPassword) { - setConfirmPassword('') + setConfirmPassword(''); } - }, [showConfirm, confirmPassword, setConfirmPassword]) + }, [showConfirm, confirmPassword, setConfirmPassword]); return ( <> @@ -158,5 +158,5 @@ export default function SignupForm({ {isSubmitting ? t('signup.creatingAccount') : t('signup.signUp')} - ) -} \ 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 72% rename from frontend/src/routes/signup/SignupFormValidation.ts rename to frontend/src/proprietary/routes/signup/SignupFormValidation.ts index 4b6dc6d22b..40c1ad7e7e 100644 --- a/frontend/src/routes/signup/SignupFormValidation.ts +++ b/frontend/src/proprietary/routes/signup/SignupFormValidation.ts @@ -1,4 +1,4 @@ -import { useTranslation } from 'react-i18next' +import { useTranslation } from 'react-i18next'; export interface SignupFieldErrors { name?: string @@ -14,7 +14,7 @@ export interface SignupValidationResult { } export const useSignupFormValidation = () => { - const { t } = useTranslation() + const { t } = useTranslation(); const validateSignupForm = ( email: string, @@ -22,43 +22,45 @@ export const useSignupFormValidation = () => { confirmPassword: string, name?: string ): SignupValidationResult => { - const fieldErrors: SignupFieldErrors = {} + const fieldErrors: SignupFieldErrors = {}; // Validate name if (name !== undefined && name !== null && !name.trim()) { - fieldErrors.name = t('signup.nameRequired', 'Name is required') + fieldErrors.name = t('signup.nameRequired', 'Name is required'); } // Validate email - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!email) { - fieldErrors.email = t('signup.emailRequired', 'Email is required') + fieldErrors.email = t('signup.emailRequired', 'Email is required'); } else if (!emailRegex.test(email)) { - fieldErrors.email = t('signup.invalidEmail') + fieldErrors.email = t('signup.invalidEmail'); } // Validate password if (!password) { - fieldErrors.password = t('signup.passwordRequired', 'Password is required') + fieldErrors.password = t('signup.passwordRequired', 'Password is required'); + } else if (password.length < 6) { + fieldErrors.password = t('signup.passwordTooShort'); } // Validate confirm password if (!confirmPassword) { - fieldErrors.confirmPassword = t('signup.confirmPasswordRequired', 'Please confirm your password') + fieldErrors.confirmPassword = t('signup.confirmPasswordRequired', 'Please confirm your password'); } else if (password !== confirmPassword) { - fieldErrors.confirmPassword = t('signup.passwordsDoNotMatch') + fieldErrors.confirmPassword = t('signup.passwordsDoNotMatch'); } - const hasErrors = Object.keys(fieldErrors).length > 0 + const hasErrors = Object.keys(fieldErrors).length > 0; return { isValid: !hasErrors, error: null, // Don't show generic error, field errors are more specific fieldErrors: hasErrors ? fieldErrors : undefined - } - } + }; + }; return { validateSignupForm - } -} \ No newline at end of file + }; +}; \ No newline at end of file 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/src/utils/scarfTracking.ts b/frontend/src/utils/scarfTracking.ts deleted file mode 100644 index 1c6688b009..0000000000 --- a/frontend/src/utils/scarfTracking.ts +++ /dev/null @@ -1,26 +0,0 @@ -let lastFiredPathname: string | null = null; -let lastFiredTime = 0; - -/** - * Fire scarf pixel for analytics tracking - * Only fires if pathname is different from last call or enough time has passed - */ -export function firePixel(pathname: string): void { - const now = Date.now(); - - // Only fire if pathname changed or it's been at least 1 second since last fire - if (pathname === lastFiredPathname && now - lastFiredTime < 250) { - return; - } - - lastFiredPathname = pathname; - lastFiredTime = now; - - const url = 'https://static.scarf.sh/a.png?x-pxid=3c1d68de-8945-4e9f-873f-65320b6fabf7' - + '&path=' + encodeURIComponent(pathname); - - const img = new Image(); - img.referrerPolicy = "no-referrer-when-downgrade"; - img.src = url; -} - 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 4730d92cca..c764d17c78 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: { host: true, // Listen on all addresses (0.0.0.0) - allows access from any domain/IP proxy: { 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' - } } });