This commit is contained in:
Anthony Stirling 2023-02-09 22:05:51 +00:00
parent dcaddb53ee
commit 6cdccdd248
27 changed files with 873 additions and 903 deletions

View File

@ -31,13 +31,10 @@ public class PdfController {
return "redirect:/"; return "redirect:/";
} }
@GetMapping("/") @GetMapping("/")
public String home(Model model) { public String home(Model model) {
model.addAttribute("currentPage", "home"); model.addAttribute("currentPage", "home");
return "home"; return "home";
} }
} }

View File

@ -49,12 +49,14 @@ public class ConvertImgPDFController {
@PostMapping("/pdf-to-img") @PostMapping("/pdf-to-img")
public ResponseEntity<Resource> convertToImage(@RequestParam("fileInput") MultipartFile file, public ResponseEntity<Resource> convertToImage(@RequestParam("fileInput") MultipartFile file,
@RequestParam("imageFormat") String imageFormat, @RequestParam("imageFormat") String imageFormat, @RequestParam("singleOrMultiple") String singleOrMultiple,
@RequestParam("singleOrMultiple") String singleOrMultiple, @RequestParam("colorType") String colorType, @RequestParam("dpi") String dpi,
@RequestParam("colorType") String colorType) throws IOException { @RequestParam("contrast") String contrast, @RequestParam("brightness") String brightness)
throws IOException {
byte[] pdfBytes = file.getBytes(); byte[] pdfBytes = file.getBytes();
ImageType colorTypeResult = ImageType.RGB; ImageType colorTypeResult = ImageType.RGB;
if("greyscale".equals(colorType)) { if ("greyscale".equals(colorType)) {
colorTypeResult = ImageType.GRAY; colorTypeResult = ImageType.GRAY;
} else if ("blackwhite".equals(colorType)) { } else if ("blackwhite".equals(colorType)) {
colorTypeResult = ImageType.BINARY; colorTypeResult = ImageType.BINARY;
@ -63,7 +65,9 @@ public class ConvertImgPDFController {
boolean singleImage = singleOrMultiple.equals("single"); boolean singleImage = singleOrMultiple.equals("single");
byte[] result = null; byte[] result = null;
try { try {
result = PdfUtils.convertFromPdf(pdfBytes, imageFormat.toLowerCase(), colorTypeResult, singleImage); result = PdfUtils.convertFromPdf(pdfBytes, imageFormat.toLowerCase(), colorTypeResult, singleImage,
Integer.valueOf(dpi), Integer.valueOf(contrast), Integer.valueOf(brightness)); // DPI, contrast,
// brightness
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
@ -71,17 +75,20 @@ public class ConvertImgPDFController {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
if(singleImage) { if (singleImage) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(getMediaType(imageFormat))); headers.setContentType(MediaType.parseMediaType(getMediaType(imageFormat)));
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<Resource> response = new ResponseEntity<>(new ByteArrayResource(result), headers, HttpStatus.OK); ResponseEntity<Resource> response = new ResponseEntity<>(new ByteArrayResource(result), headers,
HttpStatus.OK);
return response; return response;
} else { } else {
ByteArrayResource resource = new ByteArrayResource(result); ByteArrayResource resource = new ByteArrayResource(result);
// return the Resource in the response // return the Resource in the response
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=converted_documents.zip") return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(resource.contentLength()).body(resource); .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=converted_documents.zip")
.contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(resource.contentLength())
.body(resource);
} }
} }

View File

@ -38,20 +38,17 @@ public class MetadataController {
model.addAttribute("currentPage", "change-metadata"); model.addAttribute("currentPage", "change-metadata");
return "security/change-metadata"; return "security/change-metadata";
} }
@PostMapping("/update-metadata") @PostMapping("/update-metadata")
public ResponseEntity<byte[]> metadata( public ResponseEntity<byte[]> metadata(@RequestParam Map<String, String> allRequestParams) throws IOException {
@RequestParam Map<String,String> allRequestParams) throws IOException {
System.out.println("1 allRequestParams.size() = " + allRequestParams.size()); System.out.println("1 allRequestParams.size() = " + allRequestParams.size());
for(Entry entry : allRequestParams.entrySet()) { for (Entry entry : allRequestParams.entrySet()) {
System.out.println("1 key=" + entry.getKey() + ", value=" + entry.getValue()); System.out.println("1 key=" + entry.getKey() + ", value=" + entry.getValue());
} }
return null; return null;
} }
// @PostMapping("/update-metadata") // @PostMapping("/update-metadata")
// public ResponseEntity<byte[]> addWatermark(@RequestParam("fileInput") MultipartFile pdfFile, // public ResponseEntity<byte[]> addWatermark(@RequestParam("fileInput") MultipartFile pdfFile,
// @RequestParam Map<String,String> allRequestParams,HttpServletRequest request, ModelMap model) throws IOException { // @RequestParam Map<String,String> allRequestParams,HttpServletRequest request, ModelMap model) throws IOException {
@ -88,7 +85,6 @@ public class MetadataController {
// return PdfUtils.pdfDocToWebResponse(document, pdfFile.getName() + "_metadata.pdf"); // return PdfUtils.pdfDocToWebResponse(document, pdfFile.getName() + "_metadata.pdf");
// } // }
// // Loop over all pages and remove annotations // // Loop over all pages and remove annotations
// for (PDPage page : document.getPages()) { // for (PDPage page : document.getPages()) {
// page.getAnnotations().clear(); // page.getAnnotations().clear();

View File

@ -2,6 +2,7 @@ package stirling.software.SPDF.utils;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -80,20 +81,27 @@ public class PdfUtils {
} }
} }
public static byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage) throws IOException, Exception { public static byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage,
int DPI, int contrast, int brightness) throws IOException, Exception {
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) { try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) {
PDFRenderer pdfRenderer = new PDFRenderer(document); PDFRenderer pdfRenderer = new PDFRenderer(document);
int pageCount = document.getNumberOfPages(); int pageCount = document.getNumberOfPages();
List<BufferedImage> images = new ArrayList<>(); List<BufferedImage> images = new ArrayList<>();
// Create images of all pages // Create images of all pages
for (int i = 0; i < pageCount; i++) { for (int i = 0; i < pageCount; i++) {
images.add(pdfRenderer.renderImageWithDPI(i, 300, colorType)); BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, colorType);
float scale = contrast + 1f;
float offset = brightness;
RescaleOp rescaleOp = new RescaleOp(scale, offset, null);
BufferedImage dest = rescaleOp.filter(image, null);
images.add(dest);
} }
if (singleImage) { if (singleImage) {
// Combine all images into a single big image // Combine all images into a single big image
BufferedImage combined = new BufferedImage(images.get(0).getWidth() , BufferedImage combined = new BufferedImage(images.get(0).getWidth(),
images.get(0).getHeight()* pageCount, BufferedImage.TYPE_INT_RGB); images.get(0).getHeight() * pageCount, BufferedImage.TYPE_INT_RGB);
Graphics g = combined.getGraphics(); Graphics g = combined.getGraphics();
for (int i = 0; i < images.size(); i++) { for (int i = 0; i < images.size(); i++) {
g.drawImage(images.get(i), 0, i * images.get(0).getHeight(), null); g.drawImage(images.get(i), 0, i * images.get(0).getHeight(), null);
@ -101,7 +109,6 @@ public class PdfUtils {
images = Arrays.asList(combined); images = Arrays.asList(combined);
} }
// Create a ByteArrayOutputStream to save the image(s) to // Create a ByteArrayOutputStream to save the image(s) to
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (singleImage) { if (singleImage) {

View File

@ -8,7 +8,7 @@ imgPrompt=Choose Image
genericSubmit=Submit genericSubmit=Submit
processTimeWarning=Warning: This process can take up to a minute depending on file-size processTimeWarning=Warning: This process can take up to a minute depending on file-size
pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) : pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) :
goToPage=go goToPage=Go
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@ -131,6 +131,8 @@ pdfToImage.colorType=Colour type
pdfToImage.color=Colour pdfToImage.color=Colour
pdfToImage.grey=Greyscale pdfToImage.grey=Greyscale
pdfToImage.blackwhite=Black and White (May lose data!) pdfToImage.blackwhite=Black and White (May lose data!)
pdfToImage.contrast=Contrast Value:
pdfToImage.brightness=Brightness Value:
pdfToImage.submit=Convert pdfToImage.submit=Convert
#addPassword #addPassword

View File

@ -11,7 +11,7 @@ imgPrompt=Choose Image
genericSubmit=Submit genericSubmit=Submit
processTimeWarning=Warning: This process can take up to a minute depending on file-size processTimeWarning=Warning: This process can take up to a minute depending on file-size
pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) : pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) :
goToPage=go goToPage=Go
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############

View File

@ -15,7 +15,7 @@ imgPrompt=Choisir une image
genericSubmit=Soumettre genericSubmit=Soumettre
processTimeWarning=Attention : ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier processTimeWarning=Attention : ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier
pageOrderPrompt=Ordre des pages (Entrez une liste de numéros de page séparés par des virgules) : pageOrderPrompt=Ordre des pages (Entrez une liste de numéros de page séparés par des virgules) :
goToPage=aller goToPage=Aller
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############

View File

@ -9,36 +9,26 @@
<div id="page-container"> <div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{addImage.header}"></h2> <h2 th:text="#{addImage.header}"></h2>
<form method="post" th:action="@{add-image}" enctype="multipart/form-data">
<form method="post" th:action="@{add-image}"
enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="custom-file"> <div class="custom-file">
<input type="file" class="custom-file-input" id="fileInput2" <input type="file" class="custom-file-input" id="fileInput2" name="fileInput2" required>
name="fileInput2" required> <label <label class="custom-file-label" for="fileInput2" th:text="#{imgPrompt}"></label>
class="custom-file-label" for="fileInput2" th:text="#{imgPrompt}"></label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="x">X</label> <input type="number" class="form-control" <label for="x">X</label> <input type="number" class="form-control" id="x" name="x" step="0.01" required>
id="x" name="x" step="0.01" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="y">Y</label> <input type="number" class="form-control" <label for="y">Y</label> <input type="number" class="form-control" id="y" name="y" step="0.01" required>
id="y" name="y" step="0.01" required>
</div> </div>
<button type="submit" class="btn btn-primary" th:text="#{addImage.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{addImage.submit}"></button>
</form> </form>
<th:block th:insert="~{fragments/common :: filelist}"></th:block> <th:block th:insert="~{fragments/common :: filelist}"></th:block>
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,26 +5,22 @@
<th:block th:insert="~{fragments/common :: head(title=#{compress.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{compress.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{compress.header}"></h2> <h2 th:text="#{compress.header}"></h2>
<form action="#" th:action="@{compress-pdf}" <form action="#" th:action="@{compress-pdf}" th:object="${rotateForm}" method="post" enctype="multipart/form-data">
th:object="${rotateForm}" method="post"
enctype="multipart/form-data">
<p th:text="#{processTimeWarning}"></p> <p th:text="#{processTimeWarning}"></p>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="form-group"> <div class="form-group">
<label for="imageCompressionLevel" th:text="#{compress.compressLevel}"></label> <input type="number" class="form-control" <label for="imageCompressionLevel" th:text="#{compress.compressLevel}"></label>
id="imageCompressionLevel" name="imageCompressionLevel" step="1" <input type="number" class="form-control" id="imageCompressionLevel" name="imageCompressionLevel" step="1" value="1" min="1" max="100" required>
value="1" min="1" max="100" required>
</div> </div>
<button type="submit" class="btn btn-primary" th:text="#{compress.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{compress.submit}"></button>
</form> </form>
<th:block th:insert="~{fragments/common :: filelist}"></th:block> <th:block th:insert="~{fragments/common :: filelist}"></th:block>

View File

@ -4,25 +4,22 @@
<th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{imageToPDF.header}"></h2> <h2 th:text="#{imageToPDF.header}"></h2>
<form method="post" enctype="multipart/form-data" <form method="post" enctype="multipart/form-data" th:action="@{img-to-pdf}">
th:action="@{img-to-pdf}">
<div class="custom-file"> <div class="custom-file">
<input type="file" class="custom-file-input" id="fileInput" <input type="file" class="custom-file-input" id="fileInput" name="fileInput" required>
name="fileInput" required> <label <label class="custom-file-label" for="fileInput" th:text="#{imgPrompt}"></label>
class="custom-file-label" for="fileInput" th:text="#{imgPrompt}"></label>
</div> </div>
<br> <br> <br>
<br>
<button type="submit" class="btn btn-primary" th:text="#{imageToPDF.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{imageToPDF.submit}"></button>
</form> </form>

View File

@ -4,23 +4,22 @@
<th:block th:insert="~{fragments/common :: head(title=#{pdfToImage.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{pdfToImage.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{pdfToImage.header}"></h2> <h2 th:text="#{pdfToImage.header}"></h2>
<p th:text="#{processTimeWarning}"></p> <p th:text="#{processTimeWarning}"></p>
<form method="post" enctype="multipart/form-data" <form method="post" enctype="multipart/form-data" th:action="@{pdf-to-img}">
th:action="@{pdf-to-img}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="form-group"> <div class="form-group">
<label th:text="#{pdfToImage.selectText}"></label> <select class="form-control" <label th:text="#{pdfToImage.selectText}"></label>
name="imageFormat"> <select class="form-control" name="imageFormat">
<option value="png">PNG</option> <option value="png">PNG</option>
</select> </select>
</div> </div>
@ -39,6 +38,20 @@
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option> <option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select> </select>
</div> </div>
<div class="form-group">
<label for="dpi" th:text="#{pdfToImage.dpi}"></label>
<input type="number" name="dpi" class="form-control" id="dpi" min="1" max="100" step="1" value="30" required>
</div>
<div class="form-group">
<label for="contrast" th:text="#{pdfToImage.contrast}"></label>
<input type="number" name="contrast" class="form-control" id="contrast" min="-255" max="255" value="0" step="1" required>
</div>
<div class="form-group">
<label for="brightness" th:text="#{pdfToImage.brightness}"></label>
<input type="number" name="brightness" class="form-control" id="brightness" min="-255" max="255" step="1" value="1" required>
</div>
<button type="submit" class="btn btn-primary" th:text="#{pdfToImage.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{pdfToImage.submit}"></button>
</form> </form>
<th:block th:insert="~{fragments/common :: filelist}"></th:block> <th:block th:insert="~{fragments/common :: filelist}"></th:block>

View File

@ -1,29 +1,29 @@
<head th:fragment="head"> <head th:fragment="head">
<!-- Metadata --> <!-- Metadata -->
<meta charset="UTF-8"> <meta charset="UTF-8">
<title th:text="'S-PDF ' + ${title}"></title> <title th:text="'S-PDF ' + ${title}"></title>
<link rel="shortcut icon" href="favicon.svg"> <link rel="shortcut icon" href="favicon.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- jQuery --> <!-- jQuery -->
<script src="js/jquery.min.js"></script> <script src="js/jquery.min.js"></script>
<!-- Bootstrap --> <!-- Bootstrap -->
<script src="js/popper.min.js"></script> <script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script> <script src="js/bootstrap.min.js"></script>
<link rel="stylesheet" href="css/bootstrap.min.css"> <link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-icons.css"> <link rel="stylesheet" href="css/bootstrap-icons.css">
<!-- PDF.js --> <!-- PDF.js -->
<script src="pdfjs/pdf.min.js"></script> <script src="pdfjs/pdf.min.js"></script>
<link href="pdfjs/pdf_viewer.min.css" rel="stylesheet"> <link href="pdfjs/pdf_viewer.min.css" rel="stylesheet">
<!-- Custom --> <!-- Custom -->
<link rel="stylesheet" href="css/general.css"> <link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" th:href="@{css/dark-mode.css}" id="dark-mode-styles"> <link rel="stylesheet" th:href="@{css/dark-mode.css}" id="dark-mode-styles">
<script> <script>
function toggleDarkMode() { function toggleDarkMode() {
var checkbox = document.getElementById("toggle-dark-mode"); var checkbox = document.getElementById("toggle-dark-mode");
var darkModeStyles = document.getElementById("dark-mode-styles"); var darkModeStyles = document.getElementById("dark-mode-styles");

View File

@ -67,9 +67,9 @@
</li> </li>
<input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()"> <input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()">
<a class="nav-link" href="#" for="toggle-dark-mode" th:text="#{navbar.darkmode}"></a> <a class="nav-link" href="#" for="toggle-dark-mode" th:text="#{navbar.darkmode}"></a>
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="languageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" id="languageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="bi bi-globe2"></i> <i class="bi bi-globe2"></i>
@ -78,7 +78,7 @@
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_US">English (US)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_US">English (US)</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English (UK)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English (UK)</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">German</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">Deutsch</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a>
</div> </div>
</li> </li>

View File

@ -5,23 +5,24 @@
<th:block th:insert="~{fragments/common :: head(title='')}"></th:block> <th:block th:insert="~{fragments/common :: head(title='')}"></th:block>
<style> <style>
.features-container { .features-container {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr)); grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
gap: 25px 30px; gap: 25px 30px;
} }
.feature-card {
border: 1px solid rgba(0,0,0,.125); .feature-card {
border: 1px solid rgba(0, 0, 0, .125);
border-radius: 0.25rem; border-radius: 0.25rem;
padding: 1.25rem; padding: 1.25rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
.feature-card .card-text {
.feature-card .card-text {
flex: 1; flex: 1;
} }
</style> </style>
<body> <body>

View File

@ -4,23 +4,21 @@
<th:block th:insert="~{fragments/common :: head(title=#{merge.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{merge.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container" id="dropContainer"> <div class="container" id="dropContainer">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{merge.header}"></h2> <h2 th:text="#{merge.header}"></h2>
<form action="merge-pdfs" method="post" <form action="merge-pdfs" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
<label th:text="#{multiPdfDropPrompt}"></label> <label th:text="#{multiPdfDropPrompt}"></label>
<div class="custom-file"> <div class="custom-file">
<input type="file" class="custom-file-input" id="fileInput" <input type="file" class="custom-file-input" id="fileInput" name="fileInput" multiple required>
name="fileInput" multiple required> <label <label class="custom-file-label" th:text="#{pdfPrompt}"></label>
class="custom-file-label" th:text="#{pdfPrompt}">s</label>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -31,13 +29,10 @@
</div> </div>
</form> </form>
<script> <script>
document document
.getElementById("fileInput") .getElementById(
"fileInput")
.addEventListener( .addEventListener(
"change", "change",
function() { function() {
@ -51,7 +46,8 @@
item.className = "list-group-item d-flex justify-content-between align-items-center"; item.className = "list-group-item d-flex justify-content-between align-items-center";
item.textContent = files[i].name; item.textContent = files[i].name;
item.innerHTML += '<div><button class="btn btn-secondary move-up"><i class="fas fa-arrow-up"></i></button> <button class="btn btn-secondary move-down"><i class="fas fa-arrow-down"></i></button></div>'; item.innerHTML += '<div><button class="btn btn-secondary move-up"><i class="fas fa-arrow-up"></i></button> <button class="btn btn-secondary move-down"><i class="fas fa-arrow-down"></i></button></div>';
list.appendChild(item); list
.appendChild(item);
} }
var moveUpButtons = document var moveUpButtons = document
.querySelectorAll(".move-up"); .querySelectorAll(".move-up");
@ -59,7 +55,8 @@
moveUpButtons[i] moveUpButtons[i]
.addEventListener( .addEventListener(
"click", "click",
function(event) { function(
event) {
event event
.preventDefault(); .preventDefault();
var parent = this.parentNode.parentNode; var parent = this.parentNode.parentNode;
@ -79,7 +76,8 @@
moveDownButtons[i] moveDownButtons[i]
.addEventListener( .addEventListener(
"click", "click",
function(event) { function(
event) {
event event
.preventDefault(); .preventDefault();
var parent = this.parentNode.parentNode; var parent = this.parentNode.parentNode;
@ -119,10 +117,6 @@
} }
}); });
</script> </script>
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,23 +4,21 @@
<th:block th:insert="~{fragments/common :: head(title=#{pdfOrganiser.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{pdfOrganiser.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{pdfOrganiser.header}"></h2> <h2 th:text="#{pdfOrganiser.header}"></h2>
<form th:action="@{rearrange-pages}" method="post" <form th:action="@{rearrange-pages}" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="form-group"> <div class="form-group">
<label for="pageOrder" th:text="#{pageOrderPrompt}"></label> <input type="text" class="form-control" <label for="pageOrder" th:text="#{pageOrderPrompt}"></label>
id="fileInput" name="pageOrder" <input type="text" class="form-control" id="fileInput" name="pageOrder" placeholder="(e.g. 1,3,2 or 4-8,2,10-12)" required>
placeholder="(e.g. 1,3,2 or 4-8,2,10-12)" required>
</div> </div>
<button type="submit" class="btn btn-primary" th:text="#{pdfOrganiser.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{pdfOrganiser.submit}"></button>
</form> </form>

View File

@ -4,23 +4,21 @@
<th:block th:insert="~{fragments/common :: head(title=#{pageRemover.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{pageRemover.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{pageRemover.header}"></h2> <h2 th:text="#{pageRemover.header}"></h2>
<form th:action="@{remove-pages}" method="post" <form th:action="@{remove-pages}" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="form-group"> <div class="form-group">
<label for="pagesToDelete" th:text="#{pageRemover.pagesToDelete}"></label> <input type="text" class="form-control" <label for="pagesToDelete" th:text="#{pageRemover.pagesToDelete}"></label>
id="fileInput" name="pagesToDelete" <input type="text" class="form-control" id="fileInput" name="pagesToDelete" placeholder="(e.g. 1,2,6 or 1-10,15-30)" required>
placeholder="(e.g. 1,2,6 or 1-10,15-30)" required>
</div> </div>
<button type="submit" class="btn btn-primary" th:text="#{pageRemover.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{pageRemover.submit}"></button>
</form> </form>

View File

@ -5,11 +5,11 @@
<th:block th:insert="~{fragments/common :: head(title=#{rotate.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{rotate.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
@ -21,21 +21,21 @@
<div id="editSection" style="display: none"> <div id="editSection" style="display: none">
<div class="previewContainer"> <div class="previewContainer">
<img id="pdf-preview"/> <img id="pdf-preview" />
</div> </div>
<div class="buttonContainer"> <div class="buttonContainer">
<button type="button" class="btn btn-secondary" onclick="rotate(-90)"> <button type="button" class="btn btn-secondary" onclick="rotate(-90)">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/> <path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/> <path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
</svg> </svg>
</button> </button>
<button type="submit" class="btn btn-primary" th:text="#{rotate.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{rotate.submit}"></button>
<button type="button" class="btn btn-secondary" onclick="rotate(90)"> <button type="button" class="btn btn-secondary" onclick="rotate(90)">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/> <path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/> <path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
</svg> </svg>
</button> </button>
</div> </div>
@ -97,35 +97,36 @@
} }
</script> </script>
<style> <style>
#pdf-preview { #pdf-preview {
margin: 0 auto; margin: 0 auto;
display: block; display: block;
max-width: calc(100% - 30px); max-width: calc(100% - 30px);
max-height: calc(100% - 30px); max-height: calc(100% - 30px);
box-shadow: 0 0 4px rgba(100,100,100,.25); box-shadow: 0 0 4px rgba(100, 100, 100, .25);
transition: rotate .3s; transition: rotate .3s;
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
translate: -50% -50%; translate: -50% -50%;
} }
.previewContainer {
.previewContainer {
aspect-ratio: 1; aspect-ratio: 1;
width: 100%; width: 100%;
border: 1px solid rgba(0,0,0,.125); border: 1px solid rgba(0, 0, 0, .125);
border-radius: 0.25rem; border-radius: 0.25rem;
margin: 1rem 0; margin: 1rem 0;
padding: 15px; padding: 15px;
display: block; display: block;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
} }
.buttonContainer { .buttonContainer {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
} }
</style> </style>
</body> </body>
</html> </html>

View File

@ -3,29 +3,26 @@
<th:block th:insert="~{fragments/common :: head(title=#{addPassword.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{addPassword.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{addPassword.header}"></h2> <h2 th:text="#{addPassword.header}"></h2>
<form action="add-password" method="post" <form action="add-password" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
<label th:text="#{addPassword.selectText.1}"></label> <label th:text="#{addPassword.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label th:text="#{addPassword.selectText.2}"></label> <input type="password" <label th:text="#{addPassword.selectText.2}"></label> <input type="password" class="form-control" id="password" name="password" required>
class="form-control" id="password" name="password" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label th:text="#{addPassword.selectText.3}"></label> <select class="form-control" <label th:text="#{addPassword.selectText.3}"></label> <select class="form-control" id="keyLength" name="keyLength">
id="keyLength" name="keyLength">
<option value="40">40</option> <option value="40">40</option>
<option value="128">128</option> <option value="128">128</option>
<option value="256">256</option> <option value="256">256</option>
@ -34,45 +31,36 @@
<div class="form-group"> <div class="form-group">
<label th:text="#{addPassword.selectText.5}"></label> <label th:text="#{addPassword.selectText.5}"></label>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canAssembleDocument" name="canAssembleDocument">
id="canAssembleDocument" name="canAssembleDocument"> <label <label class="form-check-label" for="canAssembleDocument" th:text="#{addPassword.selectText.6}"></label>
class="form-check-label" for="canAssembleDocument" th:text="#{addPassword.selectText.6}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canExtractContent" name="canExtractContent">
id="canExtractContent" name="canExtractContent"> <label <label class="form-check-label" for="canExtractContent" th:text="#{addPassword.selectText.7}"></label>
class="form-check-label" for="canExtractContent" th:text="#{addPassword.selectText.7}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canExtractForAccessibility" name="canExtractForAccessibility">
id="canExtractForAccessibility" <label class="form-check-label" for="canExtractForAccessibility" th:text="#{addPassword.selectText.8}"></label>
name="canExtractForAccessibility"> <label
class="form-check-label" for="canExtractForAccessibility" th:text="#{addPassword.selectText.8}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canFillInForm" name="canFillInForm">
id="canFillInForm" name="canFillInForm"> <label <label class="form-check-label" for="canFillInForm" th:text="#{addPassword.selectText.9}"></label>
class="form-check-label" for="canFillInForm" th:text="#{addPassword.selectText.9}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="canModify" <input class="form-check-input" type="checkbox" id="canModify" name="canModify">
name="canModify"> <label class="form-check-label" <label class="form-check-label" for="canModify" th:text="#{addPassword.selectText.10}"></label>
for="canModify" th:text="#{addPassword.selectText.10}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canModifyAnnotations" name="canModifyAnnotations">
id="canModifyAnnotations" name="canModifyAnnotations"> <label <label class="form-check-label" for="canModifyAnnotations" th:text="#{addPassword.selectText.11}"></label>
class="form-check-label" for="canModifyAnnotations" th:text="#{addPassword.selectText.11}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="canPrint" <input class="form-check-input" type="checkbox" id="canPrint" name="canPrint">
name="canPrint"> <label class="form-check-label" <label class="form-check-label" for="canPrint" th:text="#{addPassword.selectText.12}"></label>
for="canPrint" th:text="#{addPassword.selectText.12}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canPrintFaithful" name="canPrintFaithful">
id="canPrintFaithful" name="canPrintFaithful"> <label <label class="form-check-label" for="canPrintFaithful" th:text="#{addPassword.selectText.13}"></label>
class="form-check-label" for="canPrintFaithful" th:text="#{addPassword.selectText.13}"></label>
</div> </div>
</div> </div>

View File

@ -3,11 +3,11 @@
<th:block th:insert="~{fragments/common :: head(title=#{watermark.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{watermark.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
@ -20,29 +20,29 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="watermarkText" th:text="#{watermark.selectText.2}"></label> <label for="watermarkText" th:text="#{watermark.selectText.2}"></label>
<input type="text" id="watermarkText" name="watermarkText" class="form-control" placeholder="Stirling-PDF" required/> <input type="text" id="watermarkText" name="watermarkText" class="form-control" placeholder="Stirling-PDF" required />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="fontSize" th:text="#{watermark.selectText.3}"></label> <label for="fontSize" th:text="#{watermark.selectText.3}"></label>
<input type="text" id="fontSize" name="fontSize" class="form-control" value="30"/> <input type="text" id="fontSize" name="fontSize" class="form-control" value="30" />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="rotation" th:text="#{watermark.selectText.4}"></label> <label for="rotation" th:text="#{watermark.selectText.4}"></label>
<input type="text" id="rotation" name="rotation" class="form-control" value="45"/> <input type="text" id="rotation" name="rotation" class="form-control" value="45" />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="widthSpacer" th:text="#{watermark.selectText.5}"></label> <label for="widthSpacer" th:text="#{watermark.selectText.5}"></label>
<input type="text" id="widthSpacer" name="widthSpacer" class="form-control" value="50"/> <input type="text" id="widthSpacer" name="widthSpacer" class="form-control" value="50" />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="heightSpacer" th:text="#{watermark.selectText.6}"></label> <label for="heightSpacer" th:text="#{watermark.selectText.6}"></label>
<input type="text" id="heightSpacer" name="heightSpacer" class="form-control" value="50"/> <input type="text" id="heightSpacer" name="heightSpacer" class="form-control" value="50" />
</div> </div>
<div class="form-group text-center"> <div class="form-group text-center">
<input type="submit" th:value="#{watermark.submit}" class="btn btn-primary"/> <input type="submit" th:value="#{watermark.submit}" class="btn btn-primary" />
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,11 +3,11 @@
<th:block th:insert="~{fragments/common :: head(title=#{changeMetadata.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{changeMetadata.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
@ -15,19 +15,17 @@
<form method="post" enctype="multipart/form-data" th:action="@{/update-metadata}"> <form method="post" enctype="multipart/form-data" th:action="@{/update-metadata}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<p class="text-muted">Please select the variables you wish to change</p> <p class="text-muted">Please select the variables you wish to change</p>
<div class="form-group form-check form-check-inline"> <div class="form-group form-check form-check-inline">
<input type="checkbox" class="form-check-input" id="deleteAll"> <input type="checkbox" class="form-check-input" id="deleteAll">
<label class="ml-3" for="deleteAll">Delete all metadata</label> <label class="ml-3" for="deleteAll">Delete all metadata</label>
</div> </div>
<div class="form-group form-check form-check-inline"> <div class="form-group form-check form-check-inline">
<input type="checkbox" class="form-check-input" id="advancedModeCheckbox"> <input type="checkbox" class="form-check-input" id="advancedModeCheckbox">
<label class="ml-3" for="advancedModeCheckbox">Show Advanced Metadata:</label> <label class="ml-3" for="advancedModeCheckbox">Show Advanced Metadata:</label>
</div> </div>
<div class="form-group form-check"> <div class="form-group form-check">
<label class="form-check-label" for="author">Author:</label> <label class="form-check-label" for="author">Author:</label>
@ -73,13 +71,14 @@
<label class="form-check-label" for="trapped">Trapped:</label> <label class="form-check-label" for="trapped">Trapped:</label>
<input type="text" class="form-control" id="trapped"> <input type="text" class="form-control" id="trapped">
</div> </div>
<div id="advancedMetadata" style="display:none;"> <div id="advancedMetadata" style="display: none;">
<p>Other Metadata:</p> <p>Other Metadata:</p>
<div class="form-group" id="otherMetadataEntries"></div> <div class="form-group" id="otherMetadataEntries"></div>
</div> </div>
<div id="customMetadataEntries"></div> <div id="customMetadataEntries"></div>
<button type="button" class="btn btn-secondary" id="addMetadataBtn">Add Custom Metadata Entry</button> <button type="button" class="btn btn-secondary" id="addMetadataBtn">Add Custom Metadata Entry</button>
<br><br> <br>
<br>
<button class="btn btn-primary" type="submit">Save Changes and Download PDF</button> <button class="btn btn-primary" type="submit">Save Changes and Download PDF</button>
<script> <script>

View File

@ -4,18 +4,17 @@
<th:block th:insert="~{fragments/common :: head(title=#{permissions.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{permissions.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{permissions.header}"></h2> <h2 th:text="#{permissions.header}"></h2>
<p th:text="#{permissions.warning}"></p> <p th:text="#{permissions.warning}"></p>
<form action="add-password" method="post" <form action="add-password" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
<label th:text="#{permissions.selectText.1}"></label> <label th:text="#{permissions.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
@ -23,45 +22,36 @@
<div class="form-group"> <div class="form-group">
<label th:text="#{permissions.selectText.2}"></label> <label th:text="#{permissions.selectText.2}"></label>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canAssembleDocument" name="canAssembleDocument">
id="canAssembleDocument" name="canAssembleDocument"> <label <label class="form-check-label" for="canAssembleDocument" th:text="#{permissions.selectText.3}"></label>
class="form-check-label" for="canAssembleDocument" th:text="#{permissions.selectText.3}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canExtractContent" name="canExtractContent">
id="canExtractContent" name="canExtractContent"> <label <label class="form-check-label" for="canExtractContent" th:text="#{permissions.selectText.4}"></label>
class="form-check-label" for="canExtractContent" th:text="#{permissions.selectText.4}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canExtractForAccessibility" name="canExtractForAccessibility">
id="canExtractForAccessibility" <label class="form-check-label" for="canExtractForAccessibility" th:text="#{permissions.selectText.5}"></label>
name="canExtractForAccessibility"> <label
class="form-check-label" for="canExtractForAccessibility" th:text="#{permissions.selectText.5}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canFillInForm" name="canFillInForm">
id="canFillInForm" name="canFillInForm"> <label <label class="form-check-label" for="canFillInForm" th:text="#{permissions.selectText.6}"></label>
class="form-check-label" for="canFillInForm" th:text="#{permissions.selectText.6}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="canModify" <input class="form-check-input" type="checkbox" id="canModify" name="canModify">
name="canModify"> <label class="form-check-label" <label class="form-check-label" for="canModify" th:text="#{permissions.selectText.7}"></label>
for="canModify" th:text="#{permissions.selectText.7}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canModifyAnnotations" name="canModifyAnnotations">
id="canModifyAnnotations" name="canModifyAnnotations"> <label <label class="form-check-label" for="canModifyAnnotations" th:text="#{permissions.selectText.8}"></label>
class="form-check-label" for="canModifyAnnotations" th:text="#{permissions.selectText.8}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="canPrint" <input class="form-check-input" type="checkbox" id="canPrint" name="canPrint">
name="canPrint"> <label class="form-check-label" <label class="form-check-label" for="canPrint" th:text="#{permissions.selectText.9}"></label>
for="canPrint" th:text="#{permissions.selectText.9}"></label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox" id="canPrintFaithful" name="canPrintFaithful">
id="canPrintFaithful" name="canPrintFaithful"> <label <label class="form-check-label" for="canPrintFaithful" th:text="#{permissions.selectText.10}"></label>
class="form-check-label" for="canPrintFaithful" th:text="#{permissions.selectText.10}"></label>
</div> </div>
</div> </div>

View File

@ -3,25 +3,24 @@
<th:block th:insert="~{fragments/common :: head(title=#{removePassword.title})}"></th:block> <th:block th:insert="~{fragments/common :: head(title=#{removePassword.title})}"></th:block>
<body> <div id="page-container"> <body>
<div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{removePassword.header}"></h2> <h2 th:text="#{removePassword.header}"></h2>
<form action="add-password" method="post" <form action="add-password" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
<label th:text="#{removePassword.selectText.1}"></label> <label th:text="#{removePassword.selectText.1}"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label th:text="#{removePassword.selectText.2}"></label> <input type="password" <label th:text="#{removePassword.selectText.2}"></label>
class="form-control" id="password" name="password" required> <input type="password" class="form-control" id="password" name="password" required>
</div> </div>
<br /> <br />
<div class="form-group text-center"> <div class="form-group text-center">

View File

@ -9,8 +9,7 @@
<div id="page-container"> <div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br> <br>
<br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
@ -24,14 +23,12 @@
<p th:text="#{split.desc.7}"></p> <p th:text="#{split.desc.7}"></p>
<p th:text="#{split.desc.8}"></p> <p th:text="#{split.desc.8}"></p>
<form th:action="@{split-pages}" method="post" <form th:action="@{split-pages}" method="post" enctype="multipart/form-data">
enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div class="form-group"> <div class="form-group">
<label for="pages" th:text="#{split.splitPages}"></label> <input <label for="pages" th:text="#{split.splitPages}"></label>
type="text" class="form-control" id="pages" name="pages" <input type="text" class="form-control" id="pages" name="pages" placeholder="1,3,5-10" required>
placeholder="1,3,5-10" required>
</div> </div>
<br> <br>
<button type="submit" class="btn btn-primary" th:text="#{split.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{split.submit}"></button>