This commit is contained in:
Anthony Stirling
2023-12-23 15:47:18 +00:00
parent 93f12d1313
commit 03450454c5
11 changed files with 164 additions and 79 deletions

View File

@@ -254,8 +254,10 @@ public class PipelineController {
List<Resource> processFiles(List<Resource> outputFiles, String jsonString) throws Exception {
ObjectMapper mapper = new ObjectMapper();
logger.info("Running jsonString {}", jsonString);
JsonNode jsonNode = mapper.readTree(jsonString);
logger.info("Running jsonNode {}", jsonNode);
JsonNode pipelineNode = jsonNode.get("pipeline");
logger.info("Running pipelineNode: {}", pipelineNode);
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
@@ -364,12 +366,7 @@ public class PipelineController {
logger.info("Handling files: {} files, with JSON string of length: {}", files.length, jsonString.length());
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(jsonString);
JsonNode pipelineNode = jsonNode.get("pipeline");
boolean hasErrors = false;
List<Resource> outputFiles = new ArrayList<>();
for (File file : files) {

View File

@@ -42,6 +42,8 @@ public class GeneralWebController {
model.addAttribute("currentPage", "pipeline");
List<String> pipelineConfigs = new ArrayList<>();
List<Map<String, String>> pipelineConfigsWithNames = new ArrayList<>();
if(new File("./pipeline/defaultWebUIConfigs/").exists()) {
try (Stream<Path> paths = Files.walk(Paths.get("./pipeline/defaultWebUIConfigs/"))) {
List<Path> jsonFiles = paths
@@ -53,7 +55,7 @@ public class GeneralWebController {
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, new TypeReference<Map<String, Object>>(){});
@@ -63,12 +65,21 @@ public class GeneralWebController {
configWithName.put("name", name);
pipelineConfigsWithNames.add(configWithName);
}
model.addAttribute("pipelineConfigsWithNames", pipelineConfigsWithNames);
} catch (IOException e) {
e.printStackTrace();
}
}
if(pipelineConfigsWithNames.size() == 0) {
Map<String, String> configWithName = new HashMap<>();
configWithName.put("json", "");
configWithName.put("name", "No preloaded configs found");
pipelineConfigsWithNames.add(configWithName);
}
model.addAttribute("pipelineConfigsWithNames", pipelineConfigsWithNames);
model.addAttribute("pipelineConfigs", pipelineConfigs);

View File

@@ -12,31 +12,17 @@ function validatePipeline() {
if (currentOperation === '/add-password') {
containsAddPassword = true;
}
console.log(currentOperation);
console.log(apiDocs[currentOperation]);
let currentOperationDescription = apiDocs[currentOperation]?.post?.description || "";
let nextOperationDescription = apiDocs[nextOperation]?.post?.description || "";
console.log("currentOperationDescription", currentOperationDescription);
console.log("nextOperationDescription", nextOperationDescription);
// Strip off 'ZIP-' prefix
currentOperationDescription = currentOperationDescription.replace("ZIP-", '');
nextOperationDescription = nextOperationDescription.replace("ZIP-", '');
console.log("currentOperationDescription", currentOperationDescription);
console.log("nextOperationDescription", nextOperationDescription);
let currentOperationOutput = currentOperationDescription.match(/Output:([A-Z\/]*)/)?.[1] || "";
let nextOperationInput = nextOperationDescription.match(/Input:([A-Z\/]*)/)?.[1] || "";
console.log("Operation " + currentOperation + " Output: " + currentOperationOutput);
console.log("Operation " + nextOperation + " Input: " + nextOperationInput);
// Splitting in case of multiple possible output/input
let currentOperationOutputArr = currentOperationOutput.split('/');
let nextOperationInputArr = nextOperationInput.split('/');
@@ -78,14 +64,14 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
return;
}
let selectedOperation = document.getElementById('operationsDropdown').value;
let parameters = operationSettings[selectedOperation] || {};
var pipelineName = document.getElementById('pipelineName').value;
let pipelineList = document.getElementById('pipelineList').children;
let pipelineConfig = {
"name": "uniquePipelineName",
"pipeline": [{
"operation": selectedOperation,
"parameters": parameters
}],
"name": pipelineName,
"pipeline": [],
"_examples": {
"outputDir": "{outputFolder}/{folderName}",
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
@@ -94,6 +80,28 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
"outputFileName": "{filename}"
};
for (let i = 0; i < pipelineList.length; i++) {
let operationName = pipelineList[i].querySelector('.operationName').textContent;
let parameters = operationSettings[operationName] || {};
pipelineConfig.pipeline.push({
"operation": operationName,
"parameters": parameters
});
}
let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2);
let formData = new FormData();
@@ -111,32 +119,35 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
console.log("formData", formData);
fetch('/api/v1/pipeline/handleData', {
method: 'POST',
body: formData
method: 'POST',
body: formData
})
.then(response => response.blob())
.then(blob => {
.then(response => {
// Save the response to use it later
const responseToUseLater = response;
return response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
// Use responseToUseLater instead of response
const contentDisposition = responseToUseLater.headers.get('Content-Disposition');
let filename = 'download';
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
}
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
});
})
.catch((error) => {
console.error('Error:', error);
});
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
const contentDisposition = response.headers.get('Content-Disposition');
let filename = 'download';
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
}
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
})
.catch((error) => {
console.error('Error:', error);
});
});
let apiDocs = {};
@@ -170,7 +181,6 @@ fetch('v1/api-docs')
operationsByTag[operationTag].push(operationPath);
}
});
console.log("operationsByTag", operationsByTag);
// Specify the order of tags
let tagOrder = ["General", "Security", "Convert", "Misc", "Filter"];
@@ -188,10 +198,7 @@ fetch('v1/api-docs')
if(operationPath.includes("/convert")){
console.log("operationPathDisplay", operationPathDisplay);
operationPathDisplay = operationPathDisplay.replace(/^\//, '').replaceAll("/", " to ");
console.log("operationPathDisplay2", operationPathDisplay);
} else {
operationPathDisplay = operationPathDisplay.replace(/\//g, ''); // Remove slashes
}
@@ -223,7 +230,6 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
} else if (postMethod.requestBody && postMethod.requestBody.content['multipart/form-data']) {
// Extract the reference key
const refKey = postMethod.requestBody.content['multipart/form-data'].schema['$ref'].split('/').pop();
console.log("refKey", refKey);
// Check if the referenced schema exists and has properties
if (apiSchemas[refKey] && Object.keys(apiSchemas[refKey].properties).length > 0) {
hasSettings = true;
@@ -296,7 +302,6 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
// If the parameter name is 'fileInput', return early to skip the rest of this iteration
if (parameter.name === 'fileInput') return;
console.log("parameter", parameter);
let parameterDiv = document.createElement('div');
parameterDiv.className = "mb-3";
@@ -407,7 +412,6 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
event.preventDefault();
let settings = {};
operationData.forEach(parameter => {
console.log("parameter.name", parameter.name);
if(parameter.name !== "fileInput"){
let value = document.getElementById(parameter.name).value;
switch (parameter.schema.type) {
@@ -432,7 +436,6 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
}
});
operationSettings[operation] = settings;
console.log(settings);
//pipelineSettingsModal.style.display = "none";
});
pipelineSettingsContent.appendChild(saveButton);

View File

@@ -36,7 +36,7 @@
<div class="container">
<div class="row justify-content-center">
<h1>Pipeline Menu (Huge work in progress, very buggy!)</h1>
<h1>(Alpha) Pipeline Menu (Huge work in progress, very buggy!)</h1>
<div class="bordered-box">
<div class="text-end text-top">
<button id="uploadPipelineBtn" class="btn btn-primary">Upload
@@ -48,7 +48,6 @@
<div class="center-element">
<div class="element-margin">
<select id="pipelineSelect" class="custom-select">
<option value="">Select a pipeline</option>
<th:block th:each="config : ${pipelineConfigsWithNames}">
<option th:value="${config.json}" th:text="${config.name}"></option>
</th:block>
@@ -63,14 +62,18 @@
</div>
</div>
<h3>Current Limitations</h3>
<p>Cant have more than one of the same operation</p>
<p>Cant input additional files via UI</p>
<h3>Current Limitations</h3>
<ul>
<li>Cannot have more than one of the same operation</li>
<li>Cannot input additional files via UI</li>
<li>Does not work with multi-input functions yet (like merges)</li>
</ul>
<h3>How it works notes</h3>
<p>Configre pipeline config file and input files to run files against it</p>
<p>For reuse, download config file and reupload it when needed or place in /pipeline/defaultWebUIConfigs/ to auto load in webUI for all users</p>
<h3>How it Works Notes</h3>
<ul>
<li>Configure the pipeline config file and input files to run files against it</li>
<li>For reuse, download the config file and re-upload it when needed, or place it in /pipeline/defaultWebUIConfigs/ to auto-load in the web UI for all users</li>
</ul>