This commit is contained in:
Anthony Stirling 2024-01-05 18:00:30 +00:00
parent 6c963e1b6c
commit 572f9f728f
29 changed files with 174 additions and 107 deletions

41
FolderScanning.md Normal file
View file

@ -0,0 +1,41 @@
## User Guide for Local Directory Scanning and File Processing
### Whilst Pipelines are in alpha...
You must enable this alpha functionality by setting
```
system:
enableAlphaFunctionality: true
```
To true like in the above for your `/config/settings.yml` file, after restarting Stirling-PDF you should see both UI and folder scanning enabled.
### Setting Up Watched Folders:
- Create a folder where you want your files to be monitored. This is your 'watched folder'.
- The default directory for this is `./pipeline/watchedFolders/`
- Place any directories you want to be scanned into this folder, this folder should contain multiple folders each for their own tasks and pipelines.
### Configuring Processing with JSON Files:
- In each directory you want processed (e.g `./pipeline/watchedFolders/officePrinter`), include a JSON configuration file.
- This JSON file should specify how you want the files in the directory to be handled (e.g., what operations to perform on them) which can be made, configured and downloaded from Stirling-PDF Pipeline interface.r
### Automatic Scanning and Processing:
- The system automatically checks the watched folder every minute for new directories and files to process.
- When a directory with a valid JSON configuration file is found, it begins processing the files inside as per the configuration.
### Processing Steps:
- Files in each directory are processed according to the instructions in the JSON file.
- This might involve file conversions, data filtering, renaming files, etc. If the output of a step is a zip, this zip will be automatically unzipped as it passes to next process.
### Results and Output:
- After processing, the results are saved in a specified output location. This could be a different folder or location as defined in the JSON file or the default location `./pipeline/finishedFolders/`.
- Each processed file is named and organized according to the rules set in the JSON configuration.
### Completion and Cleanup:
- Once processing is complete, the original files in the watched folder's directory are removed.
- You can find the processed files in the designated output location.
### Error Handling:
- If there's an error during processing, the system will not delete the original files, allowing you to check and retry if necessary.
### User Interaction:
- As a user, your main tasks are to set up the watched folders, place directories with files for processing, and create the corresponding JSON configuration files.
- The system handles the rest, including scanning, processing, and outputting results.

0
PipelineUsage.md Normal file
View file

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,8 +66,9 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.selectOperation=Select Operation
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:
pipelineOptions.saveButton=Download

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -66,7 +66,7 @@ pipeline.submitButton=Submit
######################
pipelineOptions.header=Pipeline Configuration
pipelineOptions.pipelineNameLabel=Pipeline Name
pipelineOptions.saveSettings=Save Settings
pipelineOptions.saveSettings=Save Operation Settings
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
pipelineOptions.addOperationButton=Add operation
pipelineOptions.pipelineHeader=Pipeline:

View file

