diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b38abe5dc..be04dbd64 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 250f71abb..f8058d906 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 75c5dd8ad..2cc988cfa 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 d9b8836f4..310fc43ab 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 82daf89e7..9657d8f15 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 4a2fef040..b578d7c42 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 602116e4f..70417f65b 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 322fd2709..bee830430 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 4668e9a38..870c96f23 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 000000000..0f1c31cf8 --- /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 000000000..b8ebfd42b --- /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 000000000..92e08e4aa --- /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 000000000..c7d217b34 --- /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 000000000..6f0488aa2 --- /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 000000000..5dd59d668 --- /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 000000000..92075ff3a --- /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 000000000..77ee17f89 --- /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 b563bdcd8..b8c8bcc57 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 7dd9e15cd..c884272c4 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 c49b2297b..892e48569 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 f5908b086..7ca6ab9c8 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 74b5e0534..000000000 --- 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 b42d14c9a..000000000 --- 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 000000000..e87843325 --- /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 000000000..4dbd632b9 --- /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 4f8c203ca..440ab4acb 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 31c991208..d04fd11ac 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 cf30f2e7e..c61b61cfd 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 87362f74d..4b9de1cbb 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 b7af60295..aca7430ce 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 80b950a33..f3643de35 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 744882b43..d9b4defec 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 0f9aa2883..471198d8e 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 a873b7211..fe833c17f 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 54901902c..fbafa8b89 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 7f6bf0950..93ed2b05a 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 054f7c535..1895371da 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 c7e833404..6da3b553e 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 78f90a97a..c4bd72e16 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 55a3766b9..c9f72a7ad 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 7bc8d27bc..d32ed0314 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 d4ef7bd07..428dbb53a 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 771499584..75d8f0e50 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 160ddcc62..f898cbc67 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 556ecc4f1..439af6996 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 a721961ec..d8c0aac70 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 78ab8ce39..71abaa53f 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 8dee9e278..27482df51 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 3f101ab0b..070187485 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 f47da0dca..2b318604c 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 1b5953a63..7f6d9f26d 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 0ad8a4137..d27819a2b 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 b52da494b..4a4a770f1 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 82aeaf26a..0e4eea9c9 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 16ec84453..50b304e0b 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 715929567..c76aa2a43 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 b7b18e239..9cfc1e4c3 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 13f702e69..079ea747e 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 3017d3a11..896da5780 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 f6d77a3e4..f0124b2c6 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 e61caab6a..c8d170dde 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 37d35953c..49812da61 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 46652d85a..6a7bbec53 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 c2787d05e..70652af45 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 26fcfb8da..dbcdb6cf9 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 7ac6a8377..b39fe663d 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 e921903f9..1d3ecfb22 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 23faa99af..03479c943 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 000000000..7a8974a3a --- /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 62fad704e..9a333878a 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 a710823e9..45cd7ad1b 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 4253ac46e..09bcd20fe 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 e3adf1def..12a509abd 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 97b109ef2..3354f06d7 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 a8e4a2725..8ab206b70 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 853e341aa..43333aff1 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 50d43dc06..6eff26db9 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 b03995fc7..8a78e7631 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 678bedca1..5bd31008d 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 bb571b589..336070a74 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 eb2917029..4377c851c 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 935fa4ac1..fa3e42bae 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 0a5e2711b..efdb1c226 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 a82ed430d..52ee4165b 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 1c55f5f0a..51b3155b3 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 293efc1b4..f25aaedfc 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 507dab16b..53e239064 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 000000000..dced85215 --- /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 6d16c6c34..25f85688c 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 8188be435..faff07427 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 0e918151f..2329d624d 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 cbed210a2..d10d4df07 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 18efba256..992aa79b5 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 149aa9eaa..551ef1328 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 63c69bb08..0203e83c0 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 4d9a4bd51..d3c25f653 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 775cbbee1..77db24d46 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 62f01f9ef..6c6ac6999 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 000000000..7be820620 --- /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 d52535aef..b97b17a0c 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 ac539368b..cb967378b 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 45963582e..b979a22b1 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 f2aed551d..663295b38 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 a8f742fe2..647364f19 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 b29b97fce..bf04d89b3 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 7f6170529..cb90e502b 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 4cf0f938f..c17c88f6a 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 ef19c44cc..9ed833e9c 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 860f13bb6..fbbfeebbf 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 69a77a8f3..42f45cb64 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 fccc12605..efe1a46f1 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 6c489cd0f..9d51ecc99 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 937ff3d07..da71d3c6c 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 520f1730a..2839ccb9d 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 762fb6eaa..4e552cec0 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 022bfea45..3eb90db6e 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 a44868a6e..6209fb4b6 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 07e6510e6..61dfe2a84 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 48fff701e..e8b3b5b41 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 cf4245770..d57a77a5f 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 71b95db27..ffa465fc9 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 9a08414b1..043cb09f9 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 03e028834..84658daef 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 0ffa3102e..ba49ffb70 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 e8e504ded..7a91cdbe3 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 0e347cd1c..8bd85966a 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 1b0cc1539..dd1d0f836 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 38993bc30..825ad3591 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 d0b1045f2..e13ab3801 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 ce76b7375..4c01b492b 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 c2d94d203..4b6ea3eb4 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 770cf2eee..af0eb11bd 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 f158f036e..396f97ed6 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 89d1b025c..bfa2eb91a 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 632ed71f1..80078d0d7 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 0b7ecb02e..09b0218a8 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 86888d0e4..2cb4ff17c 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 2907ff498..c64f1cac1 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 8a762278a..830703f21 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 775ee9009..160aaa39a 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 ca5c1e2e1..a8b910697 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 b483eca74..4dea56e1e 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 beb8c432c..e0aa7dfc7 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 25091d854..c9a9dbd96 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 d1c0d0c9f..058b38bc4 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 b6299f474..2c2d52f90 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 0001aec45..173d18a6a 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 8d13073a5..ac53a9a5a 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 c41c440fc..12b9c0a1a 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 3df4900f8..3f6ee99e9 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 90e75e98a..347c4f185 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 4ebe62356..1e9b224e8 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 e64b03646..39f614845 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 f92ca48e5..89a74076d 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 a445084b0..b4a1dcd3d 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 2c7548df8..19bb42d83 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 cee909fca..eb3655c86 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 6993186bb..061eac659 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 0f2722873..f713ca24b 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 a50fb98ca..3fb42b46c 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 ce19b8012..5fc9fe10f 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 16dfc199f..939c05acc 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 d71655cdc..c5e5fc933 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 9262bcba4..104be7faa 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 9c3ec4de6..f0e268d4c 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 a05ab509d..836c14fed 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 f29a63a18..7871033b9 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 105a8981a..41c56558f 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 9c3a637dc..1b53ff900 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 9294d5635..3b7733cf0 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 2185d0be7..a4b415856 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 a0215c1f2..7a5c66860 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 6958ca7d4..3fc6b0a2a 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 967ac1d65..f0c76f04c 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 74da5b745..0c4aed6a3 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 a11ba5b72..ffedbe70d 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 6fac53f4d..6e584618e 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 2d514a161..4cf85c66c 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 aa99be742..f6ddbe241 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 ef95718e9..c13bb4f72 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 0edffe21d..9bf733e10 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 beb139e50..323114407 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 fbd983a18..ec86ea57d 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 e46e7799d..abcf7330c 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 02b5715cd..3086dd587 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 d126c7d31..c50d20580 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 06ac6ac69..db6c4e731 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 7304c09b0..7a7c93d67 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 070fe8b6a..fd7b1ec97 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 1767726db..e56bb6b2a 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 99d0809ab..f2832cb3a 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 9b065e571..d332f888e 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 0d82181f7..e5649f241 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 18d2bafcb..0b699693e 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 03d316c93..5139f99ef 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 a098d39af..dd668c607 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 8607e3b94..abed4fd47 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 9643b39ae..fae3afe57 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 2dde8b53a..6d4b9dc10 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 8386ad493..ad3849595 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 31323ee81..648f79267 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 8363396d9..2ebf93b35 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 6355c3828..adaf36098 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 302777261..b60c7565b 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 7989fa6d0..821d708a5 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 a12695081..cb036e171 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 a6965bb09..ca4d5fc24 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 31f0fe301..428853b53 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 959601166..abd0d6285 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 43ba64db5..86b788183 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 296bd73bb..7b748b6ab 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 92f359abd..064a0b2a8 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 26a96056b..4e482c7f2 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 c073bc520..47f15da66 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 2bfe94e06..4b516aa3b 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 71e48596a..badea4634 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 35bb3dc5d..84d6f65b9 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 e2618ad42..0b4ee89d9 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 fa4ec6e55..e39cab96c 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 cb1f480d3..c9463ad76 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 2d8d0b7d6..13b3ded2b 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 9aac9cd31..bf0a006d6 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 cd97dbd96..edc07de7e 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 13328a631..cf23766ad 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 ea134b93b..a18664f7f 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 ac0db45ce..a49342cd5 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 8449c2000..d449578b1 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 f8c1ea83d..2136817ff 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 055de2466..bb40faefd 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 21ef7c0aa..1aaa76010 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 e0aef436a..28afd15d1 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 8979f344e..017934c20 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 f63cfe593..aed2c5d6e 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 5ce118bbe..b1e8933f5 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 399a3ab5d..feb4004f7 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 243e787b5..30c8c906e 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 ad8720f19..bd7517c79 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 e20af455c..89c39aad8 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 24619387f..8090b85aa 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 53d74c47b..3ff8a3cc9 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 e2d77ff85..8e1b986cf 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 6a4e4bbe8..09200727d 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 11bf7009f..dbd9ccb1a 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 a6ad634e5..ac328897d 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 ca20c24cc..e2349ac88 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 fc3963128..5b756c8ba 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 d94003d2c..00c6de54d 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 d7ca66f25..d1eea7deb 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 f97fe4d75..16e0b90a7 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 7cb2c7957..ccda07370 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 bd7a48de7..a744212a4 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 23d83ca28..d981662e1 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 8d8f58e15..68b95e3b7 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 e534205fa..c6bef701f 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 462710cf5..342c6713e 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 3b8312b3d..33d76144f 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 696a4f9f3..624dc31db 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 ea699152b..7a361a64c 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 dbd6bd9d2..71bef0dd6 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 e1b4532c1..004a97066 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 50e8ea9ce..8b77e39b7 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 e690bf284..f453f22b8 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 77245a130..4cc480502 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 9e6a13076..23633e8a4 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 3b8618955..60e2e17d2 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 39c6fc299..9075f8a96 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 c42e8d63a..c49ceaca2 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 a60e5a4bc..aa927594b 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 554c71540..decd109ef 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 0ae5e387e..d57182711 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 eb4980179..f7502592f 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 70874968d..19c03116f 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 d51034992..aed449cd4 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 6c9910299..7689a6a2a 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 a011bd4ee..ef054bdb8 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 1da2a1ad1..a20fbc81d 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 1ec303cd6..06ad72abf 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 58cc5f9d5..3fa8f7234 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 b7dfd57f3..83ad3e85e 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 7f84aa325..022a30553 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 6b68565f1..a8cbaf49e 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 79dc3f65a..43ec61914 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 0ccead8d6..57105be6e 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 bfc80a7d9..536806348 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 d9ffbd7d9..ede2b0bf3 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 62e49d861..05b50ecab 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 4daa0c554..f85058a73 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 20983bc92..1bf5d5991 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 352fdee50..bdbf80429 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 d9eae66c4..bfe75df2f 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 25efcb7dd..87a5d7514 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 26e8c73ee..a2efd1041 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 48373ba02..93d05b377 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 30aa9b304..5b12590d7 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 45522f7f8..f918b3bea 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 67bb4c446..4b0eadd23 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 ff91153ad..da6f6472a 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 f57c8dd78..3492c8166 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 2042c0487..6eb8d58e0 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 81a2eaa99..e256ecc8d 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 fc3a583bc..a5e3f13d5 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 e6c515941..510a6c1a6 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 dab9ff826..e296c9d6d 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 129cf00bd..000bf47d9 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 ea0237518..95153f5d2 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 50352ae07..deff3cfe4 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 9f849203e..63a8ba4e3 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 27e977788..0fdd64d9e 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 824c87268..60d95b676 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 8c7f6182d..75c6d9276 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 e850fa4dd..468609f7d 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 c5a0f2649..c7d353c41 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 6c9130f00..4a29cd97e 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 b29a26d25..377ee43e6 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 d2898e46d..21bdadc4d 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 e9c9cead7..b28d1b35b 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 6366545af..5919a53e4 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 edcbc0711..6568c9ff4 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 bbb165564..753a52414 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 77dcf5567..6a131ebed 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 30a020501..fb8e5e48f 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 57e38b92d..2c8670012 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 8c6c0c05b..3c55fd394 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 e3aa94487..8e0bea44a 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 3811572c0..2baa22a86 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 2474f1094..c37da46bb 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 c1b23d408..5b4d1d2d9 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 e42860562..d046fe87d 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 a004831cc..5fa54f33c 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 c65fec127..93feac375 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 5d19b3674..42fdd6f15 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 a0204f1ca..0733d9fcc 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 000000000..d0a64efa5 --- /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 f50b5ed55..0860b5d96 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 91e216c18..9785fa998 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 fe254aac5..7a1b1753e 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 f271a5a5a..7b8e003f7 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 92a876087..7c09938c5 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 50fe74d56..9c05e8f01 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 d718a1762..6dcdec4eb 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 5b9a25da6..53a89abb9 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 c52ed9864..176ddd4b5 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 14dd543d8..9160c0ce7 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 458e7fda1..bf95b9854 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 d68cdd861..6fb9ef71e 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 108d7d3ea..07c6dff84 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 237cc7cf6..60c7887ff 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 ede570c33..7e6e149ce 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 e7a2ea19c..004f28902 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 91df79ac9..c86d112d6 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 8ad7a80b6..a4bba4857 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 dfa2b79b5..378380050 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 5daed63c3..c01fde036 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 fd794379b..dd7442398 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 0422e7d56..c81b73fea 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 aa49cb31c..374cffd2c 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 8836189ac..cade2be5a 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 1f1c8695b..828fa01ab 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 fb27ef7a5..f932f658f 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 0523166de..cbc07ed6c 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 423e19d7e..9df398b66 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 b85f5533f..22cd5c67c 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 89b6c07d8..6e391f739 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 fe85434a5..585f1c172 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 7092798b7..4a28df2a5 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 ef468032d..5b1417b21 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 d551dc292..1ae9298f5 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 4aaed74ee..28080407d 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 1c809c190..340115a81 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 74a1bd3a1..c9c19176e 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 e208d4479..e626671f9 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 452b3ddf1..85d1cc30d 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 d16cb5af5..443d79a1c 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 a5ef98357..317630317 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 d5937b59c..183fdd2a7 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 e2b687434..f36b9d078 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 98c5b9655..af47ab3e1 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 4d41c5162..bcdd62167 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 a334babb6..e21814a4f 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 8294cdf6e..d5fbf5ef9 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 2abc416ca..b9b0c3b7a 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 b2d3a434a..6e86a083e 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 a3fd546d2..a2b687031 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 268962883..a3499eb78 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 c401d7205..056747e84 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 b96aeaaf8..f2b684b7b 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 13cbc860c..5c10700c7 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 8ca6cc84d..9e7460d85 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 407716395..bf2a05121 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 b87719ad9..40e350010 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 33e95e93d..f29f56f96 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 cdf16846e..4078b2b07 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 b62e1da08..55a5c81f9 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 15cfe1724..ddb0ba2d2 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 b6716c681..4a57f8bf8 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 48ade3940..a2a1277b9 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 59903ccfc..67476734a 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 0f6649598..e975cf8d5 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 f57a9e93e..5684bc003 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 aa9f5d574..85ca86545 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 31484f54e..e2b013909 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 d3dc93f7b..f29ba1511 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 e2a76638b..ce6140730 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 f7310847b..d3d2a4c5c 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 fc39db546..9c2ad4981 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 ca5af1327..de18207fb 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 ce5e93ec4..59f8c9eea 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 5c924de93..9b613d764 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 45eb8e8dd..87713a5b4 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 2b269aa1a..a91459715 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 53370ca5a..93dd6a560 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 3399d8b21..c7b1e1a5e 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 6d3393fcc..1c9233e9a 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 dff87bb8a..f69f98caf 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 97e539fcb..580fabe31 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 f86a6c81a..60559e548 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 9e050a7e5..18978f945 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 65f7a4b58..144a31678 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 bb028c0e7..ef4b89b94 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 56174a73a..aad6556ea 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 5747ec226..a8e6a88a0 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 f5e575a14..3d8e1406e 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 eb5a3f37d..086a00f49 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 ba128c54d..79bca1da8 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 bc379a36d..f81097db6 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 ab51c0cc4..db34b93bd 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 df401b1a4..7005ae062 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 955149868..c2cfe02a5 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 8d77604e5..ca3d556e2 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 c60375a94..b2a45cd74 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 ad2536643..e4624bafd 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 9101e3e3e..4678d4481 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 a1149c443..c3b7cbea9 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 d17cb2684..9ae2ab43e 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 27402e5c3..78378f6d6 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 0d8946e5f..c055a80a7 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 820fc78cb..5e5bf8fa3 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 f23ddbb12..4596a0fe7 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 5f026a89d..b61e928d1 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 9f6e1c20c..cac9b158a 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 7785f4c13..864b08aea 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 06a7d7530..b348f506f 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 9b4ed3950..25c0687e1 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 8e0b48344..1a485c37b 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 d4615b52f..cdff64c43 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 6ee5310d7..981fa02e3 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 6ef96aea2..bb98afc8c 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 d7321c1b3..00c3af432 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 5db03705e..f8e237dc8 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 1dd324ce7..5c437d717 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 f87c0187a..3c418aac2 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 2f0ab923d..932428dd0 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 c29b5bd36..93c7fe286 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 0d583201c..c07b23591 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 5176c1225..ce0d5945e 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 5c9ead572..9e60c2357 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 c0431eef5..174946335 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 23b8f6d37..b116545e2 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 77b7f79ac..cabfbb83d 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 a7db9b07e..9d01efc3e 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 5fc049007..6e768c0b0 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 000000000..ff0d09ddf --- /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 c90101733..aa43b0189 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 000000000..b0297d510 --- /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 000000000..7de00567a --- /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 42f92e0f1..50065b6cf 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 3cf6179bf..857108ed4 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 694fdeeb7..48f7b241b 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 75d4c4c7f..fcc543d27 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 1fdc8f2c7..7b0c055a2 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 8bfe18a64..79850f559 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 51ef2e9c3..7b7d9a923 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 545285c5e..577dfa5f2 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 c4531346e..283ccbc0e 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 475c5a25b..f546ed8bf 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 000000000..0b6a293ff --- /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 000000000..f7de717a3 --- /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 54a967509..edcb2a535 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 be58d0a6e..b084d2eb1 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 5655902a0..e168e530b 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 be822b846..261adb6c0 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 b4b128164..3668f5cf2 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 5f5545e76..b3304aba6 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 cb5b02b87..d2956c38a 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 044af4199..fa5160adf 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 fa6d4775f..8c6fb90b1 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 d42eeeab2..ebbd4d2b0 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 74e2e9407..3c1dd2b38 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 abcd492ac..02d29898c 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 da5e4350b..5894eae50 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 820cfcbef..53a4356be 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 f6871008d..2cc55cf39 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 cdcc725fe..1468b8dc4 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 25b11cef0..36434a293 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 2d76a623f..c20b7aa47 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 656cc493b..8e92cf350 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 2b5162cad..f7f157283 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 642372870..c69fcd3d3 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 b24cd17d9..f1bc929dd 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 5e250030e..2d2e387a2 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 1b8c437f1..5d0d899d7 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 45cd461e8..a47bb26fc 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 cf0474dac..2fbb07b81 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 908ab1504..2991ecaad 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 4251d3124..3e4caa8b8 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 80b3c74cf..72f435e87 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 933e78611..c248eab96 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 57566750b..3740c5f22 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 c29491437..0986422ab 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 87b6c53cc..efb99ee8a 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 3bafbd329..c7c040f2b 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 0de528a40..7acd606fa 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 1ae862e6a..66b1ab2f7 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 c00f880b3..73e91cc0d 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 c91ad8825..11e716656 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 de3821710..6e89cdeee 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 fd8dabc9c..10d6b491e 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 455828b7d..988667a97 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 3982d1520..7035a52e3 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 6fbc92b09..9b4815328 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 9019e6fc7..51353cad4 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 4cf6e6b6e..57c8b3025 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 de124d8b0..3aee009c9 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 833757ecd..6f80686cd 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 ef9f8228a..e725291db 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 c480972ad..d9ad71c7a 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 ffd83cdd5..adae6fffb 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 57a99724a..1b8608dab 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 3c15938b7..27604da0b 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 3c1518fcf..82d2f47b8 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 d7478bdac..f47a02f93 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 13a3068e6..c182d920e 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 f636f9f65..27b07a9a3 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 ec3e9762d..93b905f21 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 970eb324b..a39fc4efd 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 e2a68e883..9ce1ec2da 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 88cf4eb28..22e2fff9f 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 5486fc591..a86512b09 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 0b45d8d54..78178055c 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 9e0c46db3..121c8a9ab 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 2b0a12ff5..1acf17d63 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 64a304042..d8999a920 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 d31836feb..faa6e7932 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 96b335f5f..769a25a08 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 32034def3..c860ed93f 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 7dd4aeb18..e8ba292d5 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 0932d8555..5ad21c83d 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 78acc81b4..3dc2c41f5 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 7fb8d7132..837516487 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 7f62f945a..fa8a5da45 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 13aac82dd..0afbc7f93 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 b66b3276d..996cd5792 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 d200ffdbc..b2d7a5e89 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 b8ee88f57..5c46ed063 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 000000000..295cd3062 --- /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 0e1d48992..a6a41eefe 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 d485cd220..123bc6f4b 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 8c59be9b1..760a86d7b 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 4b7417177..b07fe961b 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 de674844c..bc1319a7d 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 4f44f949b..7441bbcef 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 63e00da46..ef2836058 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 41ee8715e..4bf8223fb 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 2773ab39d..a67d0f4f8 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 3fda8a4a5..fac7b14cc 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 2f16a7c61..6aee7e707 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 4dae97e01..06ba74dfe 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 000000000..9824d9b3b --- /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 cef144971..67b0a4123 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 062313df5..2baf7586b 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 14ae78fee..956e9843d 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 84dc64457..8faec2644 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 c57678c27..1bff28b81 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 595bf7c19..b915cdf4d 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 5fb0a86ce..c76adf856 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 12abf2ae0..6d04817be 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 c964da3c2..96d969c97 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 083d779a5..c8e9081c1 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 000000000..defb7c21e --- /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 7728627f1..0f3436b9a 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 000000000..74a42f573 --- /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 9b82240a1..888f4acfb 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 c2ebb29bf..00b5dac98 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 000000000..2361fce97 --- /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 aa3d7f443..167b2e6c5 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 000000000..e6d62693b --- /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 000000000..79795a920 --- /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 000000000..270188bc8 --- /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 285d58251..9c7a11ba7 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 641ad4785..f40290ab9 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 78d69e741..73b07063b 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 c8e0a6847..855793a93 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 0a5ee32ac..192a3a95a 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 e32f629e0..ba7df3795 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 7036e24cf..65dd6c588 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 4f237b77c..4563a2450 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 19483b8bc..e211e82af 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 093100574..2ba418635 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 965a659b9..935654381 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 0de8f3179..e7fcb1b06 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 ce2426fa2..d21bbc062 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 2ae809467..35caf7764 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 4b6dc6d22..40c1ad7e7 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 000000000..be51b165c --- /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 000000000..abc474d12 --- /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 000000000..084cffa29 --- /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 906c3cefb..000000000 --- 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 1c6688b00..000000000 --- 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 000000000..a2491e09c --- /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 3e4c6105d..f0c859e07 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 000000000..bcb363546 --- /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 4730d92cc..c764d17c7 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 dd393c6be..de759c5f8 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' - } } });