pipeline stuff

This commit is contained in:
Anthony Stirling 2023-07-12 00:17:44 +01:00
parent 94526de04b
commit 50bcca10e2
6 changed files with 1242 additions and 1180 deletions

View File

@ -59,6 +59,9 @@ public class SPdfApplication {
GeneralUtils.createDir("customFiles/static/"); GeneralUtils.createDir("customFiles/static/");
GeneralUtils.createDir("customFiles/templates/"); GeneralUtils.createDir("customFiles/templates/");
GeneralUtils.createDir("config"); GeneralUtils.createDir("config");
System.out.println("Stirling-PDF Started."); System.out.println("Stirling-PDF Started.");
String port = System.getProperty("local.server.port"); String port = System.getProperty("local.server.port");

View File

@ -60,8 +60,8 @@ public class Controller {
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
final String jsonFileName = "pipelineConfig.json"; final String jsonFileName = "pipelineConfig.json";
final String watchedFoldersDir = "watchedFolders/"; final String watchedFoldersDir = "./pipeline/watchedFolders/";
final String finishedFoldersDir = "finishedFolders/"; final String finishedFoldersDir = "./pipeline/finishedFolders/";
@Scheduled(fixedRate = 25000) @Scheduled(fixedRate = 25000)
public void scanFolders() { public void scanFolders() {

View File

@ -1,29 +1,77 @@
package stirling.software.SPDF.controller.web; package stirling.software.SPDF.controller.web;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
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;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@Controller @Controller
@Tag(name = "General", description = "General APIs") @Tag(name = "General", description = "General APIs")
public class GeneralWebController { public class GeneralWebController {
@GetMapping("/pipeline") @GetMapping("/pipeline")
@Hidden @Hidden
public String pipelineForm(Model model) { public String pipelineForm(Model model) {
model.addAttribute("currentPage", "pipeline"); model.addAttribute("currentPage", "pipeline");
List<String> pipelineConfigs = new ArrayList<>();
try (Stream<Path> paths = Files.walk(Paths.get("./pipeline/defaultWebUIConfigs/"))) {
List<Path> jsonFiles = paths
.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(".json"))
.collect(Collectors.toList());
for (Path jsonFile : jsonFiles) {
String content = Files.readString(jsonFile, StandardCharsets.UTF_8);
pipelineConfigs.add(content);
}
List<Map<String, String>> pipelineConfigsWithNames = new ArrayList<>();
for (String config : pipelineConfigs) {
Map<String, Object> jsonContent = new ObjectMapper().readValue(config, Map.class);
String name = (String) jsonContent.get("name");
Map<String, String> configWithName = new HashMap<>();
configWithName.put("json", config);
configWithName.put("name", name);
pipelineConfigsWithNames.add(configWithName);
}
model.addAttribute("pipelineConfigsWithNames", pipelineConfigsWithNames);
} catch (IOException e) {
e.printStackTrace();
}
model.addAttribute("pipelineConfigs", pipelineConfigs);
return "pipeline"; return "pipeline";
} }
@GetMapping("/merge-pdfs") @GetMapping("/merge-pdfs")
@Hidden @Hidden
public String mergePdfForm(Model model) { public String mergePdfForm(Model model) {

View File

@ -381,30 +381,27 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
document.body.removeChild(a); document.body.removeChild(a);
}); });
document.getElementById('uploadPipelineBtn').addEventListener('click', function() { async function processPipelineConfig(configString) {
document.getElementById('uploadPipelineInput').click(); let pipelineConfig = JSON.parse(configString);
});
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
let reader = new FileReader();
reader.onload = function(event) {
let pipelineConfig = JSON.parse(event.target.result);
let pipelineList = document.getElementById('pipelineList'); let pipelineList = document.getElementById('pipelineList');
while (pipelineList.firstChild) { while (pipelineList.firstChild) {
pipelineList.removeChild(pipelineList.firstChild); pipelineList.removeChild(pipelineList.firstChild);
} }
document.getElementById('pipelineName').value = pipelineConfig.name document.getElementById('pipelineName').value = pipelineConfig.name
pipelineConfig.pipeline.forEach(operationConfig => { for (const operationConfig of pipelineConfig.pipeline) {
let operationsDropdown = document.getElementById('operationsDropdown'); let operationsDropdown = document.getElementById('operationsDropdown');
operationsDropdown.value = operationConfig.operation; operationsDropdown.value = operationConfig.operation;
operationSettings[operationConfig.operation] = operationConfig.parameters; operationSettings[operationConfig.operation] = operationConfig.parameters;
// assuming addOperation is async
await new Promise((resolve) => {
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
document.getElementById('addOperationBtn').click(); document.getElementById('addOperationBtn').click();
});
let lastOperation = pipelineList.lastChild; let lastOperation = pipelineList.lastChild;
lastOperation.querySelector('.pipelineSettings').click();
Object.keys(operationConfig.parameters).forEach(parameterName => { Object.keys(operationConfig.parameters).forEach(parameterName => {
let input = document.getElementById(parameterName); let input = document.getElementById(parameterName);
if (input) { if (input) {
@ -414,6 +411,17 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
break; break;
case 'number': case 'number':
input.value = operationConfig.parameters[parameterName].toString(); input.value = operationConfig.parameters[parameterName].toString();
break;
case 'file':
if (parameterName !== 'fileInput') {
// Create a new file input element
let newInput = document.createElement('input');
newInput.type = 'file';
newInput.id = parameterName;
// Add the new file input to the main page (change the selector according to your needs)
document.querySelector('#main').appendChild(newInput);
}
break; break;
case 'text': case 'text':
case 'textarea': case 'textarea':
@ -423,10 +431,26 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
} }
}); });
document.querySelector('#pipelineSettingsModal .btn-primary').click(); }
}
document.getElementById('uploadPipelineBtn').addEventListener('click', function() {
document.getElementById('uploadPipelineInput').click();
}); });
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
let reader = new FileReader();
reader.onload = function(event) {
processPipelineConfig(event.target.result);
}; };
reader.readAsText(e.target.files[0]); reader.readAsText(e.target.files[0]);
}); });
document.getElementById('pipelineSelect').addEventListener('change', function(e) {
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
processPipelineConfig(selectedPipelineJson);
});
}); });

