mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-03 17:52:30 +02:00
rework navbar and also multi submits
This commit is contained in:
parent
721645273c
commit
4a2da2b7e0
@ -2,6 +2,9 @@ package stirling.software.SPDF.controller;
|
|||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -11,6 +14,9 @@ public class PdfController {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PdfController.class);
|
private static final Logger logger = LoggerFactory.getLogger(PdfController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
@GetMapping("/home")
|
@GetMapping("/home")
|
||||||
public String root(Model model) {
|
public String root(Model model) {
|
||||||
return "redirect:/";
|
return "redirect:/";
|
||||||
@ -19,7 +25,11 @@ public class PdfController {
|
|||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public String home(Model model) {
|
public String home(Model model) {
|
||||||
model.addAttribute("currentPage", "home");
|
model.addAttribute("currentPage", "home");
|
||||||
|
String appVersion = environment.getProperty("version");
|
||||||
|
model.addAttribute("appVersion", appVersion);
|
||||||
return "home";
|
return "home";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -15,3 +15,5 @@ server.error.whitelabel.enabled=false
|
|||||||
server.error.include-stacktrace=always
|
server.error.include-stacktrace=always
|
||||||
server.error.include-exception=true
|
server.error.include-exception=true
|
||||||
server.error.include-message=always
|
server.error.include-message=always
|
||||||
|
|
||||||
|
server.servlet.session.tracking-modes=cookie
|
@ -27,17 +27,19 @@
|
|||||||
<button type="submit" class="btn btn-primary" th:text="#{extractImages.submit}"></button>
|
<button type="submit" class="btn btn-primary" th:text="#{extractImages.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<th:block th:insert="~{fragments/common :: filelist}"></th:block>
|
<th:block th:insert="~{fragments/common :: filelist}"></th:block>
|
||||||
<div id="progressBarContainer" style="display: none;">
|
|
||||||
<div class="progress">
|
<br>
|
||||||
<div id="progressBar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$('#multiPdfForm').submit(function(event) {
|
$('form').submit(function(event) {
|
||||||
event.preventDefault(); // Prevent the default form handling behavior
|
event.preventDefault(); // Prevent the default form handling behavior
|
||||||
|
|
||||||
|
|
||||||
submitMultiPdfForm(event);
|
submitMultiPdfForm(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -115,23 +115,41 @@
|
|||||||
<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'" th:multiple="${multiple}">
|
||||||
<label class="custom-file-label" th:for="${name}+'-input'" th:text="#{pdfPrompt}"></label>
|
<label class="custom-file-label" th:for="${name}+'-input'" th:text="#{pdfPrompt}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="selected-files"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script th:inline="javascript">
|
<script th:inline="javascript">
|
||||||
$([[${"#"+name+"-input"}]]).on("change", function() {
|
$([[${"#"+name+"-input"}]]).on("change", function() {
|
||||||
const files = $(this).get(0).files;
|
const files = $(this).get(0).files;
|
||||||
const fileNames = Array.from(files).map(f => f.name).join(", ");
|
const fileNames = Array.from(files).map(f => f.name);
|
||||||
if (fileNames) {
|
const selectedFilesContainer = $(this).siblings(".selected-files");
|
||||||
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames);
|
selectedFilesContainer.empty();
|
||||||
|
fileNames.forEach(fileName => {
|
||||||
|
selectedFilesContainer.append("<div>" + fileName + "</div>");
|
||||||
|
});
|
||||||
|
if (fileNames.length === 1) {
|
||||||
|
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
|
||||||
|
} else if (fileNames.length > 1) {
|
||||||
|
$(this).siblings(".custom-file-label").addClass("selected").html(fileNames.length + " files selected");
|
||||||
} else {
|
} else {
|
||||||
$(this).siblings(".custom-file-label").addClass("selected").html([[#{pdfPrompt}]]);
|
$(this).siblings(".custom-file-label").addClass("selected").html([[#{pdfPrompt}]]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.custom-file-label {
|
.custom-file-label {
|
||||||
padding-right: 90px;
|
padding-right: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selected-files {
|
||||||
|
margin-top: 10px;
|
||||||
|
max-height: 150px;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</th:block>
|
</th:block>
|
@ -1,37 +1,166 @@
|
|||||||
<div th:fragment="navbar">
|
<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(
|
||||||
|
'DOMContentLoaded',
|
||||||
|
function() {
|
||||||
|
// Get the dropdown items
|
||||||
|
var dropdownItems = document
|
||||||
|
.querySelectorAll('.lang_dropdown-item');
|
||||||
|
|
||||||
|
// Loop through the dropdown items
|
||||||
|
for (var i = 0; i < dropdownItems.length; i++) {
|
||||||
|
dropdownItems[i].classList
|
||||||
|
.remove('active');
|
||||||
|
if (dropdownItems[i].dataset.languageCode === localStorage
|
||||||
|
.getItem('languageCode')) {
|
||||||
|
dropdownItems[i].classList
|
||||||
|
.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a click event listener to each dropdown item
|
||||||
|
dropdownItems[i]
|
||||||
|
.addEventListener(
|
||||||
|
'click',
|
||||||
|
function(event) {
|
||||||
|
|
||||||
|
// Prevent the default link behavior
|
||||||
|
event
|
||||||
|
.preventDefault();
|
||||||
|
|
||||||
|
// Get the language code
|
||||||
|
var languageCode = this.dataset.languageCode;
|
||||||
|
|
||||||
|
// Save the language code to local storage
|
||||||
|
localStorage
|
||||||
|
.setItem(
|
||||||
|
'languageCode',
|
||||||
|
languageCode);
|
||||||
|
|
||||||
|
// Get the current URL
|
||||||
|
var currentUrl = window.location.href;
|
||||||
|
|
||||||
|
// Check if the URL already contains a "?lang" query parameter
|
||||||
|
if (currentUrl
|
||||||
|
.indexOf('?lang=') === -1) {
|
||||||
|
// Update the URL with the "?lang" query parameter
|
||||||
|
window.location.href = currentUrl
|
||||||
|
+ '?lang='
|
||||||
|
+ languageCode;
|
||||||
|
} else {
|
||||||
|
// Replace the "?lang" query parameter with the new value
|
||||||
|
window.location.href = currentUrl
|
||||||
|
.replace(
|
||||||
|
/\?lang=\w{2,}/,
|
||||||
|
'?lang='
|
||||||
|
+ languageCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<div class="container">
|
<div class="container ">
|
||||||
|
|
||||||
<a class="navbar-brand" href="#" th:href="@{/}">Stirling PDF</a>
|
<a class="navbar-brand" href="#" th:href="@{/}">Stirling PDF</a>
|
||||||
|
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
data-target="#navbarNav" aria-controls="navbarNav"
|
|
||||||
aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav mr-auto flex-nowrap">
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{merge-pdfs}" th:classappend="${currentPage}=='merge-pdfs' ? 'active' : ''" th:text="#{home.merge.title}"></a></li>
|
||||||
<a class="nav-link" href="#" th:href="@{merge-pdfs}" th:classappend="${currentPage}=='merge-pdfs' ? 'active' : ''" th:text="#{home.merge.title}"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{split-pdfs}" th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:text="#{home.split.title}"></a></li>
|
||||||
<a class="nav-link" href="#" th:href="@{split-pdfs}" th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:text="#{home.split.title}"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{pdf-organizer}" th:classappend="${currentPage}=='pdf-organizer' ? 'active' : ''" th:text="#{home.pdfOrganiser.title}"></a></li>
|
||||||
<a class="nav-link" href="#" th:href="@{pdf-organizer}" th:classappend="${currentPage}=='pdf-organizer' ? 'active' : ''" th:text="#{home.pdfOrganiser.title}"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{rotate-pdf}" th:classappend="${currentPage}=='rotate-pdf' ? 'active' : ''" th:text="#{home.rotate.title}"></a></li>
|
||||||
<a class="nav-link" href="#" th:href="@{rotate-pdf}" th:classappend="${currentPage}=='rotate-pdf' ? 'active' : ''" th:text="#{home.rotate.title}"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='xlsx-to-pdf' ? 'active' : ''">
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='xlsx-to-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.convert}"></a>
|
aria-haspopup="true" aria-expanded="false" th:text="#{navbar.convert}"></a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="#" th:href="@{pdf-to-img}" th:classappend="${currentPage}=='pdf-to-img' ? 'active' : ''" th:text="#{home.pdfToImage.title}"></a>
|
<a class="dropdown-item" href="#" th:href="@{pdf-to-img}" th:classappend="${currentPage}=='pdf-to-img' ? 'active' : ''" th:text="#{home.pdfToImage.title}"></a>
|
||||||
<a class="dropdown-item" href="#" th:href="@{img-to-pdf}" th:classappend="${currentPage}=='img-to-pdf' ? 'active' : ''" th:text="#{home.imageToPdf.title}"></a>
|
<a class="dropdown-item" href="#" th:href="@{img-to-pdf}" th:classappend="${currentPage}=='img-to-pdf' ? 'active' : ''" th:text="#{home.imageToPdf.title}"></a>
|
||||||
@ -39,6 +168,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='change-permissions' OR ${currentPage}=='add-watermark' OR ${currentPage}=='remove-watermark' ? 'active' : ''">
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='change-permissions' OR ${currentPage}=='add-watermark' OR ${currentPage}=='remove-watermark' ? 'active' : ''">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.security}"></a>
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.security}"></a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
@ -50,40 +180,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='add-image' OR ${currentPage}=='compress-pdf' ? 'active' : ''">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.other}"></a>
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='add-image' OR ${currentPage}=='compress-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false" th:text="#{navbar.other}"></a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''" th:text="#{home.addImage.title}"></a>
|
<a class="dropdown-item" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''" th:text="#{home.addImage.title}"></a> <a class="dropdown-item" href="#" th:href="@{compress-pdf}"
|
||||||
<a class="dropdown-item" href="#" th:href="@{compress-pdf}" th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:text="#{home.compressPdfs.title}"></a>
|
th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:text="#{home.compressPdfs.title}"></a> <a class="dropdown-item" href="#" th:href="@{remove-pages}" th:classappend="${currentPage}=='remove-pages' ? 'active' : ''" th:text="#{home.removePages.title}"></a>
|
||||||
<a class="dropdown-item" href="#" th:href="@{remove-pages}" th:classappend="${currentPage}=='remove-pages' ? 'active' : ''" th:text="#{home.removePages.title}"></a>
|
</div></li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<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>
|
</div>
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#" th:href="@{compress-pdf}" th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''"></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<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">
|
|
||||||
<i class="bi bi-globe2"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<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>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="languageDropdown">
|
<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_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="en_GB">English (UK)</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="ar_AR">العربية</a>
|
</div></li>
|
||||||
<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>
|
||||||
|
|
||||||
@ -92,48 +220,59 @@
|
|||||||
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
|
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Get the dropdown items
|
|
||||||
var dropdownItems = document.querySelectorAll('.lang_dropdown-item');
|
|
||||||
|
|
||||||
// Loop through the dropdown items
|
|
||||||
for (var i = 0; i < dropdownItems.length; i++) {
|
|
||||||
dropdownItems[i].classList.remove('active');
|
|
||||||
if (dropdownItems[i].dataset.languageCode === localStorage.getItem('languageCode')) {
|
|
||||||
dropdownItems[i].classList.add('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a click event listener to each dropdown item
|
|
||||||
dropdownItems[i].addEventListener('click', function(event) {
|
|
||||||
|
|
||||||
// Prevent the default link behavior
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// Get the language code
|
|
||||||
var languageCode = this.dataset.languageCode;
|
|
||||||
|
|
||||||
// Save the language code to local storage
|
|
||||||
localStorage.setItem('languageCode', languageCode);
|
|
||||||
|
|
||||||
// Get the current URL
|
|
||||||
var currentUrl = window.location.href;
|
|
||||||
|
|
||||||
// Check if the URL already contains a "?lang" query parameter
|
|
||||||
if (currentUrl.indexOf('?lang=') === -1) {
|
|
||||||
// Update the URL with the "?lang" query parameter
|
|
||||||
window.location.href = currentUrl + '?lang=' + languageCode;
|
|
||||||
} else {
|
|
||||||
// Replace the "?lang" query parameter with the new value
|
|
||||||
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, '?lang=' + languageCode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div>
|
<div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div>
|
||||||
|
|
||||||
|
<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-header">
|
||||||
|
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<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>
|
||||||
|
<option value="newWindow">Open in new window</option>
|
||||||
|
<option value="downloadFile">Download file</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Settings Button -->
|
||||||
|
<button type="button" class="btn btn-secondary float-right" data-toggle="modal" data-target="#settingsModal">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span> Settings/About
|
||||||
|
</button>
|
||||||
|
<script>
|
||||||
|
// Get the download option from local storage, or set it to 'sameWindow' if it doesn't exist
|
||||||
|
var downloadOption = localStorage.getItem('downloadOption')
|
||||||
|
|| 'sameWindow';
|
||||||
|
|
||||||
|
// Set the selected option in the dropdown
|
||||||
|
document.getElementById('downloadOption').value = downloadOption;
|
||||||
|
|
||||||
|
// Save the selected option to local storage when the dropdown value changes
|
||||||
|
document.getElementById('downloadOption').addEventListener(
|
||||||
|
'change',
|
||||||
|
function() {
|
||||||
|
downloadOption = this.value;
|
||||||
|
localStorage.setItem('downloadOption',
|
||||||
|
downloadOption);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,65 +28,79 @@
|
|||||||
<button type="submit" class="btn btn-primary" th:text="#{merge.submit}"></button>
|
<button type="submit" class="btn btn-primary" th:text="#{merge.submit}"></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filename {
|
||||||
|
flex-grow: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrows {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.move-up span,
|
||||||
|
.move-down span {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
<script>
|
<script>
|
||||||
document
|
document.getElementById("fileInput").addEventListener("change", function() {
|
||||||
.getElementById(
|
|
||||||
"fileInput")
|
|
||||||
.addEventListener(
|
|
||||||
"change",
|
|
||||||
function() {
|
|
||||||
var files = this.files;
|
var files = this.files;
|
||||||
var list = document
|
var list = document.getElementById("selectedFiles");
|
||||||
.getElementById("selectedFiles");
|
|
||||||
list.innerHTML = "";
|
list.innerHTML = "";
|
||||||
for (var i = 0; i < files.length; i++) {
|
for (var i = 0; i < files.length; i++) {
|
||||||
var item = document
|
var item = document.createElement("li");
|
||||||
.createElement("li");
|
item.className = "list-group-item";
|
||||||
item.className = "list-group-item d-flex justify-content-between align-items-center";
|
item.innerHTML = `
|
||||||
item.textContent = files[i].name;
|
<div class="d-flex justify-content-between align-items-center w-100">
|
||||||
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>';
|
<div class="filename">${files[i].name}</div>
|
||||||
list
|
<div class="arrows d-flex">
|
||||||
.appendChild(item);
|
<button class="btn btn-secondary move-up"><span>↑</span></button>
|
||||||
|
<button class="btn btn-secondary move-down"><span>↓</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
list.appendChild(item);
|
||||||
}
|
}
|
||||||
var moveUpButtons = document
|
|
||||||
.querySelectorAll(".move-up");
|
var moveUpButtons = document.querySelectorAll(".move-up");
|
||||||
for (var i = 0; i < moveUpButtons.length; i++) {
|
for (var i = 0; i < moveUpButtons.length; i++) {
|
||||||
moveUpButtons[i]
|
moveUpButtons[i].addEventListener("click", function(event) {
|
||||||
.addEventListener(
|
event.preventDefault();
|
||||||
"click",
|
var parent = this.closest(".list-group-item");
|
||||||
function(
|
|
||||||
event) {
|
|
||||||
event
|
|
||||||
.preventDefault();
|
|
||||||
var parent = this.parentNode.parentNode;
|
|
||||||
var grandParent = parent.parentNode;
|
var grandParent = parent.parentNode;
|
||||||
if (parent.previousElementSibling) {
|
if (parent.previousElementSibling) {
|
||||||
grandParent
|
grandParent.insertBefore(parent, parent.previousElementSibling);
|
||||||
.insertBefore(
|
|
||||||
parent,
|
|
||||||
parent.previousElementSibling);
|
|
||||||
updateFiles();
|
updateFiles();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var moveDownButtons = document
|
|
||||||
.querySelectorAll(".move-down");
|
var moveDownButtons = document.querySelectorAll(".move-down");
|
||||||
for (var i = 0; i < moveDownButtons.length; i++) {
|
for (var i = 0; i < moveDownButtons.length; i++) {
|
||||||
moveDownButtons[i]
|
moveDownButtons[i].addEventListener("click", function(event) {
|
||||||
.addEventListener(
|
event.preventDefault();
|
||||||
"click",
|
var parent = this.closest(".list-group-item");
|
||||||
function(
|
|
||||||
event) {
|
|
||||||
event
|
|
||||||
.preventDefault();
|
|
||||||
var parent = this.parentNode.parentNode;
|
|
||||||
var grandParent = parent.parentNode;
|
var grandParent = parent.parentNode;
|
||||||
if (parent.nextElementSibling) {
|
if (parent.nextElementSibling) {
|
||||||
grandParent
|
grandParent.insertBefore(parent.nextElementSibling, parent);
|
||||||
.insertBefore(
|
|
||||||
parent.nextElementSibling,
|
|
||||||
parent);
|
|
||||||
updateFiles();
|
updateFiles();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -94,28 +108,23 @@
|
|||||||
|
|
||||||
function updateFiles() {
|
function updateFiles() {
|
||||||
var dataTransfer = new DataTransfer();
|
var dataTransfer = new DataTransfer();
|
||||||
var liElements = document
|
var liElements = document.querySelectorAll("#selectedFiles li");
|
||||||
.querySelectorAll("#selectedFiles li");
|
|
||||||
|
|
||||||
for (var i = 0; i < liElements.length; i++) {
|
for (var i = 0; i < liElements.length; i++) {
|
||||||
var fileNameFromList = liElements[i].innerText
|
var fileNameFromList = liElements[i].querySelector(".filename").innerText;
|
||||||
.replace(
|
var fileFromFiles;
|
||||||
"\nMove Up Move Down",
|
|
||||||
"");
|
|
||||||
var fileFromFiles
|
|
||||||
for (var j = 0; j < files.length; j++) {
|
for (var j = 0; j < files.length; j++) {
|
||||||
var file = files[j];
|
var file = files[j];
|
||||||
if (file.name === fileNameFromList) {
|
if (file.name === fileNameFromList) {
|
||||||
dataTransfer.items
|
dataTransfer.items.add(file);
|
||||||
.add(file);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document
|
document.getElementById("fileInput").files = dataTransfer.files;
|
||||||
.getElementById("fileInput").files = dataTransfer.files;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user