change add numbers grid and remove files from pipelines

This commit is contained in:
Anthony Stirling 2023-07-16 16:07:08 +01:00
parent 29aabdfba8
commit d07e3e6522
2 changed files with 322 additions and 278 deletions

View File

@ -75,12 +75,12 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
"operation": selectedOperation, "operation": selectedOperation,
"parameters": parameters "parameters": parameters
}], }],
"_examples": { "_examples": {
"outputDir" : "{outputFolder}/{folderName}", "outputDir": "{outputFolder}/{folderName}",
"outputFileName" : "{filename}-{pipelineName}-{date}-{time}" "outputFileName": "{filename}-{pipelineName}-{date}-{time}"
}, },
"outputDir" : "httpWebRequest", "outputDir": "httpWebRequest",
"outputFileName" : "{filename}" "outputFileName": "{filename}"
}; };
let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2); let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2);
@ -126,11 +126,11 @@ let operationSettings = {};
fetch('v3/api-docs') fetch('v3/api-docs')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
apiDocs = data.paths; apiDocs = data.paths;
let operationsDropdown = document.getElementById('operationsDropdown'); let operationsDropdown = document.getElementById('operationsDropdown');
const ignoreOperations = ["/handleData", "operationToIgnore"]; // Add the operations you want to ignore here const ignoreOperations = ["/handleData", "operationToIgnore"]; // Add the operations you want to ignore here
operationsDropdown.innerHTML = ''; operationsDropdown.innerHTML = '';
let operationsByTag = {}; let operationsByTag = {};
@ -148,25 +148,25 @@ fetch('v3/api-docs')
}); });
// Specify the order of tags // Specify the order of tags
let tagOrder = ["General", "Security", "Convert", "Other", "Filter"]; let tagOrder = ["General", "Security", "Convert", "Other", "Filter"];
// Create dropdown options // Create dropdown options
tagOrder.forEach(tag => { tagOrder.forEach(tag => {
if (operationsByTag[tag]) { if (operationsByTag[tag]) {
let group = document.createElement('optgroup'); let group = document.createElement('optgroup');
group.label = tag; group.label = tag;
operationsByTag[tag].forEach(operationPath => { operationsByTag[tag].forEach(operationPath => {
let option = document.createElement('option'); let option = document.createElement('option');
let operationWithoutSlash = operationPath.replace(/\//g, ''); // Remove slashes let operationWithoutSlash = operationPath.replace(/\//g, ''); // Remove slashes
option.textContent = operationWithoutSlash; option.textContent = operationWithoutSlash;
option.value = operationPath; // Keep the value with slashes for querying option.value = operationPath; // Keep the value with slashes for querying
group.appendChild(option); group.appendChild(option);
}); });
operationsDropdown.appendChild(group); operationsDropdown.appendChild(group);
} }
}); });
}); });
@ -177,9 +177,9 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
let listItem = document.createElement('li'); let listItem = document.createElement('li');
listItem.className = "list-group-item"; listItem.className = "list-group-item";
let hasSettings = (apiDocs[selectedOperation] && apiDocs[selectedOperation].post && let hasSettings = (apiDocs[selectedOperation] && apiDocs[selectedOperation].post &&
((apiDocs[selectedOperation].post.parameters && apiDocs[selectedOperation].post.parameters.length > 0) || ((apiDocs[selectedOperation].post.parameters && apiDocs[selectedOperation].post.parameters.length > 0) ||
(apiDocs[selectedOperation].post.requestBody && (apiDocs[selectedOperation].post.requestBody &&
apiDocs[selectedOperation].post.requestBody.content['multipart/form-data'].schema.properties))); apiDocs[selectedOperation].post.requestBody.content['multipart/form-data'].schema.properties)));
@ -226,77 +226,86 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
let pipelineSettingsModal = document.getElementById('pipelineSettingsModal'); let pipelineSettingsModal = document.getElementById('pipelineSettingsModal');
let pipelineSettingsContent = document.getElementById('pipelineSettingsContent'); let pipelineSettingsContent = document.getElementById('pipelineSettingsContent');
let operationData = apiDocs[operation].post.parameters || []; let operationData = apiDocs[operation].post.parameters || [];
let requestBodyData = apiDocs[operation].post.requestBody.content['multipart/form-data'].schema.properties || {}; let requestBodyData = apiDocs[operation].post.requestBody.content['multipart/form-data'].schema.properties || {};
// Combine operationData and requestBodyData into a single array // Combine operationData and requestBodyData into a single array
operationData = operationData.concat(Object.keys(requestBodyData).map(key => ({ operationData = operationData.concat(Object.keys(requestBodyData).map(key => ({
name: key, name: key,
schema: requestBodyData[key] schema: requestBodyData[key]
}))); })));
pipelineSettingsContent.innerHTML = ''; pipelineSettingsContent.innerHTML = '';
operationData.forEach(parameter => { operationData.forEach(parameter => {
let parameterDiv = document.createElement('div'); // If the parameter name is 'fileInput', return early to skip the rest of this iteration
parameterDiv.className = "form-group"; if (parameter.name === 'fileInput') return;
let parameterDiv = document.createElement('div');
parameterDiv.className = "form-group";
let parameterLabel = document.createElement('label'); let parameterLabel = document.createElement('label');
parameterLabel.textContent = `${parameter.name} (${parameter.schema.type}): `; parameterLabel.textContent = `${parameter.name} (${parameter.schema.type}): `;
parameterLabel.title = parameter.description; parameterLabel.title = parameter.description;
parameterDiv.appendChild(parameterLabel); parameterDiv.appendChild(parameterLabel);
let parameterInput; let parameterInput;
// check if enum exists in schema // check if enum exists in schema
if (parameter.schema.enum) { if (parameter.schema.enum) {
// if enum exists, create a select element // if enum exists, create a select element
parameterInput = document.createElement('select'); parameterInput = document.createElement('select');
parameterInput.className = "form-control"; parameterInput.className = "form-control";
// iterate over each enum value and create an option for it // iterate over each enum value and create an option for it
parameter.schema.enum.forEach(value => { parameter.schema.enum.forEach(value => {
let option = document.createElement('option'); let option = document.createElement('option');
option.value = value; option.value = value;
option.text = value; option.text = value;
parameterInput.appendChild(option); parameterInput.appendChild(option);
}); });
} else { } else {
// switch-case statement for handling non-enum types // switch-case statement for handling non-enum types
switch (parameter.schema.type) { switch (parameter.schema.type) {
case 'string': case 'string':
if (parameter.schema.format === 'binary') { if (parameter.schema.format === 'binary') {
// This is a file input // This is a file input
parameterInput = document.createElement('input');
parameterInput.type = 'file'; //parameterInput = document.createElement('input');
parameterInput.className = "form-control"; //parameterInput.type = 'file';
} else { //parameterInput.className = "form-control";
parameterInput = document.createElement('input');
parameterInput.type = 'text'; parameterInput = document.createElement('input');
parameterInput.className = "form-control"; parameterInput.type = 'text';
} parameterInput.className = "form-control";
break; parameterInput.value = "automatedFileInput";
case 'number': } else {
case 'integer': parameterInput = document.createElement('input');
parameterInput = document.createElement('input'); parameterInput.type = 'text';
parameterInput.type = 'number'; parameterInput.className = "form-control";
parameterInput.className = "form-control"; }
break; break;
case 'boolean': case 'number':
parameterInput = document.createElement('input'); case 'integer':
parameterInput.type = 'checkbox'; parameterInput = document.createElement('input');
break; parameterInput.type = 'number';
case 'array': parameterInput.className = "form-control";
case 'object': break;
parameterInput = document.createElement('textarea'); case 'boolean':
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}`; parameterInput = document.createElement('input');
parameterInput.className = "form-control"; parameterInput.type = 'checkbox';
break; break;
default: case 'array':
parameterInput = document.createElement('input'); case 'object':
parameterInput.type = 'text'; parameterInput = document.createElement('textarea');
parameterInput.className = "form-control"; parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}`;
} parameterInput.className = "form-control";
} break;
default:
parameterInput = document.createElement('input');
parameterInput.type = 'text';
parameterInput.className = "form-control";
}
}
parameterInput.id = parameter.name; parameterInput.id = parameter.name;
if (operationSettings[operation] && operationSettings[operation][parameter.name] !== undefined) { if (operationSettings[operation] && operationSettings[operation][parameter.name] !== undefined) {
@ -380,12 +389,12 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
let pipelineConfig = { let pipelineConfig = {
"name": pipelineName, "name": pipelineName,
"pipeline": [], "pipeline": [],
"_examples": { "_examples": {
"outputDir" : "{outputFolder}/{folderName}", "outputDir": "{outputFolder}/{folderName}",
"outputFileName" : "{filename}-{pipelineName}-{date}-{time}" "outputFileName": "{filename}-{pipelineName}-{date}-{time}"
}, },
"outputDir" : "httpWebRequest", "outputDir": "httpWebRequest",
"outputFileName" : "{filename}" "outputFileName": "{filename}"
}; };
for (let i = 0; i < pipelineList.length; i++) { for (let i = 0; i < pipelineList.length; i++) {
@ -411,74 +420,74 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
}); });
async function processPipelineConfig(configString) { async function processPipelineConfig(configString) {
let pipelineConfig = JSON.parse(configString); let pipelineConfig = JSON.parse(configString);
let pipelineList = document.getElementById('pipelineList'); let pipelineList = document.getElementById('pipelineList');
while (pipelineList.firstChild) {
pipelineList.removeChild(pipelineList.firstChild);
}
document.getElementById('pipelineName').value = pipelineConfig.name
for (const operationConfig of pipelineConfig.pipeline) {
let operationsDropdown = document.getElementById('operationsDropdown');
operationsDropdown.value = operationConfig.operation;
operationSettings[operationConfig.operation] = operationConfig.parameters;
// assuming addOperation is async while (pipelineList.firstChild) {
await new Promise((resolve) => { pipelineList.removeChild(pipelineList.firstChild);
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true }); }
document.getElementById('addOperationBtn').click(); document.getElementById('pipelineName').value = pipelineConfig.name
}); for (const operationConfig of pipelineConfig.pipeline) {
let operationsDropdown = document.getElementById('operationsDropdown');
operationsDropdown.value = operationConfig.operation;
operationSettings[operationConfig.operation] = operationConfig.parameters;
let lastOperation = pipelineList.lastChild; // assuming addOperation is async
await new Promise((resolve) => {
Object.keys(operationConfig.parameters).forEach(parameterName => { document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
let input = document.getElementById(parameterName); document.getElementById('addOperationBtn').click();
if (input) { });
switch (input.type) {
case 'checkbox':
input.checked = operationConfig.parameters[parameterName];
break;
case 'number':
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) let lastOperation = pipelineList.lastChild;
document.querySelector('#main').appendChild(newInput);
} Object.keys(operationConfig.parameters).forEach(parameterName => {
break; let input = document.getElementById(parameterName);
case 'text': if (input) {
case 'textarea': switch (input.type) {
default: case 'checkbox':
input.value = JSON.stringify(operationConfig.parameters[parameterName]); input.checked = operationConfig.parameters[parameterName];
} break;
} case 'number':
}); 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;
case 'text':
case 'textarea':
default:
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
}
}
});
}
}
}
}
document.getElementById('uploadPipelineBtn').addEventListener('click', function() { document.getElementById('uploadPipelineBtn').addEventListener('click', function() {
document.getElementById('uploadPipelineInput').click(); document.getElementById('uploadPipelineInput').click();
}); });
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) { document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
let reader = new FileReader(); let reader = new FileReader();
reader.onload = function(event) { reader.onload = function(event) {
processPipelineConfig(event.target.result); processPipelineConfig(event.target.result);
}; };
reader.readAsText(e.target.files[0]); reader.readAsText(e.target.files[0]);
}); });
document.getElementById('pipelineSelect').addEventListener('change', function(e) { document.getElementById('pipelineSelect').addEventListener('change', function(e) {
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
processPipelineConfig(selectedPipelineJson); processPipelineConfig(selectedPipelineJson);
}); });

