mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-03 17:52:30 +02:00
footer and header changes
This commit is contained in:
parent
4a2da2b7e0
commit
4d8f4096c3
11
build.gradle
11
build.gradle
@ -21,6 +21,7 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.27'
|
||||
//implementation 'org.apache.pdfbox:preflight:2.0.27'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
|
||||
implementation 'e-iceblue:spire.pdf.free:5.1.0'
|
||||
|
||||
@ -33,6 +34,11 @@ dependencies {
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
manifest {
|
||||
attributes 'Implementation-Title': 'Stirling-PDF',
|
||||
'Implementation-Version': project.version
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
@ -43,3 +49,8 @@ task printVersion {
|
||||
println project.version
|
||||
}
|
||||
|
||||
bootRun {
|
||||
systemProperty 'version', project.version
|
||||
systemProperties['version'] = version
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,9 @@ package stirling.software.SPDF;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
import stirling.software.SPDF.config.AppConfig;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SPdfApplication {
|
||||
|
14
src/main/java/stirling/software/SPDF/config/AppConfig.java
Normal file
14
src/main/java/stirling/software/SPDF/config/AppConfig.java
Normal file
@ -0,0 +1,14 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
@Bean(name = "appVersion")
|
||||
public String appVersion() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "Develop";
|
||||
}
|
||||
}
|
@ -134,7 +134,7 @@ public class SplitPDFController {
|
||||
ByteArrayResource resource = new ByteArrayResource(data);
|
||||
new File("split_documents.zip").delete();
|
||||
// return the Resource in the response
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=split_documents.zip").contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_split.zip").contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(resource.contentLength()).body(resource);
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ public class ConvertImgPDFController {
|
||||
} else {
|
||||
ByteArrayResource resource = new ByteArrayResource(result);
|
||||
// return the Resource in the response
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=converted_documents.zip").contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+ file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToImages.zip").contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(resource.contentLength()).body(resource);
|
||||
}
|
||||
}
|
||||
|
3
src/main/resources/static/images/discord.svg
Normal file
3
src/main/resources/static/images/discord.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" fill="#007bff" class="bi bi-discord" viewBox="0 0 16 16">
|
||||
<path d="M13.545 2.907a13.227 13.227 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019c.308-.42.582-.863.818-1.329a.05.05 0 0 0-.01-.059.051.051 0 0 0-.018-.011 8.875 8.875 0 0 1-1.248-.595.05.05 0 0 1-.02-.066.051.051 0 0 1 .015-.019c.084-.063.168-.129.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.052.052 0 0 1 .053.007c.08.066.164.132.248.195a.051.051 0 0 1-.004.085 8.254 8.254 0 0 1-1.249.594.05.05 0 0 0-.03.03.052.052 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.235 13.235 0 0 0 4.001-2.02.049.049 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.034.034 0 0 0-.02-.019Zm-8.198 7.307c-.789 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612Zm5.316 0c-.788 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -2,4 +2,5 @@
|
||||
<svg width="50px" height="50px" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke="#007bff" stroke-width="38" d="M 297.507 242.806 L 339.507 242.806 M 247.507 242.806 L 289.507 242.806 M 198.507 242.806 L 240.507 242.806 M 149.507 242.806 L 190.507 242.806 M 99.507 242.806 L 141.507 242.806 M 149.507 196.806 L 190.507 196.806 M 198.507 196.806 L 240.507 196.806 M 247.507 196.806 L 289.507 196.806 M 247.507 150.806 L 289.507 150.806"/>
|
||||
<path fill="#007bff" d="M 473.507 244.806 C 473.507 244.806 455.507 227.806 418.507 233.806 C 414.507 204.806 383.507 187.806 383.507 187.806 C 383.507 187.806 354.507 222.806 375.507 261.806 C 369.507 264.806 359.507 268.806 344.507 268.806 L 69.507 268.806 C 64.507 287.806 64.507 413.806 202.507 413.806 C 301.507 413.806 375.507 367.806 410.507 283.806 C 462.507 287.806 473.507 244.806 473.507 244.806"/>
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 919 B After Width: | Height: | Size: 921 B |
@ -15,7 +15,7 @@
|
||||
<h2 th:text="#{extractImages.header}"></h2>
|
||||
|
||||
<form id="multiPdfForm" th:action="@{extract-images}" method="post" enctype="multipart/form-data">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=true)}"></div>
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
||||
<div class="form-group">
|
||||
<label th:text="#{extractImages.selectText}"></label>
|
||||
<select class="form-control" name="format">
|
||||
@ -26,102 +26,6 @@
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{extractImages.submit}"></button>
|
||||
</form>
|
||||
<th:block th:insert="~{fragments/common :: filelist}"></th:block>
|
||||
|
||||
<br>
|
||||
<div id="progressBarContainer" style="display: none; position: relative;">
|
||||
<div class="progress" style="height: 1rem;">
|
||||
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$('form').submit(function(event) {
|
||||
event.preventDefault(); // Prevent the default form handling behavior
|
||||
submitMultiPdfForm(event);
|
||||
});
|
||||
|
||||
|
||||
|
||||
async function submitMultiPdfForm(event) {
|
||||
// Get the selected PDF files
|
||||
var files = $('#fileInput-input')[0].files;
|
||||
|
||||
// Get the existing form data
|
||||
var formData = new FormData($('form')[0]);
|
||||
formData.delete('fileInput');
|
||||
|
||||
// Show the progress bar
|
||||
$('#progressBarContainer').show();
|
||||
|
||||
// Initialize the progress bar
|
||||
var progressBar = $('#progressBar');
|
||||
progressBar.css('width', '0%');
|
||||
progressBar.attr('aria-valuenow', 0);
|
||||
progressBar.attr('aria-valuemax', files.length);
|
||||
|
||||
// Submit each PDF file in parallel
|
||||
var promises = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
var fileFormData = new FormData();
|
||||
fileFormData.append('fileInput', files[i]);
|
||||
fileFormData.append('format', $('select[name="format"]').val());
|
||||
|
||||
fetch('extract-images', {
|
||||
method: 'POST',
|
||||
body: fileFormData
|
||||
}).then(function(response) {
|
||||
console.log('Received response for file ' + i + ': ' + response);
|
||||
|
||||
var contentDisposition = response.headers.get('content-disposition');
|
||||
var fileName = contentDisposition.split('filename=')[1].replace(/"/g, '');
|
||||
|
||||
response.blob().then(function(blob) {
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
resolve();
|
||||
});
|
||||
}).catch(function(error) {
|
||||
console.error('Error submitting request for file ' + i + ': ' + error);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
|
||||
// Update the progress bar as each request finishes
|
||||
promise.then(function() {
|
||||
var progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
|
||||
progressBar.css('width', progress + '%');
|
||||
progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
// Wait for all requests to finish
|
||||
try {
|
||||
await Promise.all(promises);
|
||||
} catch (error) {
|
||||
console.error('Error while uploading files: ' + error);
|
||||
}
|
||||
|
||||
// Update the progress bar
|
||||
progressBar.css('width', '100%');
|
||||
progressBar.attr('aria-valuenow', files.length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,30 +24,41 @@
|
||||
<link rel="stylesheet" th:href="@{css/dark-mode.css}" id="dark-mode-styles">
|
||||
|
||||
<script>
|
||||
function toggleDarkMode() {
|
||||
var checkbox = document.getElementById("toggle-dark-mode");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
if (checkbox.checked) {
|
||||
localStorage.setItem("dark-mode", "on");
|
||||
darkModeStyles.disabled = false;
|
||||
} else {
|
||||
localStorage.setItem("dark-mode", "off");
|
||||
darkModeStyles.disabled = true;
|
||||
}
|
||||
}
|
||||
$(document).ready(function() {
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var checkbox = document.getElementById("toggle-dark-mode");
|
||||
if (localStorage.getItem("dark-mode") == "on") {
|
||||
darkModeStyles.disabled = false;
|
||||
checkbox.checked = true;
|
||||
}
|
||||
if (localStorage.getItem("dark-mode") == "off") {
|
||||
darkModeStyles.disabled = true;
|
||||
checkbox.checked = false;
|
||||
}
|
||||
function toggleDarkMode() {
|
||||
var checkbox = document.getElementById("toggle-dark-mode");
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
if (checkbox.checked) {
|
||||
localStorage.setItem("dark-mode", "on");
|
||||
darkModeStyles.disabled = false;
|
||||
} else {
|
||||
localStorage.setItem("dark-mode", "off");
|
||||
darkModeStyles.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var darkModeStyles = document.getElementById("dark-mode-styles");
|
||||
var checkbox = document.getElementById("toggle-dark-mode");
|
||||
|
||||
// Check if the user has already set a preference
|
||||
if (localStorage.getItem("dark-mode") == "on") {
|
||||
darkModeStyles.disabled = false;
|
||||
checkbox.checked = true;
|
||||
} else if (localStorage.getItem("dark-mode") == "off") {
|
||||
darkModeStyles.disabled = true;
|
||||
checkbox.checked = false;
|
||||
} else {
|
||||
// Check the OS's default dark mode setting
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
darkModeStyles.disabled = false;
|
||||
checkbox.checked = true;
|
||||
} else {
|
||||
darkModeStyles.disabled = true;
|
||||
checkbox.checked = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@ -112,13 +123,176 @@
|
||||
<th:block th:fragment="fileSelector(name, multiple)">
|
||||
<div class="custom-file-chooser">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" th:name="${name}" th:id="${name}+'-input'" th:multiple="${multiple}">
|
||||
<input type="file" class="custom-file-input" th:name="${name}" th:id="${name}+'-input'" multiple>
|
||||
<label class="custom-file-label" th:for="${name}+'-input'" th:text="#{pdfPrompt}"></label>
|
||||
</div>
|
||||
<div class="selected-files"></div>
|
||||
</div>
|
||||
<br>
|
||||
<div id="progressBarContainer" style="display: none; position: relative;">
|
||||
<div class="progress" style="height: 1rem;">
|
||||
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
$('form').submit(function(event) {
|
||||
var files = $('#fileInput-input')[0].files;
|
||||
var url = this.action;
|
||||
/* Check if ${multiple} is false */
|
||||
var multiple = [[${multiple}]] || false;
|
||||
if (!multiple && files.length > 1) {
|
||||
event.preventDefault(); // Prevent the default form handling behavior
|
||||
submitMultiPdfForm(event,url);
|
||||
} else {
|
||||
// Get the selected download option from localStorage
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
// Create an XMLHttpRequest object to send the request to the server
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
// Set up the response type and event listener for the XMLHttpRequest object
|
||||
xhr.responseType = 'blob';
|
||||
xhr.addEventListener('load', function() {
|
||||
const filename = xhr.getResponseHeader('Content-Disposition').match(/filename=(.+)$/)[1];
|
||||
// Check if the response is a PDF or an image
|
||||
if (xhr.response.type.includes('pdf') || xhr.response.type.includes('image')) {
|
||||
// Perform the appropriate action based on the download option
|
||||
if (downloadOption === 'sameWindow') {
|
||||
// Open the file in the same window
|
||||
window.location.href = URL.createObjectURL(xhr.response);
|
||||
} else if (downloadOption === 'newWindow') {
|
||||
// Open the file in a new window
|
||||
window.open(URL.createObjectURL(xhr.response), '_blank');
|
||||
} else {
|
||||
// Download the file
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(xhr.response);
|
||||
link.download = filename
|
||||
link.click();
|
||||
}
|
||||
} else {
|
||||
// For ZIP files or other file types, just download the file
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(xhr.response);
|
||||
link.download = filename
|
||||
link.click();
|
||||
}
|
||||
});
|
||||
|
||||
// Set up the error listener for the XMLHttpRequest object
|
||||
xhr.addEventListener('error', function() {
|
||||
// Extract the error message and stack trace from the response
|
||||
const errorResponse = JSON.parse(xhr.responseText);
|
||||
const errorMessage = errorResponse.message;
|
||||
const stackTrace = errorResponse.stackTrace.join('\n');
|
||||
|
||||
// Create an error message to display to the user
|
||||
const message = `${errorMessage}\n\n${stackTrace}`;
|
||||
|
||||
|
||||
// Display the error message to the user
|
||||
alert(message);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function submitMultiPdfForm(event,url) {
|
||||
// Get the selected PDF files
|
||||
var files = $('#fileInput-input')[0].files;
|
||||
|
||||
// Get the existing form data
|
||||
var formData = new FormData($('form')[0]);
|
||||
formData.delete('fileInput');
|
||||
// Show the progress bar
|
||||
$('#progressBarContainer').show();
|
||||
|
||||
// Initialize the progress bar
|
||||
var progressBar = $('#progressBar');
|
||||
progressBar.css('width', '0%');
|
||||
progressBar.attr('aria-valuenow', 0);
|
||||
progressBar.attr('aria-valuemax', files.length);
|
||||
|
||||
// Submit each PDF file in parallel
|
||||
var promises = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
|
||||
var fileFormData = new FormData();
|
||||
fileFormData.append('fileInput', files[i]);
|
||||
for (var pair of formData.entries()) {
|
||||
fileFormData.append(pair[0], pair[1]);
|
||||
}
|
||||
console.log(fileFormData);
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: fileFormData
|
||||
}).then(function(response) {
|
||||
if (!response) {
|
||||
throw new Error('Received null response for file ' + i);
|
||||
}
|
||||
console.log('Received response for file ' + i + ': ' + response);
|
||||
|
||||
var contentDisposition = response.headers.get('content-disposition');
|
||||
var fileName = contentDisposition.split('filename=')[1].replace(/"/g, '');
|
||||
|
||||
response.blob().then(function(blob) {
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
resolve();
|
||||
});
|
||||
}).catch(function(error) {
|
||||
console.error('Error submitting request for file ' + i + ': ' + error);
|
||||
/* Set default values or fallbacks for error properties */
|
||||
var status = error && error.status || 500;
|
||||
var statusText = error && error.statusText || 'Internal Server Error';
|
||||
var message = error && error.message || 'An error occurred while processing your request.';
|
||||
|
||||
/* Reject the Promise to signal that the request has failed */
|
||||
reject();
|
||||
/* Redirect to error page with Spring Boot error parameters */
|
||||
var url = '/error?status=' + status + '&error=' + encodeURIComponent(statusText) + '&message=' + encodeURIComponent(message);
|
||||
window.location.href = url;
|
||||
});
|
||||
});
|
||||
|
||||
// Update the progress bar as each request finishes
|
||||
promise.then(function() {
|
||||
var progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
|
||||
progressBar.css('width', progress + '%');
|
||||
progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
|
||||
});
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
// Wait for all requests to finish
|
||||
try {
|
||||
await Promise.all(promises);
|
||||
} catch (error) {
|
||||
console.error('Error while uploading files: ' + error);
|
||||
}
|
||||
|
||||
// Update the progress bar
|
||||
progressBar.css('width', '100%');
|
||||
progressBar.attr('aria-valuenow', files.length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script th:inline="javascript">
|
||||
$([[${"#"+name+"-input"}]]).on("change", function() {
|
||||
const files = $(this).get(0).files;
|
||||
@ -152,4 +326,6 @@
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</th:block>
|
@ -1,6 +1,7 @@
|
||||
<div th:fragment="footer">
|
||||
<footer id="footer" class="text-center py-3">
|
||||
<a href="https://github.com/Frooodle/Stirling-PDF" target="_blank" class="mx-1"><img src="images/github.svg"></img></a>
|
||||
<a href="https://hub.docker.com/r/frooodle/s-pdf" target="_blank" class="mx-1"><img src="images/docker.svg"></img></a>
|
||||
<a href="https://hub.docker.com/r/frooodle/s-pdf" target="_blank" class="mx-1"><img src="images/docker.svg"></img></a>
|
||||
<a href="https://discord.gg/Cn8pWhQRxZ" target="_blank" class="mx-1"><img src="images/discord.svg"></img></a>
|
||||
</footer>
|
||||
</div>
|
@ -1,81 +1,4 @@
|
||||
<div th:fragment="navbar" class="mx-auto">
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.toggle-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.toggle input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
border-radius: 28px;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked+.slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus+.slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked+.slider:before {
|
||||
transform: translateX(22px);
|
||||
}
|
||||
|
||||
.toggle-label {
|
||||
margin-top: 2px;
|
||||
margin-left: 2px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 20px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
width: 100% !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document
|
||||
.addEventListener(
|
||||
@ -190,36 +113,30 @@ input:checked+.slider:before {
|
||||
|
||||
|
||||
|
||||
<div class="toggle-container">
|
||||
<label class="toggle"> <input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()"> <span class="slider round"></span>
|
||||
</label> <label class="toggle-label" for="toggle-dark-mode" th:text="#{navbar.darkmode}"></label>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
|
||||
|
||||
<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">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-globe2" viewBox="0 0 20 20">
|
||||
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.539c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.312.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a13.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.694.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.418.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/>
|
||||
</svg>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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"> <i class="bi bi-globe2"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="languageDropdown">
|
||||
<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="ar_AR">العربية</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>
|
||||
</div></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item">
|
||||
<li class="nav-item">
|
||||
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -228,7 +145,7 @@ input:checked+.slider:before {
|
||||
|
||||
<div class="modal fade" id="settingsModal" tabindex="-1" role="dialog" aria-labelledby="settingsModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-content dark-card">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
@ -236,7 +153,7 @@ input:checked+.slider:before {
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p th:text="'App Version:' + ${appVersion}"></p>
|
||||
<p th:text="'App Version:' + ${@appVersion}"></p>
|
||||
<div class="form-group">
|
||||
<label for="downloadOption">Choose download option (For non ZIP downloads):</label> <select class="form-control" id="downloadOption">
|
||||
<option value="sameWindow">Open in same window (Single file downloads only)</option>
|
||||
|
Loading…
Reference in New Issue
Block a user