@ -61,9 +61,7 @@ document.addEventListener('DOMContentLoaded', function() {
//Sort languages by alphabet
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
list.sort(function(a, b) {
var A = a.textContent.toUpperCase();
var B = b.textContent.toUpperCase();
return (A < B) ? -1 : (A > B) ? 1 : 0;
return a.textContent.toUpperCase().localeCompare(b.textContent.toUpperCase());
}).forEach(node => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
});

View file

@ -1,81 +1,107 @@
<th:block th:fragment="langs">
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="bg_BG">
<img src="images/flags/bg.svg" alt="icon" width="20" height="15"> Български
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="bg_BG"> <img src="images/flags/bg.svg"
alt="icon" width="20" height="15"> Български
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ar_AR">
<img src="images/flags/sa.svg" alt="icon" width="20" height="15"> العربية
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ar_AR"> <img src="images/flags/sa.svg"
alt="icon" width="20" height="15"> العربية
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ca_CA">
<img src="images/flags/es-ct.svg" alt="icon" width="20" height="15"> Català
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ca_CA"> <img src="images/flags/es-ct.svg"
alt="icon" width="20" height="15"> Català
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="zh_CN">
<img src="images/flags/cn.svg" alt="icon" width="20" height="15"> 简体中文
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="zh_CN"> <img src="images/flags/cn.svg"
alt="icon" width="20" height="15"> 简体中文
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="zh_TW">
<img src="images/flags/tw.svg" alt="icon" width="20" height="15"> 正體中文
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="zh_TW"> <img src="images/flags/tw.svg"
alt="icon" width="20" height="15"> 正體中文
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="de_DE">
<img src="images/flags/de.svg" alt="icon" width="20" height="15"> Deutsch
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="de_DE"> <img src="images/flags/de.svg"
alt="icon" width="20" height="15"> Deutsch
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="en_GB">
<img src="images/flags/gb.svg" alt="icon" width="20" height="15"> English (GB)
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="en_GB"> <img src="images/flags/gb.svg"
alt="icon" width="20" height="15"> English (GB)
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="en_US">
<img src="images/flags/us.svg" alt="icon" width="20" height="15"> English (US)
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="en_US"> <img src="images/flags/us.svg"
alt="icon" width="20" height="15"> English (US)
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="eu_ES">
<img src="images/flags/eu.svg" alt="icon" width="20" height="15"> Euskara
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="eu_ES"> <img src="images/flags/eu.svg"
alt="icon" width="20" height="15"> Euskara
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="es_ES">
<img src="images/flags/es.svg" alt="icon" width="20" height="15"> Español
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="es_ES"> <img src="images/flags/es.svg"
alt="icon" width="20" height="15"> Español
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="fr_FR">
<img src="images/flags/fr.svg" alt="icon" width="20" height="15"> Français
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="fr_FR"> <img src="images/flags/fr.svg"
alt="icon" width="20" height="15"> Français
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="id_ID">
<img src="images/flags/id.svg" alt="icon" width="20" height="15"> Indonesia
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="id_ID"> <img src="images/flags/id.svg"
alt="icon" width="20" height="15"> Indonesia
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="it_IT">
<img src="images/flags/it.svg" alt="icon" width="20" height="15"> Italiano
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="it_IT"> <img src="images/flags/it.svg"
alt="icon" width="20" height="15"> Italiano
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="nl_NL">
<img src="images/flags/nl.svg" alt="icon" width="20" height="15"> Nederlands
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="nl_NL"> <img src="images/flags/nl.svg"
alt="icon" width="20" height="15"> Nederlands
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="pl_PL">
<img src="images/flags/pl.svg" alt="icon" width="20" height="15"> Polski
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="pl_PL"> <img src="images/flags/pl.svg"
alt="icon" width="20" height="15"> Polski
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="pt_BR">
<img src="images/flags/pt_br.svg" alt="icon" width="20" height="15"> Português (BR)
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="pt_BR"> <img src="images/flags/pt_br.svg"
alt="icon" width="20" height="15"> Português (BR)
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ro_RO">
<img src="images/flags/ro.svg" alt="icon" width="20" height="15"> Romanian
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ro_RO"> <img src="images/flags/ro.svg"
alt="icon" width="20" height="15"> Romanian
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="sv_SE">
<img src="images/flags/se.svg" alt="icon" width="20" height="15"> Svenska
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="sv_SE"> <img src="images/flags/se.svg"
alt="icon" width="20" height="15"> Svenska
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="tr_TR">
<img src="images/flags/tr.svg" alt="icon" width="20" height="15"> Türkçe
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="tr_TR"> <img src="images/flags/tr.svg"
alt="icon" width="20" height="15"> Türkçe
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ru_RU">
<img src="images/flags/ru.svg" alt="icon" width="20" height="15"> Русский
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ru_RU"> <img src="images/flags/ru.svg"
alt="icon" width="20" height="15"> Русский
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ko_KR">
<img src="images/flags/kr.svg" alt="icon" width="20" height="15"> 한국어
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ko_KR"> <img src="images/flags/kr.svg"
alt="icon" width="20" height="15"> 한국어
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="ja_JP">
<img src="images/flags/jp.svg" alt="icon" width="20" height="15"> 日本語
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="ja_JP"> <img src="images/flags/jp.svg"
alt="icon" width="20" height="15"> 日本語
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="el_GR">
<img src="images/flags/gr.svg" alt="icon" width="20" height="15"> Ελληνικά
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="el_GR"> <img src="images/flags/gr.svg"
alt="icon" width="20" height="15"> Ελληνικά
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="hu_HU">
<img src="images/flags/hu.svg" alt="icon" width="20" height="15"> Hungarian
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="hu_HU"> <img src="images/flags/hu.svg"
alt="icon" width="20" height="15"> Hungarian
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="hi_IN">
<img src="images/flags/in.svg" alt="icon" width="20" height="15"> हिन्दी
<a class="dropdown-item lang_dropdown-item" href=""
data-bs-language-code="hi_IN"> <img src="images/flags/in.svg"
alt="icon" width="20" height="15"> हिन्दी
</a>
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="sr-Latn-RS">
<img src="images/flags/rs.svg" alt="icon" width="20" height="15"> Srpski
<a class="dropdown-item lang_dropdown-item" href=""
data-language-code="sr-Latn-RS"> <img src="images/flags/rs.svg"
alt="icon" width="20" height="15"> Srpski
</a>
</th:block>

View file

@ -80,6 +80,7 @@
</div>
<p>Below info is Alpha only, will be removed and hence not translated</p>
<h3>Current Limitations</h3>
<ul>
<li>Cannot have more than one of the same operation</li>
@ -106,9 +107,8 @@
<h3>Todo</h3>
<ul>
<li>Translation support</li>
<li>Save to browser/Account</li>
<li>offline mode checks and testing</li>
<li>offline folder scan mode checks and testing for unique usecases</li>
<li>Improve operation config settings UI</li>
</ul>
@ -203,6 +203,7 @@
th:placeholder="#{pipelineOptions.pipelineNamePrompt}">
</div>
<div class="mb-3">
<label for="operationsDropdown" th:text="#{pipelineOptions.selectOperation}"></label>
<select id="operationsDropdown" class="form-select">
<!-- Options will be dynamically populated here -->
</select>