View File

@ -1,125 +1,160 @@
<!DOCTYPE html> <!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org"> <html th:lang="${#locale.toString()}"
th:lang-direction="#{language.direction}"
<th:block th:insert="~{fragments/common :: head(title=#{autoCrop.title})}"></th:block> xmlns:th="http://www.thymeleaf.org">
<th:block
<body> th:insert="~{fragments/common :: head(title=#{autoCrop.title})}"></th:block>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap"> <body>
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <th:block th:insert="~{fragments/common :: game}"></th:block>
<br> <br> <div id="page-container">
<div class="container"> <div id="content-wrap">
<div class="row justify-content-center"> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<div class="col-md-6"> <br> <br>
<h2 th:text="#{addPageNumbers.header}"></h2> <div class="container">
<form method="post" enctype="multipart/form-data" th:action="@{add-page-numbers}"> <div class="row justify-content-center">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div> <div class="col-md-6">
<br> <h2 th:text="#{addPageNumbers.header}"></h2>
<div class="form-group"> <form method="post" enctype="multipart/form-data"
<label for="customMargin">Margin Size</label> th:action="@{add-page-numbers}">
<select class="form-control" id="customMargin" name="customMargin" required> <div
<option value="" disabled selected>Select a margin size</option> th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<option value="small">Small</option> <br>
<option value="medium">Medium</option> <div class="form-group">
<option value="large">Large</option> <label for="customMargin">Margin Size</label> <select
<option value="x-large">X-Large</option> class="form-control" id="customMargin" name="customMargin"
</select> required>
</div> <option value="" disabled selected>Select a margin
<style> size</option>
.a4container { <option value="small">Small</option>
<option value="medium">Medium</option>
display: grid; <option value="large">Large</option>
grid-template-columns: repeat(3, 1fr); <option value="x-large">X-Large</option>
grid-template-rows: repeat(3, 1fr); </select>
gap: 0; /* No gap between the cells */ </div>
width: 50%; <style>
aspect-ratio: 0.707; /* this sets the width-height ratio approximately same as A4 paper */ .a4container {
justify-items: stretch; /* Stretch items to fill their cells */ position: relative;
align-items: stretch; /* Stretch items to fill their cells */ width: 50%;
border: 1px solid #ddd; aspect-ratio: 0.707;
box-sizing: border-box; border: 1px solid #ddd;
} box-sizing: border-box;
background-color: white;
.cell { }
display: flex;
justify-content: center; .pageNumber {
align-items: center; position: absolute;
font-size: 1em; display: flex;
color: #333; justify-content: center;
cursor: pointer; align-items: center;
background-color: #ccc; font-size: 1em;
border: 1px solid #fff; /* Add a border to each cell */ color: #333;
box-sizing: border-box; cursor: pointer;
} background-color: #ccc;
width: 15%;
.cell:hover { height: 15%;
background-color: #eee; transform: translate(-50%, -50%);
} }
#myForm { .pageNumber:hover {
display: flex; background-color: #eee;
justify-content: center; }
align-items: center;
margin-top: 20px; #myForm {
} display: flex;
</style> justify-content: center;
align-items: center;
margin-top: 20px;
<div class="form-group"> }
<label for="position">Position</label>
<div class="a4container"> .selectedPosition {
<div id="1" class="cell">1</div> background-color: #0a0;
<div id="2" class="cell">2</div> }
<div id="3" class="cell">3</div>
<div id="4" class="cell">4</div> .selectedPosition.selectedHovered {
<div id="5" class="cell">5</div> background-color: #006600;
<div id="6" class="cell">6</div> }
<div id="7" class="cell">7</div> </style>
<div id="8" class="cell">8</div>
<div id="9" class="cell">9</div>
</div> <div class="form-group">
<label for="position">Position</label>
</div> <div class="a4container">
<form id="myForm"> <div class="pageNumber" id="1" style="top: 10%; left: 10%;">1</div>
<input type="number" id="numberInput" name="number" min="1" max="9" required> <div class="pageNumber" id="2" style="top: 10%; left: 50%;">2</div>
</form> <div class="pageNumber" id="3" style="top: 10%; left: 90%;">3</div>
<div class="pageNumber" id="4" style="top: 50%; left: 10%;">4</div>
<script> <div class="pageNumber" id="5" style="top: 50%; left: 50%;">5</div>
let cells = document.querySelectorAll('.cell'); <div class="pageNumber" id="6" style="top: 50%; left: 90%;">6</div>
let inputField = document.getElementById('numberInput'); <div class="pageNumber" id="7" style="top: 90%; left: 10%;">7</div>
<div class="pageNumber" id="8" style="top: 90%; left: 50%;">8</div>
cells.forEach(cell => { <div class="pageNumber" id="9" style="top: 90%; left: 90%;">9</div>
cell.addEventListener('click', function(e) { </div>
let selectedLocation = e.target.id;
inputField.value = selectedLocation; // Set input field's value
});
});
</div>
</script>
<input type="hidden" id="numberInput" name="position" min="1"
<div class="form-group"> max="9" required>
<label for="startingNumber">Starting Number</label> <div class="form-group">
<input type="number" class="form-control" id="startingNumber" name="startingNumber" min="1" required value="1"/> <label for="startingNumber">Starting Number</label> <input
</div> type="number" class="form-control" id="startingNumber"
<div class="form-group"> name="startingNumber" min="1" required value="1" />
<label for="pagesToNumber">Pages to Number</label> </div>
<input type="text" class="form-control" id="pagesToNumber" name="pagesToNumber" placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" /> <div class="form-group">
</div> <label for="pagesToNumber">Pages to Number</label> <input
<div class="form-group"> type="text" class="form-control" id="pagesToNumber"
<label for="customText">Custom Text</label> name="pagesToNumber"
<input type="text" class="form-control" id="customText" name="customText" placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc"/> placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" />
</div> </div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{addPageNumbers.submit}"></button> <div class="form-group">
</form> <label for="customText">Custom Text</label> <input type="text"
class="form-control" id="customText" name="customText"
</div> placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc" />
</div> </div>
</div> <button type="submit" id="submitBtn" class="btn btn-primary"
th:text="#{addPageNumbers.submit}"></button>
</div> </form>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div> </div>
</body> </div>
</div>
<script>
let cells = document.querySelectorAll('.pageNumber');
let inputField = document.getElementById('numberInput');
cells.forEach(cell => {
cell.addEventListener('click', function(e) {
cells.forEach(cell => {
cell.classList.remove('selectedPosition'); // Remove selected class from all cells
cell.classList.remove('selectedHovered'); // Also remove selectedHovered class
});
let selectedLocation = e.target.id;
inputField.value = selectedLocation;
e.target.classList.add('selectedPosition'); // Add selected class to clicked cell
e.target.classList.add('selectedHovered'); // Add selectedHovered class
});
cell.addEventListener('mouseenter', function(e) {
if(e.target.classList.contains('selectedPosition')) {
e.target.classList.add('selectedHovered');
}
});
cell.addEventListener('mouseleave', function(e) {
if(e.target.classList.contains('selectedPosition')) {
e.target.classList.remove('selectedHovered');
}
});
});
</script>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html> </html>