From 5e173b92d4a84237d3af763d34857be8e9b344a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:24:04 +0000 Subject: [PATCH 01/25] Bump peter-evans/create-pull-request from 7.0.5 to 7.0.6 (#2574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.5 to 7.0.6.
Release notes

Sourced from peter-evans/create-pull-request's releases.

Create Pull Request v7.0.6

⚙️ Fixes an issue with commit signing where unicode characters in file paths were not preserved.

What's Changed

New Contributors

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/create-pull-request&package-manager=github_actions&previous-version=7.0.5&new-version=7.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/licenses-update.yml | 2 +- .github/workflows/pre_commit.yml | 2 +- .github/workflows/sync_files.yml | 2 +- .github/workflows/update-translations.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/licenses-update.yml b/.github/workflows/licenses-update.yml index 409735c08..a3fdb2853 100644 --- a/.github/workflows/licenses-update.yml +++ b/.github/workflows/licenses-update.yml @@ -52,7 +52,7 @@ jobs: - name: Create Pull Request id: cpr if: env.CHANGES_DETECTED == 'true' - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "Update 3rd Party Licenses" diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml index 842257d73..5c591d89b 100644 --- a/.github/workflows/pre_commit.yml +++ b/.github/workflows/pre_commit.yml @@ -35,7 +35,7 @@ jobs: git diff --staged --quiet || git commit -m ":file_folder: pre-commit > Made via .github/workflows/pre_commit.yml" || echo "pre-commit: no changes" - name: Create Pull Request - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "ci: 🤖 format everything with pre-commit" diff --git a/.github/workflows/sync_files.yml b/.github/workflows/sync_files.yml index fbbb56abe..139f86fa0 100644 --- a/.github/workflows/sync_files.yml +++ b/.github/workflows/sync_files.yml @@ -42,7 +42,7 @@ jobs: git diff --staged --quiet || git commit -m ":memo: Sync README > Made via sync_files.yml" || echo "no changes" - name: Create Pull Request - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: Update files diff --git a/.github/workflows/update-translations.yml b/.github/workflows/update-translations.yml index c6b408c3b..84d9c2226 100644 --- a/.github/workflows/update-translations.yml +++ b/.github/workflows/update-translations.yml @@ -50,7 +50,7 @@ jobs: - name: Create Pull Request id: cpr if: env.CHANGES_DETECTED == 'true' - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "Update translation files" From d5faddbc8516b7ae9ea3b08ad0368d6725d28368 Mon Sep 17 00:00:00 2001 From: Omar Ahmed Hassan <98468609+omar-ahmed42@users.noreply.github.com> Date: Thu, 2 Jan 2025 16:48:20 +0200 Subject: [PATCH 02/25] Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577) # Description Enhance NFunction sanitization and support advanced functions: - Start page counting from 1 rather than 0 as PDFs are one based from the user's perspective, thus functions results would be affected by starting with "0" rather than "1". - Ignore out of bound results rather than stopping iterations to work with functions such as (n - 4) when page count is 10 as we would get positive values when n > 4. - Remove spaces to support expressions such as 2n + 1 rather just 2n+1. - Support advanced functions as follows: - Support expressions such as follows 5(n-1), n(n-1), expressions followed by opening rounded without '*' operator. - Support expressions such as follows (n-1)5, (n-1)n, expressions preceded closing rounded without '*' operator. - Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn. Closes #(issue_number) ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [x] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [x] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- cucumber/features/general.feature | 12 ++-- .../software/SPDF/utils/GeneralUtils.java | 37 +++++++++--- .../software/SPDF/utils/GeneralUtilsTest.java | 59 ++++++++++++++++++- 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/cucumber/features/general.feature b/cucumber/features/general.feature index 4255c89e7..3ac610669 100644 --- a/cucumber/features/general.feature +++ b/cucumber/features/general.feature @@ -1,7 +1,7 @@ @general Feature: API Validation - + @split-pdf-by-sections @positive Scenario Outline: split-pdf-by-sections with different parameters Given I generate a PDF file as "fileInput" @@ -66,7 +66,7 @@ Feature: API Validation | pageNumbers | file_count | | 1,3,5-9 | 8 | | all | 20 | - | 2n+1 | 11 | + | 2n+1 | 10 | | 3n | 7 | @@ -106,9 +106,9 @@ Feature: API Validation And the response ZIP should contain 2 files And the response file should have size greater than 0 And the response status code should be 200 - + Examples: - | format | - | png | + | format | + | png | | gif | - | jpeg | + | jpeg | diff --git a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java index ac4cdca8f..799511452 100644 --- a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java +++ b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java @@ -13,6 +13,8 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.simpleyaml.configuration.file.YamlFile; import org.simpleyaml.configuration.file.YamlFileWrapper; @@ -220,32 +222,51 @@ public class GeneralUtils { throw new IllegalArgumentException("Invalid expression"); } - int n = 0; - while (true) { + for (int n = 1; n <= maxValue; n++) { // Replace 'n' with the current value of n, correctly handling numbers before // 'n' - String sanitizedExpression = insertMultiplicationBeforeN(expression, n); + String sanitizedExpression = sanitizeNFunction(expression, n); Double result = evaluator.evaluate(sanitizedExpression); // Check if the result is null or not within bounds - if (result == null || result <= 0 || result.intValue() > maxValue) { - if (n != 0) break; - } else { + if (result == null) + break; + + if (result.intValue() > 0 && result.intValue() <= maxValue) results.add(result.intValue()); - } - n++; } return results; } + private static String sanitizeNFunction(String expression, int nValue) { + String sanitizedExpression = expression.replace(" ", ""); + String multiplyByOpeningRoundBracketPattern = "([0-9n)])\\("; // example: n(n-1), 9(n-1), (n-1)(n-2) + sanitizedExpression = sanitizedExpression.replaceAll(multiplyByOpeningRoundBracketPattern, "$1*("); + + String multiplyByClosingRoundBracketPattern = "\\)([0-9n)])"; // example: (n-1)n, (n-1)9, (n-1)(n-2) + sanitizedExpression = sanitizedExpression.replaceAll(multiplyByClosingRoundBracketPattern, ")*$1"); + + sanitizedExpression = insertMultiplicationBeforeN(sanitizedExpression, nValue); + return sanitizedExpression; + } + private static String insertMultiplicationBeforeN(String expression, int nValue) { // Insert multiplication between a number and 'n' (e.g., "4n" becomes "4*n") String withMultiplication = expression.replaceAll("(\\d)n", "$1*n"); + withMultiplication = formatConsecutiveNsForNFunction(withMultiplication); // Now replace 'n' with its current value return withMultiplication.replace("n", String.valueOf(nValue)); } + private static String formatConsecutiveNsForNFunction(String expression) { + String text = expression; + while (text.matches(".*n{2,}.*")) { + text = text.replaceAll("(? handlePart(String part, int totalPages, int offset) { List partResult = new ArrayList<>(); diff --git a/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java index be63e8d36..18afcad62 100644 --- a/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java +++ b/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java @@ -52,14 +52,68 @@ public class GeneralUtilsTest { @Test void nFuncAdvanced3() { List result = GeneralUtils.parsePageList(new String[]{"4n+1"}, 9, true); - assertEquals(List.of(1, 5, 9), result, "'All' keyword should return all pages."); + assertEquals(List.of(5, 9), result, "'All' keyword should return all pages."); + } + + @Test + void nFunc_spaces() { + List result = GeneralUtils.parsePageList(new String[]{"n + 1"}, 9, true); + assertEquals(List.of(2, 3, 4, 5, 6, 7, 8, 9), result); + } + + @Test + void nFunc_consecutive_Ns_nnn() { + List result = GeneralUtils.parsePageList(new String[]{"nnn"}, 9, true); + assertEquals(List.of(1, 8), result); + } + + @Test + void nFunc_consecutive_Ns_nn() { + List result = GeneralUtils.parsePageList(new String[]{"nn"}, 9, true); + assertEquals(List.of(1, 4, 9), result); + } + + @Test + void nFunc_opening_closing_round_brackets() { + List result = GeneralUtils.parsePageList(new String[]{"(n-1)(n-2)"}, 9, true); + assertEquals(List.of(2, 6), result); + } + + @Test + void nFunc_opening_round_brackets() { + List result = GeneralUtils.parsePageList(new String[]{"2(n-1)"}, 9, true); + assertEquals(List.of(2, 4, 6, 8), result); + } + + @Test + void nFunc_opening_round_brackets_n() { + List result = GeneralUtils.parsePageList(new String[]{"n(n-1)"}, 9, true); + assertEquals(List.of(2, 6), result); + } + + @Test + void nFunc_closing_round_brackets() { + List result = GeneralUtils.parsePageList(new String[]{"(n-1)2"}, 9, true); + assertEquals(List.of(2, 4, 6, 8), result); + } + + @Test + void nFunc_closing_round_brackets_n() { + List result = GeneralUtils.parsePageList(new String[]{"(n-1)n"}, 9, true); + assertEquals(List.of(2, 6), result); + } + + @Test + void nFunc_function_surrounded_with_brackets() { + List result = GeneralUtils.parsePageList(new String[]{"(n-1)"}, 9, true); + assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8), result); } @Test void nFuncAdvanced4() { List result = GeneralUtils.parsePageList(new String[]{"3+2n"}, 9, true); - assertEquals(List.of(3, 5, 7, 9), result, "'All' keyword should return all pages."); + assertEquals(List.of(5, 7, 9), result, "'All' keyword should return all pages."); } @Test @@ -80,7 +134,6 @@ public class GeneralUtilsTest { assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly."); } - @Test void testParsePageListWithRangeZeroBaseOutput() { List result = GeneralUtils.parsePageList(new String[]{"1-3"}, 5, false); From f45de05c99ddc11cb2562b7e448211b1bbf1f2d1 Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 15:52:07 +0100 Subject: [PATCH 03/25] Fixes SSO login rejection (#2566) # Description ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [x] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [x] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .../security/UserAuthenticationFilter.java | 64 ++++++++++++++++++- .../controller/web/AccountWebController.java | 3 + src/main/resources/messages_en_GB.properties | 1 + 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java index 93dff07bb..be425590e 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java @@ -22,22 +22,31 @@ import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.SPDF.config.security.session.SessionPersistentRegistry; import stirling.software.SPDF.model.ApiKeyAuthenticationToken; +import stirling.software.SPDF.model.ApplicationProperties; +import stirling.software.SPDF.model.ApplicationProperties.Security; +import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2; +import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2; import stirling.software.SPDF.model.User; +@Slf4j @Component public class UserAuthenticationFilter extends OncePerRequestFilter { + private final ApplicationProperties applicationProperties; private final UserService userService; private final SessionPersistentRegistry sessionPersistentRegistry; private final boolean loginEnabledValue; public UserAuthenticationFilter( + @Lazy ApplicationProperties applicationProperties, @Lazy UserService userService, SessionPersistentRegistry sessionPersistentRegistry, @Qualifier("loginEnabled") boolean loginEnabledValue) { + this.applicationProperties = applicationProperties; this.userService = userService; this.sessionPersistentRegistry = sessionPersistentRegistry; this.loginEnabledValue = loginEnabledValue; @@ -121,33 +130,67 @@ public class UserAuthenticationFilter extends OncePerRequestFilter { // Check if the authenticated user is disabled and invalidate their session if so if (authentication != null && authentication.isAuthenticated()) { + + Security securityProp = applicationProperties.getSecurity(); + LoginMethod loginMethod = LoginMethod.UNKNOWN; + + boolean blockRegistration = false; + + // Extract username and determine the login method Object principal = authentication.getPrincipal(); String username = null; if (principal instanceof UserDetails) { username = ((UserDetails) principal).getUsername(); + loginMethod = LoginMethod.USERDETAILS; } else if (principal instanceof OAuth2User) { username = ((OAuth2User) principal).getName(); + loginMethod = LoginMethod.OAUTH2USER; + OAUTH2 oAuth = securityProp.getOauth2(); + blockRegistration = oAuth != null && oAuth.getBlockRegistration(); } else if (principal instanceof CustomSaml2AuthenticatedPrincipal) { username = ((CustomSaml2AuthenticatedPrincipal) principal).getName(); + loginMethod = LoginMethod.SAML2USER; + SAML2 saml2 = securityProp.getSaml2(); + blockRegistration = saml2 != null && saml2.getBlockRegistration(); } else if (principal instanceof String) { username = (String) principal; + loginMethod = LoginMethod.STRINGUSER; } + // Retrieve all active sessions for the user List sessionsInformations = sessionPersistentRegistry.getAllSessions(principal, false); + // Check if the user exists, is disabled, or needs session invalidation if (username != null) { + log.debug("Validating user: {}", username); boolean isUserExists = userService.usernameExistsIgnoreCase(username); boolean isUserDisabled = userService.isUserDisabled(username); + boolean notSsoLogin = + !loginMethod.equals(LoginMethod.OAUTH2USER) + && !loginMethod.equals(LoginMethod.SAML2USER); + + // Block user registration if not allowed by configuration + if (blockRegistration && !isUserExists) { + log.warn("Blocked registration for OAuth2/SAML user: {}", username); + response.sendRedirect( + request.getContextPath() + "/logout?oauth2_admin_blocked_user=true"); + return; + } + + // Expire sessions and logout if the user does not exist or is disabled if (!isUserExists || isUserDisabled) { + log.info( + "Invalidating session for disabled or non-existent user: {}", username); for (SessionInformation sessionsInformation : sessionsInformations) { sessionsInformation.expireNow(); sessionPersistentRegistry.expireSession(sessionsInformation.getSessionId()); } } - if (!isUserExists) { + // Redirect to logout if credentials are invalid + if (!isUserExists && notSsoLogin) { response.sendRedirect(request.getContextPath() + "/logout?badcredentials=true"); return; } @@ -161,6 +204,25 @@ public class UserAuthenticationFilter extends OncePerRequestFilter { filterChain.doFilter(request, response); } + private enum LoginMethod { + USERDETAILS("UserDetails"), + OAUTH2USER("OAuth2User"), + STRINGUSER("StringUser"), + UNKNOWN("Unknown"), + SAML2USER("Saml2User"); + + private String method; + + LoginMethod(String method) { + this.method = method; + } + + @Override + public String toString() { + return method; + } + } + @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { String uri = request.getRequestURI(); diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java index 81b46166b..31c39c1fc 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java @@ -163,6 +163,9 @@ public class AccountWebController { case "invalid_destination": erroroauth = "login.invalid_destination"; break; + case "relying_party_registration_not_found": + erroroauth = "login.relyingPartyRegistrationNotFound"; + break; // Valid InResponseTo was not available from the validation context, unable to // evaluate case "invalid_in_response_to": diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 73e56c9d0..8caba5a1a 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. From a4c988c7b20f84bee063b254766c959de0c73783 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:55:42 +0000 Subject: [PATCH 04/25] Bump gradle from 8.11-jdk17 to 8.12-jdk17 (#2556) Bumps gradle from 8.11-jdk17 to 8.12-jdk17. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gradle&package-manager=docker&previous-version=8.11-jdk17&new-version=8.12-jdk17)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.fat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.fat b/Dockerfile.fat index 1ee201763..b36677b9b 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -1,5 +1,5 @@ # Build the application -FROM gradle:8.11-jdk17 AS build +FROM gradle:8.12-jdk17 AS build # Set the working directory WORKDIR /app From 715efca25d4aa2f7b20561fd9cfa61a5d153ade0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:01:30 +0000 Subject: [PATCH 05/25] Update translation files (#2579) Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Signed-off-by: GitHub Action Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/main/resources/messages_ar_AR.properties | 1 + src/main/resources/messages_az_AZ.properties | 1 + src/main/resources/messages_bg_BG.properties | 1 + src/main/resources/messages_ca_CA.properties | 1 + src/main/resources/messages_cs_CZ.properties | 1 + src/main/resources/messages_da_DK.properties | 1 + src/main/resources/messages_de_DE.properties | 1 + src/main/resources/messages_el_GR.properties | 1 + src/main/resources/messages_en_US.properties | 1 + src/main/resources/messages_es_ES.properties | 1 + src/main/resources/messages_eu_ES.properties | 1 + src/main/resources/messages_fa_IR.properties | 1 + src/main/resources/messages_fr_FR.properties | 1 + src/main/resources/messages_ga_IE.properties | 1 + src/main/resources/messages_hi_IN.properties | 1 + src/main/resources/messages_hr_HR.properties | 1 + src/main/resources/messages_hu_HU.properties | 1 + src/main/resources/messages_id_ID.properties | 1 + src/main/resources/messages_it_IT.properties | 1 + src/main/resources/messages_ja_JP.properties | 1 + src/main/resources/messages_ko_KR.properties | 1 + src/main/resources/messages_nl_NL.properties | 1 + src/main/resources/messages_no_NB.properties | 1 + src/main/resources/messages_pl_PL.properties | 1 + src/main/resources/messages_pt_BR.properties | 1 + src/main/resources/messages_pt_PT.properties | 1 + src/main/resources/messages_ro_RO.properties | 1 + src/main/resources/messages_ru_RU.properties | 1 + src/main/resources/messages_sk_SK.properties | 1 + src/main/resources/messages_sr_LATN_RS.properties | 1 + src/main/resources/messages_sv_SE.properties | 1 + src/main/resources/messages_th_TH.properties | 1 + src/main/resources/messages_tr_TR.properties | 1 + src/main/resources/messages_uk_UA.properties | 1 + src/main/resources/messages_vi_VN.properties | 1 + src/main/resources/messages_zh_CN.properties | 1 + src/main/resources/messages_zh_TW.properties | 1 + 37 files changed, 37 insertions(+) diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties index b12a12ed6..c80f540a7 100644 --- a/src/main/resources/messages_ar_AR.properties +++ b/src/main/resources/messages_ar_AR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=طلب غير صالح login.oauth2AccessDenied=تم رفض الوصول login.oauth2InvalidTokenResponse=استجابة الرمز المميز غير صالحة login.oauth2InvalidIdToken=رمز الهوية غير صالح +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=تم تعطيل المستخدم، تم حظر تسجيل الدخول حاليًا باستخدام اسم المستخدم هذا. يرجى الاتصال بالمسؤول. login.alreadyLoggedIn=لقد تسجل دخولًا إلى login.alreadyLoggedIn2=أجهزة أخرى. يرجى تسجيل الخروج من الأجهزة وحاول مرة أخرى. diff --git a/src/main/resources/messages_az_AZ.properties b/src/main/resources/messages_az_AZ.properties index 9a4cae6a9..5456c3ce0 100644 --- a/src/main/resources/messages_az_AZ.properties +++ b/src/main/resources/messages_az_AZ.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Etibarsız Sorğu login.oauth2AccessDenied=Giriş rədd edildi login.oauth2InvalidTokenResponse=Etibarsız Token Cavabı login.oauth2InvalidIdToken=Etibarsız Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=İstifadəçi deaktivləşdirilmişdir, bu istifadəçi adı ilə giriş hal-hazırda bloklanmışdır. Zəhmət olmasa, administratorla əlaqə saxlayın. login.alreadyLoggedIn=Siz artıq daxil olmusunuz login.alreadyLoggedIn2=cihazlar. Zəhmət olmasa, cihazlardan çıxış edin və yenidən cəhd edin. diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties index fb4796e56..7a35e4b9a 100644 --- a/src/main/resources/messages_bg_BG.properties +++ b/src/main/resources/messages_bg_BG.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Невалидна заявка login.oauth2AccessDenied=Отказан достъп login.oauth2InvalidTokenResponse=Невалиден отговор на токена login.oauth2InvalidIdToken=Невалиден токен за идентификатор +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Потребителят е деактивиран, влизането в момента е блокирано с това потребителско име. Моля, свържете се с администратора. login.alreadyLoggedIn=Вече сте влезли в login.alreadyLoggedIn2=устройства. Моля, излезте от устройствата и опитайте отново. diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties index 96e429a32..798742aaf 100644 --- a/src/main/resources/messages_ca_CA.properties +++ b/src/main/resources/messages_ca_CA.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Sol·licitud no vàlida login.oauth2AccessDenied=Accés denegat login.oauth2InvalidTokenResponse=Resposta de token no vàlida login.oauth2InvalidIdToken=ID Token no vàlid +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=L'usuari està desactivat, l'inici de sessió està actualment bloquejat amb aquest nom d'usuari. Si us plau, contacta amb l'administrador. login.alreadyLoggedIn=Ja has iniciat sessió a login.alreadyLoggedIn2=dispositius. Si us plau, tanca la sessió en els dispositius i torna-ho a intentar. diff --git a/src/main/resources/messages_cs_CZ.properties b/src/main/resources/messages_cs_CZ.properties index 553ec40e8..ea2491505 100644 --- a/src/main/resources/messages_cs_CZ.properties +++ b/src/main/resources/messages_cs_CZ.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Neplatný požadavek login.oauth2AccessDenied=Přístup zazobán login.oauth2InvalidTokenResponse=Neplatná odpověď tokenu login.oauth2InvalidIdToken=Neplatný identifikační token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Uživatel je deaktivován, přihlášení aktuálně pro tuto uživatelskou jmena je zakázáno. Kontaktujte správce. login.alreadyLoggedIn=Jste již přihlášeni na login.alreadyLoggedIn2=zariadení. Odhlašujte se z těchto zařízení a zkuste to znovu. diff --git a/src/main/resources/messages_da_DK.properties b/src/main/resources/messages_da_DK.properties index 9ab36d586..e6d5de751 100644 --- a/src/main/resources/messages_da_DK.properties +++ b/src/main/resources/messages_da_DK.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Ugyldig Anmodning login.oauth2AccessDenied=Adgang Nægtet login.oauth2InvalidTokenResponse=Ugyldigt Token Svar login.oauth2InvalidIdToken=Ugyldigt Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Bruger er deaktiveret, login er i øjeblikket blokeret med dette brugernavn. Kontakt venligst administratoren. login.alreadyLoggedIn=Du er allerede logget ind på login.alreadyLoggedIn2=enheder. Log ud af disse enheder og prøv igen. diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index 3681c2212..b2894d3af 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=ungültige Anfrage login.oauth2AccessDenied=Zugriff abgelehnt login.oauth2InvalidTokenResponse=Ungültige Token-Antwort login.oauth2InvalidIdToken=Ungültiges ID-Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator. login.alreadyLoggedIn=Sie sind bereits an login.alreadyLoggedIn2=Geräten angemeldet. Bitte melden Sie sich dort ab und versuchen es dann erneut. diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties index cefb83e16..d832ec8cb 100644 --- a/src/main/resources/messages_el_GR.properties +++ b/src/main/resources/messages_el_GR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Αρχαίως απαιτήσεις πληροφορ login.oauth2AccessDenied=Πρόσβαση ορισμένες τοποθετήσεις login.oauth2InvalidTokenResponse=Απάντηση άρκετο ρόταμα login.oauth2InvalidIdToken=Λιδός όρκου μη αρκετός +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Ο χρήστης είναι δευτεροβαθμιακά διακωμένος, το σύστημα άλλαξε τον καθώς βρεθεί. Παρακαλείστε τους αρχηγούς να επιβεβαιώσουν τη συμπεριφορά χρήστη. login.alreadyLoggedIn=Είστε ήδη σύνδεδες σε login.alreadyLoggedIn2=κατοχόι. Παρακαλώ δυσκέντρωση τους και προσπαθήστε ξανά. diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index 99095e195..6cd57d71c 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties index d21c2e601..05af81473 100644 --- a/src/main/resources/messages_es_ES.properties +++ b/src/main/resources/messages_es_ES.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Solicitud no válida login.oauth2AccessDenied=Acceso denegado login.oauth2InvalidTokenResponse=Respuesta de token no válida login.oauth2InvalidIdToken=Token de identificación no válido +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=El usuario está desactivado, actualmente el acceso está bloqueado para ese nombre de usuario. Por favor, póngase en contacto con el administrador. login.alreadyLoggedIn=Ya has iniciado sesión en login.alreadyLoggedIn2=dispositivos. Cierra sesión en los dispositivos y vuelve a intentarlo. diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties index f5d65e4f2..00bff8ed5 100644 --- a/src/main/resources/messages_eu_ES.properties +++ b/src/main/resources/messages_eu_ES.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_fa_IR.properties b/src/main/resources/messages_fa_IR.properties index ce7781dab..ba1bf45f4 100644 --- a/src/main/resources/messages_fa_IR.properties +++ b/src/main/resources/messages_fa_IR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=درخواست نامعتبر login.oauth2AccessDenied=دسترسی ممنوع login.oauth2InvalidTokenResponse=پاسخ توکن نامعتبر است login.oauth2InvalidIdToken=توکن شناسه نامعتبر است +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=کاربر غیرفعال شده است، ورود با این نام کاربری در حال حاضر مسدود است. لطفاً با مدیر تماس بگیرید. login.alreadyLoggedIn=شما قبلاً وارد شده‌اید در login.alreadyLoggedIn2=دستگاه‌ها. لطفاً از دستگاه‌ها خارج شده و دوباره تلاش کنید. diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties index 2a7d2f876..d1ac22eeb 100644 --- a/src/main/resources/messages_fr_FR.properties +++ b/src/main/resources/messages_fr_FR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Requête invalide login.oauth2AccessDenied=Accès refusé login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide login.oauth2InvalidIdToken=Jeton d'identification invalide +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=L'utilisateur est désactivé, la connexion est actuellement bloquée avec ce nom d'utilisateur. Veuillez contacter l'administrateur. login.alreadyLoggedIn=Vous êtes déjà connecté sur login.alreadyLoggedIn2=appareils. Veuillez vous déconnecter des appareils et réessayer. diff --git a/src/main/resources/messages_ga_IE.properties b/src/main/resources/messages_ga_IE.properties index 42ef0095a..134e9c54d 100644 --- a/src/main/resources/messages_ga_IE.properties +++ b/src/main/resources/messages_ga_IE.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Iarratas Neamhbhailí login.oauth2AccessDenied=Rochtain Diúltaithe login.oauth2InvalidTokenResponse=Freagra Comhartha Neamhbhailí login.oauth2InvalidIdToken=Comhartha Aitheantais Neamhbhailí +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties index 581f04b13..c85157523 100644 --- a/src/main/resources/messages_hi_IN.properties +++ b/src/main/resources/messages_hi_IN.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=गलत याचना login.oauth2AccessDenied=इनपुट उम्मीदवार डिसकार login.oauth2InvalidTokenResponse=अमान्तरित सिक्वेंस जवाब कैसे है login.oauth2InvalidIdToken=गलत इड टोकन +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=उपयोगकर्ता डिसबाल, यह वर्षा सभी उपयोगकर्ता जूझे वर्षाकरण बारा मिल गई है। कृपया संबवादक से संपर्क करें. login.alreadyLoggedIn=आप पहले से ही login.alreadyLoggedIn2=सुनिश्चित करने वाले डिवाइस्स पर लॉग-इन हैं। कृपया इन डिवाइस से लॉगआउट करें और पुनः प्रयास करें diff --git a/src/main/resources/messages_hr_HR.properties b/src/main/resources/messages_hr_HR.properties index efd24b4c1..df5e5ed29 100644 --- a/src/main/resources/messages_hr_HR.properties +++ b/src/main/resources/messages_hr_HR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Neispravan zahtjev login.oauth2AccessDenied=Pristup odbijen login.oauth2InvalidTokenResponse=Nevažeći odgovor tokena login.oauth2InvalidIdToken=Nevažeći ID token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Korisnik je deaktiviran, prijava sa ovim korisničkim imenom je trenutno zakazana. Molimo Vas da kontaktirate administratorske osobe. login.alreadyLoggedIn=Već ste se prijavili na login.alreadyLoggedIn2=ure. Odjavite se s ure i pokušajte ponovo. diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties index c847e6469..09d4831b9 100644 --- a/src/main/resources/messages_hu_HU.properties +++ b/src/main/resources/messages_hu_HU.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Érvénytelen kérelem login.oauth2AccessDenied=Hozzáférés megtagadva login.oauth2InvalidTokenResponse=Érvénytelen token-válasz login.oauth2InvalidIdToken=Érvénytelen azonosító token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=A felhasználó deaktivált, a bejelentkezés jelenleg megszakítva ezzel a felhasználónévvel. Kérjen segítséget a rendszergazdától. login.alreadyLoggedIn=Már be van jelentkezve az login.alreadyLoggedIn2=eszközökre. Kijelentkezzen ezekből a eszközökből, majd próbálja újra bejelentkezni. diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties index d7fd7bda3..d90d89d03 100644 --- a/src/main/resources/messages_id_ID.properties +++ b/src/main/resources/messages_id_ID.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Permintaan Tidak Valid login.oauth2AccessDenied=Akses Ditolak login.oauth2InvalidTokenResponse=Respons Token Tidak Valid login.oauth2InvalidIdToken=Token ID Tidak Valid +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Pengguna dinonaktifkan, login saat ini diblokir dengan nama pengguna ini. Silakan hubungi administrator. login.alreadyLoggedIn=Anda sudah login ke login.alreadyLoggedIn2=perangkat. Silakan keluar dari perangkat dan coba lagi. diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index e5a500b8b..a1cefa1d5 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Richiesta non valida login.oauth2AccessDenied=Accesso negato login.oauth2InvalidTokenResponse=Risposta token non valida login.oauth2InvalidIdToken=Id Token non valido +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato con questo nome utente. Si prega di contattare l'amministratore. login.alreadyLoggedIn=Hai già effettuato l'accesso a login.alreadyLoggedIn2=dispositivi. Esci dai dispositivi e riprova. diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties index e5bef7b48..e4c503e8a 100644 --- a/src/main/resources/messages_ja_JP.properties +++ b/src/main/resources/messages_ja_JP.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=無効なリクエスト login.oauth2AccessDenied=アクセス拒否 login.oauth2InvalidTokenResponse=無効なトークン応答 login.oauth2InvalidIdToken=無効なIDトークン +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=ユーザーは非アクティブ化されており、現在このユーザー名でのログインはブロックされています。管理者に連絡してください。 login.alreadyLoggedIn=すでにログインしています login.alreadyLoggedIn2=デバイスからログアウトしてもう一度お試しください。 diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties index 5ad547ecb..6552539df 100644 --- a/src/main/resources/messages_ko_KR.properties +++ b/src/main/resources/messages_ko_KR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties index 11885d9d4..fa6c47d88 100644 --- a/src/main/resources/messages_nl_NL.properties +++ b/src/main/resources/messages_nl_NL.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Ongeldig verzoek login.oauth2AccessDenied=Toegang geweigerd login.oauth2InvalidTokenResponse=Ongeldige tokenreactie login.oauth2InvalidIdToken=Ongeldige ID token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=De gebruiker is gedesactiveerd, inloggen is momenteel geblokkeerd voor deze gebruikersnaam. Neem contact op met de beheerder. login.alreadyLoggedIn=U zit reeds ingelogd bij login.alreadyLoggedIn2=apparaten. U moet u a.u.b. uitloggen van de apparaten en opnieuw proberen. diff --git a/src/main/resources/messages_no_NB.properties b/src/main/resources/messages_no_NB.properties index f7e41b53e..c6ca205bd 100644 --- a/src/main/resources/messages_no_NB.properties +++ b/src/main/resources/messages_no_NB.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Ugyldig forespørsel login.oauth2AccessDenied=Tilgang nektet login.oauth2InvalidTokenResponse=Ugyldig tokenrespons login.oauth2InvalidIdToken=Ugyldig Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties index 1b2f9c8e1..0b5744d47 100644 --- a/src/main/resources/messages_pl_PL.properties +++ b/src/main/resources/messages_pl_PL.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Nieprawidłowe żądanie login.oauth2AccessDenied=Brak dostępu login.oauth2InvalidTokenResponse=Nieprawidłowa odpowiedź na token login.oauth2InvalidIdToken=Nieprawidłowa wartość tokenu +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Użytkownik jest nieaktywny, logowanie przy użyciu tej nazwy użytkownika jest obecnie zablokowane. Prosimy o kontakt z administratorem. login.alreadyLoggedIn=Jesteś już zalogowany na login.alreadyLoggedIn2=urządzeniach. Wyloguj się z tych urządzeń i spróbuj ponownie. diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties index f5184d4a1..c2e1804f5 100644 --- a/src/main/resources/messages_pt_BR.properties +++ b/src/main/resources/messages_pt_BR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Requisição Inválida login.oauth2AccessDenied=Acesso Negado login.oauth2InvalidTokenResponse=Resposta de Token Inválida login.oauth2InvalidIdToken=Id de Token Inválido +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=O usuário está desativado, o login está atualmente bloqueado com este nome de usuário. Entre em contato com o administrador. login.alreadyLoggedIn=Você já está conectado em login.alreadyLoggedIn2=aparelhos. Por favor saia dos aparelhos e tente novamente. diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties index 86457f790..9c05e8870 100644 --- a/src/main/resources/messages_pt_PT.properties +++ b/src/main/resources/messages_pt_PT.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Requisito inválido login.oauth2AccessDenied=Acesso negado login.oauth2InvalidTokenResponse=Resposta de token inválida login.oauth2InvalidIdToken=Token de identificação inválido +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=O utilizador foi desativado, o login está atualmente bloqueado com esta conta. Por favor, contacte o administrador. login.alreadyLoggedIn=Já está logado em login.alreadyLoggedIn2=dispositivos. Por favor, faça logout nos dispositivos e tente novamente. diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties index 0e8b32266..58a521c5d 100644 --- a/src/main/resources/messages_ro_RO.properties +++ b/src/main/resources/messages_ro_RO.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Cerere Invalidă login.oauth2AccessDenied=Acces Refuzat login.oauth2InvalidTokenResponse=Răspuns Invalid la Token login.oauth2InvalidIdToken=Token de Id Invalid +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Utilizatorul este dezactivat, conectarea este în prezent blocată cu acest nume de utilizator. Te rugăm să contactezi administratorul. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties index 6bd9331dc..9161b89e2 100644 --- a/src/main/resources/messages_ru_RU.properties +++ b/src/main/resources/messages_ru_RU.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Неверный запрос login.oauth2AccessDenied=Доступ запрещен login.oauth2InvalidTokenResponse=Недействительный ответ токена login.oauth2InvalidIdToken=Недействительный идентификационный токен +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Пользователь деактивирован, вход с данным именем пользователя заблокирован. Пожалуйста, обратитесь к администратору. login.alreadyLoggedIn=Вы уже вошли в login.alreadyLoggedIn2=устройства. Выполните выход из устройств и попробуйте снова. diff --git a/src/main/resources/messages_sk_SK.properties b/src/main/resources/messages_sk_SK.properties index 66da42147..2159b7c87 100644 --- a/src/main/resources/messages_sk_SK.properties +++ b/src/main/resources/messages_sk_SK.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties index a60195457..4af2ff622 100644 --- a/src/main/resources/messages_sr_LATN_RS.properties +++ b/src/main/resources/messages_sr_LATN_RS.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Invalid Request login.oauth2AccessDenied=Access Denied login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidIdToken=Invalid Id Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties index ec26aaa1f..43b901c36 100644 --- a/src/main/resources/messages_sv_SE.properties +++ b/src/main/resources/messages_sv_SE.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Ogiltig begäran login.oauth2AccessDenied=Åtkomst nekad login.oauth2InvalidTokenResponse=Ogiltigt token-svar login.oauth2InvalidIdToken=Ogiltigt Id-token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Användaren är inaktiverad, inloggning är för närvarande blockerad med detta användarnamn. Kontakta administratören. login.alreadyLoggedIn=Du är redan inloggad på login.alreadyLoggedIn2=enheter. Logga ut från enheterna och försök igen. diff --git a/src/main/resources/messages_th_TH.properties b/src/main/resources/messages_th_TH.properties index ccf3fdd5d..7d89206a2 100644 --- a/src/main/resources/messages_th_TH.properties +++ b/src/main/resources/messages_th_TH.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=คำขอไม่ถูกต้อง login.oauth2AccessDenied=การเข้าถึงถูกปฏิเสธ login.oauth2InvalidTokenResponse=การตอบกลับโทเค็นไม่ถูกต้อง login.oauth2InvalidIdToken=โทเค็น Id ไม่ถูกต้อง +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=ผู้ใช้งานถูกระงับการใช้งาน ไม่สามารถเข้าสู่ระบบด้วยชื่อผู้ใช้นี้ได้ กรุณาติดต่อผู้ดูแลระบบ login.alreadyLoggedIn=คุณได้เข้าสู่ระบบใน login.alreadyLoggedIn2=อุปกรณ์แล้ว กรุณาออกจากระบบจากอุปกรณ์ที่ใช้งานอยู่แล้ว จากนั้นลองใหม่อีกครั้ง diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties index 5b546bc37..967c06ed2 100644 --- a/src/main/resources/messages_tr_TR.properties +++ b/src/main/resources/messages_tr_TR.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Geçersiz İstek login.oauth2AccessDenied=Erişim Reddedildi login.oauth2InvalidTokenResponse=Geçersiz Belirteç Yanıtı login.oauth2InvalidIdToken=Geçersiz Kimlik Belirteci +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=Kullanıcı devre dışı bırakıldı, şu anda bu kullanıcı adıyla giriş engellendi. Lütfen yöneticiyle iletişime geçin. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties index fcab3ea15..0d8ec5b45 100644 --- a/src/main/resources/messages_uk_UA.properties +++ b/src/main/resources/messages_uk_UA.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Недійсний запит login.oauth2AccessDenied=Доступ заблоковано login.oauth2InvalidTokenResponse=Недійсна відповідь з токеном login.oauth2InvalidIdToken=Недійсний Id токен +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_vi_VN.properties b/src/main/resources/messages_vi_VN.properties index 2200c7eba..00d706059 100644 --- a/src/main/resources/messages_vi_VN.properties +++ b/src/main/resources/messages_vi_VN.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=Yêu cầu không hợp lệ login.oauth2AccessDenied=Truy cập bị từ chối login.oauth2InvalidTokenResponse=Phản hồi token không hợp lệ login.oauth2InvalidIdToken=Id Token không hợp lệ +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator. login.alreadyLoggedIn=You are already logged in to login.alreadyLoggedIn2=devices. Please log out of the devices and try again. diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties index 1653fa11e..8aea8c546 100644 --- a/src/main/resources/messages_zh_CN.properties +++ b/src/main/resources/messages_zh_CN.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=无效请求 login.oauth2AccessDenied=拒绝访问 login.oauth2InvalidTokenResponse=无效的 Token 响应 login.oauth2InvalidIdToken=无效的 Token +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=用户被禁用,登录已被阻止。请联系管理员。 login.alreadyLoggedIn=您已经登录到了 login.alreadyLoggedIn2=设备,请注销设备后重试。 diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties index acfe2c312..c231c18e0 100644 --- a/src/main/resources/messages_zh_TW.properties +++ b/src/main/resources/messages_zh_TW.properties @@ -561,6 +561,7 @@ login.oauth2invalidRequest=無效的回應 login.oauth2AccessDenied=存取被拒 login.oauth2InvalidTokenResponse=無效的權杖回應 login.oauth2InvalidIdToken=無效的識別權杖 +login.relyingPartyRegistrationNotFound=No relying party registration found login.userIsDisabled=使用者已停用,目前此使用者無法登入。請聯絡系統管理員。 login.alreadyLoggedIn=您已經登入了 login.alreadyLoggedIn2=個裝置。請登出其他裝置後再試一次。 From 49fb634690399103da8ad70148ee32d33ae3f220 Mon Sep 17 00:00:00 2001 From: reecebrowne <74901996+reecebrowne@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:49:29 +0000 Subject: [PATCH 06/25] Feature/improved signature element (#2489) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --------- Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Co-authored-by: Reece Browne --- src/main/resources/messages_en_GB.properties | 4 +- src/main/resources/static/css/add-image.css | 35 +- src/main/resources/static/css/fileSelect.css | 56 ++- src/main/resources/static/css/sign.css | 54 ++- .../resources/static/js/draggable-utils.js | 396 +++++++++++++----- src/main/resources/static/js/fileInput.js | 170 +++++++- .../resources/static/js/pages/add-image.js | 47 ++- src/main/resources/static/js/pages/sign.js | 39 +- .../static/js/sign/signature-canvas.js | 85 ++++ .../resources/templates/fragments/common.html | 7 +- .../resources/templates/misc/add-image.html | 162 ++++--- src/main/resources/templates/sign.html | 231 +++++----- 12 files changed, 964 insertions(+), 322 deletions(-) create mode 100644 src/main/resources/static/js/sign/signature-canvas.js diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 8caba5a1a..42069459d 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Repair repair.header=Repair PDFs @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/static/css/add-image.css b/src/main/resources/static/css/add-image.css index 5a735b425..f51da024f 100644 --- a/src/main/resources/static/css/add-image.css +++ b/src/main/resources/static/css/add-image.css @@ -2,22 +2,32 @@ position: relative; margin: 20px 0; } + #pdf-canvas { box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384); width: 100%; } + .draggable-buttons-box { - position: absolute; + position: relative; top: 0; padding: 10px; - width: 100%; + width: calc(100% + 4.4rem); display: flex; gap: 5px; + z-index: 5; + margin-left: -2.2rem; } -.draggable-buttons-box > button { - z-index: 10; + +.draggable-buttons-box>button { + z-index: 4; background-color: rgba(13, 110, 253, 0.1); + flex: 1 1 auto; + min-width: 2.5rem; + max-width: 4rem; } + + .draggable-canvas { border: 1px solid red; position: absolute; @@ -26,3 +36,20 @@ top: 0px; left: 0; } + +.input-with-icon { + position: relative; + display: inline-flex; + align-items: center; +} + +.input-with-icon .icon { + position: absolute; + left: 0.5rem; + pointer-events: none; + color: #aaa; +} + +.input-with-icon input { + padding-left: 2.2rem; +} diff --git a/src/main/resources/static/css/fileSelect.css b/src/main/resources/static/css/fileSelect.css index 3f96814f9..afb0b075f 100644 --- a/src/main/resources/static/css/fileSelect.css +++ b/src/main/resources/static/css/fileSelect.css @@ -118,6 +118,7 @@ row-gap: 1px; height: 60px; width: 60px; + top:4px; } .file-icon { @@ -165,8 +166,8 @@ height: 15px; width: 15px; - right: 10px; - top: -5px; + right: 0px; + top: -17px; } .remove-selected-file * { @@ -219,3 +220,54 @@ border-radius: 1rem; border: 1px solid rgb(105, 116, 134, 0.5); } + +.draggable-image-overlay{ + position: absolute; + background: rgba(0, 0, 0, 0.7); + display: none; + z-index: 10; + align-items: center; + justify-content: center; + color: white; + font-size: 16px; + font-weight: bold; + pointer-events: none; + left:0; + top:0; + height:100%; + width:100%; + border-radius: 1rem; +} + +.small-file-container:hover .drag-icon { + display: flex; +} + +.drag-icon { + display: none; + position: absolute; + top: 5px; + width: 20px; + height: 20px; + background: rgba(0, 0, 0, 0.5); + color: white; + align-items: center; + justify-content: center; + border-radius: 50%; + font-size: 14px; + pointer-events: none; + z-index: 1; +} + +#imagePreviewModal { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + display: none; + justify-content: center; + align-items: center; + z-index: 9999; +} diff --git a/src/main/resources/static/css/sign.css b/src/main/resources/static/css/sign.css index 772fee6d0..6de4efcd6 100644 --- a/src/main/resources/static/css/sign.css +++ b/src/main/resources/static/css/sign.css @@ -22,18 +22,38 @@ select#font-select option { } .draggable-buttons-box { - position: absolute; + position: relative; top: 0; padding: 10px; - width: 100%; + width: calc(100% + 4.4rem); display: flex; gap: 5px; z-index: 5; + margin-left: -2.2rem; } .draggable-buttons-box>button { z-index: 4; background-color: rgba(13, 110, 253, 0.1); + flex: 1 1 auto; + min-width: 2.5rem; + max-width: 4rem; +} + + +.rotation-handle { + width: 20px; + height: 20px; + border: 2px solid #3498db; + background-color: rgba(52, 152, 219, 0.1); + color: white; + border-radius: 50%; + text-align: center; + line-height: 20px; + position: absolute; + cursor: grab; + top: -30px; + left: calc(50% - 10px); } .draggable-canvas { @@ -113,3 +133,33 @@ select#font-select option { text-align: right; padding: 0.5rem 1rem; } + +.input-with-icon { + position: relative; + display: inline-flex; + align-items: center; +} + +.input-with-icon .icon { + position: absolute; + left: 0.5rem; + pointer-events: none; + color: #aaa; +} + +.input-with-icon input { + padding-left: 2.2rem; +} + +.small-file-container-saved { + padding-top: 1px; + position: relative; + row-gap: 1px; + height: 60px; + width: 60px; + top: 4px; +} + +.small-file-container-saved:hover .drag-icon { + display: flex; +} diff --git a/src/main/resources/static/js/draggable-utils.js b/src/main/resources/static/js/draggable-utils.js index aa0c15a03..b6fa73b5f 100644 --- a/src/main/resources/static/js/draggable-utils.js +++ b/src/main/resources/static/js/draggable-utils.js @@ -7,75 +7,137 @@ const DraggableUtils = { elementAllPages: [], documentsMap: new Map(), lastInteracted: null, - + padding: 15, + maintainRatioEnabled: true, init() { interact('.draggable-canvas') .draggable({ listeners: { + start(event) { + const target = event.target; + x = parseFloat(target.getAttribute('data-bs-x')); + y = parseFloat(target.getAttribute('data-bs-y')); + }, move: (event) => { const target = event.target; - const x = (parseFloat(target.getAttribute('data-bs-x')) || 0) + event.dx; - const y = (parseFloat(target.getAttribute('data-bs-y')) || 0) + event.dy; + // Retrieve position attributes + let x = parseFloat(target.getAttribute('data-bs-x')) || 0; + let y = parseFloat(target.getAttribute('data-bs-y')) || 0; + const angle = parseFloat(target.getAttribute('data-angle')) || 0; + + // Update position based on drag movement + x += event.dx; + y += event.dy; + + // Apply translation to the parent container (bounding box) target.style.transform = `translate(${x}px, ${y}px)`; + + // Preserve rotation on the inner canvas + const canvas = target.querySelector('.display-canvas'); + + const canvasWidth = parseFloat(canvas.style.width); + const canvasHeight = parseFloat(canvas.style.height); + + const cosAngle = Math.abs(Math.cos(angle)); + const sinAngle = Math.abs(Math.sin(angle)); + + const rotatedWidth = canvasWidth * cosAngle + canvasHeight * sinAngle; + const rotatedHeight = canvasWidth * sinAngle + canvasHeight * cosAngle; + + const offsetX = (rotatedWidth - canvasWidth) / 2; + const offsetY = (rotatedHeight - canvasHeight) / 2; + + canvas.style.transform = `translate(${offsetX}px, ${offsetY}px) rotate(${angle}rad)`; + + // Update attributes for persistence target.setAttribute('data-bs-x', x); target.setAttribute('data-bs-y', y); - this.onInteraction(target); - //update the last interacted element - this.lastInteracted = event.target; + // Set the last interacted element + this.lastInteracted = target; }, }, }) .resizable({ - edges: {left: true, right: true, bottom: true, top: true}, + edges: { left: true, right: true, bottom: true, top: true }, listeners: { + start: (event) => { + const target = event.target; + x = parseFloat(target.getAttribute('data-bs-x')) || 0; + y = parseFloat(target.getAttribute('data-bs-y')) || 0; + }, move: (event) => { - var target = event.target; - var x = parseFloat(target.getAttribute('data-bs-x')) || 0; - var y = parseFloat(target.getAttribute('data-bs-y')) || 0; + const target = event.target; - // check if control key is pressed - if (event.ctrlKey) { - const aspectRatio = target.offsetWidth / target.offsetHeight; - // preserve aspect ratio - let width = event.rect.width; - let height = event.rect.height; + const MAX_CHANGE = 60; - if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) { - height = width / aspectRatio; - } else { - width = height * aspectRatio; + let width = event.rect.width - 2 * this.padding; + let height = event.rect.height - 2 * this.padding; + + const canvas = target.querySelector('.display-canvas'); + if (canvas) { + const originalWidth = parseFloat(canvas.style.width) || canvas.width; + const originalHeight = parseFloat(canvas.style.height) || canvas.height; + const angle = parseFloat(target.getAttribute('data-angle')) || 0; + + const aspectRatio = originalWidth / originalHeight; + + if (!event.ctrlKey && this.maintainRatioEnabled) { + if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } } - event.rect.width = width; - event.rect.height = height; + const widthChange = width - originalWidth; + const heightChange = height - originalHeight; + + if (Math.abs(widthChange) > MAX_CHANGE || Math.abs(heightChange) > MAX_CHANGE) { + const scale = MAX_CHANGE / Math.max(Math.abs(widthChange), Math.abs(heightChange)); + width = originalWidth + widthChange * scale; + height = originalHeight + heightChange * scale; + } + + const cosAngle = Math.abs(Math.cos(angle)); + const sinAngle = Math.abs(Math.sin(angle)); + const boundingWidth = width * cosAngle + height * sinAngle; + const boundingHeight = width * sinAngle + height * cosAngle; + + if (event.edges.left) { + const dx = event.deltaRect.left; + x += dx; + } + if (event.edges.top) { + const dy = event.deltaRect.top; + y += dy; + } + + target.style.transform = `translate(${x}px, ${y}px)`; + target.style.width = `${boundingWidth + 2 * this.padding}px`; + target.style.height = `${boundingHeight + 2 * this.padding}px`; + + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + canvas.style.transform = `translate(${(boundingWidth - width) / 2}px, ${(boundingHeight - height) / 2 + }px) rotate(${angle}rad)`; + + target.setAttribute('data-bs-x', x); + target.setAttribute('data-bs-y', y); + + this.lastInteracted = target; } - - target.style.width = event.rect.width + 'px'; - target.style.height = event.rect.height + 'px'; - - // translate when resizing from top or left edges - x += event.deltaRect.left; - y += event.deltaRect.top; - - target.style.transform = 'translate(' + x + 'px,' + y + 'px)'; - - target.setAttribute('data-bs-x', x); - target.setAttribute('data-bs-y', y); - target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height); - - this.onInteraction(target); }, }, - modifiers: [ interact.modifiers.restrictSize({ - min: {width: 5, height: 5}, + min: { width: 50, height: 50 }, }), ], inertia: true, }); + //Arrow key Support for Add-Image and Sign pages if (window.location.pathname.endsWith('sign') || window.location.pathname.endsWith('add-image')) { window.addEventListener('keydown', (event) => { @@ -117,7 +179,8 @@ const DraggableUtils = { } // Update position - target.style.transform = `translate(${x}px, ${y}px)`; + const angle = parseFloat(target.getAttribute('data-angle')) || 0; + target.style.transform = `translate(${x}px, ${y}px) rotate(${angle}rad)`; target.setAttribute('data-bs-x', x); target.setAttribute('data-bs-y', y); @@ -125,72 +188,97 @@ const DraggableUtils = { }); } }, - onInteraction(target) { - this.boxDragContainer.appendChild(target); - }, - - createDraggableCanvas() { - const createdCanvas = document.createElement('canvas'); - createdCanvas.id = `draggable-canvas-${this.nextId++}`; - createdCanvas.classList.add('draggable-canvas'); - - const x = 0; - const y = 20; - createdCanvas.style.transform = `translate(${x}px, ${y}px)`; - createdCanvas.setAttribute('data-bs-x', x); - createdCanvas.setAttribute('data-bs-y', y); - - //Click element in order to enable arrow keys - createdCanvas.addEventListener('click', () => { - this.lastInteracted = createdCanvas; - }); - - createdCanvas.onclick = (e) => this.onInteraction(e.target); - - this.boxDragContainer.appendChild(createdCanvas); - - //Enable Arrow keys directly after the element is created - this.lastInteracted = createdCanvas; - - return createdCanvas; + this.lastInteracted = target; + // this.boxDragContainer.appendChild(target); + // target.appendChild(target.querySelector(".display-canvas")); }, createDraggableCanvasFromUrl(dataUrl) { return new Promise((resolve) => { - var myImage = new Image(); + const canvasContainer = document.createElement('div'); + const createdCanvas = document.createElement('canvas'); // Inner canvas + const padding = this.padding; + + canvasContainer.id = `draggable-canvas-${this.nextId++}`; + canvasContainer.classList.add('draggable-canvas'); + createdCanvas.classList.add('display-canvas'); + + canvasContainer.style.position = 'absolute'; + canvasContainer.style.padding = `${padding}px`; + canvasContainer.style.overflow = 'hidden'; + + let x = 0, + y = 30, + angle = 0; + canvasContainer.style.transform = `translate(${x}px, ${y}px)`; + canvasContainer.setAttribute('data-bs-x', x); + canvasContainer.setAttribute('data-bs-y', y); + canvasContainer.setAttribute('data-angle', angle); + + canvasContainer.addEventListener('click', () => { + this.lastInteracted = canvasContainer; + this.showRotationControls(canvasContainer); + }); + canvasContainer.appendChild(createdCanvas); + this.boxDragContainer.appendChild(canvasContainer); + + const myImage = new Image(); myImage.src = dataUrl; myImage.onload = () => { - var createdCanvas = this.createDraggableCanvas(); + const context = createdCanvas.getContext('2d'); createdCanvas.width = myImage.width; createdCanvas.height = myImage.height; const imgAspect = myImage.width / myImage.height; - const pdfAspect = this.boxDragContainer.offsetWidth / this.boxDragContainer.offsetHeight; + const containerWidth = this.boxDragContainer.offsetWidth; + const containerHeight = this.boxDragContainer.offsetHeight; - var scaleMultiplier; - if (imgAspect > pdfAspect) { - scaleMultiplier = this.boxDragContainer.offsetWidth / myImage.width; - } else { - scaleMultiplier = this.boxDragContainer.offsetHeight / myImage.height; - } + let scaleMultiplier = Math.min(containerWidth / myImage.width, containerHeight / myImage.height); + const scaleFactor = 0.5; - var newWidth = createdCanvas.width; - var newHeight = createdCanvas.height; - if (scaleMultiplier < 1) { - newWidth = newWidth * scaleMultiplier; - newHeight = newHeight * scaleMultiplier; - } + const newWidth = myImage.width * scaleMultiplier * scaleFactor; + const newHeight = myImage.height * scaleMultiplier * scaleFactor; - createdCanvas.style.width = newWidth + 'px'; - createdCanvas.style.height = newHeight + 'px'; + // Calculate initial bounding box size + const cosAngle = Math.abs(Math.cos(angle)); + const sinAngle = Math.abs(Math.sin(angle)); + const boundingWidth = newWidth * cosAngle + newHeight * sinAngle; + const boundingHeight = newWidth * sinAngle + newHeight * cosAngle; - var myContext = createdCanvas.getContext('2d'); - myContext.drawImage(myImage, 0, 0); - resolve(createdCanvas); + createdCanvas.style.width = `${newWidth}px`; + createdCanvas.style.height = `${newHeight}px`; + + canvasContainer.style.width = `${boundingWidth + 2 * padding}px`; + canvasContainer.style.height = `${boundingHeight + 2 * padding}px`; + + context.imageSmoothingEnabled = true; + context.imageSmoothingQuality = 'high'; + context.drawImage(myImage, 0, 0, myImage.width, myImage.height); + this.showRotationControls(canvasContainer); + this.lastInteracted = canvasContainer; + + resolve(canvasContainer); + }; + + myImage.onerror = () => { + console.error('Failed to load the image.'); + resolve(null); }; }); }, + toggleMaintainRatio() { + this.maintainRatioEnabled = !this.maintainRatioEnabled; + const button = document.getElementById('ratioToggleBtn'); + if (this.maintainRatioEnabled) { + button.classList.remove('btn-danger'); + button.classList.add('btn-outline-secondary'); + } else { + button.classList.remove('btn-outline-secondary'); + button.classList.add('btn-danger'); + } + }, + deleteAllDraggableCanvases() { this.boxDragContainer.querySelectorAll('.draggable-canvas').forEach((el) => el.remove()); }, @@ -266,9 +354,61 @@ const DraggableUtils = { } }, getLastInteracted() { - return this.boxDragContainer.querySelector('.draggable-canvas:last-of-type'); + return this.lastInteracted; }, + showRotationControls(element) { + const rotationControls = document.getElementById('rotation-controls'); + const rotationInput = document.getElementById('rotation-input'); + rotationControls.style.display = 'flex'; + rotationInput.value = Math.round((parseFloat(element.getAttribute('data-angle')) * 180) / Math.PI); + rotationInput.addEventListener('input', this.handleRotationInputChange); + }, + hideRotationControls() { + const rotationControls = document.getElementById('rotation-controls'); + const rotationInput = document.getElementById('rotation-input'); + rotationControls.style.display = 'none'; + rotationInput.addEventListener('input', this.handleRotationInputChange); + }, + applyRotationToElement(element, degrees) { + const radians = degrees * (Math.PI / 180); // Convert degrees to radians + // Get current position + const x = parseFloat(element.getAttribute('data-bs-x')) || 0; + const y = parseFloat(element.getAttribute('data-bs-y')) || 0; + + // Get the inner canvas (image) + const canvas = element.querySelector('.display-canvas'); + if (canvas) { + const originalWidth = parseFloat(canvas.style.width); + const originalHeight = parseFloat(canvas.style.height); + const padding = this.padding; // Access the padding value + + // Calculate rotated bounding box dimensions + const cosAngle = Math.abs(Math.cos(radians)); + const sinAngle = Math.abs(Math.sin(radians)); + const boundingWidth = originalWidth * cosAngle + originalHeight * sinAngle + 2 * padding; + const boundingHeight = originalWidth * sinAngle + originalHeight * cosAngle + 2 * padding; + + // Update parent container to fit the rotated bounding box + element.style.width = `${boundingWidth}px`; + element.style.height = `${boundingHeight}px`; + + // Center the canvas within the bounding box, accounting for padding + const offsetX = (boundingWidth - originalWidth) / 2 - padding; + const offsetY = (boundingHeight - originalHeight) / 2 - padding; + + canvas.style.transform = `translate(${offsetX}px, ${offsetY}px) rotate(${radians}rad)`; + } + + // Keep the bounding box positioned properly + element.style.transform = `translate(${x}px, ${y}px)`; + element.setAttribute('data-angle', radians); + }, + handleRotationInputChange() { + const rotationInput = document.getElementById('rotation-input'); + const degrees = parseFloat(rotationInput.value) || 0; + DraggableUtils.applyRotationToElement(DraggableUtils.lastInteracted, degrees); + }, storePageContents() { var pagesMap = this.documentsMap.get(this.pdfDoc); if (!pagesMap) { @@ -325,7 +465,7 @@ const DraggableUtils = { // render the page onto the canvas var renderContext = { canvasContext: this.pdfCanvas.getContext('2d'), - viewport: page.getViewport({scale: 1}), + viewport: page.getViewport({ scale: 1 }), }; await page.render(renderContext).promise; @@ -352,8 +492,6 @@ const DraggableUtils = { this.loadPageContents(); } }, - - parseTransform(element) {}, async getOverlayedPdfDocument() { const pdfBytes = await this.pdfDoc.getData(); const pdfDocModified = await PDFLib.PDFDocument.load(pdfBytes, { @@ -367,7 +505,6 @@ const DraggableUtils = { if (pageIdx.includes('offset')) { continue; } - console.log(typeof pageIdx); const page = pdfDocModified.getPage(parseInt(pageIdx)); let draggablesData = pagesMap[pageIdx]; @@ -376,45 +513,61 @@ const DraggableUtils = { const offsetHeight = pagesMap[pageIdx + '-offsetHeight']; for (const draggableData of draggablesData) { - // embed the draggable canvas - const draggableElement = draggableData.element; + // Embed the draggable canvas + const draggableElement = draggableData.element.querySelector('.display-canvas'); const response = await fetch(draggableElement.toDataURL()); const draggableImgBytes = await response.arrayBuffer(); const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes); - // calculate the position in the pdf document - const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, ''); - const transformComponents = tansform.split(','); + // Extract transformation data + const transform = draggableData.element.style.transform || ''; + const translateRegex = /translate\((-?\d+(?:\.\d+)?)px,\s*(-?\d+(?:\.\d+)?)px\)/; + + const translateMatch = transform.match(translateRegex); + + const translateX = translateMatch ? parseFloat(translateMatch[1]) : 0; + const translateY = translateMatch ? parseFloat(translateMatch[2]) : 0; + + const childTransform = draggableElement.style.transform || ''; + const childTranslateMatch = childTransform.match(translateRegex); + + const childOffsetX = childTranslateMatch ? parseFloat(childTranslateMatch[1]) : 0; + const childOffsetY = childTranslateMatch ? parseFloat(childTranslateMatch[2]) : 0; + + const rotateAngle = parseFloat(draggableData.element.getAttribute('data-angle')) || 0; + const draggablePositionPixels = { - x: parseFloat(transformComponents[0]), - y: parseFloat(transformComponents[1]), - width: draggableData.offsetWidth, - height: draggableData.offsetHeight, + x: translateX + childOffsetX + this.padding + 2, + y: translateY + childOffsetY + this.padding + 2, + width: parseFloat(draggableElement.style.width), + height: parseFloat(draggableElement.style.height), + angle: rotateAngle, // Store rotation }; - //Auxiliary variables + // Auxiliary variables let widthAdjusted = page.getWidth(); let heightAdjusted = page.getHeight(); const rotation = page.getRotation(); - //Normalizing angle + // Normalize page rotation angle let normalizedAngle = rotation.angle % 360; if (normalizedAngle < 0) { normalizedAngle += 360; } - //Changing the page dimension if the angle is 90 or 270 + // Adjust page dimensions for rotated pages if (normalizedAngle === 90 || normalizedAngle === 270) { - let widthTemp = widthAdjusted; - widthAdjusted = heightAdjusted; - heightAdjusted = widthTemp; + [widthAdjusted, heightAdjusted] = [heightAdjusted, widthAdjusted]; } + const draggablePositionRelative = { x: draggablePositionPixels.x / offsetWidth, y: draggablePositionPixels.y / offsetHeight, width: draggablePositionPixels.width / offsetWidth, height: draggablePositionPixels.height / offsetHeight, + angle: draggablePositionPixels.angle, }; + const draggablePositionPdf = { x: draggablePositionRelative.x * widthAdjusted, y: draggablePositionRelative.y * heightAdjusted, @@ -422,11 +575,13 @@ const DraggableUtils = { height: draggablePositionRelative.height * heightAdjusted, }; - //Defining the image if the page has a 0-degree angle + // Calculate position based on normalized page rotation let x = draggablePositionPdf.x; let y = heightAdjusted - draggablePositionPdf.y - draggablePositionPdf.height; - //Defining the image position if it is at other angles + let originx = x + draggablePositionPdf.width / 2; + let originy = heightAdjusted - draggablePositionPdf.y - draggablePositionPdf.height / 2; + if (normalizedAngle === 90) { x = draggablePositionPdf.y + draggablePositionPdf.height; y = draggablePositionPdf.x; @@ -437,17 +592,32 @@ const DraggableUtils = { x = heightAdjusted - draggablePositionPdf.y - draggablePositionPdf.height; y = widthAdjusted - draggablePositionPdf.x; } - - // draw the image + // let angle = draggablePositionPixels.angle % 360; + // if (angle < 0) angle += 360; // Normalize to positive angle + const radians = -draggablePositionPixels.angle; // Convert angle to radians + page.pushOperators( + PDFLib.pushGraphicsState(), + PDFLib.concatTransformationMatrix(1, 0, 0, 1, originx, originy), + PDFLib.concatTransformationMatrix( + Math.cos(radians), + Math.sin(radians), + -Math.sin(radians), + Math.cos(radians), + 0, + 0 + ), + PDFLib.concatTransformationMatrix(1, 0, 0, 1, -1 * originx, -1 * originy) + ); page.drawImage(pdfImageObject, { x: x, y: y, width: draggablePositionPdf.width, height: draggablePositionPdf.height, - rotate: rotation, }); + page.pushOperators(PDFLib.popGraphicsState()); } } + this.loadPageContents(); return pdfDocModified; }, diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index 63485c606..b2316f4ff 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -9,6 +9,7 @@ if (!isScriptExecuted) { document.querySelectorAll('.custom-file-chooser').forEach(setupFileInput); }); } +let hasDroppedImage = false; function setupFileInput(chooser) { const elementId = chooser.getAttribute('data-bs-element-id'); @@ -18,6 +19,11 @@ function setupFileInput(chooser) { let inputContainer = document.getElementById(inputContainerId); + if (inputContainer.id === 'pdf-upload-input-container') { + inputContainer.querySelector('#dragAndDrop').innerHTML = window.fileInput.dragAndDropPDF; + } else if (inputContainer.id === 'image-upload-input-container') { + inputContainer.querySelector('#dragAndDrop').innerHTML = window.fileInput.dragAndDropImage; + } let allFiles = []; let overlay; let dragCounter = 0; @@ -141,12 +147,17 @@ function setupFileInput(chooser) { files.forEach((file) => dataTransfer.items.add(file)); return dataTransfer; } - function handleFileInputChange(inputElement) { const files = allFiles; showOrHideSelectedFilesContainer(files); - const filesInfo = files.map((f) => ({name: f.name, size: f.size, uniqueId: f.uniqueId})); + const filesInfo = files.map((f) => ({ + name: f.name, + size: f.size, + uniqueId: f.uniqueId, + type: f.type, + url: URL.createObjectURL(f), + })); const selectedFilesContainer = $(inputContainer).siblings('.selected-files'); selectedFilesContainer.empty(); @@ -157,30 +168,111 @@ function setupFileInput(chooser) { $(fileContainer).addClass(fileContainerClasses); $(fileContainer).attr('id', info.uniqueId); - let fileIconContainer = createFileIconContainer(info); + let fileIconContainer = document.createElement('div'); + const isDragAndDropEnabled = + window.location.pathname.includes('add-image') || window.location.pathname.includes('sign'); + if (info.type.startsWith('image/')) { + let imgPreview = document.createElement('img'); + imgPreview.src = info.url; + imgPreview.alt = 'Preview'; + imgPreview.style.width = '50px'; + imgPreview.style.height = '50px'; + imgPreview.style.objectFit = 'cover'; + $(fileIconContainer).append(imgPreview); + + if (isDragAndDropEnabled) { + let dragIcon = document.createElement('div'); + dragIcon.classList.add('drag-icon'); + dragIcon.innerHTML = + ''; + fileContainer.appendChild(dragIcon); + + $(fileContainer).attr('draggable', 'true'); + $(fileContainer).on('dragstart', (e) => { + e.originalEvent.dataTransfer.setData('fileUrl', info.url); + e.originalEvent.dataTransfer.setData('uniqueId', info.uniqueId); + e.originalEvent.dataTransfer.setDragImage(imgPreview, imgPreview.width / 2, imgPreview.height / 2); + }); + enableImagePreviewOnClick(fileIconContainer); + } else { + $(fileContainer).removeAttr('draggable'); + } + } else { + fileIconContainer = createFileIconContainer(info); + } let fileInfoContainer = createFileInfoContainer(info); - let removeBtn = document.createElement('div'); - removeBtn.classList.add('remove-selected-file'); + if (!isDragAndDropEnabled) { + let removeBtn = document.createElement('div'); + removeBtn.classList.add('remove-selected-file'); - let removeBtnIconHTML = ``; - $(removeBtn).append(removeBtnIconHTML); - $(removeBtn).attr('data-file-id', info.uniqueId).click(removeFileListener); - - $(fileContainer).append(fileIconContainer); - $(fileContainer).append(fileInfoContainer); - $(fileContainer).append(removeBtn); + let removeBtnIconHTML = ``; + $(removeBtn).append(removeBtnIconHTML); + $(removeBtn).attr('data-file-id', info.uniqueId).click(removeFileListener); + $(fileContainer).append(removeBtn); + } + $(fileContainer).append(fileIconContainer, fileInfoContainer); selectedFilesContainer.append(fileContainer); }); + const pageContainers = $('#box-drag-container'); + pageContainers.off('dragover').on('dragover', (e) => { + e.preventDefault(); + }); - showOrHideSelectedFilesContainer(filesInfo); + pageContainers.off('drop').on('drop', (e) => { + e.preventDefault(); + const fileUrl = e.originalEvent.dataTransfer.getData('fileUrl'); + + if (fileUrl) { + const existingImages = $(e.target).find(`img[src="${fileUrl}"]`); + if (existingImages.length === 0) { + DraggableUtils.createDraggableCanvasFromUrl(fileUrl); + } + } + const overlayElement = chooser.querySelector('.drag-drop-overlay'); + if (overlayElement) { + overlayElement.style.display = 'none'; + } + hasDroppedImage = true; + }); + + showOrHideSelectedFilesContainer(files); } function showOrHideSelectedFilesContainer(files) { - if (files && files.length > 0) chooser.style.setProperty('--selected-files-display', 'flex'); - else chooser.style.setProperty('--selected-files-display', 'none'); + if (files && files.length > 0) { + chooser.style.setProperty('--selected-files-display', 'flex'); + } else { + chooser.style.setProperty('--selected-files-display', 'none'); + } + const isDragAndDropEnabled = + (window.location.pathname.includes('add-image') || window.location.pathname.includes('sign')) && + files.some((file) => file.type.startsWith('image/')); + + if (!isDragAndDropEnabled) return; + + const selectedFilesContainer = chooser.querySelector('.selected-files'); + + let overlayElement = chooser.querySelector('.drag-drop-overlay'); + if (!overlayElement) { + selectedFilesContainer.style.position = 'relative'; + overlayElement = document.createElement('div'); + overlayElement.classList.add('draggable-image-overlay'); + + overlayElement.innerHTML = 'Drag images to add them to the page'; + selectedFilesContainer.appendChild(overlayElement); + } + if (hasDroppedImage) overlayElement.style.display = files && files.length > 0 ? 'flex' : 'none'; + + selectedFilesContainer.addEventListener('mouseenter', () => { + overlayElement.style.display = 'none'; + }); + + selectedFilesContainer.addEventListener('mouseleave', () => { + if (!hasDroppedImage) overlayElement.style.display = files && files.length > 0 ? 'flex' : 'none'; + }); } function removeFileListener(e) { @@ -235,4 +327,52 @@ function setupFileInput(chooser) { removeFileById(fileId, inputElement); showOrHideSelectedFilesContainer(allFiles); }); + function enableImagePreviewOnClick(container) { + const imagePreviewModal = document.getElementById('imagePreviewModal') || createImagePreviewModal(); + + container.querySelectorAll('img').forEach((img) => { + if (!img.hasPreviewListener) { + img.addEventListener('mouseup', function () { + const imgElement = imagePreviewModal.querySelector('img'); + imgElement.src = this.src; + imagePreviewModal.style.display = 'flex'; + }); + img.hasPreviewListener = true; + } + }); + + function createImagePreviewModal() { + const modal = document.createElement('div'); + modal.id = 'imagePreviewModal'; + modal.style.position = 'fixed'; + modal.style.top = '0'; + modal.style.left = '0'; + modal.style.width = '100vw'; + modal.style.height = '100vh'; + modal.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; + modal.style.display = 'none'; + modal.style.justifyContent = 'center'; + modal.style.alignItems = 'center'; + modal.style.zIndex = '2000'; + + const imgElement = document.createElement('img'); + imgElement.style.maxWidth = '90%'; + imgElement.style.maxHeight = '90%'; + + modal.appendChild(imgElement); + document.body.appendChild(modal); + + modal.addEventListener('click', () => { + modal.style.display = 'none'; + }); + + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && modal.style.display === 'flex') { + modal.style.display = 'none'; + } + }); + + return modal; + } + } } diff --git a/src/main/resources/static/js/pages/add-image.js b/src/main/resources/static/js/pages/add-image.js index 5899b53f9..2bafd86ec 100644 --- a/src/main/resources/static/js/pages/add-image.js +++ b/src/main/resources/static/js/pages/add-image.js @@ -1,23 +1,38 @@ +window.goToFirstOrLastPage = goToFirstOrLastPage; + document.getElementById('download-pdf').addEventListener('click', async () => { - const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); - const modifiedPdfBytes = await modifiedPdf.save(); - const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = originalFileName + '_addedImage.pdf'; - link.click(); + const downloadButton = document.getElementById('download-pdf'); + const originalContent = downloadButton.innerHTML; + + downloadButton.disabled = true; + downloadButton.innerHTML = ` + + `; + + try { + const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); + const modifiedPdfBytes = await modifiedPdf.save(); + const blob = new Blob([modifiedPdfBytes], { type: 'application/pdf' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = originalFileName + '_addedImage.pdf'; + link.click(); + } finally { + downloadButton.disabled = false; + downloadButton.innerHTML = originalContent; + } }); let originalFileName = ''; document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { const fileInput = event.target; fileInput.addEventListener('file-input-change', async (e) => { - const {allFiles} = e.detail; + const { allFiles } = e.detail; if (allFiles && allFiles.length > 0) { const file = allFiles[0]; originalFileName = file.name.replace(/\.[^/.]+$/, ''); const pdfData = await file.arrayBuffer(); pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; - const pdfDoc = await pdfjsLib.getDocument({data: pdfData}).promise; + const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise; await DraggableUtils.renderPage(pdfDoc, 0); document.querySelectorAll('.show-on-file-selected').forEach((el) => { @@ -30,6 +45,11 @@ document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.show-on-file-selected').forEach((el) => { el.style.cssText = 'display:none !important'; }); + document.addEventListener('keydown', (e) => { + if (e.key === 'Delete') { + DraggableUtils.deleteDraggableCanvas(DraggableUtils.getLastInteracted()); + } + }); }); const imageUpload = document.querySelector('input[name=image-upload]'); @@ -45,3 +65,12 @@ imageUpload.addEventListener('change', (e) => { }; } }); + +async function goToFirstOrLastPage(page) { + if (page) { + const lastPage = DraggableUtils.pdfDoc.numPages; + await DraggableUtils.goToPage(lastPage - 1); + } else { + await DraggableUtils.goToPage(0); + } +} diff --git a/src/main/resources/static/js/pages/sign.js b/src/main/resources/static/js/pages/sign.js index 8d45c9697..736ca1cd5 100644 --- a/src/main/resources/static/js/pages/sign.js +++ b/src/main/resources/static/js/pages/sign.js @@ -73,6 +73,16 @@ document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.show-on-file-selected').forEach((el) => { el.style.cssText = 'display:none !important'; }); + document.querySelectorAll('.small-file-container-saved img ').forEach((img) => { + img.addEventListener('dragstart', (e) => { + e.dataTransfer.setData('fileUrl', img.src); + }); + }); + document.addEventListener('keydown', (e) => { + if (e.key === 'Delete') { + DraggableUtils.deleteDraggableCanvas(DraggableUtils.getLastInteracted()); + } + }); }); const imageUpload = document.querySelector('input[name=image-upload]'); @@ -203,11 +213,26 @@ async function goToFirstOrLastPage(page) { } document.getElementById('download-pdf').addEventListener('click', async () => { - const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); - const modifiedPdfBytes = await modifiedPdf.save(); - const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = originalFileName + '_signed.pdf'; - link.click(); + const downloadButton = document.getElementById('download-pdf'); + const originalContent = downloadButton.innerHTML; + + downloadButton.disabled = true; + downloadButton.innerHTML = ` + + `; + + try { + const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); + const modifiedPdfBytes = await modifiedPdf.save(); + const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = originalFileName + '_signed.pdf'; + link.click(); + } catch (error) { + console.error('Error downloading PDF:', error); + } finally { + downloadButton.disabled = false; + downloadButton.innerHTML = originalContent; + } }); diff --git a/src/main/resources/static/js/sign/signature-canvas.js b/src/main/resources/static/js/sign/signature-canvas.js new file mode 100644 index 000000000..03052d9ce --- /dev/null +++ b/src/main/resources/static/js/sign/signature-canvas.js @@ -0,0 +1,85 @@ +const signaturePadCanvas = document.getElementById('drawing-pad-canvas'); +const signaturePad = new SignaturePad(signaturePadCanvas, { + minWidth: 1, + maxWidth: 2, + penColor: 'black', +}); + +function addDraggableFromPad() { + if (signaturePad.isEmpty()) return; + const startTime = Date.now(); + const croppedDataUrl = getCroppedCanvasDataUrl(signaturePadCanvas); + console.log(Date.now() - startTime); + DraggableUtils.createDraggableCanvasFromUrl(croppedDataUrl); +} + +function getCroppedCanvasDataUrl(canvas) { + let originalCtx = canvas.getContext('2d'); + let originalWidth = canvas.width; + let originalHeight = canvas.height; + let imageData = originalCtx.getImageData(0, 0, originalWidth, originalHeight); + + let minX = originalWidth + 1, + maxX = -1, + minY = originalHeight + 1, + maxY = -1, + x = 0, + y = 0, + currentPixelColorValueIndex; + + for (y = 0; y < originalHeight; y++) { + for (x = 0; x < originalWidth; x++) { + currentPixelColorValueIndex = (y * originalWidth + x) * 4; + let currentPixelAlphaValue = imageData.data[currentPixelColorValueIndex + 3]; + if (currentPixelAlphaValue > 0) { + if (minX > x) minX = x; + if (maxX < x) maxX = x; + if (minY > y) minY = y; + if (maxY < y) maxY = y; + } + } + } + + let croppedWidth = maxX - minX; + let croppedHeight = maxY - minY; + if (croppedWidth < 0 || croppedHeight < 0) return null; + let cuttedImageData = originalCtx.getImageData(minX, minY, croppedWidth, croppedHeight); + + let croppedCanvas = document.createElement('canvas'), + croppedCtx = croppedCanvas.getContext('2d'); + + croppedCanvas.width = croppedWidth; + croppedCanvas.height = croppedHeight; + croppedCtx.putImageData(cuttedImageData, 0, 0); + + return croppedCanvas.toDataURL(); +} + +function isMobile() { + const userAgentCheck = /Mobi|Android|iPhone|iPad|iPod|Windows Phone|Opera Mini/i.test(navigator.userAgent); + const viewportCheck = window.matchMedia('(max-width: 768px)').matches; + return userAgentCheck || viewportCheck; +} + +function getDeviceScalingFactor() { + return isMobile() ? 3 : 10; +} + +function resizeCanvas() { + const ratio = Math.max(window.devicePixelRatio || 1, 1); + const additionalFactor = getDeviceScalingFactor(); + + signaturePadCanvas.width = signaturePadCanvas.offsetWidth * ratio * additionalFactor; + signaturePadCanvas.height = signaturePadCanvas.offsetHeight * ratio * additionalFactor; + signaturePadCanvas.getContext('2d').scale(ratio * additionalFactor, ratio * additionalFactor); + + signaturePad.clear(); +} + +new IntersectionObserver((entries, observer) => { + if (entries.some((entry) => entry.intersectionRatio > 0)) { + resizeCanvas(); + } +}).observe(signaturePadCanvas); + +new ResizeObserver(resizeCanvas).observe(signaturePadCanvas); diff --git a/src/main/resources/templates/fragments/common.html b/src/main/resources/templates/fragments/common.html index f03e83c5b..1cd908a69 100644 --- a/src/main/resources/templates/fragments/common.html +++ b/src/main/resources/templates/fragments/common.html @@ -213,7 +213,10 @@ unexpectedError: '[[#{decrypt.unexpectedError}]]', serverError: '[[#{decrypt.serverError}]]', success: '[[#{decrypt.success}]]', - }; + }; + window.fileInput = { + dragAndDropPDF : '[[#{fileChooser.dragAndDropPDF}]]', + dragAndDropImage : '[[#{fileChooser.dragAndDropImage}]]'};
-
+
diff --git a/src/main/resources/templates/misc/add-image.html b/src/main/resources/templates/misc/add-image.html index 5d644dd3d..9addaebd4 100644 --- a/src/main/resources/templates/misc/add-image.html +++ b/src/main/resources/templates/misc/add-image.html @@ -1,65 +1,123 @@ - - + + + - - - + + + - -
-
- -