View File

@ -11,28 +11,41 @@
<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="mb-3"> <!-- Trigger/Open The Modal -->
<button id="savePipelineBtn" class="btn btn-success">Download</button> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#pipelineSettingsModal">
Open Pipeline Settings
</button>
<button id="validateButton" class="btn btn-success">Validate</button>
<div class="btn-group"> <button id="uploadPipelineBtn" class="btn btn-primary">Upload Custom Pipeline</button>
<button id="uploadPipelineBtn" class="btn btn-primary">Upload</button> <select id="pipelineSelect">
<input type="file" id="uploadPipelineInput" accept=".json" <option value="">Select a pipeline</option>
style="display: none;"> <th:block th:each="config : ${pipelineConfigsWithNames}">
</div> <option th:value="${config.json}" th:text="${config.name}"></option>
</th:block>
</select>
<input type="file" id="fileInput" multiple>
<button class="btn btn-primary" id="submitConfigBtn">Submit</button>
<!-- The Modal -->
<div class="modal" id="pipelineSettingsModal">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h2 class="modal-title">Pipeline Configuration</h2>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div> </div>
<div id="pipelineContainer" class="card"> <!-- Modal body -->
<div class="modal-body">
<!-- Pipeline Configuration Card Header -->
<div class="card-header">
<h2 class="card-title">Pipeline Configuration</h2>
</div>
<!-- Pipeline Configuration Body -->
<div class="card-body">
<div class="mb-3"> <div class="mb-3">
<label for="pipelineName" class="form-label">Pipeline Name</label> <label for="pipelineName" class="form-label">Pipeline Name</label>
<input type="text" id="pipelineName" class="form-control" placeholder="Enter pipeline name here"> <input type="text" id="pipelineName" class="form-control" placeholder="Enter pipeline name here">
@ -49,64 +62,38 @@
<ol id="pipelineList" class="list-group"> <ol id="pipelineList" class="list-group">
<!-- Pipeline operations will be dynamically populated here --> <!-- Pipeline operations will be dynamically populated here -->
</ol> </ol>
</div>
<input type="file" id="fileInput" multiple>
<button class="btn btn-primary" id="submitConfigBtn">Submit</button>
</div>
<!-- pipelineSettings modal -->
<div id="pipelineSettingsModal" class="modal">
<div class="modal-content">
<div class="modal-body">
<span class="close">&times;</span>
<h2>Operation Settings</h2>
<div id="pipelineSettingsContent"> <div id="pipelineSettingsContent">
<!-- pipelineSettings will be dynamically populated here --> <!-- pipelineSettings will be dynamically populated here -->
</div> </div>
</div> </div>
<!-- Modal footer -->
<div class="modal-footer">
<button id="savePipelineBtn" class="btn btn-success">Download</button>
<button id="validateButton" class="btn btn-success">Validate</button>
<div class="btn-group">
<input type="file" id="uploadPipelineInput" accept=".json" style="display: none;">
</div> </div>
</div>
</div>
</div>
</div>
<script src="js/pipeline.js"></script> <script src="js/pipeline.js"></script>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<style> <style>
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0, 0, 0); /* Fallback color */
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
}
.btn-margin { .btn-margin {
margin-right: 2px; margin-right: 2px;
} }
.modal-body {
display: flex;
flex-direction: column;
}
</style> </style>
<div th:insert="~{fragments/footer.html :: footer}"></div> <div th:insert="~{fragments/footer.html :: footer}"></div>
</div> </div>