Merge branch 'main' into dependabot/gradle/io.micrometer-micrometer-core-1.13.0
116
.github/ISSUE_TEMPLATE/1-bug.yml
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
name: Bug Report
|
||||
description: File a bug report.
|
||||
title: "[Bug]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Bug Report
|
||||
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
This issue form is for reporting bugs only. Please fill out the following sections to help us understand the issue you are facing.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: The Problem
|
||||
description: |
|
||||
Describe the issue you are experiencing here. Tell us what you were trying to do and what happened.
|
||||
|
||||
Provide a clear and concise description of what the problem is.
|
||||
placeholder: Provide a detailed description of the issue.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Environment
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Version of Stirling-PDF
|
||||
placeholder: e.g., 0.0.2
|
||||
description: What version of Stirling-PDF has the issue?
|
||||
|
||||
- type: input
|
||||
id: last-working-version
|
||||
attributes:
|
||||
label: Last Working Version of Stirling-PDF
|
||||
placeholder: e.g., 0.0.1
|
||||
description: |
|
||||
If known, please provide the last version where the issue did not occur. Otherwise, leave blank.
|
||||
|
||||
- type: input
|
||||
id: url
|
||||
attributes:
|
||||
label: Page Where the Problem Occurred
|
||||
placeholder: e.g., http://localhost:8080/pdf/pipeline
|
||||
description: |
|
||||
If applicable, provide the URL where the issue occurred. Otherwise, leave blank.
|
||||
|
||||
- type: textarea
|
||||
id: docker
|
||||
attributes:
|
||||
label: Docker Configuration
|
||||
description: |
|
||||
Enter your Docker configuration here if it is relevant to the error. Remove any personal data. Otherwise, leave the field blank.
|
||||
render: txt
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Logs
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant Log Output
|
||||
description: |
|
||||
Provide any log output that might help us diagnose the issue, such as error messages or stack traces.
|
||||
render: txt
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Additional Information
|
||||
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
If you have any additional information that might help us understand and resolve the issue, provide it here.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Browser Information
|
||||
|
||||
- type: dropdown
|
||||
id: browsers
|
||||
attributes:
|
||||
label: Browsers Affected
|
||||
description: |
|
||||
If applicable, select the browsers where you are experiencing the issue. Otherwise, leave blank.
|
||||
multiple: true
|
||||
options:
|
||||
- Firefox
|
||||
- Chrome
|
||||
- Safari
|
||||
- Microsoft Edge
|
||||
- Other
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: No Duplicate of the Issue
|
||||
description: |
|
||||
Please confirm that you have searched for similar issues and none of them match your problem.
|
||||
options:
|
||||
- label: I have verified that there are no existing issues raised related to my problem.
|
||||
required: true
|
76
.github/ISSUE_TEMPLATE/2-feature.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
name: Feature Request
|
||||
description: Submit a new feature request.
|
||||
title: "[Feature Request]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Feature Request
|
||||
|
||||
Thank you for taking the time to suggest a new feature!
|
||||
|
||||
This form is for proposing features or enhancements. Please fill out the following sections to help us understand your idea or suggestion.
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: |
|
||||
Describe the feature you would like to see. Tell us what the feature should do and the problem it would solve.
|
||||
|
||||
Provide a clear and concise description of what you want to happen.
|
||||
placeholder: Provide a detailed description of the desired feature.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Motivation
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Why is this feature valuable?
|
||||
description: |
|
||||
Explain why this feature is valuable to you or others. How would it improve the tool or process?
|
||||
|
||||
Describe any relevant scenarios that would benefit from this feature.
|
||||
placeholder: Describe why this feature is important.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Possible Implementation
|
||||
|
||||
- type: textarea
|
||||
id: implementation
|
||||
attributes:
|
||||
label: Suggested Implementation
|
||||
description: |
|
||||
If you have ideas about how this feature could be implemented, describe them here.
|
||||
|
||||
This section is optional but can be helpful to guide initial discussions.
|
||||
placeholder: Describe how this feature might be implemented.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Additional Information
|
||||
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
If you have any additional information, comments, or resources you think would support or be relevant to your feature request, include them here.
|
||||
|
||||
- type: checkboxes
|
||||
id: search-confirmation
|
||||
attributes:
|
||||
label: No Duplicate of the Feature
|
||||
description: |
|
||||
Please confirm that you have searched for similar features in our repository and found none that match your request.
|
||||
options:
|
||||
- label: I have verified that there are no existing features requests similar to my request.
|
||||
required: true
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 💬 Discord Server
|
||||
url: https://discord.gg/Cn8pWhQRxZ
|
||||
about: You can join our Discord server for real time discussion and support
|
18
README.md
@ -167,31 +167,31 @@ Stirling PDF currently supports 32!
|
||||
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
|
||||
| Arabic (العربية) (ar_AR) | ![40%](https://geps.dev/progress/40) |
|
||||
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
|
||||
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) |
|
||||
| Spanish (Español) (es_ES) | ![95%](https://geps.dev/progress/95) |
|
||||
| French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) |
|
||||
| Spanish (Español) (es_ES) | ![94%](https://geps.dev/progress/94) |
|
||||
| Simplified Chinese (简体中文) (zh_CN) | ![95%](https://geps.dev/progress/95) |
|
||||
| Traditional Chinese (繁體中文) (zh_TW) | ![94%](https://geps.dev/progress/94) |
|
||||
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) |
|
||||
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
|
||||
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
|
||||
| Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) |
|
||||
| Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) |
|
||||
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
|
||||
| Korean (한국어) (ko_KR) | ![87%](https://geps.dev/progress/87) |
|
||||
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
|
||||
| Russian (Русский) (ru_RU) | ![87%](https://geps.dev/progress/87) |
|
||||
| Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) |
|
||||
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
|
||||
| Japanese (日本語) (ja_JP) | ![87%](https://geps.dev/progress/87) |
|
||||
| Dutch (Nederlands) (nl_NL) | ![85%](https://geps.dev/progress/85) |
|
||||
| Dutch (Nederlands) (nl_NL) | ![84%](https://geps.dev/progress/84) |
|
||||
| Greek (Ελληνικά) (el_GR) | ![85%](https://geps.dev/progress/85) |
|
||||
| Turkish (Türkçe) (tr_TR) | ![97%](https://geps.dev/progress/97) |
|
||||
| Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) |
|
||||
| Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) |
|
||||
| Hungarian (Magyar) (hu_HU) | ![78%](https://geps.dev/progress/78) |
|
||||
| Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) |
|
||||
| Hungarian (Magyar) (hu_HU) | ![77%](https://geps.dev/progress/77) |
|
||||
| Bulgarian (Български) (bg_BG) | ![97%](https://geps.dev/progress/97) |
|
||||
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) |
|
||||
| Ukrainian (Українська) (uk_UA) | ![86%](https://geps.dev/progress/86) |
|
||||
| Slovakian (Slovensky) (sk_SK) | ![95%](https://geps.dev/progress/95) |
|
||||
| Czech (Česky) (cs_CZ) | ![94%](https://geps.dev/progress/94) |
|
||||
| Slovakian (Slovensky) (sk_SK) | ![94%](https://geps.dev/progress/94) |
|
||||
| Czech (Česky) (cs_CZ) | ![93%](https://geps.dev/progress/93) |
|
||||
| Croatian (Hrvatski) (hr_HR) | ![98%](https://geps.dev/progress/98) |
|
||||
| Norwegian (Norsk) (no_NB) | ![98%](https://geps.dev/progress/98) |
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: 0.25.2
|
||||
appVersion: 0.25.3
|
||||
description: locally hosted web application that allows you to perform various operations
|
||||
on PDF files
|
||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 44 KiB |
BIN
images/settings-light.png
Normal file
After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 12 KiB |
BIN
images/stirling-home-dark.png
Normal file
After Width: | Height: | Size: 366 KiB |
Before Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 145 KiB |
43
pipeline/defaultWebUIConfigs/OCR images.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "OCR images",
|
||||
"pipeline": [
|
||||
{
|
||||
"operation": "/api/v1/convert/img/pdf",
|
||||
"parameters": {
|
||||
"fitOption": "fillPage",
|
||||
"colorType": "color",
|
||||
"autoRotate": true,
|
||||
"fileInput": "automated"
|
||||
}
|
||||
},
|
||||
{
|
||||
"operation": "/api/v1/general/merge-pdfs",
|
||||
"parameters": {
|
||||
"sortType": "orderProvided",
|
||||
"fileInput": "automated"
|
||||
}
|
||||
},
|
||||
{
|
||||
"operation": "/api/v1/misc/ocr-pdf",
|
||||
"parameters": {
|
||||
"languages": [
|
||||
"eng"
|
||||
],
|
||||
"sidecar": false,
|
||||
"deskew": false,
|
||||
"clean": false,
|
||||
"cleanFinal": false,
|
||||
"ocrType": "skip-text",
|
||||
"ocrRenderType": "hocr",
|
||||
"removeImagesAfter": false,
|
||||
"fileInput": "automated"
|
||||
}
|
||||
}
|
||||
],
|
||||
"_examples": {
|
||||
"outputDir": "{outputFolder}/{folderName}",
|
||||
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir": "{outputFolder}",
|
||||
"outputFileName": "{filename}"
|
||||
}
|
@ -61,6 +61,7 @@ ignore = [
|
||||
[fr_FR]
|
||||
ignore = [
|
||||
'language.direction',
|
||||
'sponsor',
|
||||
]
|
||||
|
||||
[hi_IN]
|
||||
|
@ -58,7 +58,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||
|
||||
// Redirect to the URL with only allowed query parameters
|
||||
String redirectUrl = requestURI + "?" + newQueryString;
|
||||
response.sendRedirect(redirectUrl);
|
||||
|
||||
response.sendRedirect(request.getContextPath() + redirectUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,11 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
||||
String ip = request.getRemoteAddr();
|
||||
logger.error("Failed login attempt from IP: {}", ip);
|
||||
|
||||
String contextPath = request.getContextPath();
|
||||
|
||||
if (exception.getClass().isAssignableFrom(InternalAuthenticationServiceException.class)
|
||||
|| "Password must not be null".equalsIgnoreCase(exception.getMessage())) {
|
||||
response.sendRedirect("/login?error=oauth2AuthenticationError");
|
||||
response.sendRedirect(contextPath + "/login?error=oauth2AuthenticationError");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -59,13 +61,13 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
||||
loginAttemptService.loginFailed(username);
|
||||
if (loginAttemptService.isBlocked(username)
|
||||
|| exception.getClass().isAssignableFrom(LockedException.class)) {
|
||||
response.sendRedirect("/login?error=locked");
|
||||
response.sendRedirect(contextPath + "/login?error=locked");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (exception.getClass().isAssignableFrom(BadCredentialsException.class)
|
||||
|| exception.getClass().isAssignableFrom(UsernameNotFoundException.class)) {
|
||||
response.sendRedirect("/login?error=badcredentials");
|
||||
response.sendRedirect(contextPath + "/login?error=badcredentials");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class FirstLoginFilter extends OncePerRequestFilter {
|
||||
&& user.isPresent()
|
||||
&& user.get().isFirstLogin()
|
||||
&& !"/change-creds".equals(requestURI)) {
|
||||
response.sendRedirect("/change-creds");
|
||||
response.sendRedirect(request.getContextPath() + "/change-creds");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,16 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.multipdf.PDFMergerUtility;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -38,6 +43,7 @@ public class MergeController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
|
||||
|
||||
// Merges a list of PDDocument objects into a single PDDocument
|
||||
public PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
|
||||
PDDocument mergedDoc = new PDDocument();
|
||||
for (PDDocument doc : documents) {
|
||||
@ -48,6 +54,7 @@ public class MergeController {
|
||||
return mergedDoc;
|
||||
}
|
||||
|
||||
// Returns a comparator for sorting MultipartFile arrays based on the given sort type
|
||||
private Comparator<MultipartFile> getSortComparator(String sortType) {
|
||||
switch (sortType) {
|
||||
case "byFileName":
|
||||
@ -108,36 +115,77 @@ public class MergeController {
|
||||
"This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO")
|
||||
public ResponseEntity<byte[]> mergePdfs(@ModelAttribute MergePdfsRequest form)
|
||||
throws IOException {
|
||||
List<File> filesToDelete = new ArrayList<File>();
|
||||
List<File> filesToDelete = new ArrayList<>(); // List of temporary files to delete
|
||||
ByteArrayOutputStream docOutputstream =
|
||||
new ByteArrayOutputStream(); // Stream for the merged document
|
||||
PDDocument mergedDocument = null;
|
||||
|
||||
boolean removeCertSign = form.isRemoveCertSign();
|
||||
|
||||
try {
|
||||
MultipartFile[] files = form.getFileInput();
|
||||
Arrays.sort(files, getSortComparator(form.getSortType()));
|
||||
|
||||
PDFMergerUtility mergedDoc = new PDFMergerUtility();
|
||||
ByteArrayOutputStream docOutputstream = new ByteArrayOutputStream();
|
||||
Arrays.sort(
|
||||
files,
|
||||
getSortComparator(
|
||||
form.getSortType())); // Sort files based on the given sort type
|
||||
|
||||
PDFMergerUtility mergerUtility = new PDFMergerUtility();
|
||||
for (MultipartFile multipartFile : files) {
|
||||
File tempFile = GeneralUtils.convertMultipartFileToFile(multipartFile);
|
||||
filesToDelete.add(tempFile);
|
||||
mergedDoc.addSource(tempFile);
|
||||
File tempFile =
|
||||
GeneralUtils.convertMultipartFileToFile(
|
||||
multipartFile); // Convert MultipartFile to File
|
||||
filesToDelete.add(tempFile); // Add temp file to the list for later deletion
|
||||
mergerUtility.addSource(tempFile); // Add source file to the merger utility
|
||||
}
|
||||
mergerUtility.setDestinationStream(
|
||||
docOutputstream); // Set the output stream for the merged document
|
||||
mergerUtility.mergeDocuments(null); // Merge the documents
|
||||
|
||||
byte[] mergedPdfBytes = docOutputstream.toByteArray(); // Get merged document bytes
|
||||
|
||||
// Load the merged PDF document
|
||||
mergedDocument = Loader.loadPDF(mergedPdfBytes);
|
||||
|
||||
// Remove signatures if removeCertSign is true
|
||||
if (removeCertSign) {
|
||||
PDDocumentCatalog catalog = mergedDocument.getDocumentCatalog();
|
||||
PDAcroForm acroForm = catalog.getAcroForm();
|
||||
if (acroForm != null) {
|
||||
List<PDField> fieldsToRemove =
|
||||
acroForm.getFields().stream()
|
||||
.filter(field -> field instanceof PDSignatureField)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!fieldsToRemove.isEmpty()) {
|
||||
acroForm.flatten(
|
||||
fieldsToRemove,
|
||||
false); // Flatten the fields, effectively removing them
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mergedDoc.setDestinationFileName(
|
||||
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
|
||||
mergedDoc.setDestinationStream(docOutputstream);
|
||||
|
||||
mergedDoc.mergeDocuments(null);
|
||||
// Save the modified document to a new ByteArrayOutputStream
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mergedDocument.save(baos);
|
||||
|
||||
String mergedFileName =
|
||||
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "")
|
||||
+ "_merged_unsigned.pdf";
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
docOutputstream.toByteArray(), mergedDoc.getDestinationFileName());
|
||||
baos.toByteArray(), mergedFileName); // Return the modified PDF
|
||||
|
||||
} catch (Exception ex) {
|
||||
logger.error("Error in merge pdf process", ex);
|
||||
throw ex;
|
||||
} finally {
|
||||
for (File file : filesToDelete) {
|
||||
if (file != null) {
|
||||
Files.deleteIfExists(file.toPath());
|
||||
}
|
||||
Files.deleteIfExists(file.toPath()); // Delete temporary files
|
||||
}
|
||||
}
|
||||
docOutputstream.close();
|
||||
if (mergedDocument != null) {
|
||||
mergedDocument.close(); // Close the merged document
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,8 +105,15 @@ public class PipelineProcessor {
|
||||
body.add("fileInput", file);
|
||||
|
||||
for (Entry<String, Object> entry : parameters.entrySet()) {
|
||||
if (entry.getValue() instanceof List) {
|
||||
List<?> list = (List<?>) entry.getValue();
|
||||
for (Object item : list) {
|
||||
body.add(entry.getKey(), item);
|
||||
}
|
||||
} else {
|
||||
body.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
ResponseEntity<byte[]> response = sendWebRequest(url, body);
|
||||
|
||||
@ -167,8 +174,15 @@ public class PipelineProcessor {
|
||||
}
|
||||
|
||||
for (Entry<String, Object> entry : parameters.entrySet()) {
|
||||
if (entry.getValue() instanceof List) {
|
||||
List<?> list = (List<?>) entry.getValue();
|
||||
for (Object item : list) {
|
||||
body.add(entry.getKey(), item);
|
||||
}
|
||||
} else {
|
||||
body.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
ResponseEntity<byte[]> response = sendWebRequest(url, body);
|
||||
|
||||
|
@ -21,4 +21,10 @@ public class MergePdfsRequest extends MultiplePDFFiles {
|
||||
},
|
||||
defaultValue = "orderProvided")
|
||||
private String sortType = "orderProvided";
|
||||
|
||||
@Schema(
|
||||
description =
|
||||
"Flag indicating whether to remove certification signatures from the merged PDF. If true, all certification signatures will be removed from the final merged document.",
|
||||
example = "true")
|
||||
private boolean isRemoveCertSign;
|
||||
}
|
||||
|
@ -4,8 +4,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
public class UrlUtils {
|
||||
|
||||
private UrlUtils() {
|
||||
}
|
||||
private UrlUtils() {}
|
||||
|
||||
public static String getOrigin(HttpServletRequest request) {
|
||||
String scheme = request.getScheme(); // http or https
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=دمج
|
||||
merge.header=دمج ملفات PDF متعددة (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=دمج
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Потребителят не е намерен
|
||||
incorrectPasswordMessage=Текущата парола е неправилна.
|
||||
usernameExistsMessage=Новият потребител вече съществува.
|
||||
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
|
||||
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
||||
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Персонализиран
|
||||
pipeline.submitButton=Подайте
|
||||
pipeline.help=Pipeline Помощ
|
||||
pipeline.scanHelp=Помощ за сканиране на папки
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Настройки за администраторск
|
||||
adminUserSettings.admin=Администратор
|
||||
adminUserSettings.user=Потребител
|
||||
adminUserSettings.addUser=Добавяне на нов потребител
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
|
||||
adminUserSettings.roles=Роли
|
||||
adminUserSettings.role=Роля
|
||||
@ -799,6 +803,7 @@ merge.title=Обединяване
|
||||
merge.header=Обединяване на множество PDF файлове (2+)
|
||||
merge.sortByName=Сортиране по име
|
||||
merge.sortByDate=Сортиране по дата
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Обединяване
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Usuari Admin Opcions Control
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Usuari
|
||||
adminUserSettings.addUser=Afegir Usuari
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Rols
|
||||
adminUserSettings.role=Rol
|
||||
@ -799,6 +803,7 @@ merge.title=Fusiona
|
||||
merge.header=Fusiona múltiples PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Fusiona
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Uživatel nenalezen.
|
||||
incorrectPasswordMessage=Současné heslo není správné.
|
||||
usernameExistsMessage=Nové uživatelské jméno již existuje.
|
||||
invalidUsernameMessage=Nesprávné uživatelské jméno, smí obsahovat pouze písmena, číslice a následující speciální znaky @._+- nebo musí být validní emailová adresa.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Nelze smazat aktuální přihlášeného uživatele.
|
||||
deleteUsernameExistsMessage=Uživatelské jméno neexistuje a nelze ho smazat.
|
||||
downgradeCurrentUserMessage=Nelze snížit roli aktuálního uživatele.
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Vlastní
|
||||
pipeline.submitButton=Odeslat
|
||||
pipeline.help=Pomoc s pipeline
|
||||
pipeline.scanHelp=Pomoc se skenováním adresáře
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Uživatel
|
||||
adminUserSettings.addUser=Přidat Nového Uživatele
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Uživatelské Jméno může obsahovat pouze písmena, čísla a následující speciální znaky @._+- nebo musí být správná emailová adresa.
|
||||
adminUserSettings.roles=Role
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Sloučit
|
||||
merge.header=Sloučit více PDF (2+)
|
||||
merge.sortByName=Seřadit podle názvu
|
||||
merge.sortByDate=Seřadit podle data
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Sloučit
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Benutzer nicht gefunden.
|
||||
incorrectPasswordMessage=Das Passwort ist falsch.
|
||||
usernameExistsMessage=Neuer Benutzername existiert bereits.
|
||||
invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
|
||||
confirmPasswordErrorMessage=„Neues Passwort“ und „Neues Passwort bestätigen“ müssen übereinstimmen.
|
||||
deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
|
||||
deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden.
|
||||
downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Benutzerdefiniert
|
||||
pipeline.submitButton=Speichern
|
||||
pipeline.help=Hilfe für Pipeline
|
||||
pipeline.scanHelp=Hilfe zum Ordnerscan
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Administrator-Benutzerkontrolle
|
||||
adminUserSettings.admin=Administrator
|
||||
adminUserSettings.user=Benutzer
|
||||
adminUserSettings.addUser=Neuen Benutzer hinzufügen
|
||||
adminUserSettings.deleteUser=Benutzer löschen
|
||||
adminUserSettings.confirmDeleteUser=Soll der Benutzer gelöscht werden?
|
||||
adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
|
||||
adminUserSettings.roles=Rollen
|
||||
adminUserSettings.role=Rolle
|
||||
@ -332,9 +336,9 @@ home.certSign.title=Mit Zertifikat signieren
|
||||
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
|
||||
certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
|
||||
|
||||
home.removeCertSign.title=Remove Certificate Sign
|
||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||
home.removeCertSign.title=Zertifikatsignatur entfernen
|
||||
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
|
||||
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln,decrypt
|
||||
|
||||
home.pageLayout.title=Mehrseitiges Layout
|
||||
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
||||
@ -799,6 +803,7 @@ merge.title=Zusammenführen
|
||||
merge.header=Mehrere PDFs zusammenführen (2+)
|
||||
merge.sortByName=Nach Namen sortieren
|
||||
merge.sortByDate=Nach Datum sortieren
|
||||
merge.removeCertSign=Digitale Signatur in der zusammengeführten Datei entfernen?
|
||||
merge.submit=Zusammenführen
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
|
||||
incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
|
||||
usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
|
||||
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
|
||||
deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
|
||||
downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Υποβολή
|
||||
pipeline.help=Βοήθεια για το Pipeline
|
||||
pipeline.scanHelp=Βοήθεια για Σάρωση Φακέλων
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστ
|
||||
adminUserSettings.admin=Διαχειριστής
|
||||
adminUserSettings.user=Χρήστης
|
||||
adminUserSettings.addUser=Προσθήκη νέου Χρήστη
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Ρόλοι
|
||||
adminUserSettings.role=Ρόλος
|
||||
@ -799,6 +803,7 @@ merge.title=Συγχώνευση
|
||||
merge.header=Συγχώνευση πολλαπλών PDFs (2+)
|
||||
merge.sortByName=Ταξινόμηση με βάση το Όνομα
|
||||
merge.sortByDate=Ταξινόμηση με βάση την Ημερομηνία
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Συγχώνευση
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Cannot downgrade current user's role
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Merge
|
||||
merge.header=Merge multiple PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Merge
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Cannot downgrade current user's role
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Merge
|
||||
merge.header=Merge multiple PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Merge
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Usuario no encontrado.
|
||||
incorrectPasswordMessage=La contraseña actual no es correcta.
|
||||
usernameExistsMessage=El nuevo nombre de usuario está en uso.
|
||||
invalidUsernameMessage=Nombre de usuario no válido, el nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
|
||||
deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
|
||||
downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizar
|
||||
pipeline.submitButton=Enviar
|
||||
pipeline.help=Ayuda de Canalización
|
||||
pipeline.scanHelp=Ayuda de escaneado de carpetas
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Configuración de control de usuario administrador
|
||||
adminUserSettings.admin=Administrador
|
||||
adminUserSettings.user=Usuario
|
||||
adminUserSettings.addUser=Añadir Nuevo Usuario
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=El nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Rol
|
||||
@ -799,6 +803,7 @@ merge.title=Unir
|
||||
merge.header=Unir múltiples PDFs (2+)
|
||||
merge.sortByName=Ordenar por nombre
|
||||
merge.sortByDate=Ordenar por fecha
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Unir
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Erabiltzaile
|
||||
adminUserSettings.addUser=Erabiltzaile berria
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Rolak
|
||||
adminUserSettings.role=Rol
|
||||
@ -799,6 +803,7 @@ merge.title=Elkartu
|
||||
merge.header=Elkartu zenbait PDF (2+)
|
||||
merge.sortByName=Sort by nameOrdenatu izenaren arabera
|
||||
merge.sortByDate=Ordenatu dataren arabera
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Elkartu
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Utilisateur non trouvé.
|
||||
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
||||
usernameExistsMessage=Le nouveau nom d’utilisateur existe déjà.
|
||||
invalidUsernameMessage=Nom d’utilisateur invalide, le nom d’utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Impossible de supprimer l’utilisateur actuellement connecté.
|
||||
deleteUsernameExistsMessage=Le nom d’utilisateur n’existe pas et ne peut pas être supprimé.
|
||||
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Personnaliser
|
||||
pipeline.submitButton=Soumettre
|
||||
pipeline.help=Aide Pipeline
|
||||
pipeline.scanHelp=Aide analyse de dossier
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
|
||||
adminUserSettings.admin=Administateur
|
||||
adminUserSettings.user=Utilisateur
|
||||
adminUserSettings.addUser=Ajouter un utilisateur
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
|
||||
adminUserSettings.roles=Rôles
|
||||
adminUserSettings.role=Rôle
|
||||
@ -456,12 +460,12 @@ login.locked=Votre compte a été verrouillé.
|
||||
login.signinTitle=Veuillez vous connecter
|
||||
login.ssoSignIn=Se connecter via l'authentification unique
|
||||
login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
|
||||
login.oauth2RequestNotFound=Authorization request not found
|
||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
||||
login.oauth2invalidRequest=Invalid Request
|
||||
login.oauth2AccessDenied=Access Denied
|
||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||
login.oauth2InvalidIdToken=Invalid Id Token
|
||||
login.oauth2RequestNotFound=Demande d'autorisation introuvable
|
||||
login.oauth2InvalidUserInfoResponse=Réponse contenant les informations de l'utilisateur est invalide
|
||||
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
|
||||
|
||||
|
||||
#auto-redact
|
||||
@ -690,14 +694,14 @@ compare.document.2=Document 2
|
||||
compare.submit=Comparer
|
||||
|
||||
#BookToPDF
|
||||
BookToPDF.title=Books and Comics to PDF
|
||||
BookToPDF.header=Book to PDF
|
||||
BookToPDF.title=Livres et BD vers PDF
|
||||
BookToPDF.header=Livre vers PDF
|
||||
BookToPDF.credit=Utiliser Calibre
|
||||
BookToPDF.submit=Convertir
|
||||
|
||||
#PDFToBook
|
||||
PDFToBook.title=PDF to Book
|
||||
PDFToBook.header=PDF to Book
|
||||
PDFToBook.title=PDF vers Livre
|
||||
PDFToBook.header=PDF vers Livre
|
||||
PDFToBook.selectText.1=Format
|
||||
PDFToBook.credit=Utiliser Calibre
|
||||
PDFToBook.submit=Convertir
|
||||
@ -799,6 +803,7 @@ merge.title=Fusionner
|
||||
merge.header=Fusionner plusieurs PDF
|
||||
merge.sortByName=Trier par nom
|
||||
merge.sortByDate=Trier par date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Fusionner
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=उपयोगकर्ता नहीं मिला।
|
||||
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
|
||||
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
|
||||
adminUserSettings.admin=व्यवस्थापक
|
||||
adminUserSettings.user=उपयोगकर्ता
|
||||
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=रोल्स
|
||||
adminUserSettings.role=रोल
|
||||
@ -799,6 +803,7 @@ merge.title=मर्ज
|
||||
merge.header=एक से अधिक PDF एक साथ मर्ज करें (2+)
|
||||
merge.sortByName=नाम से क्रमबद्ध करें
|
||||
merge.sortByDate=तारीख से क्रमबद्ध करें
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=मर्ज करें
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Korisnik nije pronađen.
|
||||
incorrectPasswordMessage=Kriva zaporka.
|
||||
usernameExistsMessage=Korisničko ime već postoji
|
||||
invalidUsernameMessage=Nevažeće korisničko ime, korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Nije moguće izbrisati trenutno prijavljenog korisnika.
|
||||
deleteUsernameExistsMessage=Korisničko ime ne postoji i ne može se izbrisati.
|
||||
downgradeCurrentUserMessage=Nije moguće vratiti unazad ulogu trenutnog korisnika
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Prilagođeno
|
||||
pipeline.submitButton=Pošalji
|
||||
pipeline.help=Pipeline Pomoć
|
||||
pipeline.scanHelp=Pomoć za skeniranje mapa
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Postavka kontrole korisnika za administratora
|
||||
adminUserSettings.admin=Administrator
|
||||
adminUserSettings.user=Korisnik
|
||||
adminUserSettings.addUser=Dodaj novog korisnika
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte.
|
||||
adminUserSettings.roles=Uloge
|
||||
adminUserSettings.role=Uloga
|
||||
@ -799,6 +803,7 @@ merge.title=Spajanje
|
||||
merge.header=Spajanje više PDF-ova (2+)
|
||||
merge.sortByName=Poredaj po imenu
|
||||
merge.sortByDate=Poredaj po datumu
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Spajanje
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=A felhasználó nem található.
|
||||
incorrectPasswordMessage=A jelenlegi jelszó helytelen.
|
||||
usernameExistsMessage=Az új felhasználónév már létezik.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
|
||||
adminUserSettings.admin=Adminisztrátor
|
||||
adminUserSettings.user=Felhasználó
|
||||
adminUserSettings.addUser=Új felhasználó hozzáadása
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Szerepek
|
||||
adminUserSettings.role=Szerep
|
||||
@ -799,6 +803,7 @@ merge.title=Összevonás
|
||||
merge.header=Több PDF összevonása (2+)
|
||||
merge.sortByName=Név szerinti rendezés
|
||||
merge.sortByDate=Dátum szerinti rendezés
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Összevonás
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Pengguna tidak ditemukan.
|
||||
incorrectPasswordMessage=Kata sandi saat ini salah.
|
||||
usernameExistsMessage=Nama pengguna baru sudah ada.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Pengaturan Kontrol Admin
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Pengguna
|
||||
adminUserSettings.addUser=Tambahkan Pengguna Baru
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Peran
|
||||
adminUserSettings.role=Peran
|
||||
@ -799,6 +803,7 @@ merge.title=Gabungkan
|
||||
merge.header=Gabungkan beberapa PDFs (2+)
|
||||
merge.sortByName=Sortir berdasarkan nama
|
||||
merge.sortByDate=Sortir berdasrkan tanggal
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Gabungkan
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Utente non trovato.
|
||||
incorrectPasswordMessage=La password attuale non è corretta.
|
||||
usernameExistsMessage=Il nuovo nome utente esiste già.
|
||||
invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
|
||||
confirmPasswordErrorMessage=La nuova password e la conferma della nuova password devono corrispondere.
|
||||
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
|
||||
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
|
||||
downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizzato
|
||||
pipeline.submitButton=Invia
|
||||
pipeline.help=Aiuto sulla pipeline
|
||||
pipeline.scanHelp=Aiuto per la scansione delle cartelle
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Impostazioni di controllo utente amministratore
|
||||
adminUserSettings.admin=Amministratore
|
||||
adminUserSettings.user=Utente
|
||||
adminUserSettings.addUser=Aggiungi un nuovo Utente
|
||||
adminUserSettings.deleteUser=Elimina utente
|
||||
adminUserSettings.confirmDeleteUser=L'utente deve essere eliminato?
|
||||
adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
|
||||
adminUserSettings.roles=Ruoli
|
||||
adminUserSettings.role=Ruolo
|
||||
@ -332,9 +336,9 @@ home.certSign.title=Firma con certificato
|
||||
home.certSign.desc=Firma un PDF con un certificato/chiave (PEM/P12)
|
||||
certSign.tags=autenticare,PEM,P12,ufficiale,crittografare
|
||||
|
||||
home.removeCertSign.title=Remove Certificate Sign
|
||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||
home.removeCertSign.title=Rimuovere firma dal certificato
|
||||
home.removeCertSign.desc=Rimuovi la firma del certificato dal PDF
|
||||
removeCertSign.tags=autenticare,PEM,P12,ufficiale,decifrare
|
||||
|
||||
home.pageLayout.title=Layout multipagina
|
||||
home.pageLayout.desc=Unisci più pagine di un documento PDF in un'unica pagina
|
||||
@ -799,6 +803,7 @@ merge.title=Unisci
|
||||
merge.header=Unisci 2 o più PDF
|
||||
merge.sortByName=Ordina per nome
|
||||
merge.sortByDate=Ordina per data
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Unisci
|
||||
|
||||
|
||||
@ -976,7 +981,7 @@ pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
|
||||
pdfToPDFA.submit=Converti
|
||||
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
|
||||
pdfToPDFA.outputFormat=Formato di output
|
||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||
pdfToPDFA.pdfWithDigitalSignature=Il PDF contiene una firma digitale. Questo verrà rimosso nel passaggio successivo.
|
||||
|
||||
|
||||
#PDFToWord
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=ユーザーが見つかりません。
|
||||
incorrectPasswordMessage=現在のパスワードが正しくありません。
|
||||
usernameExistsMessage=新しいユーザー名はすでに存在します。
|
||||
invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
|
||||
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
|
||||
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=カスタム
|
||||
pipeline.submitButton=送信
|
||||
pipeline.help=パイプラインのヘルプ
|
||||
pipeline.scanHelp=フォルダ スキャンのヘルプ
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=管理者ユーザー制御設定
|
||||
adminUserSettings.admin=管理者
|
||||
adminUserSettings.user=ユーザー
|
||||
adminUserSettings.addUser=新しいユーザを追加
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
|
||||
adminUserSettings.roles=役割
|
||||
adminUserSettings.role=役割
|
||||
@ -799,6 +803,7 @@ merge.title=結合
|
||||
merge.header=複数のPDFを結合 (2ファイル以上)
|
||||
merge.sortByName=名前で並べ替え
|
||||
merge.sortByDate=日付で並べ替え
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=結合
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=사용자를 찾을 수 없습니다.
|
||||
incorrectPasswordMessage=현재 비밀번호가 틀립니다.
|
||||
usernameExistsMessage=새 사용자명이 이미 존재합니다.
|
||||
invalidUsernameMessage=잘못된 사용자 이름입니다. 사용자 이름에는 문자, 숫자 및 다음 특수 문자(@._+-)만 포함할 수 있거나 유효한 이메일 주소여야 합니다.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다.
|
||||
deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다.
|
||||
downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=관습
|
||||
pipeline.submitButton=전송
|
||||
pipeline.help=파이프라인 도움말
|
||||
pipeline.scanHelp=폴더 스캔 도움말
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=사용자 관리
|
||||
adminUserSettings.admin=관리자
|
||||
adminUserSettings.user=사용자
|
||||
adminUserSettings.addUser=새 사용자 추가
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=사용자 이름은 문자, 숫자, 특수 문자 @._+-만 포함할 수 있으며 유효한 이메일 주소여야 합니다.
|
||||
adminUserSettings.roles=역할
|
||||
adminUserSettings.role=역할
|
||||
@ -799,6 +803,7 @@ merge.title=병합
|
||||
merge.header=여러 개의 PDF 병합 (2개 이상)
|
||||
merge.sortByName=이름순 정렬
|
||||
merge.sortByDate=날짜순 정렬
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=병합
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Gebruiker niet gevonden.
|
||||
incorrectPasswordMessage=Huidige wachtwoord is onjuist.
|
||||
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Aangepast
|
||||
pipeline.submitButton=Opslaan
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Beheer gebruikers
|
||||
adminUserSettings.admin=Beheerder
|
||||
adminUserSettings.user=Gebruiker
|
||||
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Rollen
|
||||
adminUserSettings.role=Rol
|
||||
@ -799,6 +803,7 @@ merge.title=Samenvoegen
|
||||
merge.header=Meerdere PDF's samenvoegen (2+)
|
||||
merge.sortByName=Sorteer op naam
|
||||
merge.sortByDate=Sorteer op datum
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Samenvoegen
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Bruker ikke funnet.
|
||||
incorrectPasswordMessage=Nåværende passord er feil.
|
||||
usernameExistsMessage=Det nye brukernavnet eksisterer allerede.
|
||||
invalidUsernameMessage=Ugyldig brukernavn, brukernavnet kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Kan ikke slette den innloggede brukeren.
|
||||
deleteUsernameExistsMessage=Brukernavnet eksisterer ikke og kan ikke slettes.
|
||||
downgradeCurrentUserMessage=Kan ikke nedgradere den innloggede brukerens rolle.
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Tilpasset
|
||||
pipeline.submitButton=Send inn
|
||||
pipeline.help=Pipeline hjelp
|
||||
pipeline.scanHelp=Mappe skanning hjelp
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin Brukerkontroll Innstillinger
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Bruker
|
||||
adminUserSettings.addUser=Legg til Ny Bruker
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Brukernavn kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
|
||||
adminUserSettings.roles=Roller
|
||||
adminUserSettings.role=Rolle
|
||||
@ -799,6 +803,7 @@ merge.title=Slå sammen
|
||||
merge.header=Slå sammen flere PDF-er (2+)
|
||||
merge.sortByName=Sorter etter navn
|
||||
merge.sortByDate=Sorter etter dato
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Slå sammen
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Połącz
|
||||
merge.header=Połącz wiele dokumentów PDF (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Połącz
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Mesclar
|
||||
merge.header=Mesclar Vários PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Mesclar
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Utilizador inexistente.
|
||||
incorrectPasswordMessage=Senha incorreta.
|
||||
usernameExistsMessage=Esse utilizador já existe.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizar
|
||||
pipeline.submitButton=Submeter
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Juntar
|
||||
merge.header=Juntar Vários PDFs (2+)
|
||||
merge.sortByName=Ordenar por nome
|
||||
merge.sortByDate=Ordenar por data
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Juntar
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Unire
|
||||
merge.header=Unirea mai multor PDF-uri (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Unire
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Пользователь не найден.
|
||||
incorrectPasswordMessage=Текущий пароль неверен.
|
||||
usernameExistsMessage=Новое имя пользователя уже существует.
|
||||
invalidUsernameMessage=Неверное имя пользователя. Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему.
|
||||
deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено.
|
||||
downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Пользовательский
|
||||
pipeline.submitButton=Отправить
|
||||
pipeline.help=Справка по конвейерной обработке
|
||||
pipeline.scanHelp=Справка по сканированию папок
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Настройки контроля пользоват
|
||||
adminUserSettings.admin=Администратор
|
||||
adminUserSettings.user=Пользователь
|
||||
adminUserSettings.addUser=Добавить нового пользователя
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
|
||||
adminUserSettings.roles=Роли
|
||||
adminUserSettings.role=Роль
|
||||
@ -799,6 +803,7 @@ merge.title=Объединить
|
||||
merge.header=Объединение нескольких PDF-файлов (2+)
|
||||
merge.sortByName=Сортировка по имени
|
||||
merge.sortByDate=Сортировка по дате
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Объединить
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Používateľ nebol nájdený.
|
||||
incorrectPasswordMessage=Aktuálne heslo je nesprávne.
|
||||
usernameExistsMessage=Nové používateľské meno už existuje.
|
||||
invalidUsernameMessage=Neplatné používateľské meno, používateľské meno musí obsahovať len abecedné znaky a čísla.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Nie je možné zmazať aktuálne prihláseného používateľa.
|
||||
deleteUsernameExistsMessage=Používateľské meno neexistuje a nemôže byť zmazané.
|
||||
downgradeCurrentUserMessage=Nie je možné znížiť rolu aktuálneho používateľa
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Vlastné
|
||||
pipeline.submitButton=Odoslať
|
||||
pipeline.help=Pomoc s pipeline
|
||||
pipeline.scanHelp=Pomoc so skenovaním priečinka
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin nastavenia kontroly používateľov
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=Používateľ
|
||||
adminUserSettings.addUser=Pridať nového používateľa
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Používateľské meno musí obsahovať iba písmená a čísla, žiadne medzery alebo špeciálne znaky.
|
||||
adminUserSettings.roles=Role
|
||||
adminUserSettings.role=Rola
|
||||
@ -799,6 +803,7 @@ merge.title=Zlúčiť
|
||||
merge.header=Zlúčiť viacero PDF (2+)
|
||||
merge.sortByName=Zoradiť podľa názvu
|
||||
merge.sortByDate=Zoradiť podľa dátumu
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Zlúčiť
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Korisnik nije pronađen.
|
||||
incorrectPasswordMessage=Trenutna šifra je netačna.
|
||||
usernameExistsMessage=Novi korisnik već postoji
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Prilagođeno
|
||||
pipeline.submitButton=Pošalji
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Podešavanja kontrole korisnika za administratora
|
||||
adminUserSettings.admin=Administrator
|
||||
adminUserSettings.user=Korisnik
|
||||
adminUserSettings.addUser=Dodaj novog korisnika
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Uloge
|
||||
adminUserSettings.role=Uloga
|
||||
@ -799,6 +803,7 @@ merge.title=Spajanje
|
||||
merge.header=Spajanje više PDF fajlova (2+)
|
||||
merge.sortByName=Sortiraj po imenu
|
||||
merge.sortByDate=Sortiraj po datumu
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Spajanje
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
|
||||
incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
||||
downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.help=Pipeline Help
|
||||
pipeline.scanHelp=Folder Scanning Help
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
@ -799,6 +803,7 @@ merge.title=Sammanfoga
|
||||
merge.header=Slå samman flera PDF-filer (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Slå samman
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Kullanıcı bulunamadı.
|
||||
incorrectPasswordMessage=Mevcut şifre yanlış.
|
||||
usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
|
||||
invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
|
||||
deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
|
||||
downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Özel
|
||||
pipeline.submitButton=Gönder
|
||||
pipeline.help=Çoklu İşlemler Yardım
|
||||
pipeline.scanHelp=Klasör Tarama Yardımı
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
|
||||
adminUserSettings.admin=Yönetici
|
||||
adminUserSettings.user=Kullanıcı
|
||||
adminUserSettings.addUser=Yeni Kullanıcı Ekle
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
|
||||
adminUserSettings.roles=Roller
|
||||
adminUserSettings.role=Rol
|
||||
@ -799,6 +803,7 @@ merge.title=Birleştir
|
||||
merge.header=Çoklu PDF'leri Birleştir (2+)
|
||||
merge.sortByName=İsme göre sırala
|
||||
merge.sortByDate=Tarihe göre sırala
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Birleştir
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=Користувача не знайдено.
|
||||
incorrectPasswordMessage=Поточний пароль невірний.
|
||||
usernameExistsMessage=Нове ім'я користувача вже існує.
|
||||
invalidUsernameMessage=Недійсне ім’я користувача, ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему.
|
||||
deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено.
|
||||
downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=Користувацький
|
||||
pipeline.submitButton=Надіслати
|
||||
pipeline.help=Довідка з конвеєрної обробки
|
||||
pipeline.scanHelp=Довідка зі сканування папок
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=Налаштування контролю корист
|
||||
adminUserSettings.admin=Адміністратор
|
||||
adminUserSettings.user=Користувач
|
||||
adminUserSettings.addUser=Додати нового користувача
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=Ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
|
||||
adminUserSettings.roles=Ролі
|
||||
adminUserSettings.role=Роль
|
||||
@ -799,6 +803,7 @@ merge.title=Об'єднати
|
||||
merge.header=Об'єднання кількох PDF-файлів (2+)
|
||||
merge.sortByName=Сортування за ім'ям
|
||||
merge.sortByDate=Сортування за датою
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Об'єднати
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=未找到用户。
|
||||
incorrectPasswordMessage=当前密码不正确。
|
||||
usernameExistsMessage=新用户名已存在。
|
||||
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=无法删除当前登录的用户。
|
||||
deleteUsernameExistsMessage=用户名不存在,无法删除。
|
||||
downgradeCurrentUserMessage=无法降级当前用户的角色
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=自定义
|
||||
pipeline.submitButton=提交
|
||||
pipeline.help=工作流帮助
|
||||
pipeline.scanHelp=文件夹扫描帮助
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=管理员用户控制设置
|
||||
adminUserSettings.admin=管理员
|
||||
adminUserSettings.user=用户
|
||||
adminUserSettings.addUser=添加新用户
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。
|
||||
adminUserSettings.roles=角色
|
||||
adminUserSettings.role=角色
|
||||
@ -799,6 +803,7 @@ merge.title=合并
|
||||
merge.header=合并多个PDF(2个以上)。
|
||||
merge.sortByName=按名称排序
|
||||
merge.sortByDate=按日期排序
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=合并
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ userNotFoundMessage=找不到使用者。
|
||||
incorrectPasswordMessage=目前密碼不正確。
|
||||
usernameExistsMessage=新使用者名稱已存在。
|
||||
invalidUsernameMessage=使用者名稱無效,使用者名稱只能包含字母、數字和以下特殊字元@._+- 或必須是有效的電子郵件地址。
|
||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
||||
deleteCurrentUserMessage=無法刪除目前登錄的使用者。
|
||||
deleteUsernameExistsMessage=使用者名不存在,無法刪除。
|
||||
downgradeCurrentUserMessage=無法降級目前使用者的角色
|
||||
@ -85,6 +86,7 @@ pipeline.defaultOption=自訂
|
||||
pipeline.submitButton=送出
|
||||
pipeline.help=管道説明
|
||||
pipeline.scanHelp=資料夾掃描説明
|
||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
@ -173,6 +175,8 @@ adminUserSettings.header=管理使用者控制設定
|
||||
adminUserSettings.admin=管理員
|
||||
adminUserSettings.user=使用者
|
||||
adminUserSettings.addUser=新增使用者
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元@._+-,或必須是有效的電子郵件地址。
|
||||
adminUserSettings.roles=角色
|
||||
adminUserSettings.role=角色
|
||||
@ -799,6 +803,7 @@ merge.title=合併
|
||||
merge.header=合併多個 PDF
|
||||
merge.sortByName=依名稱排序
|
||||
merge.sortByDate=依日期排序
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=合併
|
||||
|
||||
|
||||
|
@ -20,10 +20,35 @@ async function getLatestReleaseVersion() {
|
||||
const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
return data.tag_name ? data.tag_name.substring(1) : "";
|
||||
} else {
|
||||
// If the status is not 200, try to get the version from build.gradle
|
||||
return await getCurrentVersionFromBypass();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch latest version:", error);
|
||||
console.error("Failed to fetch latest version from GitHub:", error);
|
||||
// If an error occurs, try to get the version from build.gradle
|
||||
return await getCurrentVersionFromBypass();
|
||||
}
|
||||
}
|
||||
|
||||
async function getCurrentVersionFromBypass() {
|
||||
const url = "https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/master/build.gradle";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (response.status === 200) {
|
||||
const text = await response.text();
|
||||
const versionRegex = /version\s*=\s*['"](\d+\.\d+\.\d+)['"]/;
|
||||
const match = versionRegex.exec(text);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
throw new Error("Version number not found");
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch latest version from build.gradle:", error);
|
||||
return ""; // Return an empty string if the fetch fails
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ document.getElementById("submitConfigBtn").addEventListener("click", function ()
|
||||
for (let i = 0; i < pipelineList.length; i++) {
|
||||
let operationName = pipelineList[i].querySelector(".operationName").textContent;
|
||||
let parameters = operationSettings[operationName] || {};
|
||||
|
||||
pipelineConfig.pipeline.push({
|
||||
operation: operationName,
|
||||
parameters: parameters,
|
||||
@ -104,7 +103,6 @@ document.getElementById("submitConfigBtn").addEventListener("click", function ()
|
||||
}
|
||||
|
||||
let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2);
|
||||
|
||||
let formData = new FormData();
|
||||
|
||||
let fileInput = document.getElementById("fileInput-input");
|
||||
@ -218,6 +216,41 @@ fetch("v1/api-docs")
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('deletePipelineBtn').addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
let pipelineName = document.getElementById('pipelineName').value;
|
||||
if (confirm(deletePipelineText + pipelineName)) {
|
||||
removePipelineFromUI(pipelineName);
|
||||
let key = "#Pipeline-" + pipelineName;
|
||||
if (localStorage.getItem(key)) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
let pipelineSelect = document.getElementById("pipelineSelect");
|
||||
let modal = document.getElementById('pipelineSettingsModal');
|
||||
if (modal.style.display !== 'none') {
|
||||
$('#pipelineSettingsModal').modal('hide');
|
||||
}
|
||||
|
||||
if (pipelineSelect.options.length > 0) {
|
||||
pipelineSelect.selectedIndex = 0;
|
||||
pipelineSelect.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function removePipelineFromUI(pipelineName) {
|
||||
let pipelineSelect = document.getElementById("pipelineSelect");
|
||||
for (let i = 0; i < pipelineSelect.options.length; i++) {
|
||||
console.log(pipelineSelect.options[i])
|
||||
console.log("list " + pipelineSelect.options[i].innerText + " vs " + pipelineName)
|
||||
if (pipelineSelect.options[i].innerText === pipelineName) {
|
||||
pipelineSelect.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.getElementById("addOperationBtn").addEventListener("click", function () {
|
||||
let selectedOperation = document.getElementById("operationsDropdown").value;
|
||||
let pipelineList = document.getElementById("pipelineList");
|
||||
@ -379,10 +412,14 @@ document.getElementById("addOperationBtn").addEventListener("click", function ()
|
||||
if (defaultValue === true) parameterInput.checked = true;
|
||||
break;
|
||||
case "array":
|
||||
case "object":
|
||||
//TODO compare to doc and check if fileInput array? parameter.schema.format === 'binary'
|
||||
// If parameter.schema.format === 'binary' is to be checked, it should be checked here
|
||||
parameterInput = document.createElement("textarea");
|
||||
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}, If this is a fileInput, it is not currently supported`;
|
||||
parameterInput.placeholder = 'Enter a JSON formatted array, e.g., ["item1", "item2", "item3"]';
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
case "object":
|
||||
parameterInput = document.createElement("textarea");
|
||||
parameterInput.placeholder = 'Enter a JSON formatted object, e.g., {"key": "value"} If this is a fileInput, it is not currently supported';
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
default:
|
||||
@ -445,9 +482,14 @@ document.getElementById("addOperationBtn").addEventListener("click", function ()
|
||||
settings[parameter.name] = "";
|
||||
} else {
|
||||
try {
|
||||
settings[parameter.name] = JSON.parse(value);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON format for ${parameter.name}`);
|
||||
const parsedValue = JSON.parse(value);
|
||||
if (Array.isArray(parsedValue)) {
|
||||
settings[parameter.name] = parsedValue;
|
||||
} else {
|
||||
settings[parameter.name] = value;
|
||||
}
|
||||
} catch (e) {
|
||||
settings[parameter.name] = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -558,7 +600,6 @@ function configToJson() {
|
||||
parameters: parameters,
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify(pipelineConfig, null, 2);
|
||||
}
|
||||
|
||||
@ -642,7 +683,13 @@ async function processPipelineConfig(configString) {
|
||||
case "text":
|
||||
case "textarea":
|
||||
default:
|
||||
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
|
||||
var value = operationConfig.parameters[parameterName]
|
||||
if (typeof value !== 'string') {
|
||||
input.value = JSON.stringify(value) ;
|
||||
} else {
|
||||
input.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
489
src/main/resources/static/pdfjs/css/viewer.css
vendored
@ -13,6 +13,242 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.dialog{
|
||||
--dialog-bg-color:white;
|
||||
--dialog-border-color:white;
|
||||
--dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);
|
||||
--text-primary-color:#15141a;
|
||||
--text-secondary-color:#5b5b66;
|
||||
--hover-filter:brightness(0.9);
|
||||
--focus-ring-color:#0060df;
|
||||
--focus-ring-outline:2px solid var(--focus-ring-color);
|
||||
|
||||
--textarea-border-color:#8f8f9d;
|
||||
--textarea-bg-color:white;
|
||||
--textarea-fg-color:var(--text-secondary-color);
|
||||
|
||||
--radio-bg-color:#f0f0f4;
|
||||
--radio-checked-bg-color:#fbfbfe;
|
||||
--radio-border-color:#8f8f9d;
|
||||
--radio-checked-border-color:#0060df;
|
||||
|
||||
--button-secondary-bg-color:#f0f0f4;
|
||||
--button-secondary-fg-color:var(--text-primary-color);
|
||||
--button-secondary-border-color:var(--button-secondary-bg-color);
|
||||
--button-secondary-hover-bg-color:var(--button-secondary-bg-color);
|
||||
--button-secondary-hover-fg-color:var(--button-secondary-fg-color);
|
||||
--button-secondary-hover-border-color:var(--button-secondary-hover-bg-color);
|
||||
|
||||
--button-primary-bg-color:#0060df;
|
||||
--button-primary-fg-color:#fbfbfe;
|
||||
--button-primary-hover-bg-color:var(--button-primary-bg-color);
|
||||
--button-primary-hover-fg-color:var(--button-primary-fg-color);
|
||||
--button-primary-hover-border-color:var(--button-primary-hover-bg-color);
|
||||
|
||||
font:message-box;
|
||||
font-size:13px;
|
||||
font-weight:400;
|
||||
line-height:150%;
|
||||
border-radius:4px;
|
||||
padding:12px 16px;
|
||||
border:1px solid var(--dialog-border-color);
|
||||
background:var(--dialog-bg-color);
|
||||
color:var(--text-primary-color);
|
||||
box-shadow:var(--dialog-shadow);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark){
|
||||
|
||||
:where(html:not(.is-light)) .dialog{
|
||||
--dialog-bg-color:#1c1b22;
|
||||
--dialog-border-color:#1c1b22;
|
||||
--dialog-shadow:0 2px 14px 0 #15141a;
|
||||
--text-primary-color:#fbfbfe;
|
||||
--text-secondary-color:#cfcfd8;
|
||||
--focus-ring-color:#0df;
|
||||
--hover-filter:brightness(1.4);
|
||||
|
||||
--textarea-bg-color:#42414d;
|
||||
|
||||
--radio-bg-color:#2b2a33;
|
||||
--radio-checked-bg-color:#15141a;
|
||||
--radio-checked-border-color:#0df;
|
||||
|
||||
--button-secondary-bg-color:#2b2a33;
|
||||
--button-primary-bg-color:#0df;
|
||||
--button-primary-fg-color:#15141a;
|
||||
}
|
||||
}
|
||||
|
||||
:where(html.is-dark) .dialog{
|
||||
--dialog-bg-color:#1c1b22;
|
||||
--dialog-border-color:#1c1b22;
|
||||
--dialog-shadow:0 2px 14px 0 #15141a;
|
||||
--text-primary-color:#fbfbfe;
|
||||
--text-secondary-color:#cfcfd8;
|
||||
--focus-ring-color:#0df;
|
||||
--hover-filter:brightness(1.4);
|
||||
|
||||
--textarea-bg-color:#42414d;
|
||||
|
||||
--radio-bg-color:#2b2a33;
|
||||
--radio-checked-bg-color:#15141a;
|
||||
--radio-checked-border-color:#0df;
|
||||
|
||||
--button-secondary-bg-color:#2b2a33;
|
||||
--button-primary-bg-color:#0df;
|
||||
--button-primary-fg-color:#15141a;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active){
|
||||
|
||||
.dialog{
|
||||
--dialog-bg-color:Canvas;
|
||||
--dialog-border-color:CanvasText;
|
||||
--dialog-shadow:none;
|
||||
--text-primary-color:CanvasText;
|
||||
--text-secondary-color:CanvasText;
|
||||
--hover-filter:none;
|
||||
--focus-ring-color:ButtonBorder;
|
||||
|
||||
--textarea-border-color:ButtonBorder;
|
||||
--textarea-bg-color:Field;
|
||||
--textarea-fg-color:ButtonText;
|
||||
|
||||
--radio-bg-color:ButtonFace;
|
||||
--radio-checked-bg-color:ButtonFace;
|
||||
--radio-border-color:ButtonText;
|
||||
--radio-checked-border-color:ButtonText;
|
||||
|
||||
--button-secondary-bg-color:ButtonFace;
|
||||
--button-secondary-fg-color:ButtonText;
|
||||
--button-secondary-border-color:ButtonText;
|
||||
--button-secondary-hover-bg-color:AccentColor;
|
||||
--button-secondary-hover-fg-color:AccentColorText;
|
||||
|
||||
--button-primary-bg-color:ButtonText;
|
||||
--button-primary-fg-color:ButtonFace;
|
||||
--button-primary-hover-bg-color:AccentColor;
|
||||
--button-primary-hover-fg-color:AccentColorText;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog .mainContainer *:focus-visible{
|
||||
outline:var(--focus-ring-outline);
|
||||
outline-offset:2px;
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio{
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:flex-start;
|
||||
gap:4px;
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioButton{
|
||||
display:flex;
|
||||
gap:8px;
|
||||
align-self:stretch;
|
||||
align-items:center;
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioButton input{
|
||||
-webkit-appearance:none;
|
||||
-moz-appearance:none;
|
||||
appearance:none;
|
||||
box-sizing:border-box;
|
||||
width:16px;
|
||||
height:16px;
|
||||
border-radius:50%;
|
||||
background-color:var(--radio-bg-color);
|
||||
border:1px solid var(--radio-border-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioButton input:hover{
|
||||
filter:var(--hover-filter);
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioButton input:checked{
|
||||
background-color:var(--radio-checked-bg-color);
|
||||
border:4px solid var(--radio-checked-border-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioLabel{
|
||||
display:flex;
|
||||
padding-inline-start:24px;
|
||||
align-items:flex-start;
|
||||
gap:10px;
|
||||
align-self:stretch;
|
||||
}
|
||||
|
||||
.dialog .mainContainer .radio > .radioLabel > span{
|
||||
flex:1 0 0;
|
||||
font-size:11px;
|
||||
color:var(--text-secondary-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer button{
|
||||
border-radius:4px;
|
||||
border:1px solid;
|
||||
font:menu;
|
||||
font-weight:600;
|
||||
padding:4px 16px;
|
||||
width:auto;
|
||||
height:32px;
|
||||
}
|
||||
|
||||
.dialog .mainContainer button:hover{
|
||||
cursor:pointer;
|
||||
filter:var(--hover-filter);
|
||||
}
|
||||
|
||||
.dialog .mainContainer button.secondaryButton{
|
||||
color:var(--button-secondary-fg-color);
|
||||
background-color:var(--button-secondary-bg-color);
|
||||
border-color:var(--button-secondary-border-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer button.secondaryButton:hover{
|
||||
color:var(--button-secondary-hover-fg-color);
|
||||
background-color:var(--button-secondary-hover-bg-color);
|
||||
border-color:var(--button-secondary-hover-border-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer button.primaryButton{
|
||||
color:var(--button-primary-hover-fg-color);
|
||||
background-color:var(--button-primary-hover-bg-color);
|
||||
border-color:var(--button-primary-hover-border-color);
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
.dialog .mainContainer button.primaryButton:hover{
|
||||
color:var(--button-primary-hover-fg-color);
|
||||
background-color:var(--button-primary-hover-bg-color);
|
||||
border-color:var(--button-primary-hover-border-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer textarea{
|
||||
font:inherit;
|
||||
padding:8px;
|
||||
resize:none;
|
||||
margin:0;
|
||||
box-sizing:border-box;
|
||||
border-radius:4px;
|
||||
border:1px solid var(--textarea-border-color);
|
||||
background:var(--textarea-bg-color);
|
||||
color:var(--textarea-fg-color);
|
||||
}
|
||||
|
||||
.dialog .mainContainer textarea:focus{
|
||||
outline-offset:0;
|
||||
border-color:transparent;
|
||||
}
|
||||
|
||||
.dialog .mainContainer textarea:disabled{
|
||||
pointer-events:none;
|
||||
opacity:0.4;
|
||||
}
|
||||
|
||||
.textLayer{
|
||||
position:absolute;
|
||||
text-align:initial;
|
||||
@ -1946,136 +2182,16 @@
|
||||
inset-block-start:0;
|
||||
}
|
||||
|
||||
#altTextDialog{
|
||||
--dialog-bg-color:white;
|
||||
--dialog-border-color:white;
|
||||
--dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);
|
||||
--text-primary-color:#15141a;
|
||||
--text-secondary-color:#5b5b66;
|
||||
--hover-filter:brightness(0.9);
|
||||
--focus-ring-color:#0060df;
|
||||
--focus-ring-outline:2px solid var(--focus-ring-color);
|
||||
|
||||
--textarea-border-color:#8f8f9d;
|
||||
--textarea-bg-color:white;
|
||||
--textarea-fg-color:var(--text-secondary-color);
|
||||
|
||||
--radio-bg-color:#f0f0f4;
|
||||
--radio-checked-bg-color:#fbfbfe;
|
||||
--radio-border-color:#8f8f9d;
|
||||
--radio-checked-border-color:#0060df;
|
||||
|
||||
--button-cancel-bg-color:#f0f0f4;
|
||||
--button-cancel-fg-color:var(--text-primary-color);
|
||||
--button-cancel-border-color:var(--button-cancel-bg-color);
|
||||
--button-cancel-hover-bg-color:var(--button-cancel-bg-color);
|
||||
--button-cancel-hover-fg-color:var(--button-cancel-fg-color);
|
||||
--button-cancel-hover-border-color:var(--button-cancel-hover-bg-color);
|
||||
|
||||
--button-save-bg-color:#0060df;
|
||||
--button-save-fg-color:#fbfbfe;
|
||||
--button-save-hover-bg-color:var(--button-save-bg-color);
|
||||
--button-save-hover-fg-color:var(--button-save-fg-color);
|
||||
--button-save-hover-border-color:var(--button-save-hover-bg-color);
|
||||
|
||||
font:message-box;
|
||||
font-size:13px;
|
||||
font-weight:400;
|
||||
line-height:150%;
|
||||
border-radius:4px;
|
||||
padding:12px 16px;
|
||||
border:1px solid var(--dialog-border-color);
|
||||
background:var(--dialog-bg-color);
|
||||
color:var(--text-primary-color);
|
||||
box-shadow:var(--dialog-shadow);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark){
|
||||
|
||||
:where(html:not(.is-light)) #altTextDialog{
|
||||
--dialog-bg-color:#1c1b22;
|
||||
--dialog-border-color:#1c1b22;
|
||||
--dialog-shadow:0 2px 14px 0 #15141a;
|
||||
--text-primary-color:#fbfbfe;
|
||||
--text-secondary-color:#cfcfd8;
|
||||
--focus-ring-color:#0df;
|
||||
--hover-filter:brightness(1.4);
|
||||
|
||||
--textarea-bg-color:#42414d;
|
||||
|
||||
--radio-bg-color:#2b2a33;
|
||||
--radio-checked-bg-color:#15141a;
|
||||
--radio-checked-border-color:#0df;
|
||||
|
||||
--button-cancel-bg-color:#2b2a33;
|
||||
--button-save-bg-color:#0df;
|
||||
--button-save-fg-color:#15141a;
|
||||
}
|
||||
}
|
||||
|
||||
:where(html.is-dark) #altTextDialog{
|
||||
--dialog-bg-color:#1c1b22;
|
||||
--dialog-border-color:#1c1b22;
|
||||
--dialog-shadow:0 2px 14px 0 #15141a;
|
||||
--text-primary-color:#fbfbfe;
|
||||
--text-secondary-color:#cfcfd8;
|
||||
--focus-ring-color:#0df;
|
||||
--hover-filter:brightness(1.4);
|
||||
|
||||
--textarea-bg-color:#42414d;
|
||||
|
||||
--radio-bg-color:#2b2a33;
|
||||
--radio-checked-bg-color:#15141a;
|
||||
--radio-checked-border-color:#0df;
|
||||
|
||||
--button-cancel-bg-color:#2b2a33;
|
||||
--button-save-bg-color:#0df;
|
||||
--button-save-fg-color:#15141a;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active){
|
||||
|
||||
#altTextDialog{
|
||||
--dialog-bg-color:Canvas;
|
||||
--dialog-border-color:CanvasText;
|
||||
--dialog-shadow:none;
|
||||
--text-primary-color:CanvasText;
|
||||
--text-secondary-color:CanvasText;
|
||||
--hover-filter:none;
|
||||
--focus-ring-color:ButtonBorder;
|
||||
|
||||
--textarea-border-color:ButtonBorder;
|
||||
--textarea-bg-color:Field;
|
||||
--textarea-fg-color:ButtonText;
|
||||
|
||||
--radio-bg-color:ButtonFace;
|
||||
--radio-checked-bg-color:ButtonFace;
|
||||
--radio-border-color:ButtonText;
|
||||
--radio-checked-border-color:ButtonText;
|
||||
|
||||
--button-cancel-bg-color:ButtonFace;
|
||||
--button-cancel-fg-color:ButtonText;
|
||||
--button-cancel-border-color:ButtonText;
|
||||
--button-cancel-hover-bg-color:AccentColor;
|
||||
--button-cancel-hover-fg-color:AccentColorText;
|
||||
|
||||
--button-save-bg-color:ButtonText;
|
||||
--button-save-fg-color:ButtonFace;
|
||||
--button-save-hover-bg-color:AccentColor;
|
||||
--button-save-hover-fg-color:AccentColorText;
|
||||
}
|
||||
}
|
||||
|
||||
#altTextDialog::backdrop{
|
||||
.dialog.altText::backdrop{
|
||||
-webkit-mask:url(#alttext-manager-mask);
|
||||
mask:url(#alttext-manager-mask);
|
||||
}
|
||||
|
||||
#altTextDialog.positioned{
|
||||
.dialog.altText.positioned{
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer{
|
||||
.dialog.altText #altTextContainer{
|
||||
width:300px;
|
||||
height:-moz-fit-content;
|
||||
height:fit-content;
|
||||
@ -2085,61 +2201,7 @@
|
||||
gap:16px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer *:focus-visible{
|
||||
outline:var(--focus-ring-outline);
|
||||
outline-offset:2px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio{
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:flex-start;
|
||||
gap:4px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioButton{
|
||||
display:flex;
|
||||
gap:8px;
|
||||
align-self:stretch;
|
||||
align-items:center;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioButton input{
|
||||
-webkit-appearance:none;
|
||||
-moz-appearance:none;
|
||||
appearance:none;
|
||||
box-sizing:border-box;
|
||||
width:16px;
|
||||
height:16px;
|
||||
border-radius:50%;
|
||||
background-color:var(--radio-bg-color);
|
||||
border:1px solid var(--radio-border-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioButton input:hover{
|
||||
filter:var(--hover-filter);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioButton input:checked{
|
||||
background-color:var(--radio-checked-bg-color);
|
||||
border:4px solid var(--radio-checked-border-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioLabel{
|
||||
display:flex;
|
||||
padding-inline-start:24px;
|
||||
align-items:flex-start;
|
||||
gap:10px;
|
||||
align-self:stretch;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer .radio .radioLabel span{
|
||||
flex:1 0 0;
|
||||
font-size:11px;
|
||||
color:var(--text-secondary-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #overallDescription{
|
||||
.dialog.altText #altTextContainer #overallDescription{
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:flex-start;
|
||||
@ -2147,53 +2209,34 @@
|
||||
align-self:stretch;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #overallDescription span{
|
||||
.dialog.altText #altTextContainer #overallDescription span{
|
||||
align-self:stretch;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #overallDescription .title{
|
||||
.dialog.altText #altTextContainer #overallDescription .title{
|
||||
font-size:13px;
|
||||
font-style:normal;
|
||||
font-weight:590;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #addDescription{
|
||||
.dialog.altText #altTextContainer #addDescription{
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:stretch;
|
||||
gap:8px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #addDescription .descriptionArea{
|
||||
.dialog.altText #altTextContainer #addDescription .descriptionArea{
|
||||
flex:1;
|
||||
padding-inline:24px 10px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea{
|
||||
font:inherit;
|
||||
.dialog.altText #altTextContainer #addDescription .descriptionArea textarea{
|
||||
width:100%;
|
||||
min-height:75px;
|
||||
padding:8px;
|
||||
resize:none;
|
||||
margin:0;
|
||||
box-sizing:border-box;
|
||||
border-radius:4px;
|
||||
border:1px solid var(--textarea-border-color);
|
||||
background:var(--textarea-bg-color);
|
||||
color:var(--textarea-fg-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:focus{
|
||||
outline-offset:0;
|
||||
border-color:transparent;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:disabled{
|
||||
pointer-events:none;
|
||||
opacity:0.4;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons{
|
||||
.dialog.altText #altTextContainer #buttons{
|
||||
display:flex;
|
||||
justify-content:flex-end;
|
||||
align-items:flex-start;
|
||||
@ -2201,46 +2244,6 @@
|
||||
align-self:stretch;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button{
|
||||
border-radius:4px;
|
||||
border:1px solid;
|
||||
font:menu;
|
||||
font-weight:600;
|
||||
padding:4px 16px;
|
||||
width:auto;
|
||||
height:32px;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button:hover{
|
||||
cursor:pointer;
|
||||
filter:var(--hover-filter);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button#altTextCancel{
|
||||
color:var(--button-cancel-fg-color);
|
||||
background-color:var(--button-cancel-bg-color);
|
||||
border-color:var(--button-cancel-border-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button#altTextCancel:hover{
|
||||
color:var(--button-cancel-hover-fg-color);
|
||||
background-color:var(--button-cancel-hover-bg-color);
|
||||
border-color:var(--button-cancel-hover-border-color);
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button#altTextSave{
|
||||
color:var(--button-save-hover-fg-color);
|
||||
background-color:var(--button-save-hover-bg-color);
|
||||
border-color:var(--button-save-hover-border-color);
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
#altTextDialog #altTextContainer #buttons button#altTextSave:hover{
|
||||
color:var(--button-save-hover-fg-color);
|
||||
background-color:var(--button-save-hover-bg-color);
|
||||
border-color:var(--button-save-hover-border-color);
|
||||
}
|
||||
|
||||
.colorPicker{
|
||||
--hover-outline-color:#0250bb;
|
||||
--selected-outline-color:#0060df;
|
||||
|
227
src/main/resources/static/pdfjs/js/viewer.mjs
vendored
@ -8912,17 +8912,18 @@ class TextHighlighter {
|
||||
class TextLayerBuilder {
|
||||
#enablePermissions = false;
|
||||
#onAppend = null;
|
||||
#textContentSource = null;
|
||||
#renderingDone = false;
|
||||
#textLayer = null;
|
||||
static #textLayers = new Map();
|
||||
static #selectionChangeAbortController = null;
|
||||
constructor({
|
||||
pdfPage,
|
||||
highlighter = null,
|
||||
accessibilityManager = null,
|
||||
enablePermissions = false,
|
||||
onAppend = null
|
||||
}) {
|
||||
this.renderingDone = false;
|
||||
this.pdfPage = pdfPage;
|
||||
this.highlighter = highlighter;
|
||||
this.accessibilityManager = accessibilityManager;
|
||||
this.#enablePermissions = enablePermissions === true;
|
||||
@ -8932,17 +8933,14 @@ class TextLayerBuilder {
|
||||
this.div.className = "textLayer";
|
||||
}
|
||||
#finishRendering() {
|
||||
this.renderingDone = true;
|
||||
this.#renderingDone = true;
|
||||
const endOfContent = document.createElement("div");
|
||||
endOfContent.className = "endOfContent";
|
||||
this.div.append(endOfContent);
|
||||
this.#bindMouse(endOfContent);
|
||||
}
|
||||
async render(viewport) {
|
||||
if (!this.#textContentSource) {
|
||||
throw new Error('No "textContentSource" parameter specified.');
|
||||
}
|
||||
if (this.renderingDone && this.#textLayer) {
|
||||
async render(viewport, textContentParams = null) {
|
||||
if (this.#renderingDone && this.#textLayer) {
|
||||
this.#textLayer.update({
|
||||
viewport,
|
||||
onBefore: this.hide.bind(this)
|
||||
@ -8952,7 +8950,10 @@ class TextLayerBuilder {
|
||||
}
|
||||
this.cancel();
|
||||
this.#textLayer = new TextLayer({
|
||||
textContentSource: this.#textContentSource,
|
||||
textContentSource: this.pdfPage.streamTextContent(textContentParams || {
|
||||
includeMarkedContent: true,
|
||||
disableNormalization: true
|
||||
}),
|
||||
container: this.div,
|
||||
viewport
|
||||
});
|
||||
@ -8969,13 +8970,13 @@ class TextLayerBuilder {
|
||||
this.accessibilityManager?.enable();
|
||||
}
|
||||
hide() {
|
||||
if (!this.div.hidden && this.renderingDone) {
|
||||
if (!this.div.hidden && this.#renderingDone) {
|
||||
this.highlighter?.disable();
|
||||
this.div.hidden = true;
|
||||
}
|
||||
}
|
||||
show() {
|
||||
if (this.div.hidden && this.renderingDone) {
|
||||
if (this.div.hidden && this.#renderingDone) {
|
||||
this.div.hidden = false;
|
||||
this.highlighter?.enable();
|
||||
}
|
||||
@ -8987,10 +8988,6 @@ class TextLayerBuilder {
|
||||
this.accessibilityManager?.disable();
|
||||
TextLayerBuilder.#removeGlobalSelectionListener(this.div);
|
||||
}
|
||||
setTextContentSource(source) {
|
||||
this.cancel();
|
||||
this.#textContentSource = source;
|
||||
}
|
||||
#bindMouse(end) {
|
||||
const {
|
||||
div
|
||||
@ -9261,6 +9258,13 @@ class PDFPageView {
|
||||
findController: this.#layerProperties.findController
|
||||
}));
|
||||
}
|
||||
#dispatchLayerRendered(name, error) {
|
||||
this.eventBus.dispatch(name, {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
error
|
||||
});
|
||||
}
|
||||
async #renderAnnotationLayer() {
|
||||
let error = null;
|
||||
try {
|
||||
@ -9269,11 +9273,7 @@ class PDFPageView {
|
||||
console.error(`#renderAnnotationLayer: "${ex}".`);
|
||||
error = ex;
|
||||
} finally {
|
||||
this.eventBus.dispatch("annotationlayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
error
|
||||
});
|
||||
this.#dispatchLayerRendered("annotationlayerrendered", error);
|
||||
}
|
||||
}
|
||||
async #renderAnnotationEditorLayer() {
|
||||
@ -9284,11 +9284,7 @@ class PDFPageView {
|
||||
console.error(`#renderAnnotationEditorLayer: "${ex}".`);
|
||||
error = ex;
|
||||
} finally {
|
||||
this.eventBus.dispatch("annotationeditorlayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
error
|
||||
});
|
||||
this.#dispatchLayerRendered("annotationeditorlayerrendered", error);
|
||||
}
|
||||
}
|
||||
async #renderDrawLayer() {
|
||||
@ -9314,32 +9310,16 @@ class PDFPageView {
|
||||
this.#addLayer(this.xfaLayer.div, "xfaLayer");
|
||||
this.l10n.resume();
|
||||
}
|
||||
this.eventBus.dispatch("xfalayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
error
|
||||
});
|
||||
this.#dispatchLayerRendered("xfalayerrendered", error);
|
||||
}
|
||||
}
|
||||
async #renderTextLayer() {
|
||||
const {
|
||||
pdfPage,
|
||||
textLayer,
|
||||
viewport
|
||||
} = this;
|
||||
if (!textLayer) {
|
||||
if (!this.textLayer) {
|
||||
return;
|
||||
}
|
||||
let error = null;
|
||||
try {
|
||||
if (!textLayer.renderingDone) {
|
||||
const readableStream = pdfPage.streamTextContent({
|
||||
includeMarkedContent: true,
|
||||
disableNormalization: true
|
||||
});
|
||||
textLayer.setTextContentSource(readableStream);
|
||||
}
|
||||
await textLayer.render(viewport);
|
||||
await this.textLayer.render(this.viewport);
|
||||
} catch (ex) {
|
||||
if (ex instanceof AbortException) {
|
||||
return;
|
||||
@ -9347,11 +9327,7 @@ class PDFPageView {
|
||||
console.error(`#renderTextLayer: "${ex}".`);
|
||||
error = ex;
|
||||
}
|
||||
this.eventBus.dispatch("textlayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
error
|
||||
});
|
||||
this.#dispatchLayerRendered("textlayerrendered", error);
|
||||
this.#renderStructTreeLayer();
|
||||
}
|
||||
async #renderStructTreeLayer() {
|
||||
@ -9694,6 +9670,7 @@ class PDFPageView {
|
||||
if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
|
||||
this._accessibilityManager ||= new TextAccessibilityManager();
|
||||
this.textLayer = new TextLayerBuilder({
|
||||
pdfPage,
|
||||
highlighter: this._textHighlighter,
|
||||
accessibilityManager: this._accessibilityManager,
|
||||
enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
|
||||
@ -9801,7 +9778,7 @@ class PDFPageView {
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
pageColors
|
||||
};
|
||||
const renderTask = this.renderTask = this.pdfPage.render(renderContext);
|
||||
const renderTask = this.renderTask = pdfPage.render(renderContext);
|
||||
renderTask.onContinue = renderContinueCallback;
|
||||
const resultPromise = renderTask.promise.then(async () => {
|
||||
showCanvas?.(true);
|
||||
@ -9969,7 +9946,7 @@ class PDFViewer {
|
||||
#scaleTimeoutId = null;
|
||||
#textLayerMode = TextLayerMode.ENABLE;
|
||||
constructor(options) {
|
||||
const viewerVersion = "4.3.118";
|
||||
const viewerVersion = "4.3.136";
|
||||
if (version !== viewerVersion) {
|
||||
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
|
||||
}
|
||||
@ -10634,7 +10611,8 @@ class PDFViewer {
|
||||
#setScaleUpdatePages(newScale, newValue, {
|
||||
noScroll = false,
|
||||
preset = false,
|
||||
drawingDelay = -1
|
||||
drawingDelay = -1,
|
||||
origin = null
|
||||
}) {
|
||||
this._currentScaleValue = newValue.toString();
|
||||
if (this.#isSameScale(newScale)) {
|
||||
@ -10659,6 +10637,7 @@ class PDFViewer {
|
||||
this.refresh();
|
||||
}, drawingDelay);
|
||||
}
|
||||
const previousScale = this._currentScale;
|
||||
this._currentScale = newScale;
|
||||
if (!noScroll) {
|
||||
let page = this._currentPageNumber,
|
||||
@ -10674,6 +10653,12 @@ class PDFViewer {
|
||||
destArray: dest,
|
||||
allowNegativeOffset: true
|
||||
});
|
||||
if (Array.isArray(origin)) {
|
||||
const scaleDiff = newScale / previousScale - 1;
|
||||
const [top, left] = this.containerTopLeft;
|
||||
this.container.scrollLeft += (origin[0] - left) * scaleDiff;
|
||||
this.container.scrollTop += (origin[1] - top) * scaleDiff;
|
||||
}
|
||||
}
|
||||
this.eventBus.dispatch("scalechanging", {
|
||||
source: this,
|
||||
@ -11281,48 +11266,46 @@ class PDFViewer {
|
||||
this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
|
||||
return true;
|
||||
}
|
||||
increaseScale({
|
||||
updateScale({
|
||||
drawingDelay,
|
||||
scaleFactor,
|
||||
steps
|
||||
} = {}) {
|
||||
scaleFactor = null,
|
||||
steps = null,
|
||||
origin
|
||||
}) {
|
||||
if (steps === null && scaleFactor === null) {
|
||||
throw new Error("Invalid updateScale options: either `steps` or `scaleFactor` must be provided.");
|
||||
}
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
let newScale = this._currentScale;
|
||||
if (scaleFactor > 1) {
|
||||
if (scaleFactor > 0 && scaleFactor !== 1) {
|
||||
newScale = Math.round(newScale * scaleFactor * 100) / 100;
|
||||
} else {
|
||||
steps ??= 1;
|
||||
} else if (steps) {
|
||||
const delta = steps > 0 ? DEFAULT_SCALE_DELTA : 1 / DEFAULT_SCALE_DELTA;
|
||||
const round = steps > 0 ? Math.ceil : Math.floor;
|
||||
steps = Math.abs(steps);
|
||||
do {
|
||||
newScale = Math.ceil((newScale * DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
|
||||
} while (--steps > 0 && newScale < MAX_SCALE);
|
||||
newScale = round((newScale * delta).toFixed(2) * 10) / 10;
|
||||
} while (--steps > 0);
|
||||
}
|
||||
this.#setScale(Math.min(MAX_SCALE, newScale), {
|
||||
newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, newScale));
|
||||
this.#setScale(newScale, {
|
||||
noScroll: false,
|
||||
drawingDelay
|
||||
drawingDelay,
|
||||
origin
|
||||
});
|
||||
}
|
||||
decreaseScale({
|
||||
drawingDelay,
|
||||
scaleFactor,
|
||||
steps
|
||||
} = {}) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
increaseScale(options = {}) {
|
||||
this.updateScale({
|
||||
...options,
|
||||
steps: options.steps ?? 1
|
||||
});
|
||||
}
|
||||
let newScale = this._currentScale;
|
||||
if (scaleFactor > 0 && scaleFactor < 1) {
|
||||
newScale = Math.round(newScale * scaleFactor * 100) / 100;
|
||||
} else {
|
||||
steps ??= 1;
|
||||
do {
|
||||
newScale = Math.floor((newScale / DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
|
||||
} while (--steps > 0 && newScale > MIN_SCALE);
|
||||
}
|
||||
this.#setScale(Math.max(MIN_SCALE, newScale), {
|
||||
noScroll: false,
|
||||
drawingDelay
|
||||
decreaseScale(options = {}) {
|
||||
this.updateScale({
|
||||
...options,
|
||||
steps: -(options.steps ?? 1)
|
||||
});
|
||||
}
|
||||
#updateContainerHeightCss(height = this.container.clientHeight) {
|
||||
@ -12465,25 +12448,22 @@ const PDFViewerApplication = {
|
||||
get initializedPromise() {
|
||||
return this._initializedCapability.promise;
|
||||
},
|
||||
zoomIn(steps, scaleFactor) {
|
||||
updateZoom(steps, scaleFactor, origin) {
|
||||
if (this.pdfViewer.isInPresentationMode) {
|
||||
return;
|
||||
}
|
||||
this.pdfViewer.increaseScale({
|
||||
this.pdfViewer.updateScale({
|
||||
drawingDelay: AppOptions.get("defaultZoomDelay"),
|
||||
steps,
|
||||
scaleFactor
|
||||
scaleFactor,
|
||||
origin
|
||||
});
|
||||
},
|
||||
zoomOut(steps, scaleFactor) {
|
||||
if (this.pdfViewer.isInPresentationMode) {
|
||||
return;
|
||||
}
|
||||
this.pdfViewer.decreaseScale({
|
||||
drawingDelay: AppOptions.get("defaultZoomDelay"),
|
||||
steps,
|
||||
scaleFactor
|
||||
});
|
||||
zoomIn() {
|
||||
this.updateZoom(1);
|
||||
},
|
||||
zoomOut() {
|
||||
this.updateZoom(-1);
|
||||
},
|
||||
zoomReset() {
|
||||
if (this.pdfViewer.isInPresentationMode) {
|
||||
@ -13510,17 +13490,6 @@ const PDFViewerApplication = {
|
||||
this[prop] = factor / newFactor;
|
||||
return newFactor;
|
||||
},
|
||||
_centerAtPos(previousScale, x, y) {
|
||||
const {
|
||||
pdfViewer
|
||||
} = this;
|
||||
const scaleDiff = pdfViewer.currentScale / previousScale - 1;
|
||||
if (scaleDiff !== 0) {
|
||||
const [top, left] = pdfViewer.containerTopLeft;
|
||||
pdfViewer.container.scrollLeft += (x - left) * scaleDiff;
|
||||
pdfViewer.container.scrollTop += (y - top) * scaleDiff;
|
||||
}
|
||||
},
|
||||
_unblockDocumentLoadEvent() {
|
||||
document.blockUnblockOnload?.(false);
|
||||
this._unblockDocumentLoadEvent = () => {};
|
||||
@ -13866,21 +13835,15 @@ function webViewerWheel(evt) {
|
||||
let scaleFactor = Math.exp(-evt.deltaY / 100);
|
||||
const isBuiltInMac = false;
|
||||
const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;
|
||||
const origin = [evt.clientX, evt.clientY];
|
||||
if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
|
||||
evt.preventDefault();
|
||||
if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
|
||||
return;
|
||||
}
|
||||
const previousScale = pdfViewer.currentScale;
|
||||
if (isPinchToZoom && supportsPinchToZoom) {
|
||||
scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, "_wheelUnusedFactor");
|
||||
if (scaleFactor < 1) {
|
||||
PDFViewerApplication.zoomOut(null, scaleFactor);
|
||||
} else if (scaleFactor > 1) {
|
||||
PDFViewerApplication.zoomIn(null, scaleFactor);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
scaleFactor = PDFViewerApplication._accumulateFactor(pdfViewer.currentScale, scaleFactor, "_wheelUnusedFactor");
|
||||
PDFViewerApplication.updateZoom(null, scaleFactor, origin);
|
||||
} else {
|
||||
const delta = normalizeWheelEventDirection(evt);
|
||||
let ticks = 0;
|
||||
@ -13894,16 +13857,9 @@ function webViewerWheel(evt) {
|
||||
const PIXELS_PER_LINE_SCALE = 30;
|
||||
ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks");
|
||||
}
|
||||
if (ticks < 0) {
|
||||
PDFViewerApplication.zoomOut(-ticks);
|
||||
} else if (ticks > 0) {
|
||||
PDFViewerApplication.zoomIn(ticks);
|
||||
} else {
|
||||
return;
|
||||
PDFViewerApplication.updateZoom(ticks, null, origin);
|
||||
}
|
||||
}
|
||||
PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY);
|
||||
}
|
||||
}
|
||||
function webViewerTouchStart(evt) {
|
||||
if (PDFViewerApplication.pdfViewer.isInPresentationMode || evt.touches.length < 2) {
|
||||
@ -13988,31 +13944,18 @@ function webViewerTouchMove(evt) {
|
||||
}
|
||||
}
|
||||
evt.preventDefault();
|
||||
const origin = [(page0X + page1X) / 2, (page0Y + page1Y) / 2];
|
||||
const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;
|
||||
const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;
|
||||
const previousScale = pdfViewer.currentScale;
|
||||
if (supportsPinchToZoom) {
|
||||
const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, "_touchUnusedFactor");
|
||||
if (newScaleFactor < 1) {
|
||||
PDFViewerApplication.zoomOut(null, newScaleFactor);
|
||||
} else if (newScaleFactor > 1) {
|
||||
PDFViewerApplication.zoomIn(null, newScaleFactor);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
const newScaleFactor = PDFViewerApplication._accumulateFactor(pdfViewer.currentScale, distance / pDistance, "_touchUnusedFactor");
|
||||
PDFViewerApplication.updateZoom(null, newScaleFactor, origin);
|
||||
} else {
|
||||
const PIXELS_PER_LINE_SCALE = 30;
|
||||
const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks");
|
||||
if (ticks < 0) {
|
||||
PDFViewerApplication.zoomOut(-ticks);
|
||||
} else if (ticks > 0) {
|
||||
PDFViewerApplication.zoomIn(ticks);
|
||||
} else {
|
||||
return;
|
||||
PDFViewerApplication.updateZoom(ticks, null, origin);
|
||||
}
|
||||
}
|
||||
PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2);
|
||||
}
|
||||
function webViewerTouchEnd(evt) {
|
||||
if (!PDFViewerApplication._touchInfo) {
|
||||
return;
|
||||
@ -14329,8 +14272,8 @@ function webViewerReportTelemetry({
|
||||
|
||||
|
||||
|
||||
const pdfjsVersion = "4.3.118";
|
||||
const pdfjsBuild = "17e09e547";
|
||||
const pdfjsVersion = "4.3.136";
|
||||
const pdfjsBuild = "0cec64437";
|
||||
const AppConstants = {
|
||||
LinkTarget: LinkTarget,
|
||||
RenderingStates: RenderingStates,
|
||||
@ -14465,7 +14408,7 @@ function getViewerConfiguration() {
|
||||
editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"),
|
||||
editorHighlightShowAll: document.getElementById("editorHighlightShowAll")
|
||||
},
|
||||
printContainer: document.getElementById("printContainer"),
|
||||
printContainer: document.getElementById("printContainer")
|
||||
};
|
||||
}
|
||||
function webViewerLoad() {
|
||||
|
12
src/main/resources/static/pdfjs/pdf.mjs
vendored
@ -10256,7 +10256,6 @@ class TextLayer {
|
||||
this.#pageWidth = pageWidth;
|
||||
this.#pageHeight = pageHeight;
|
||||
setLayerDimensions(container, viewport);
|
||||
TextLayer.#pendingTextLayers.add(this);
|
||||
this.#capability.promise.catch(() => {}).then(() => {
|
||||
TextLayer.#pendingTextLayers.delete(this);
|
||||
this.#layoutTextParams = null;
|
||||
@ -10280,6 +10279,7 @@ class TextLayer {
|
||||
}, this.#capability.reject);
|
||||
};
|
||||
this.#reader = this.#textContentSource.getReader();
|
||||
TextLayer.#pendingTextLayers.add(this);
|
||||
pump();
|
||||
return this.#capability.promise;
|
||||
}
|
||||
@ -10724,7 +10724,7 @@ function getDocument(src) {
|
||||
}
|
||||
const docParams = {
|
||||
docId,
|
||||
apiVersion: "4.3.118",
|
||||
apiVersion: "4.3.136",
|
||||
data,
|
||||
password,
|
||||
disableAutoFetch,
|
||||
@ -12491,8 +12491,8 @@ class InternalRenderTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
const version = "4.3.118";
|
||||
const build = "17e09e547";
|
||||
const version = "4.3.136";
|
||||
const build = "0cec64437";
|
||||
|
||||
;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
|
||||
function makeColorComp(n) {
|
||||
@ -19367,8 +19367,8 @@ class DrawLayer {
|
||||
|
||||
|
||||
|
||||
const pdfjsVersion = "4.3.118";
|
||||
const pdfjsBuild = "17e09e547";
|
||||
const pdfjsVersion = "4.3.136";
|
||||
const pdfjsBuild = "0cec64437";
|
||||
|
||||
var __webpack_exports__AbortException = __webpack_exports__.AbortException;
|
||||
var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;
|
||||
|
2
src/main/resources/static/pdfjs/pdf.mjs.map
vendored
42
src/main/resources/static/pdfjs/pdf.worker.mjs
vendored
@ -8930,11 +8930,10 @@ class Parser {
|
||||
if (this.tryShift() && isCmd(this.buf2, "endstream")) {
|
||||
this.shift();
|
||||
} else {
|
||||
const actualLength = this.#findStreamLength(startPos);
|
||||
if (actualLength < 0) {
|
||||
length = this.#findStreamLength(startPos);
|
||||
if (length < 0) {
|
||||
throw new FormatError("Missing endstream command.");
|
||||
}
|
||||
length = actualLength;
|
||||
lexer.nextChar();
|
||||
this.shift();
|
||||
this.shift();
|
||||
@ -29696,7 +29695,7 @@ class PartialEvaluator {
|
||||
this.globalImageCache = globalImageCache;
|
||||
this.systemFontCache = systemFontCache;
|
||||
this.options = options || DefaultPartialEvaluatorOptions;
|
||||
this.parsingType3Font = false;
|
||||
this.type3FontRefs = null;
|
||||
this._regionalImageCache = new RegionalImageCache();
|
||||
this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this);
|
||||
ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes);
|
||||
@ -29708,6 +29707,9 @@ class PartialEvaluator {
|
||||
});
|
||||
return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory);
|
||||
}
|
||||
get parsingType3Font() {
|
||||
return !!this.type3FontRefs;
|
||||
}
|
||||
clone(newOptions = null) {
|
||||
const newEvaluator = Object.create(this);
|
||||
newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions);
|
||||
@ -30396,7 +30398,7 @@ class PartialEvaluator {
|
||||
}
|
||||
}
|
||||
if (fontRef) {
|
||||
if (this.parsingType3Font && this.type3FontRefs.has(fontRef)) {
|
||||
if (this.type3FontRefs?.has(fontRef)) {
|
||||
return errorFont();
|
||||
}
|
||||
if (this.fontCache.has(fontRef)) {
|
||||
@ -32831,7 +32833,6 @@ class TranslatedFont {
|
||||
const type3Evaluator = evaluator.clone({
|
||||
ignoreErrors: false
|
||||
});
|
||||
type3Evaluator.parsingType3Font = true;
|
||||
const type3FontRefs = new RefSet(evaluator.type3FontRefs);
|
||||
if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) {
|
||||
type3FontRefs.put(this.dict.objId);
|
||||
@ -53722,19 +53723,18 @@ class Page {
|
||||
systemFontCache: this.systemFontCache,
|
||||
options: this.evaluatorOptions
|
||||
});
|
||||
const newAnnotationsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null;
|
||||
let deletedAnnotations = null;
|
||||
const newAnnotsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null;
|
||||
const newAnnots = newAnnotsByPage?.get(this.pageIndex);
|
||||
let newAnnotationsPromise = Promise.resolve(null);
|
||||
if (newAnnotationsByPage) {
|
||||
const newAnnotations = newAnnotationsByPage.get(this.pageIndex);
|
||||
if (newAnnotations) {
|
||||
let deletedAnnotations = null;
|
||||
if (newAnnots) {
|
||||
const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals");
|
||||
let imagePromises;
|
||||
const missingBitmaps = new Set();
|
||||
for (const {
|
||||
bitmapId,
|
||||
bitmap
|
||||
} of newAnnotations) {
|
||||
} of newAnnots) {
|
||||
if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) {
|
||||
missingBitmaps.add(bitmapId);
|
||||
}
|
||||
@ -53743,7 +53743,7 @@ class Page {
|
||||
isOffscreenCanvasSupported
|
||||
} = this.evaluatorOptions;
|
||||
if (missingBitmaps.size > 0) {
|
||||
const annotationWithBitmaps = newAnnotations.slice();
|
||||
const annotationWithBitmaps = newAnnots.slice();
|
||||
for (const [key, annotation] of annotationStorage) {
|
||||
if (!key.startsWith(AnnotationEditorPrefix)) {
|
||||
continue;
|
||||
@ -53754,20 +53754,18 @@ class Page {
|
||||
}
|
||||
imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported);
|
||||
} else {
|
||||
imagePromises = AnnotationFactory.generateImages(newAnnotations, this.xref, isOffscreenCanvasSupported);
|
||||
imagePromises = AnnotationFactory.generateImages(newAnnots, this.xref, isOffscreenCanvasSupported);
|
||||
}
|
||||
deletedAnnotations = new RefSet();
|
||||
this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);
|
||||
this.#replaceIdByRef(newAnnots, deletedAnnotations, null);
|
||||
newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => {
|
||||
if (!annotationGlobals) {
|
||||
return null;
|
||||
}
|
||||
return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnotations, imagePromises);
|
||||
return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnots, imagePromises);
|
||||
});
|
||||
}
|
||||
}
|
||||
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
||||
const pageListPromise = dataPromises.then(([contentStream]) => {
|
||||
const pageListPromise = Promise.all([contentStreamPromise, resourcesPromise]).then(([contentStream]) => {
|
||||
const opList = new OperatorList(intent, sink);
|
||||
handler.send("StartRenderPage", {
|
||||
transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet),
|
||||
@ -55532,7 +55530,7 @@ class WorkerMessageHandler {
|
||||
docId,
|
||||
apiVersion
|
||||
} = docParams;
|
||||
const workerVersion = "4.3.118";
|
||||
const workerVersion = "4.3.136";
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
@ -56102,8 +56100,8 @@ if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" &&
|
||||
|
||||
;// CONCATENATED MODULE: ./src/pdf.worker.js
|
||||
|
||||
const pdfjsVersion = "4.3.118";
|
||||
const pdfjsBuild = "17e09e547";
|
||||
const pdfjsVersion = "4.3.136";
|
||||
const pdfjsBuild = "0cec64437";
|
||||
|
||||
var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;
|
||||
export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };
|
||||
|
@ -12,7 +12,7 @@
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9">
|
||||
<div class="col-md-9 bg-card">
|
||||
|
||||
<!-- User Settings Title -->
|
||||
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
|
||||
@ -33,15 +33,15 @@
|
||||
<!-- Change Username Form -->
|
||||
<th:block th:if="${!oAuth2Login}">
|
||||
<h4 th:text="#{account.changeUsername}">Change Username?</h4>
|
||||
<form id="formsavechangeusername" class="bg-card mt-4 mb-4" action="api/v1/user/change-username" method="post">
|
||||
<form id="formsavechangeusername" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-username'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="newUsername" th:text="#{account.newUsername}">Change Username</label>
|
||||
<input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}">
|
||||
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{password}">
|
||||
<label for="currentPasswordChangeUsername" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="currentPasswordChangeUsername" id="currentPasswordChangeUsername" th:placeholder="#{password}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
|
||||
@ -52,7 +52,7 @@
|
||||
<!-- Change Password Form -->
|
||||
<th:block th:if="${!oAuth2Login}">
|
||||
<h4 th:text="#{account.changePassword}">Change Password?</h4>
|
||||
<form id="formsavechangepassword" class="bg-card mt-4 mb-4" action="api/v1/user/change-password" method="post">
|
||||
<form id="formsavechangepassword" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-password'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{account.oldPassword}">
|
||||
@ -66,6 +66,7 @@
|
||||
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span id="confirmPasswordError" style="display: none;" th:text="#{confirmPasswordErrorMessage}">New Password and Confirm New Password must match.</span>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -103,6 +104,9 @@
|
||||
return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value);
|
||||
}, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format");
|
||||
$(document).ready(function() {
|
||||
$.validator.addMethod("passwordMatch", function(value, element) {
|
||||
return $('#newPassword').val() === $('#confirmNewPassword').val();
|
||||
}, /*[[#{confirmPasswordErrorMessage}]]*/ "New Password and Confirm New Password must match.");
|
||||
$('#formsavechangepassword').validate({
|
||||
rules: {
|
||||
currentPassword: {
|
||||
@ -112,17 +116,31 @@
|
||||
required: true
|
||||
},
|
||||
confirmNewPassword: {
|
||||
required: true
|
||||
required: true,
|
||||
passwordMatch: true
|
||||
},
|
||||
errorPlacement: function(error, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").text(error.text()).show();
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
success: function(label, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#formsavechangeusername').validate({
|
||||
rules: {
|
||||
newUsername: {
|
||||
required: true,
|
||||
usernamePattern: true
|
||||
},
|
||||
currentPassword: {
|
||||
currentPasswordChangeUsername: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
@ -144,32 +162,10 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#formsavechangepassword').on('submit', function(event) {
|
||||
var newPassword = $('#newPassword').val();
|
||||
var confirmNewPassword = $('#confirmNewPassword').val();
|
||||
|
||||
if (newPassword !== confirmNewPassword) {
|
||||
alert('New Password and Confirm New Password must match.');
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
$('#newUsername').on('input', function() {
|
||||
var usernameInput = $(this);
|
||||
var isValid = usernameInput[0].checkValidity();
|
||||
var errorSpan = $('#usernameError');
|
||||
|
||||
if (isValid) {
|
||||
usernameInput.removeClass('invalid').addClass('valid');
|
||||
errorSpan.hide();
|
||||
} else {
|
||||
usernameInput.removeClass('valid').addClass('invalid');
|
||||
errorSpan.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
<script th:inline="javascript">
|
||||
function copyToClipboard() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
apiKeyElement.select();
|
||||
@ -192,8 +188,12 @@
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
showApiKey();
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/get-api-key', { method: 'POST' });
|
||||
/*<![CDATA[*/
|
||||
const urlGetApiKey = /*[[@{/api/v1/user/get-api-key}]]*/ "/api/v1/user/get-api-key";
|
||||
/*]]>*/
|
||||
let response = await fetch(urlGetApiKey, { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
@ -207,7 +207,10 @@
|
||||
|
||||
async function refreshApiKey() {
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/update-api-key', { method: 'POST' });
|
||||
/*<![CDATA[*/
|
||||
const urlUpdateApiKey = /*[[@{/api/v1/user/update-api-key}]]*/ "/api/v1/user/update-api-key";
|
||||
/*]]>*/
|
||||
let response = await fetch(urlUpdateApiKey, { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
@ -229,27 +232,13 @@
|
||||
if (apiKey && apiKey.trim().length > 0) {
|
||||
apiKeyElement.value = apiKey;
|
||||
showBtn.disabled = false;
|
||||
copyBtn.disabled = true;
|
||||
copyBtn.disabled = false;
|
||||
} else {
|
||||
apiKeyElement.value = "";
|
||||
showBtn.disabled = true;
|
||||
copyBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const form = document.querySelector('form[action="api/v1/user/change-password"]');
|
||||
|
||||
form.addEventListener('submit', function(event) {
|
||||
const newPassword = document.getElementById('newPassword').value;
|
||||
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
|
||||
|
||||
if (newPassword !== confirmNewPassword) {
|
||||
alert('New Password and Confirm New Password must match.');
|
||||
event.preventDefault(); // Prevent form submission
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
|
||||
@ -315,9 +304,12 @@
|
||||
});
|
||||
|
||||
document.getElementById('syncToAccount').addEventListener('click', function() {
|
||||
/*<![CDATA[*/
|
||||
const urlUpdateUserSettings = /*[[@{/api/v1/user/updateUserSettings}]]*/ "/api/v1/user/updateUserSettings";
|
||||
/*]]>*/
|
||||
let form = document.createElement("form");
|
||||
form.method = "POST";
|
||||
form.action = "api/v1/user/updateUserSettings"; // Your endpoint URL
|
||||
form.action = urlUpdateUserSettings; // Your endpoint URL
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
|
@ -16,6 +16,16 @@
|
||||
|
||||
<!-- User Settings Title -->
|
||||
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>
|
||||
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}">
|
||||
<span class="material-symbols-rounded">person_add</span>
|
||||
<span th:text="#{adminUserSettings.addUser}">Add New User</span>
|
||||
</a>
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#changeUserRoleModal" class="btn btn-outline-info" th:title="#{adminUserSettings.changeUserRole}">
|
||||
<span class="material-symbols-rounded">edit</span>
|
||||
<span th:text="#{adminUserSettings.changeUserRole}">Change User's Role</span>
|
||||
</a>
|
||||
</div>
|
||||
<div th:if="${deleteMessage}" class="alert alert-danger">
|
||||
<span th:text="#{${deleteMessage}}">Message</span>
|
||||
</div>
|
||||
@ -30,55 +40,47 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="user : ${users}">
|
||||
<td th:text="${user.username}"></td>
|
||||
<td th:text="#{${user.roleName}}"></td>
|
||||
<td>
|
||||
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post">
|
||||
<button class="btn btn-danger" type="submit" th:text="#{delete}">Delete</button>
|
||||
<td style="align-content: center;" th:text="${user.username}"></td>
|
||||
<td style="align-content: center;" th:text="#{${user.roleName}}"></td>
|
||||
<td style="align-content: center;">
|
||||
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()">
|
||||
<button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button>
|
||||
</form>
|
||||
<script th:inline="javascript">
|
||||
const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
|
||||
function confirmDelete() {
|
||||
return confirm(confirm_text);
|
||||
}
|
||||
</script>
|
||||
<a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a>
|
||||
</td>
|
||||
<td th:text="${user.authenticationType}"></td>
|
||||
<td style="align-content: center;" th:text="${user.authenticationType}"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 th:text="#{adminUserSettings.addUser}">Add New User</h2>
|
||||
<div th:if="${addMessage}" class="alert alert-danger">
|
||||
<span th:text="#{${addMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
|
||||
<form id="formsaveuser" th:action="@{/api/v1/user/admin/saveUser}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" th:text="#{username}">Username</label>
|
||||
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
|
||||
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
|
||||
<select name="role" class="form-control" required>
|
||||
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
|
||||
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="forceChange" name="forceChange">
|
||||
<label class="form-check-label" for="forceChange" th:text="#{adminUserSettings.forceChange}">Force user to change username/password on login</label>
|
||||
</div>
|
||||
|
||||
<!-- Add other fields as required -->
|
||||
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
|
||||
</form>
|
||||
<hr />
|
||||
<!-- change User role Modal start -->
|
||||
<div class="modal fade" id="changeUserRoleModal" tabindex="-1" aria-labelledby="changeUserRoleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 th:text="#{adminUserSettings.changeUserRole}">Change User's Role</h2>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span class="material-symbols-rounded">
|
||||
close
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{downgradeCurrentUserLongMessage}" th:text="#{help}">Help</button>
|
||||
<div th:if="${changeMessage}" class="alert alert-danger">
|
||||
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
<form th:action="@{/api/v1/user/admin/changeRole}" method="post">
|
||||
<form th:action="@{'/api/v1/user/admin/changeRole'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" th:text="#{username}">Username</label>
|
||||
<select name="username" class="form-control" required>
|
||||
@ -98,9 +100,59 @@
|
||||
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- change User role Modal end -->
|
||||
|
||||
<!-- Add User Modal start -->
|
||||
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="addUserModalLabel" th:text="#{adminUserSettings.addUser}">Add New User</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span class="material-symbols-rounded">
|
||||
close
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div th:if="${addMessage}" class="alert alert-danger">
|
||||
<span th:text="#{${addMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
|
||||
<form id="formsaveuser" th:action="@{'/api/v1/user/admin/saveUser'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" th:text="#{username}">Username</label>
|
||||
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
|
||||
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
|
||||
<select name="role" class="form-control" required>
|
||||
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
|
||||
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="forceChange" name="forceChange">
|
||||
<label class="form-check-label" for="forceChange" th:text="#{adminUserSettings.forceChange}">Force user to change username/password on login</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add User Modal end -->
|
||||
|
||||
<script th:inline="javascript">
|
||||
jQuery.validator.addMethod("usernamePattern", function(value, element) {
|
||||
return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value);
|
||||
@ -154,5 +206,27 @@
|
||||
</script>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
<div th:if="${oAuth2Enabled}" class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editUserModalLabel" th:text="#{login.ssoSignIn}"></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span class="material-symbols-rounded">
|
||||
close
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3" th:each="provider : ${providerlist}">
|
||||
<a th:href="@{|/oauth2/authorization/${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">OpenID Connect</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" th:text="#{close}"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -27,7 +27,7 @@
|
||||
|
||||
<!-- Change Username Form -->
|
||||
<h4 th:text="#{changeCreds.changePassword}">Change password</h4>
|
||||
<form action="api/v1/user/change-password-on-login" method="post">
|
||||
<form action="api/v1/user/change-password-on-login" method="post" id="formsavechangecreds">
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{changeCreds.oldPassword}">Old Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{changeCreds.oldPassword}">
|
||||
@ -41,20 +41,39 @@
|
||||
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span id="confirmPasswordError" style="display: none;" th:text="#{confirmPasswordErrorMessage}">New Password and Confirm New Password must match.</span>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{changeCreds.submit}">Change credentials!</button>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const form = document.querySelector('form[action="api/v1/user/change-password-on-login"]');
|
||||
|
||||
form.addEventListener('submit', function(event) {
|
||||
const newPassword = document.getElementById('newPassword').value;
|
||||
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
|
||||
|
||||
if (newPassword !== confirmNewPassword) {
|
||||
alert('New Password and Confirm New Password must match.');
|
||||
event.preventDefault(); // Prevent form submission
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
$.validator.addMethod("passwordMatch", function(value, element) {
|
||||
return $('#newPassword').val() === $('#confirmNewPassword').val();
|
||||
}, /*[[#{confirmPasswordErrorMessage}]]*/ "New Password and Confirm New Password must match.");
|
||||
$('#formsavechangecreds').validate({
|
||||
rules: {
|
||||
currentPassword: {
|
||||
required: true
|
||||
},
|
||||
newPassword: {
|
||||
required: true
|
||||
},
|
||||
confirmNewPassword: {
|
||||
required: true,
|
||||
passwordMatch: true
|
||||
},
|
||||
errorPlacement: function(error, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").text(error.text()).show();
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
success: function(label, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -12,7 +12,7 @@
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="mb-3 bg-card">
|
||||
<div class="col-md-6 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon convert">html</span>
|
||||
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>
|
||||
|
@ -403,7 +403,7 @@
|
||||
|
||||
<a href="swagger-ui/index.html" class="btn btn-sm btn-outline-primary mx-1" role="button"
|
||||
target="_blank">API</a>
|
||||
<a th:if="${@shouldShow}" href="https://github.com/Stirling-Tools/Stirling-PDF/releases"
|
||||
<a href="https://github.com/Stirling-Tools/Stirling-PDF/releases"
|
||||
class="btn btn-sm btn-outline-primary mx-1" id="update-btn" th:utext="#{settings.update}" role="button"
|
||||
target="_blank"></a>
|
||||
</div>
|
||||
|
@ -44,7 +44,6 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', toolIcon='family_history', tags=#{pipeline.tags}, toolGroup='advance')}">
|
||||
</div>
|
||||
|
@ -19,9 +19,13 @@
|
||||
</div>
|
||||
<form action="api/v1/general/merge-pdfs" method="post" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label th:text="#{multiPdfDropPrompt}"></label>
|
||||
<label th:text="#{multiPdfDropPrompt}" for="fileInput-input"></label>
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=true, accept='application/pdf')}"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="checkbox" name="removeCertSign" id="removeCertSign">
|
||||
<label for="removeCertSign" th:text="#{merge.removeCertSign}">Remove digital signature in the merged file?</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<ul id="selectedFiles" class="list-group"></ul>
|
||||
</div>
|
||||
|
@ -16,6 +16,7 @@
|
||||
/>
|
||||
<script th:inline="javascript">
|
||||
const saveSettings = /*[[#{pipelineOptions.saveSettings}]]*/ "";
|
||||
const deletePipelineText = /*[[#{pipeline.pipeline.deletePrompt}]]*/ "Are you sure you want to delete pipeline";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@ -92,7 +93,7 @@
|
||||
|
||||
<!-- The Modal -->
|
||||
<div class="modal" id="pipelineSettingsModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content dark-card">
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header">
|
||||
@ -158,6 +159,12 @@
|
||||
|
||||
<!-- Modal footer -->
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
id="deletePipelineBtn"
|
||||
class="btn btn-danger"
|
||||
th:text="#{delete}"
|
||||
></button>
|
||||
|
||||
<button
|
||||
id="saveBrowserPipelineBtn"
|
||||
class="btn btn-success"
|
||||
|
@ -20,23 +20,23 @@
|
||||
<div class="mb-3">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<div class="form-check ms-3">
|
||||
<input type="checkbox" id="removeJavaScript" name="removeJavaScript" checked>
|
||||
<label for="removeJavaScript" th:text="#{sanitizePDF.selectText.1}"></label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<div class="form-check ms-3">
|
||||
<input type="checkbox" id="removeEmbeddedFiles" name="removeEmbeddedFiles" checked>
|
||||
<label for="removeEmbeddedFiles" th:text="#{sanitizePDF.selectText.2}"></label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<div class="form-check ms-3">
|
||||
<input type="checkbox" id="removeMetadata" name="removeMetadata" checked>
|
||||
<label for="removeMetadata" th:text="#{sanitizePDF.selectText.3}"></label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<div class="form-check ms-3">
|
||||
<input type="checkbox" id="removeLinks" name="removeLinks">
|
||||
<label for="removeLinks" th:text="#{sanitizePDF.selectText.4}"></label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<div class="form-check ms-3">
|
||||
<input type="checkbox" id="removeFonts" name="removeFonts">
|
||||
<label for="removeFonts" th:text="#{sanitizePDF.selectText.5}"></label>
|
||||
</div>
|
||||
|
@ -461,8 +461,8 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
<button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="pdfjs-document-properties-close-button">Close</span></button>
|
||||
</div>
|
||||
</dialog>
|
||||
<dialog id="altTextDialog" aria-labelledby="dialogLabel" aria-describedby="dialogDescription">
|
||||
<div id="altTextContainer">
|
||||
<dialog class="dialog altText" id="altTextDialog" aria-labelledby="dialogLabel" aria-describedby="dialogDescription">
|
||||
<div id="altTextContainer" class="mainContainer">
|
||||
<div id="overallDescription">
|
||||
<span id="dialogLabel" data-l10n-id="pdfjs-editor-alt-text-dialog-label" class="title">Choose an option</span>
|
||||
<span id="dialogDescription" data-l10n-id="pdfjs-editor-alt-text-dialog-description">
|
||||
@ -499,8 +499,8 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
</div>
|
||||
</div>
|
||||
<div id="buttons">
|
||||
<button id="altTextCancel" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-cancel-button">Cancel</span></button>
|
||||
<button id="altTextSave" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-save-button">Save</span></button>
|
||||
<button id="altTextCancel" class="secondaryButton" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-cancel-button">Cancel</span></button>
|
||||
<button id="altTextSave" class="primaryButton" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-save-button">Save</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
@ -0,0 +1,45 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
public class ErrorUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testExceptionToModel() {
|
||||
// Create a mock Model
|
||||
Model model = new org.springframework.ui.ExtendedModelMap();
|
||||
|
||||
// Create a test exception
|
||||
Exception ex = new Exception("Test Exception");
|
||||
|
||||
// Call the method under test
|
||||
Model resultModel = ErrorUtils.exceptionToModel(model, ex);
|
||||
|
||||
// Verify the result
|
||||
assertNotNull(resultModel);
|
||||
assertEquals("Test Exception", resultModel.getAttribute("errorMessage"));
|
||||
assertNotNull(resultModel.getAttribute("stackTrace"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionToModelView() {
|
||||
// Create a mock Model
|
||||
Model model = new org.springframework.ui.ExtendedModelMap();
|
||||
|
||||
// Create a test exception
|
||||
Exception ex = new Exception("Test Exception");
|
||||
|
||||
// Call the method under test
|
||||
ModelAndView modelAndView = ErrorUtils.exceptionToModelView(model, ex);
|
||||
|
||||
// Verify the result
|
||||
assertNotNull(modelAndView);
|
||||
assertEquals("Test Exception", modelAndView.getModel().get("errorMessage"));
|
||||
assertNotNull(modelAndView.getModel().get("stackTrace"));
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
|
||||
|
||||
public class FileToPdfTest {
|
||||
|
||||
@Test
|
||||
public void testConvertHtmlToPdf() {
|
||||
HTMLToPdfRequest request = new HTMLToPdfRequest();
|
||||
byte[] fileBytes = new byte[10]; // Sample file bytes
|
||||
String fileName = "test.html"; // Sample file name
|
||||
boolean htmlFormatsInstalled = true; // Sample boolean value
|
||||
|
||||
// Check if the method throws IOException
|
||||
assertThrows(IOException.class, () -> {
|
||||
FileToPdf.convertHtmlToPdf(request, fileBytes, fileName, htmlFormatsInstalled);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertBookTypeToPdf() {
|
||||
byte[] bytes = new byte[10]; // Sample bytes
|
||||
String originalFilename = "test.epub"; // Sample original filename
|
||||
|
||||
// Check if the method throws IOException
|
||||
assertThrows(IOException.class, () -> {
|
||||
FileToPdf.convertBookTypeToPdf(bytes, originalFilename);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.Color;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ImageProcessingUtilsTest {
|
||||
|
||||
@Test
|
||||
void testConvertColorTypeToGreyscale() {
|
||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
fillImageWithColor(sourceImage, Color.RED);
|
||||
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
|
||||
|
||||
assertNotNull(convertedImage);
|
||||
assertEquals(BufferedImage.TYPE_BYTE_GRAY, convertedImage.getType());
|
||||
assertEquals(sourceImage.getWidth(), convertedImage.getWidth());
|
||||
assertEquals(sourceImage.getHeight(), convertedImage.getHeight());
|
||||
|
||||
// Check if a pixel is correctly converted to greyscale
|
||||
Color grey = new Color(convertedImage.getRGB(0, 0));
|
||||
assertEquals(grey.getRed(), grey.getGreen());
|
||||
assertEquals(grey.getGreen(), grey.getBlue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConvertColorTypeToBlackWhite() {
|
||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
fillImageWithColor(sourceImage, Color.RED);
|
||||
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
|
||||
|
||||
assertNotNull(convertedImage);
|
||||
assertEquals(BufferedImage.TYPE_BYTE_BINARY, convertedImage.getType());
|
||||
assertEquals(sourceImage.getWidth(), convertedImage.getWidth());
|
||||
assertEquals(sourceImage.getHeight(), convertedImage.getHeight());
|
||||
|
||||
// Check if a pixel is converted correctly (binary image will be either black or white)
|
||||
int rgb = convertedImage.getRGB(0, 0);
|
||||
assertTrue(rgb == Color.BLACK.getRGB() || rgb == Color.WHITE.getRGB());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConvertColorTypeToFullColor() {
|
||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
fillImageWithColor(sourceImage, Color.RED);
|
||||
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
|
||||
|
||||
assertNotNull(convertedImage);
|
||||
assertEquals(sourceImage, convertedImage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConvertColorTypeInvalid() {
|
||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||
fillImageWithColor(sourceImage, Color.RED);
|
||||
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
|
||||
|
||||
assertNotNull(convertedImage);
|
||||
assertEquals(sourceImage, convertedImage);
|
||||
}
|
||||
|
||||
private void fillImageWithColor(BufferedImage image, Color color) {
|
||||
for (int y = 0; y < image.getHeight(); y++) {
|
||||
for (int x = 0; x < image.getWidth(); x++) {
|
||||
image.setRGB(x, y, color.getRGB());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
60
src/test/java/stirling/software/SPDF/utils/PdfUtilsTest.java
Normal file
@ -0,0 +1,60 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import stirling.software.SPDF.model.PdfMetadata;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
|
||||
public class PdfUtilsTest {
|
||||
|
||||
@Test
|
||||
void testTextToPageSize() {
|
||||
assertEquals(PDRectangle.A4, PdfUtils.textToPageSize("A4"));
|
||||
assertEquals(PDRectangle.LETTER, PdfUtils.textToPageSize("LETTER"));
|
||||
assertThrows(IllegalArgumentException.class, () -> PdfUtils.textToPageSize("INVALID"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasImagesOnPage() throws IOException {
|
||||
// Mock a PDPage and its resources
|
||||
PDPage page = Mockito.mock(PDPage.class);
|
||||
PDResources resources = Mockito.mock(PDResources.class);
|
||||
Mockito.when(page.getResources()).thenReturn(resources);
|
||||
|
||||
// Case 1: No images in resources
|
||||
Mockito.when(resources.getXObjectNames()).thenReturn(Collections.emptySet());
|
||||
assertFalse(PdfUtils.hasImagesOnPage(page));
|
||||
|
||||
// Case 2: Resources with an image
|
||||
Set<COSName> xObjectNames = new HashSet<>();
|
||||
COSName cosName = Mockito.mock(COSName.class);
|
||||
xObjectNames.add(cosName);
|
||||
|
||||
PDImageXObject imageXObject = Mockito.mock(PDImageXObject.class);
|
||||
Mockito.when(resources.getXObjectNames()).thenReturn(xObjectNames);
|
||||
Mockito.when(resources.getXObject(cosName)).thenReturn(imageXObject);
|
||||
|
||||
assertTrue(PdfUtils.hasImagesOnPage(page));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractMetadataFromPdf() throws IOException {
|
||||
PDDocument document = Mockito.mock(PDDocument.class);
|
||||
Mockito.when(document.getDocumentInformation()).thenReturn(Mockito.mock(org.apache.pdfbox.pdmodel.PDDocumentInformation.class));
|
||||
PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
|
||||
|
||||
assertNotNull(metadata);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ProcessExecutorTest {
|
||||
|
||||
private ProcessExecutor processExecutor;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
// Initialize the ProcessExecutor instance
|
||||
processExecutor = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunCommandWithOutputHandling() throws IOException, InterruptedException {
|
||||
// Mock the command to execute
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("java");
|
||||
command.add("-version");
|
||||
|
||||
// Execute the command
|
||||
ProcessExecutor.ProcessExecutorResult result = processExecutor.runCommandWithOutputHandling(command);
|
||||
|
||||
// Check the exit code and output messages
|
||||
assertEquals(0, result.getRc());
|
||||
assertNotNull(result.getMessages()); // Check if messages are not null
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunCommandWithOutputHandling_Error() {
|
||||
// Mock the command to execute
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("nonexistent-command");
|
||||
|
||||
// Execute the command and expect an IOException
|
||||
IOException thrown = assertThrows(IOException.class, () -> {
|
||||
processExecutor.runCommandWithOutputHandling(command);
|
||||
});
|
||||
|
||||
// Log the actual error message
|
||||
System.out.println("Caught IOException: " + thrown.getMessage());
|
||||
|
||||
// Check the exception message to ensure it indicates the command was not found
|
||||
String errorMessage = thrown.getMessage();
|
||||
assertTrue(errorMessage.contains("error=2") || errorMessage.contains("No such file or directory"), "Unexpected error message: " + errorMessage);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class PropertyConfigsTest {
|
||||
|
||||
@Test
|
||||
public void testGetBooleanValue_WithKeys() {
|
||||
// Define keys and default value
|
||||
List<String> keys = Arrays.asList("test.key1", "test.key2", "test.key3");
|
||||
boolean defaultValue = false;
|
||||
|
||||
// Set property for one of the keys
|
||||
System.setProperty("test.key2", "true");
|
||||
|
||||
// Call the method under test
|
||||
boolean result = PropertyConfigs.getBooleanValue(keys, defaultValue);
|
||||
|
||||
// Verify the result
|
||||
assertEquals(true, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStringValue_WithKeys() {
|
||||
// Define keys and default value
|
||||
List<String> keys = Arrays.asList("test.key1", "test.key2", "test.key3");
|
||||
String defaultValue = "default";
|
||||
|
||||
// Set property for one of the keys
|
||||
System.setProperty("test.key2", "value");
|
||||
|
||||
// Call the method under test
|
||||
String result = PropertyConfigs.getStringValue(keys, defaultValue);
|
||||
|
||||
// Verify the result
|
||||
assertEquals("value", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBooleanValue_WithKey() {
|
||||
// Define key and default value
|
||||
String key = "test.key";
|
||||
boolean defaultValue = true;
|
||||
|
||||
// Call the method under test
|
||||
boolean result = PropertyConfigs.getBooleanValue(key, defaultValue);
|
||||
|
||||
// Verify the result
|
||||
assertEquals(true, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStringValue_WithKey() {
|
||||
// Define key and default value
|
||||
String key = "test.key";
|
||||
String defaultValue = "default";
|
||||
|
||||
// Call the method under test
|
||||
String result = PropertyConfigs.getStringValue(key, defaultValue);
|
||||
|
||||
// Verify the result
|
||||
assertEquals("default", result);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class RequestUriUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testIsStaticResource() {
|
||||
assertTrue(RequestUriUtils.isStaticResource("/css/styles.css"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/js/script.js"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/images/logo.png"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/public/index.html"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/pdfjs/pdf.worker.js"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/api/v1/info/status"));
|
||||
assertTrue(RequestUriUtils.isStaticResource("/some-path/icon.svg"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/api/v1/users"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/api/v1/orders"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/login"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/register"));
|
||||
assertFalse(RequestUriUtils.isStaticResource("/api/v1/products"));
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import stirling.software.SPDF.SPdfApplication;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SPdfApplicationTest {
|
||||
|
||||
@Mock
|
||||
private Environment env;
|
||||
|
||||
@Mock
|
||||
private ApplicationProperties applicationProperties;
|
||||
|
||||
@InjectMocks
|
||||
private SPdfApplication sPdfApplication;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
sPdfApplication = new SPdfApplication();
|
||||
sPdfApplication.setServerPortStatic("8080");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetServerPortStatic() {
|
||||
sPdfApplication.setServerPortStatic("9090");
|
||||
assertEquals("9090", SPdfApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainApplicationStartup() throws IOException, InterruptedException {
|
||||
// Setup mock environment for the main method
|
||||
Path settingsPath = Paths.get("configs/settings.yml");
|
||||
Path customSettingsPath = Paths.get("configs/custom_settings.yml");
|
||||
|
||||
// Ensure the files do not exist for the test
|
||||
if (Files.exists(settingsPath)) {
|
||||
Files.delete(settingsPath);
|
||||
}
|
||||
if (Files.exists(customSettingsPath)) {
|
||||
Files.delete(customSettingsPath);
|
||||
}
|
||||
|
||||
// Run the main method
|
||||
SPdfApplication.main(new String[]{});
|
||||
|
||||
// Verify that the directories were created
|
||||
assertTrue(Files.exists(Path.of("customFiles/static/")));
|
||||
assertTrue(Files.exists(Path.of("customFiles/templates/")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStaticPort() {
|
||||
assertEquals("8080", SPdfApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNonStaticPort() {
|
||||
assertEquals("8080", sPdfApplication.getNonStaticPort());
|
||||
}
|
||||
}
|
26
src/test/java/stirling/software/SPDF/utils/UrlUtilsTest.java
Normal file
@ -0,0 +1,26 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class UrlUtilsTest {
|
||||
|
||||
@Test
|
||||
void testGetOrigin() {
|
||||
// Mock HttpServletRequest
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getScheme()).thenReturn("http");
|
||||
Mockito.when(request.getServerName()).thenReturn("localhost");
|
||||
Mockito.when(request.getServerPort()).thenReturn(8080);
|
||||
Mockito.when(request.getContextPath()).thenReturn("/myapp");
|
||||
|
||||
// Call the method under test
|
||||
String origin = UrlUtils.getOrigin(request);
|
||||
|
||||
// Assert the result
|
||||
assertEquals("http://localhost:8080/myapp", origin);
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
public class WebResponseUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testBoasToWebResponse() {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
baos.write("Sample PDF content".getBytes());
|
||||
String docName = "sample.pdf";
|
||||
|
||||
ResponseEntity<byte[]> responseEntity = WebResponseUtils.boasToWebResponse(baos, docName);
|
||||
|
||||
assertNotNull(responseEntity);
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
assertNotNull(responseEntity.getBody());
|
||||
|
||||
HttpHeaders headers = responseEntity.getHeaders();
|
||||
assertNotNull(headers);
|
||||
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
|
||||
assertNotNull(headers.getContentDisposition());
|
||||
//assertEquals("attachment; filename=\"sample.pdf\"", headers.getContentDisposition().toString());
|
||||
|
||||
} catch (IOException e) {
|
||||
fail("Exception thrown: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPartFileToWebResponse() {
|
||||
try {
|
||||
byte[] fileContent = "Sample file content".getBytes();
|
||||
MockMultipartFile file = new MockMultipartFile("file", "sample.txt", "text/plain", fileContent);
|
||||
|
||||
ResponseEntity<byte[]> responseEntity = WebResponseUtils.multiPartFileToWebResponse(file);
|
||||
|
||||
assertNotNull(responseEntity);
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
assertNotNull(responseEntity.getBody());
|
||||
|
||||
HttpHeaders headers = responseEntity.getHeaders();
|
||||
assertNotNull(headers);
|
||||
assertEquals(MediaType.TEXT_PLAIN, headers.getContentType());
|
||||
assertNotNull(headers.getContentDisposition());
|
||||
|
||||
} catch (IOException e) {
|
||||
fail("Exception thrown: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesToWebResponse() {
|
||||
try {
|
||||
byte[] bytes = "Sample bytes".getBytes();
|
||||
String docName = "sample.txt";
|
||||
MediaType mediaType = MediaType.TEXT_PLAIN;
|
||||
|
||||
ResponseEntity<byte[]> responseEntity = WebResponseUtils.bytesToWebResponse(bytes, docName, mediaType);
|
||||
|
||||
assertNotNull(responseEntity);
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
assertNotNull(responseEntity.getBody());
|
||||
|
||||
HttpHeaders headers = responseEntity.getHeaders();
|
||||
assertNotNull(headers);
|
||||
assertEquals(MediaType.TEXT_PLAIN, headers.getContentType());
|
||||
assertNotNull(headers.getContentDisposition());
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
fail("Exception thrown: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPdfDocToWebResponse() {
|
||||
try {
|
||||
PDDocument document = new PDDocument();
|
||||
document.addPage(new org.apache.pdfbox.pdmodel.PDPage());
|
||||
String docName = "sample.pdf";
|
||||
|
||||
ResponseEntity<byte[]> responseEntity = WebResponseUtils.pdfDocToWebResponse(document, docName);
|
||||
|
||||
assertNotNull(responseEntity);
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
assertNotNull(responseEntity.getBody());
|
||||
|
||||
HttpHeaders headers = responseEntity.getHeaders();
|
||||
assertNotNull(headers);
|
||||
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
|
||||
assertNotNull(headers.getContentDisposition());
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
fail("Exception thrown: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|