-
-
-
-
- add_photo_alternate - + +
+
+ +

+
+
+
+
+ add_photo_alternate + +
+ + +
+
+ + +
+
+
- -
- - -
-
-
- - -
- - -
- - - +
+ + + - - -
- -
+ + + + + + +
+ +
+ +
-
- + +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/sign.html b/src/main/resources/templates/sign.html index 546cbe986..85bce6c2f 100644 --- a/src/main/resources/templates/sign.html +++ b/src/main/resources/templates/sign.html @@ -21,8 +21,6 @@ - - @@ -32,7 +30,7 @@

-
+
signature @@ -46,7 +44,7 @@
+ th:replace="~{fragments/common :: fileSelector(name='image-upload', disableMultipleFiles=false, multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}">
@@ -61,13 +59,6 @@
- -
- -
- - -
- -
-
-
-
- + +
+
+
+
+
+ + +
+ +
+
+
- -
-
-
-
- + +
+
+
+
+
+ + +
+ +
- -

No saved signatures found

@@ -169,72 +143,99 @@
+ -
- - -
- - + + + + + + + +
- -
- +
+ + + + + +
+
+ + \ No newline at end of file From 807639308a0a97d9bd9073c4e1d1e4e6fbb363fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:54:07 +0000 Subject: [PATCH 07/25] Update translation files (#2582) Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Signed-off-by: GitHub Action Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/main/resources/messages_ar_AR.properties | 4 +++- src/main/resources/messages_az_AZ.properties | 4 +++- src/main/resources/messages_bg_BG.properties | 4 +++- src/main/resources/messages_ca_CA.properties | 4 +++- src/main/resources/messages_cs_CZ.properties | 4 +++- src/main/resources/messages_da_DK.properties | 4 +++- src/main/resources/messages_de_DE.properties | 4 +++- src/main/resources/messages_el_GR.properties | 4 +++- src/main/resources/messages_en_US.properties | 4 +++- src/main/resources/messages_es_ES.properties | 4 +++- src/main/resources/messages_eu_ES.properties | 4 +++- src/main/resources/messages_fa_IR.properties | 4 +++- src/main/resources/messages_fr_FR.properties | 4 +++- src/main/resources/messages_ga_IE.properties | 4 +++- src/main/resources/messages_hi_IN.properties | 4 +++- src/main/resources/messages_hr_HR.properties | 4 +++- src/main/resources/messages_hu_HU.properties | 4 +++- src/main/resources/messages_id_ID.properties | 4 +++- src/main/resources/messages_it_IT.properties | 4 +++- src/main/resources/messages_ja_JP.properties | 4 +++- src/main/resources/messages_ko_KR.properties | 4 +++- src/main/resources/messages_nl_NL.properties | 4 +++- src/main/resources/messages_no_NB.properties | 4 +++- src/main/resources/messages_pl_PL.properties | 4 +++- src/main/resources/messages_pt_BR.properties | 4 +++- src/main/resources/messages_pt_PT.properties | 4 +++- src/main/resources/messages_ro_RO.properties | 4 +++- src/main/resources/messages_ru_RU.properties | 4 +++- src/main/resources/messages_sk_SK.properties | 4 +++- src/main/resources/messages_sr_LATN_RS.properties | 4 +++- src/main/resources/messages_sv_SE.properties | 4 +++- src/main/resources/messages_th_TH.properties | 4 +++- src/main/resources/messages_tr_TR.properties | 4 +++- src/main/resources/messages_uk_UA.properties | 4 +++- src/main/resources/messages_vi_VN.properties | 4 +++- src/main/resources/messages_zh_CN.properties | 4 +++- src/main/resources/messages_zh_TW.properties | 4 +++- 37 files changed, 111 insertions(+), 37 deletions(-) diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties index c80f540a7..67b08084a 100644 --- a/src/main/resources/messages_ar_AR.properties +++ b/src/main/resources/messages_ar_AR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=إصلاح repair.header=إصلاح ملفات PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=تقطيع ملف PDF fileChooser.click=انقر هنا fileChooser.or=أو fileChooser.dragAndDrop=قم بسحب الملفات وإفلاتها +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=قم بسحب المفات وإفلاتها هنا #release notes diff --git a/src/main/resources/messages_az_AZ.properties b/src/main/resources/messages_az_AZ.properties index 5456c3ce0..471eafaa6 100644 --- a/src/main/resources/messages_az_AZ.properties +++ b/src/main/resources/messages_az_AZ.properties @@ -831,7 +831,7 @@ sign.first=İlk səhifə sign.last=Son səhifə sign.next=Növbəti səhifə sign.previous=Əvvəlki səhifə - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Bərpa Et repair.header=PDFləri Bərpa Et @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF-i Ayır fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties index 7a35e4b9a..57c0e8a36 100644 --- a/src/main/resources/messages_bg_BG.properties +++ b/src/main/resources/messages_bg_BG.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Поправи repair.header=Поправи PDF-и @@ -1285,6 +1285,8 @@ splitByChapters.submit=Разделяне на PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties index 798742aaf..3257a1551 100644 --- a/src/main/resources/messages_ca_CA.properties +++ b/src/main/resources/messages_ca_CA.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparar repair.header=Repara els PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Divideix PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_cs_CZ.properties b/src/main/resources/messages_cs_CZ.properties index ea2491505..bc793279b 100644 --- a/src/main/resources/messages_cs_CZ.properties +++ b/src/main/resources/messages_cs_CZ.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Opravit repair.header=Opravit PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Podělit se PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_da_DK.properties b/src/main/resources/messages_da_DK.properties index e6d5de751..71fea7630 100644 --- a/src/main/resources/messages_da_DK.properties +++ b/src/main/resources/messages_da_DK.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparér repair.header=Reparér PDF'er @@ -1285,6 +1285,8 @@ splitByChapters.submit=Splitter PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index b2894d3af..0d9c3e1c2 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -831,7 +831,7 @@ sign.first=Erste Seite sign.last=Letzte Seite sign.next=Nächste Seite sign.previous=Vorherige Seite - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparieren repair.header=PDFs reparieren @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF teilen fileChooser.click=Klicken fileChooser.or=oder fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Datei(en) hierhin Ziehen & Fallenlassen #release notes diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties index d832ec8cb..99cc37e92 100644 --- a/src/main/resources/messages_el_GR.properties +++ b/src/main/resources/messages_el_GR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Επιδιόρθωση repair.header=Επιδιόρθωση PDFs @@ -1285,6 +1285,8 @@ splitByChapters.submit=Διαλύστε το PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index 6cd57d71c..6c90e559a 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Repair repair.header=Repair PDFs @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties index 05af81473..7401569e1 100644 --- a/src/main/resources/messages_es_ES.properties +++ b/src/main/resources/messages_es_ES.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparar repair.header=Reparar archivos PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Dividir PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties index 00bff8ed5..44df5362d 100644 --- a/src/main/resources/messages_eu_ES.properties +++ b/src/main/resources/messages_eu_ES.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Konpondu repair.header=Konpondu PDF fitxategiak @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_fa_IR.properties b/src/main/resources/messages_fa_IR.properties index ba1bf45f4..0be077386 100644 --- a/src/main/resources/messages_fa_IR.properties +++ b/src/main/resources/messages_fa_IR.properties @@ -831,7 +831,7 @@ sign.first=صفحه اول sign.last=صفحه آخر sign.next=صفحه بعدی sign.previous=صفحه قبلی - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=تعمیر repair.header=تعمیر PDFها @@ -1285,6 +1285,8 @@ splitByChapters.submit=تقسیم PDF fileChooser.click=کلیک کنید fileChooser.or=یا fileChooser.dragAndDrop=بکشید و رها کنید +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=فایل(های) خود را اینجا بکشید و رها کنید #release notes diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties index d1ac22eeb..36c92b5e3 100644 --- a/src/main/resources/messages_fr_FR.properties +++ b/src/main/resources/messages_fr_FR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Réparer repair.header=Réparer @@ -1285,6 +1285,8 @@ splitByChapters.submit=Diviser le PDF fileChooser.click=Cliquez fileChooser.or=ou fileChooser.dragAndDrop=Glisser & Déposer +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Glisser & Déposer le(s) fichier(s) ici #release notes diff --git a/src/main/resources/messages_ga_IE.properties b/src/main/resources/messages_ga_IE.properties index 134e9c54d..c9cb7355f 100644 --- a/src/main/resources/messages_ga_IE.properties +++ b/src/main/resources/messages_ga_IE.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Deisiúchán repair.header=PDF a dheisiú @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties index c85157523..994d2e800 100644 --- a/src/main/resources/messages_hi_IN.properties +++ b/src/main/resources/messages_hi_IN.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=मरम्मत repair.header=पीडीएफ़ मरम्मत करें @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF विभाजित fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_hr_HR.properties b/src/main/resources/messages_hr_HR.properties index df5e5ed29..2e2157488 100644 --- a/src/main/resources/messages_hr_HR.properties +++ b/src/main/resources/messages_hr_HR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Popravi repair.header=Popravi PDF datoteku @@ -1285,6 +1285,8 @@ splitByChapters.submit=Podijeli PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties index 09d4831b9..a1bcc7ae7 100644 --- a/src/main/resources/messages_hu_HU.properties +++ b/src/main/resources/messages_hu_HU.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Javítás repair.header=PDF-ek javítása @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF osztás fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties index d90d89d03..f61147f04 100644 --- a/src/main/resources/messages_id_ID.properties +++ b/src/main/resources/messages_id_ID.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Perbaiki repair.header=Perbaiki PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Pecah PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index a1cefa1d5..99ab34797 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -831,7 +831,7 @@ sign.first=Prima pagina sign.last=Ultima pagina sign.next=Prossima pagina sign.previous=Pagina precedente - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Ripara repair.header=Ripara PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Dividi PDF fileChooser.click=Clicca fileChooser.or=o fileChooser.dragAndDrop=Trascina & Rilascia +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Trascina & rilascia i file qui #release notes diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties index e4c503e8a..16afc859b 100644 --- a/src/main/resources/messages_ja_JP.properties +++ b/src/main/resources/messages_ja_JP.properties @@ -831,7 +831,7 @@ sign.first=最初のページ sign.last=最後のページ sign.next=次のページ sign.previous=前のページ - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=修復 repair.header=PDFを修復 @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDFを分割 fileChooser.click=クリック fileChooser.or=または fileChooser.dragAndDrop=ドラッグ&ドロップ +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=ファイルをここにドラッグ&ドロップ #release notes diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties index 6552539df..83c48e470 100644 --- a/src/main/resources/messages_ko_KR.properties +++ b/src/main/resources/messages_ko_KR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=복구 repair.header=PDF 복구 @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF 분할 fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties index fa6c47d88..76b57ef75 100644 --- a/src/main/resources/messages_nl_NL.properties +++ b/src/main/resources/messages_nl_NL.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Repareren repair.header=PDF's repareren @@ -1285,6 +1285,8 @@ splitByChapters.submit=PDF splitsen fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_no_NB.properties b/src/main/resources/messages_no_NB.properties index c6ca205bd..d6fb339df 100644 --- a/src/main/resources/messages_no_NB.properties +++ b/src/main/resources/messages_no_NB.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparer repair.header=Reparer PDF-er @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties index 0b5744d47..ee5672123 100644 --- a/src/main/resources/messages_pl_PL.properties +++ b/src/main/resources/messages_pl_PL.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Napraw repair.header=Napraw dokument(y) PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Podziel PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties index c2e1804f5..b5b1656c1 100644 --- a/src/main/resources/messages_pt_BR.properties +++ b/src/main/resources/messages_pt_BR.properties @@ -831,7 +831,7 @@ sign.first=Primeira página sign.last=Última página sign.next=Próxima página sign.previous=Página anterior - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparar repair.header=Reparar @@ -1285,6 +1285,8 @@ splitByChapters.submit=Dividir fileChooser.click=Clique fileChooser.or=ou fileChooser.dragAndDrop=Arraste & Solte +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Arraste & Solte arquivo(s) aqui #release notes diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties index 9c05e8870..0fe76bb7a 100644 --- a/src/main/resources/messages_pt_PT.properties +++ b/src/main/resources/messages_pt_PT.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparar repair.header=Reparar PDFs @@ -1285,6 +1285,8 @@ splitByChapters.submit=Dividir o PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties index 58a521c5d..f3688a73d 100644 --- a/src/main/resources/messages_ro_RO.properties +++ b/src/main/resources/messages_ro_RO.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Repară repair.header=Repară documente PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties index 9161b89e2..6a5b1569a 100644 --- a/src/main/resources/messages_ru_RU.properties +++ b/src/main/resources/messages_ru_RU.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Ремонт repair.header=Ремонт PDF ов @@ -1285,6 +1285,8 @@ splitByChapters.submit=Разделить PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_sk_SK.properties b/src/main/resources/messages_sk_SK.properties index 2159b7c87..aed436354 100644 --- a/src/main/resources/messages_sk_SK.properties +++ b/src/main/resources/messages_sk_SK.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Opraviť repair.header=Opraviť PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties index 4af2ff622..4c17fd28a 100644 --- a/src/main/resources/messages_sr_LATN_RS.properties +++ b/src/main/resources/messages_sr_LATN_RS.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Popravi repair.header=Popravi PDF fajlove @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties index 43b901c36..aa5e74818 100644 --- a/src/main/resources/messages_sv_SE.properties +++ b/src/main/resources/messages_sv_SE.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Reparera repair.header=Reparera PDF-filer @@ -1285,6 +1285,8 @@ splitByChapters.submit=Dela upp PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_th_TH.properties b/src/main/resources/messages_th_TH.properties index 7d89206a2..33711c130 100644 --- a/src/main/resources/messages_th_TH.properties +++ b/src/main/resources/messages_th_TH.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=ซ่อมแซม repair.header=ซ่อมแซม PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=แบ่งไฟล์ PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties index 967c06ed2..7c5ca7b67 100644 --- a/src/main/resources/messages_tr_TR.properties +++ b/src/main/resources/messages_tr_TR.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Onar repair.header=PDF'leri Onar @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties index 0d8ec5b45..a43bb399f 100644 --- a/src/main/resources/messages_uk_UA.properties +++ b/src/main/resources/messages_uk_UA.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Ремонт repair.header=Ремонт PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_vi_VN.properties b/src/main/resources/messages_vi_VN.properties index 00d706059..ae1e47f03 100644 --- a/src/main/resources/messages_vi_VN.properties +++ b/src/main/resources/messages_vi_VN.properties @@ -831,7 +831,7 @@ sign.first=First page sign.last=Last page sign.next=Next page sign.previous=Previous page - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=Sửa chữa repair.header=Sửa chữa PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=Split PDF fileChooser.click=Click fileChooser.or=or fileChooser.dragAndDrop=Drag & Drop +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here #release notes diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties index 8aea8c546..921faf0cf 100644 --- a/src/main/resources/messages_zh_CN.properties +++ b/src/main/resources/messages_zh_CN.properties @@ -831,7 +831,7 @@ sign.first=首页 sign.last=末页 sign.next=下一页 sign.previous=上一页 - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=修复 repair.header=修复 PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=拆分 PDF fileChooser.click=单击 fileChooser.or=或 fileChooser.dragAndDrop=拖放文件 +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=拖放文件到此处 #release notes diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties index c231c18e0..cf6dfb9d4 100644 --- a/src/main/resources/messages_zh_TW.properties +++ b/src/main/resources/messages_zh_TW.properties @@ -831,7 +831,7 @@ sign.first=第一頁 sign.last=最後一頁 sign.next=下一頁 sign.previous=上一頁 - +sign.maintainRatio=Toggle maintain aspect ratio #repair repair.title=修復 repair.header=修復 PDF @@ -1285,6 +1285,8 @@ splitByChapters.submit=分割 PDF fileChooser.click=點選 fileChooser.or=或 fileChooser.dragAndDrop=拖放檔案 +fileChooser.dragAndDropPDF=Drag & Drop PDF file +fileChooser.dragAndDropImage=Drag & Drop Image file fileChooser.hoveredDragAndDrop=將檔案拖放至此 #release notes From 4544fb721158617ef22f509d8421f7a25d930ddd Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 16:58:08 +0100 Subject: [PATCH 08/25] Fix: Translation Verification (#2581) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/check_properties.yml | 153 +++++++++++++++++++------ 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/.github/workflows/check_properties.yml b/.github/workflows/check_properties.yml index 5fc4dce95..62a3537ff 100644 --- a/.github/workflows/check_properties.yml +++ b/.github/workflows/check_properties.yml @@ -8,12 +8,13 @@ on: permissions: contents: read # Allow read access to repository content - issues: write # Allow posting comments on issues/PRs jobs: check-files: if: github.event_name == 'pull_request_target' runs-on: ubuntu-latest + permissions: + issues: write # Allow posting comments on issues/PRs steps: - name: Harden Runner uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 @@ -41,48 +42,125 @@ jobs: echo "Getting list of changed files from PR..." gh pr view ${{ github.event.pull_request.number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]+\.properties$' > changed_files.txt # Filter only matching property files - - name: Determine reference file - id: determine-file - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "Determining reference file..." - REPO_OWNER=$(gh pr view ${{ github.event.pull_request.number }} --json author -q '.author.login') # Get PR author's username - REPO_NAME=$(gh pr view ${{ github.event.pull_request.number }} --json headRepository -q '.headRepository.name') # Get PR repository name - BRANCH=$(gh pr view ${{ github.event.pull_request.number }} --json headRefName -q '.headRefName') # Get PR branch name + - name: Get PR data + id: get-pr-data + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const prNumber = context.payload.pull_request.number; + const repoOwner = context.payload.repository.owner.login; + const repoName = context.payload.repository.name; + const branch = context.payload.pull_request.head.ref; - mkdir -p pr-branch # Create a directory for PR files + console.log(`PR Number: ${prNumber}`); + console.log(`Repo Owner: ${repoOwner}`); + console.log(`Repo Name: ${repoName}`); + console.log(`Branch: ${branch}`); - # Download the content of each changed file - while IFS= read -r file; do - mkdir -p "pr-branch/$(dirname "$file")" # Create directories for files - gh api repos/$REPO_OWNER/$REPO_NAME/contents/$file?ref=$BRANCH --jq '.content' | base64 -d > "pr-branch/src/main/resources/$(basename "$file")" # Save decoded file content - done < changed_files.txt + core.setOutput("pr_number", prNumber); + core.setOutput("repo_owner", repoOwner); + core.setOutput("repo_name", repoName); + core.setOutput("branch", branch); + continue-on-error: true + - name: Determine reference file test + id: determine-file-1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const prNumber = ${{ steps.get-pr-data.outputs.pr_number }}; + const repoOwner = "${{ steps.get-pr-data.outputs.repo_owner }}"; + const repoName = "${{ steps.get-pr-data.outputs.repo_name }}"; + const branch = "${{ steps.get-pr-data.outputs.branch }}"; - # Generate a list of files without the "pr-branch/" prefix - find pr-branch/ -type f | awk -F'pr-branch/' '{print $2}' > file_list.txt + console.log(`Determining reference file for PR #${prNumber}`); - mapfile -t FILES_LIST < file_list.txt # Read the file list into an array - FILES_LIST_STR="${FILES_LIST[*]}" # Join array into a space-separated string - echo "FILES_LIST=${FILES_LIST_STR}" >> $GITHUB_ENV # Export the file list to the environment - echo "Changed files: ${FILES_LIST_STR}" + // Validate inputs + const validateInput = (input, regex, name) => { + if (!regex.test(input)) { + throw new Error(`Invalid ${name}: ${input}`); + } + }; - cat file_list.txt # Display the file list + validateInput(repoOwner, /^[a-zA-Z0-9_-]+$/, "repository owner"); + validateInput(repoName, /^[a-zA-Z0-9._-]+$/, "repository name"); + validateInput(branch, /^[a-zA-Z0-9._/-]+$/, "branch name"); - # Determine which reference file to use - if grep -Fxq "src/main/resources/messages_en_GB.properties" changed_files.txt; then - echo "Using PR branch reference file" - REFERENCE_FILE="pr-branch-messages_en_GB.properties" - gh api repos/$REPO_OWNER/$REPO_NAME/contents/src/main/resources/messages_en_GB.properties?ref=${{ github.event.pull_request.head.ref }} \ - --jq '.content' | base64 -d > $REFERENCE_FILE # Save PR branch reference file - else - echo "Using main branch reference file" - REFERENCE_FILE="main-branch-messages_en_GB.properties" - gh api repos/Ludy87/test_java/contents/src/main/resources/messages_en_GB.properties?ref=main \ - --jq '.content' | base64 -d > $REFERENCE_FILE # Save main branch reference file - fi + // Get the list of changed files in the PR + const { data: files } = await github.rest.pulls.listFiles({ + owner: repoOwner, + repo: repoName, + pull_number: prNumber, + }); - echo "REFERENCE_FILE=$REFERENCE_FILE" >> $GITHUB_ENV # Export reference file path to the environment + // Filter for relevant files based on the PR changes + const changedFiles = files + .map(file => file.filename) + .filter(file => /^src\/main\/resources\/messages_[a-zA-Z_]+\.properties$/.test(file)); + + console.log("Changed files:", changedFiles); + + // Create a temporary directory for PR files + const tempDir = "pr-branch"; + if (!require("fs").existsSync(tempDir)) { + require("fs").mkdirSync(tempDir, { recursive: true }); + } + + // Download and save each changed file + for (const file of changedFiles) { + const { data: fileContent } = await github.rest.repos.getContent({ + owner: repoOwner, + repo: repoName, + path: file, + ref: branch, + }); + + const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); + const filePath = `${tempDir}/${file}`; + const dirPath = require("path").dirname(filePath); + + if (!require("fs").existsSync(dirPath)) { + require("fs").mkdirSync(dirPath, { recursive: true }); + } + + require("fs").writeFileSync(filePath, content); + console.log(`Saved file: ${filePath}`); + } + + // Output the list of changed files for further processing + const fileList = changedFiles.join(" "); + core.exportVariable("FILES_LIST", fileList); + console.log("Files saved and listed in FILES_LIST."); + + // Determine reference file + let referenceFilePath; + if (changedFiles.includes("src/main/resources/messages_en_GB.properties")) { + console.log("Using PR branch reference file."); + const { data: fileContent } = await github.rest.repos.getContent({ + owner: repoOwner, + repo: repoName, + path: "src/main/resources/messages_en_GB.properties", + ref: branch, + }); + + referenceFilePath = "pr-branch-messages_en_GB.properties"; + const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); + require("fs").writeFileSync(referenceFilePath, content); + } else { + console.log("Using main branch reference file."); + const { data: fileContent } = await github.rest.repos.getContent({ + owner: "Stirling-Tools", + repo: "Stirling-PDF", + path: "src/main/resources/messages_en_GB.properties", + ref: "main", + }); + + referenceFilePath = "main-branch-messages_en_GB.properties"; + const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); + require("fs").writeFileSync(referenceFilePath, content); + } + + console.log(`Reference file path: ${referenceFilePath}`); + core.exportVariable("REFERENCE_FILE", referenceFilePath); - name: Run Python script to check files id: run-check @@ -92,7 +170,8 @@ jobs: --actor ${{ github.event.pull_request.user.login }} \ --reference-file "${REFERENCE_FILE}" \ --branch "pr-branch" \ - --files "${FILES_LIST[@]}" > result.txt || true + --files "${FILES_LIST[@]}" > result.txt + continue-on-error: true # Continue the job even if this step fails - name: Capture output id: capture-output From 36c4d8552ddf22deaa39c69b594da34c49a8464b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:58:24 +0000 Subject: [PATCH 09/25] :memo: Update README: Translation Progress Table (#2580) Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 785a4e2f2..2dc3b26a8 100644 --- a/README.md +++ b/README.md @@ -116,43 +116,43 @@ Stirling-PDF currently supports 38 languages! | Language | Progress | | -------------------------------------------- | -------------------------------------- | -| Arabic (العربية) (ar_AR) | ![94%](https://geps.dev/progress/94) | +| Arabic (العربية) (ar_AR) | ![93%](https://geps.dev/progress/93) | | Azerbaijani (Azərbaycan Dili) (az_AZ) | ![92%](https://geps.dev/progress/92) | | Basque (Euskara) (eu_ES) | ![53%](https://geps.dev/progress/53) | | Bulgarian (Български) (bg_BG) | ![89%](https://geps.dev/progress/89) | | Catalan (Català) (ca_CA) | ![84%](https://geps.dev/progress/84) | -| Croatian (Hrvatski) (hr_HR) | ![91%](https://geps.dev/progress/91) | +| Croatian (Hrvatski) (hr_HR) | ![90%](https://geps.dev/progress/90) | | Czech (Česky) (cs_CZ) | ![90%](https://geps.dev/progress/90) | | Danish (Dansk) (da_DK) | ![89%](https://geps.dev/progress/89) | -| Dutch (Nederlands) (nl_NL) | ![89%](https://geps.dev/progress/89) | +| Dutch (Nederlands) (nl_NL) | ![88%](https://geps.dev/progress/88) | | 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) | ![96%](https://geps.dev/progress/96) | -| German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) | +| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) | | Greek (Ελληνικά) (el_GR) | ![90%](https://geps.dev/progress/90) | | Hindi (हिंदी) (hi_IN) | ![88%](https://geps.dev/progress/88) | -| Hungarian (Magyar) (hu_HU) | ![91%](https://geps.dev/progress/91) | +| Hungarian (Magyar) (hu_HU) | ![90%](https://geps.dev/progress/90) | | Indonesian (Bahasa Indonesia) (id_ID) | ![90%](https://geps.dev/progress/90) | | Irish (Gaeilge) (ga_IE) | ![82%](https://geps.dev/progress/82) | -| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | +| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | | Japanese (日本語) (ja_JP) | ![93%](https://geps.dev/progress/93) | -| Korean (한국어) (ko_KR) | ![89%](https://geps.dev/progress/89) | +| Korean (한국어) (ko_KR) | ![88%](https://geps.dev/progress/88) | | Norwegian (Norsk) (no_NB) | ![82%](https://geps.dev/progress/82) | -| Persian (فارسی) (fa_IR) | ![99%](https://geps.dev/progress/99) | -| Polish (Polski) (pl_PL) | ![90%](https://geps.dev/progress/90) | +| Persian (فارسی) (fa_IR) | ![98%](https://geps.dev/progress/98) | +| Polish (Polski) (pl_PL) | ![89%](https://geps.dev/progress/89) | | Portuguese (Português) (pt_PT) | ![90%](https://geps.dev/progress/90) | | Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) | | Romanian (Română) (ro_RO) | ![84%](https://geps.dev/progress/84) | | Russian (Русский) (ru_RU) | ![90%](https://geps.dev/progress/90) | -| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![67%](https://geps.dev/progress/67) | +| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![66%](https://geps.dev/progress/66) | | Simplified Chinese (简体中文) (zh_CN) | ![93%](https://geps.dev/progress/93) | -| Slovakian (Slovensky) (sk_SK) | ![78%](https://geps.dev/progress/78) | -| Spanish (Español) (es_ES) | ![91%](https://geps.dev/progress/91) | -| Swedish (Svenska) (sv_SE) | ![90%](https://geps.dev/progress/90) | -| Thai (ไทย) (th_TH) | ![90%](https://geps.dev/progress/90) | +| Slovakian (Slovensky) (sk_SK) | ![77%](https://geps.dev/progress/77) | +| Spanish (Español) (es_ES) | ![90%](https://geps.dev/progress/90) | +| Swedish (Svenska) (sv_SE) | ![89%](https://geps.dev/progress/89) | +| Thai (ไทย) (th_TH) | ![89%](https://geps.dev/progress/89) | | Traditional Chinese (繁體中文) (zh_TW) | ![99%](https://geps.dev/progress/99) | | Turkish (Türkçe) (tr_TR) | ![86%](https://geps.dev/progress/86) | -| Ukrainian (Українська) (uk_UA) | ![76%](https://geps.dev/progress/76) | +| Ukrainian (Українська) (uk_UA) | ![75%](https://geps.dev/progress/75) | | Vietnamese (Tiếng Việt) (vi_VN) | ![83%](https://geps.dev/progress/83) | From 7b768db969aba77310627bb68549b222f0493085 Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 18:28:32 +0100 Subject: [PATCH 10/25] Fix: Translation Verification hard-coded repo properties (#2584) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/check_properties.yml | 68 ++++++++++++++------------ 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/.github/workflows/check_properties.yml b/.github/workflows/check_properties.yml index 62a3537ff..b45da71fb 100644 --- a/.github/workflows/check_properties.yml +++ b/.github/workflows/check_properties.yml @@ -15,6 +15,7 @@ jobs: runs-on: ubuntu-latest permissions: issues: write # Allow posting comments on issues/PRs + pull-requests: write steps: - name: Harden Runner uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 @@ -29,19 +30,6 @@ jobs: with: python-version: "3.x" - - name: Fetch PR changed files - id: fetch-pr-changes - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "Fetching PR changed files..." - - gh repo set-default ${{ github.event.pull_request.head.repo.full_name }} # Set the fork repository as default - - # Fetch the list of changed files in the PR - echo "Getting list of changed files from PR..." - gh pr view ${{ github.event.pull_request.number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]+\.properties$' > changed_files.txt # Filter only matching property files - - name: Get PR data id: get-pr-data uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 @@ -62,14 +50,30 @@ jobs: core.setOutput("repo_name", repoName); core.setOutput("branch", branch); continue-on-error: true + + - name: Fetch PR changed files + id: fetch-pr-changes + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "Fetching PR changed files..." + echo "Getting list of changed files from PR..." + gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]+\.properties$' > changed_files.txt # Filter only matching property files + - name: Determine reference file test - id: determine-file-1 + id: determine-file uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | + const fs = require("fs"); + const path = require("path"); + const prNumber = ${{ steps.get-pr-data.outputs.pr_number }}; const repoOwner = "${{ steps.get-pr-data.outputs.repo_owner }}"; const repoName = "${{ steps.get-pr-data.outputs.repo_name }}"; + + const prRepoOwner = "${{ github.event.pull_request.head.repo.owner.login }}"; + const prRepoName = "${{ github.event.pull_request.head.repo.name }}"; const branch = "${{ steps.get-pr-data.outputs.branch }}"; console.log(`Determining reference file for PR #${prNumber}`); @@ -101,28 +105,28 @@ jobs: // Create a temporary directory for PR files const tempDir = "pr-branch"; - if (!require("fs").existsSync(tempDir)) { - require("fs").mkdirSync(tempDir, { recursive: true }); + if (!fs.existsSync(tempDir)) { + fs.mkdirSync(tempDir, { recursive: true }); } // Download and save each changed file for (const file of changedFiles) { const { data: fileContent } = await github.rest.repos.getContent({ - owner: repoOwner, - repo: repoName, + owner: prRepoOwner, + repo: prRepoName, path: file, ref: branch, }); const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); - const filePath = `${tempDir}/${file}`; - const dirPath = require("path").dirname(filePath); + const filePath = path.join(tempDir, file); + const dirPath = path.dirname(filePath); - if (!require("fs").existsSync(dirPath)) { - require("fs").mkdirSync(dirPath, { recursive: true }); + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); } - require("fs").writeFileSync(filePath, content); + fs.writeFileSync(filePath, content); console.log(`Saved file: ${filePath}`); } @@ -136,27 +140,27 @@ jobs: if (changedFiles.includes("src/main/resources/messages_en_GB.properties")) { console.log("Using PR branch reference file."); const { data: fileContent } = await github.rest.repos.getContent({ - owner: repoOwner, - repo: repoName, + owner: prRepoOwner, + repo: prRepoName, path: "src/main/resources/messages_en_GB.properties", ref: branch, }); referenceFilePath = "pr-branch-messages_en_GB.properties"; const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); - require("fs").writeFileSync(referenceFilePath, content); + fs.writeFileSync(referenceFilePath, content); } else { console.log("Using main branch reference file."); const { data: fileContent } = await github.rest.repos.getContent({ - owner: "Stirling-Tools", - repo: "Stirling-PDF", + owner: repoOwner, + repo: repoName, path: "src/main/resources/messages_en_GB.properties", ref: "main", }); referenceFilePath = "main-branch-messages_en_GB.properties"; const content = Buffer.from(fileContent.content, "base64").toString("utf-8"); - require("fs").writeFileSync(referenceFilePath, content); + fs.writeFileSync(referenceFilePath, content); } console.log(`Reference file path: ${referenceFilePath}`); @@ -203,13 +207,13 @@ jobs: script: | const { GITHUB_REPOSITORY, SCRIPT_OUTPUT } = process.env; const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/'); - const prNumber = context.issue.number; + const issueNumber = context.issue.number; // Find existing comment const comments = await github.rest.issues.listComments({ owner: repoOwner, repo: repoName, - issue_number: prNumber + issue_number: issueNumber }); const comment = comments.data.find(c => c.body.includes("## 🚀 Translation Verification Summary")); @@ -231,7 +235,7 @@ jobs: await github.rest.issues.createComment({ owner: repoOwner, repo: repoName, - issue_number: prNumber, + issue_number: issueNumber, body: `## 🚀 Translation Verification Summary\n\n\n${SCRIPT_OUTPUT}\n` }); console.log("Created new comment."); From 56ab9c3eee9a3dea0332a25715958f04f0af130a Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 18:38:23 +0100 Subject: [PATCH 11/25] Update messages_de_DE.properties (#2583) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- src/main/resources/messages_de_DE.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index 0d9c3e1c2..910649566 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -561,7 +561,7 @@ login.oauth2invalidRequest=ungültige Anfrage login.oauth2AccessDenied=Zugriff abgelehnt login.oauth2InvalidTokenResponse=Ungültige Token-Antwort login.oauth2InvalidIdToken=Ungültiges ID-Token -login.relyingPartyRegistrationNotFound=No relying party registration found +login.relyingPartyRegistrationNotFound=Keine Relying-Party-Registrierung gefunden login.userIsDisabled=Benutzer ist deaktiviert, die Anmeldung ist mit diesem Benutzernamen derzeit gesperrt. Bitte wenden Sie sich an den Administrator. login.alreadyLoggedIn=Sie sind bereits an login.alreadyLoggedIn2=Geräten angemeldet. Bitte melden Sie sich dort ab und versuchen es dann erneut. From 958c214605da901de83b2508f58378ec91cb1222 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:48:27 +0000 Subject: [PATCH 12/25] Update build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a65af4129..32d2a6963 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ ext { } group = "stirling.software" -version = "0.36.5" +version = "0.36.6" java { From ef174a1e8a39f0f1c0dcfbff219f10e15dba0ddd Mon Sep 17 00:00:00 2001 From: swanemar <107953493+swanemar@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:21:39 +0000 Subject: [PATCH 13/25] additional Swedish translations (#2585) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [X] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [X] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [X] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- src/main/resources/messages_sv_SE.properties | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties index aa5e74818..78d6b6466 100644 --- a/src/main/resources/messages_sv_SE.properties +++ b/src/main/resources/messages_sv_SE.properties @@ -250,7 +250,7 @@ database.fileNullOrEmpty=Filen får inte vara null eller tom database.failedImportFile=Misslyckades med att importera fil session.expired=Din session har löpt ut. Uppdatera sidan och försök igen. -session.refreshPage=Refresh Page +session.refreshPage=Uppdatera sida ############# # HOME-PAGE # @@ -519,9 +519,9 @@ home.validateSignature.desc=Verify digital signatures and certificates in PDF do validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate #replace-invert-color -replace-color.title=Replace-Invert-Color +replace-color.title=Ersätt-Invertera-Färg replace-color.header=Ersätt-Invertera färg på PDF -home.replaceColorPdf.title=Replace and Invert Color +home.replaceColorPdf.title=Ersätt och Invertera färg home.replaceColorPdf.desc=Ersätt färg för text och bakgrund i PDF och invertera hela färgen på PDF för att minska filstorlek replaceColorPdf.tags=Ersätt Färg, Sidåtgärder, Bakomliggande, Serversid replace-color.selectText.1=Ersätt eller Invertera färgalternativ @@ -969,17 +969,17 @@ multiTool.undo=Undo multiTool.redo=Redo #decrypt -decrypt.passwordPrompt=This file is password-protected. Please enter the password: -decrypt.cancelled=Operation cancelled for PDF: {0} -decrypt.noPassword=No password provided for encrypted PDF: {0} -decrypt.invalidPassword=Please try again with the correct password. -decrypt.invalidPasswordHeader=Incorrect password or unsupported encryption for PDF: {0} -decrypt.unexpectedError=There was an error processing the file. Please try again. -decrypt.serverError=Server error while decrypting: {0} -decrypt.success=File decrypted successfully. +decrypt.passwordPrompt=Denna fil är lösenordsskyddad. Fyll i lösenord: +decrypt.cancelled=Operation misslyckades för PDF: {0} +decrypt.noPassword=Inget lösenord angivet för krypterad PDF: {0} +decrypt.invalidPassword=Försök igen med korrekt lösenord. +decrypt.invalidPasswordHeader=Felaktigt lösenord eller osupportad kryptering för PDF: {0} +decrypt.unexpectedError=Det uppstod ett fel vid processering av filen. Vänligen försök igen. +decrypt.serverError=Serverfel vid avkryptering: {0} +decrypt.success=Fil avkrypterad. #multiTool-advert -multiTool-advert.message=This feature is also available in our multi-tool page. Check it out for enhanced page-by-page UI and additional features! +multiTool-advert.message=Denna funktion finns också tillgänglig i vår multi-tool page. Spana in den för bättre sida-för-sida anpassning och ytterligare funktioner! #view pdf viewPdf.title=Visa PDF From 875f5a85ef0184f0603385693a3dd6fb022d9a67 Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 19:22:14 +0100 Subject: [PATCH 14/25] Token-Permissions & Pinned-Dependencies (#2586) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/PR-Demo-Comment.yml | 6 ++++++ .github/workflows/PR-Demo-cleanup.yml | 3 ++- .github/workflows/auto-labeler.yml | 3 ++- .github/workflows/build.yml | 6 ++++-- .github/workflows/licenses-update.yml | 3 ++- .github/workflows/manage-label.yml | 3 ++- .github/workflows/multiOSReleases.yml | 3 ++- .github/workflows/pre_commit.yml | 5 +++-- .github/workflows/push-docker.yml | 5 ++--- .github/workflows/releaseArtifacts.yml | 3 ++- .github/workflows/stale.yml | 3 ++- .github/workflows/swagger.yml | 3 ++- .github/workflows/sync_files.yml | 3 ++- .github/workflows/update-translations.yml | 3 ++- 14 files changed, 35 insertions(+), 17 deletions(-) diff --git a/.github/workflows/PR-Demo-Comment.yml b/.github/workflows/PR-Demo-Comment.yml index 0ad568899..c9e5898b3 100644 --- a/.github/workflows/PR-Demo-Comment.yml +++ b/.github/workflows/PR-Demo-Comment.yml @@ -4,9 +4,15 @@ on: issue_comment: types: [created] +permissions: + contents: read + jobs: check-comment: runs-on: ubuntu-latest + permissions: + pull-requests: read + issues: read if: | github.event.issue.pull_request && ( diff --git a/.github/workflows/PR-Demo-cleanup.yml b/.github/workflows/PR-Demo-cleanup.yml index 6ed7bea88..57b6750fb 100644 --- a/.github/workflows/PR-Demo-cleanup.yml +++ b/.github/workflows/PR-Demo-cleanup.yml @@ -4,7 +4,8 @@ on: pull_request: types: [opened, synchronize, reopened, closed] -permissions: read-all +permissions: + contents: read env: SERVER_IP: ${{ secrets.VPS_IP }} # Add this to your GitHub secrets diff --git a/.github/workflows/auto-labeler.yml b/.github/workflows/auto-labeler.yml index 3495f7ae0..501d9863e 100644 --- a/.github/workflows/auto-labeler.yml +++ b/.github/workflows/auto-labeler.yml @@ -3,7 +3,8 @@ on: pull_request_target: types: [opened, synchronize] -permissions: read-all +permissions: + contents: read jobs: labeler: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5a0784bb..c7e987251 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,13 +6,15 @@ on: pull_request: branches: ["main"] -permissions: read-all +permissions: + contents: read jobs: build: runs-on: ubuntu-latest permissions: + actions: read security-events: write strategy: @@ -44,7 +46,7 @@ jobs: run: ./gradlew clean build env: DOCKER_ENABLE_SECURITY: true - + docker-compose-tests: # if: github.event_name == 'push' && github.ref == 'refs/heads/main' || # (github.event_name == 'pull_request' && diff --git a/.github/workflows/licenses-update.yml b/.github/workflows/licenses-update.yml index a3fdb2853..8a7d07c34 100644 --- a/.github/workflows/licenses-update.yml +++ b/.github/workflows/licenses-update.yml @@ -7,7 +7,8 @@ on: paths: - "build.gradle" -permissions: read-all +permissions: + contents: read jobs: generate-license-report: diff --git a/.github/workflows/manage-label.yml b/.github/workflows/manage-label.yml index 05367ee8c..6f765438b 100644 --- a/.github/workflows/manage-label.yml +++ b/.github/workflows/manage-label.yml @@ -4,7 +4,8 @@ on: schedule: - cron: "30 20 * * *" -permissions: read-all +permissions: + contents: read jobs: labeler: diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index e445dc2b9..9121bf53a 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -5,7 +5,8 @@ on: release: types: [created] -permissions: read-all +permissions: + contents: read jobs: build-installers: diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml index 5c591d89b..df4e5a0f8 100644 --- a/.github/workflows/pre_commit.yml +++ b/.github/workflows/pre_commit.yml @@ -4,7 +4,8 @@ on: push: branches: [main] -permissions: read-all +permissions: + contents: read jobs: update: @@ -19,7 +20,7 @@ jobs: with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: 3.12 - name: Run Pre-Commit Hooks diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index dea71c096..c04cbcf13 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -9,14 +9,13 @@ on: permissions: contents: read - packages: write - id-token: write jobs: push: runs-on: ubuntu-latest permissions: packages: write + id-token: write steps: - name: Harden Runner uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 @@ -42,7 +41,7 @@ jobs: - name: Install cosign if: github.ref == 'refs/heads/master' - uses: sigstore/cosign-installer@v3.7.0 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 with: cosign-release: 'v2.4.1' diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 21f2fb147..2a71c85e1 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -5,7 +5,8 @@ on: release: types: [created] -permissions: read-all +permissions: + contents: read jobs: push: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3746016ce..f8631b55b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -5,7 +5,8 @@ on: - cron: "30 0 * * *" workflow_dispatch: -permissions: read-all +permissions: + contents: read jobs: stale: diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml index 502208684..6478aeb18 100644 --- a/.github/workflows/swagger.yml +++ b/.github/workflows/swagger.yml @@ -6,7 +6,8 @@ on: branches: - master -permissions: read-all +permissions: + contents: read jobs: push: diff --git a/.github/workflows/sync_files.yml b/.github/workflows/sync_files.yml index 139f86fa0..e27f1b395 100644 --- a/.github/workflows/sync_files.yml +++ b/.github/workflows/sync_files.yml @@ -9,7 +9,8 @@ on: - "src/main/resources/messages_*.properties" - "scripts/ignore_translation.toml" -permissions: read-all +permissions: + contents: read jobs: sync-readme: diff --git a/.github/workflows/update-translations.yml b/.github/workflows/update-translations.yml index 84d9c2226..8c1a82d63 100644 --- a/.github/workflows/update-translations.yml +++ b/.github/workflows/update-translations.yml @@ -6,7 +6,8 @@ on: paths: - "src/main/resources/messages_en_GB.properties" -permissions: read-all +permissions: + contents: read jobs: update-translations-main: From e3c7b6f9559ef5967f2aba124242dab2698af8a3 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:41:33 +0000 Subject: [PATCH 15/25] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2dc3b26a8..7bd0a1c9f 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ [![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf) [![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/HYmhKj45pU) [![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Stirling-Tools/Stirling-PDF/) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Stirling-Tools/Stirling-PDF/badge)](https://scorecard.dev/viewer/?uri=github.com/Stirling-Tools/Stirling-PDF) [![GitHub Repo stars](https://img.shields.io/github/stars/stirling-tools/stirling-pdf?style=social)](https://github.com/Stirling-Tools/stirling-pdf) - Stirling PDF - Open source locally hosted web PDF editor | Product Hunt [![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af) @@ -169,4 +169,4 @@ Join our community: - [Translation Guide (How to add custom languages)](HowToAddNewLanguage.md) - [Issue Tracker](https://github.com/Stirling-Tools/Stirling-PDF/issues) - [Discord Community](https://discord.gg/HYmhKj45pU) -- [Developer Guide](DeveloperGuide.md) \ No newline at end of file +- [Developer Guide](DeveloperGuide.md) From 01288dafe81357d486a6644f071f79d3748e37e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:43:44 +0000 Subject: [PATCH 16/25] :memo: Update README: Translation Progress Table (#2587) Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Ludy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bd0a1c9f..3a2bfd1fd 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ Stirling-PDF currently supports 38 languages! | Simplified Chinese (简体中文) (zh_CN) | ![93%](https://geps.dev/progress/93) | | Slovakian (Slovensky) (sk_SK) | ![77%](https://geps.dev/progress/77) | | Spanish (Español) (es_ES) | ![90%](https://geps.dev/progress/90) | -| Swedish (Svenska) (sv_SE) | ![89%](https://geps.dev/progress/89) | +| Swedish (Svenska) (sv_SE) | ![90%](https://geps.dev/progress/90) | | Thai (ไทย) (th_TH) | ![89%](https://geps.dev/progress/89) | | Traditional Chinese (繁體中文) (zh_TW) | ![99%](https://geps.dev/progress/99) | | Turkish (Türkçe) (tr_TR) | ![86%](https://geps.dev/progress/86) | From e80eaaa6d1d201d7c7e116d34959222278b0e29a Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 20:42:24 +0100 Subject: [PATCH 17/25] changes the permission to write issues (#2590) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/PR-Demo-Comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PR-Demo-Comment.yml b/.github/workflows/PR-Demo-Comment.yml index c9e5898b3..7bc6ba641 100644 --- a/.github/workflows/PR-Demo-Comment.yml +++ b/.github/workflows/PR-Demo-Comment.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: read - issues: read + issues: write if: | github.event.issue.pull_request && ( From 6f04f01c2bb17253f84bdbdecc101496b57c05c2 Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 21:21:27 +0100 Subject: [PATCH 18/25] changes the permission deploy-pr (#2592) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/PR-Demo-Comment.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/PR-Demo-Comment.yml b/.github/workflows/PR-Demo-Comment.yml index 7bc6ba641..6d5a68ffb 100644 --- a/.github/workflows/PR-Demo-Comment.yml +++ b/.github/workflows/PR-Demo-Comment.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: read - issues: write + issues: read if: | github.event.issue.pull_request && ( @@ -74,6 +74,9 @@ jobs: deploy-pr: needs: check-comment runs-on: ubuntu-latest + permissions: + pull-requests: read + issues: write steps: - name: Harden Runner From 50575bc80b7bf406fd6c520e3b8a889c68417b0d Mon Sep 17 00:00:00 2001 From: albanobattistella <34811668+albanobattistella@users.noreply.github.com> Date: Thu, 2 Jan 2025 21:22:35 +0100 Subject: [PATCH 19/25] Update messages_it_IT.properties (#2591) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- src/main/resources/messages_it_IT.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties index 99ab34797..6f2602e25 100644 --- a/src/main/resources/messages_it_IT.properties +++ b/src/main/resources/messages_it_IT.properties @@ -561,7 +561,7 @@ login.oauth2invalidRequest=Richiesta non valida login.oauth2AccessDenied=Accesso negato login.oauth2InvalidTokenResponse=Risposta token non valida login.oauth2InvalidIdToken=Id Token non valido -login.relyingPartyRegistrationNotFound=No relying party registration found +login.relyingPartyRegistrationNotFound=Nessuna registrazione di parte affidabile trovata login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato con questo nome utente. Si prega di contattare l'amministratore. login.alreadyLoggedIn=Hai già effettuato l'accesso a login.alreadyLoggedIn2=dispositivi. Esci dai dispositivi e riprova. @@ -831,7 +831,7 @@ sign.first=Prima pagina sign.last=Ultima pagina sign.next=Prossima pagina sign.previous=Pagina precedente -sign.maintainRatio=Toggle maintain aspect ratio +sign.maintainRatio=Attiva il mantenimento delle proporzioni #repair repair.title=Ripara repair.header=Ripara PDF @@ -1285,8 +1285,8 @@ splitByChapters.submit=Dividi PDF fileChooser.click=Clicca fileChooser.or=o fileChooser.dragAndDrop=Trascina & Rilascia -fileChooser.dragAndDropPDF=Drag & Drop PDF file -fileChooser.dragAndDropImage=Drag & Drop Image file +fileChooser.dragAndDropPDF=Trascina & rilascia il file PDF +fileChooser.dragAndDropImage=Trascina & rilascia il file immagine fileChooser.hoveredDragAndDrop=Trascina & rilascia i file qui #release notes From bc282c6aa5492a5578916882aa832b3d79a286c3 Mon Sep 17 00:00:00 2001 From: Ludy Date: Thu, 2 Jan 2025 21:38:45 +0100 Subject: [PATCH 20/25] Update PR-Demo-Comment.yml (#2594) # Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --- .github/workflows/PR-Demo-Comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PR-Demo-Comment.yml b/.github/workflows/PR-Demo-Comment.yml index 6d5a68ffb..6fa18f5bd 100644 --- a/.github/workflows/PR-Demo-Comment.yml +++ b/.github/workflows/PR-Demo-Comment.yml @@ -75,7 +75,7 @@ jobs: needs: check-comment runs-on: ubuntu-latest permissions: - pull-requests: read + pull-requests: write issues: write steps: From 0ff45c656acb97a3da80104af7ddd397bc39c76e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:39:00 +0000 Subject: [PATCH 21/25] :memo: Update README: Translation Progress Table (#2593) Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a2bfd1fd..96bf8f60a 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Stirling-PDF currently supports 38 languages! | Hungarian (Magyar) (hu_HU) | ![90%](https://geps.dev/progress/90) | | Indonesian (Bahasa Indonesia) (id_ID) | ![90%](https://geps.dev/progress/90) | | Irish (Gaeilge) (ga_IE) | ![82%](https://geps.dev/progress/82) | -| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | +| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) | | Japanese (日本語) (ja_JP) | ![93%](https://geps.dev/progress/93) | | Korean (한국어) (ko_KR) | ![88%](https://geps.dev/progress/88) | | Norwegian (Norsk) (no_NB) | ![82%](https://geps.dev/progress/82) | From 38633d4db12d7d1a56bb96b4b1f9224f55b4cc40 Mon Sep 17 00:00:00 2001 From: reecebrowne <74901996+reecebrowne@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:23:26 +0000 Subject: [PATCH 22/25] Green buttons (#2597) # Description Making buttons green Closes #() ![image](https://github.com/user-attachments/assets/29417e03-664d-4a77-a3ca-80d0a8b76f07) ## Checklist - [X ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ X] I have performed a self-review of my own code - [X ] I have attached images of the change if it is UI based - [ X] I have commented my code, particularly in hard-to-understand areas - [ X] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ X] My changes generate no new warnings - [ X] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) Co-authored-by: Reece Browne --- .../resources/templates/misc/add-image.html | 2 +- src/main/resources/templates/multi-tool.html | 87 ++++++++++--------- src/main/resources/templates/sign.html | 2 +- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/main/resources/templates/misc/add-image.html b/src/main/resources/templates/misc/add-image.html index 9addaebd4..51fbc94ef 100644 --- a/src/main/resources/templates/misc/add-image.html +++ b/src/main/resources/templates/misc/add-image.html @@ -100,7 +100,7 @@ +
-
- -
@@ -151,29 +152,29 @@ window.selectAll = false; window.translations = { - rotateLeft: '[[#{multiTool.rotateLeft}]]', - rotateRight: '[[#{multiTool.rotateRight}]]', - moveLeft: '[[#{multiTool.moveLeft}]]', - moveRight: '[[#{multiTool.moveRight}]]', - delete: '[[#{multiTool.delete}]]', - split: '[[#{multiTool.split}]]', - addFile: '[[#{multiTool.addFile}]]', - insertPageBreak:'[[#{multiTool.insertPageBreak}]]', - dragDropMessage:'[[#{multiTool.dragDropMessage}]]', - undo: '[[#{multiTool.undo}]]', - redo: '[[#{multiTool.redo}]]', + rotateLeft: '[[#{multiTool.rotateLeft}]]', + rotateRight: '[[#{multiTool.rotateRight}]]', + moveLeft: '[[#{multiTool.moveLeft}]]', + moveRight: '[[#{multiTool.moveRight}]]', + delete: '[[#{multiTool.delete}]]', + split: '[[#{multiTool.split}]]', + addFile: '[[#{multiTool.addFile}]]', + insertPageBreak: '[[#{multiTool.insertPageBreak}]]', + dragDropMessage: '[[#{multiTool.dragDropMessage}]]', + undo: '[[#{multiTool.undo}]]', + redo: '[[#{multiTool.redo}]]', }; window.decrypt = { - passwordPrompt: '[[#{decrypt.passwordPrompt}]]', - cancelled: '[[#{decrypt.cancelled}]]', - noPassword: '[[#{decrypt.noPassword}]]', - invalidPassword: '[[#{decrypt.invalidPassword}]]', - invalidPasswordHeader: '[[#{decrypt.invalidPasswordHeader}]]', - unexpectedError: '[[#{decrypt.unexpectedError}]]', - serverError: '[[#{decrypt.serverError}]]', - success: '[[#{decrypt.success}]]', - } + passwordPrompt: '[[#{decrypt.passwordPrompt}]]', + cancelled: '[[#{decrypt.cancelled}]]', + noPassword: '[[#{decrypt.noPassword}]]', + invalidPassword: '[[#{decrypt.invalidPassword}]]', + invalidPasswordHeader: '[[#{decrypt.invalidPasswordHeader}]]', + unexpectedError: '[[#{decrypt.unexpectedError}]]', + serverError: '[[#{decrypt.serverError}]]', + success: '[[#{decrypt.success}]]', + } const csvInput = document.getElementById("csv-input"); csvInput.addEventListener("keydown", function (event) { @@ -217,18 +218,18 @@ ) fileDragManager.setCallback(async (files) => pdfContainer.handleDroppedFiles(files)); - document.addEventListener('keydown', function(event) { - let targetElementId = event.target.id; + document.addEventListener('keydown', function (event) { + let targetElementId = event.target.id; - // To avoid undoing/redoing the page when the user is simply undoing/redoing text - const isFilenameInputField = (targetElementId === 'filename-input') && (event.target === document.activeElement); + // To avoid undoing/redoing the page when the user is simply undoing/redoing text + const isFilenameInputField = (targetElementId === 'filename-input') && (event.target === document.activeElement); - const isUndo = (event.ctrlKey && event.key === 'z'); - const isRedo = (event.ctrlKey && event.key == 'y'); - if (isUndo && !isFilenameInputField) - undoManager.undo(); - else if (isRedo && !isFilenameInputField) undoManager.redo(); -}); + const isUndo = (event.ctrlKey && event.key === 'z'); + const isRedo = (event.ctrlKey && event.key == 'y'); + if (isUndo && !isFilenameInputField) + undoManager.undo(); + else if (isRedo && !isFilenameInputField) undoManager.redo(); + }); diff --git a/src/main/resources/templates/sign.html b/src/main/resources/templates/sign.html index 85bce6c2f..5c7ecf7ea 100644 --- a/src/main/resources/templates/sign.html +++ b/src/main/resources/templates/sign.html @@ -212,7 +212,7 @@