PoC: flat and advanced mode
This commit is contained in:
234
static/js/app.js
Normal file
234
static/js/app.js
Normal file
@@ -0,0 +1,234 @@
|
||||
class ArgumentBuilder {
|
||||
constructor() {
|
||||
this.arguments = [];
|
||||
this.container = document.getElementById('arguments-container');
|
||||
this.headerInput = document.getElementById('custom-header');
|
||||
this.generateBtn = document.getElementById('generate-btn');
|
||||
this.helpContent = document.getElementById('help-content');
|
||||
this.outputSection = document.getElementById('output-section');
|
||||
this.generatedCode = document.getElementById('generated-code');
|
||||
this.copyBtn = document.getElementById('copy-btn');
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Add initial empty row
|
||||
this.addArgumentRow();
|
||||
|
||||
// Event listeners
|
||||
this.generateBtn.addEventListener('click', () => this.generateScript());
|
||||
this.headerInput.addEventListener('input', () => this.updateHelpPreview());
|
||||
this.copyBtn.addEventListener('click', () => this.copyToClipboard());
|
||||
|
||||
// Update help preview initially
|
||||
this.updateHelpPreview();
|
||||
}
|
||||
|
||||
addArgumentRow(params = '', command = '', helpText = '') {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'argument-row';
|
||||
|
||||
const paramsInput = document.createElement('input');
|
||||
paramsInput.type = 'text';
|
||||
paramsInput.placeholder = '-v --verbose';
|
||||
paramsInput.value = params;
|
||||
|
||||
const commandInput = document.createElement('input');
|
||||
commandInput.type = 'text';
|
||||
commandInput.placeholder = 'verbose';
|
||||
commandInput.value = command;
|
||||
|
||||
const helpTextInput = document.createElement('input');
|
||||
helpTextInput.type = 'text';
|
||||
helpTextInput.placeholder = 'Enable verbose output';
|
||||
helpTextInput.value = helpText;
|
||||
|
||||
const removeBtn = document.createElement('button');
|
||||
removeBtn.className = 'remove-btn';
|
||||
removeBtn.innerHTML = '×';
|
||||
removeBtn.addEventListener('click', () => {
|
||||
row.remove();
|
||||
this.updateHelpPreview();
|
||||
});
|
||||
|
||||
// Add input event listeners for real-time updates
|
||||
const updatePreview = () => {
|
||||
this.updateHelpPreview();
|
||||
// Add new empty row if this is the last row and has content
|
||||
const rows = this.container.querySelectorAll('.argument-row');
|
||||
const isLastRow = rows[rows.length - 1] === row;
|
||||
const hasContent = commandInput.value.trim() !== '';
|
||||
|
||||
if (isLastRow && hasContent) {
|
||||
this.addArgumentRow();
|
||||
}
|
||||
};
|
||||
|
||||
paramsInput.addEventListener('input', updatePreview);
|
||||
commandInput.addEventListener('input', updatePreview);
|
||||
helpTextInput.addEventListener('input', updatePreview);
|
||||
|
||||
row.appendChild(paramsInput);
|
||||
row.appendChild(commandInput);
|
||||
row.appendChild(helpTextInput);
|
||||
row.appendChild(removeBtn);
|
||||
|
||||
this.container.appendChild(row);
|
||||
}
|
||||
|
||||
getArguments() {
|
||||
const rows = this.container.querySelectorAll('.argument-row');
|
||||
const args = [];
|
||||
|
||||
rows.forEach(row => {
|
||||
const inputs = row.querySelectorAll('input');
|
||||
const params = inputs[0].value.trim();
|
||||
const command = inputs[1].value.trim();
|
||||
const helpText = inputs[2].value.trim();
|
||||
|
||||
if (command) {
|
||||
args.push({
|
||||
params: params || command,
|
||||
command: command,
|
||||
helpText: helpText || command
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
addSubcommand(name = '', description = '') {
|
||||
const subcommandSection = document.createElement('div');
|
||||
subcommandSection.className = 'subcommand-section';
|
||||
|
||||
const header = this.createSubcommandHeader(name, description);
|
||||
const argsContainer = this.createArgumentsContainer();
|
||||
|
||||
subcommandSection.appendChild(header);
|
||||
subcommandSection.appendChild(argsContainer);
|
||||
|
||||
this.subcommandContainer.appendChild(subcommandSection);
|
||||
|
||||
return subcommandSection;
|
||||
}
|
||||
|
||||
updateHelpPreview() {
|
||||
const header = this.headerInput.value.trim();
|
||||
const args = this.getArguments();
|
||||
|
||||
if (args.length === 0) {
|
||||
this.helpContent.textContent = 'Add arguments to see the help output...';
|
||||
return;
|
||||
}
|
||||
|
||||
let helpText = '';
|
||||
|
||||
if (header) {
|
||||
helpText += header + '\n\n';
|
||||
}
|
||||
|
||||
helpText += 'Usage: script.sh [OPTIONS]\n\n';
|
||||
helpText += 'Options:\n';
|
||||
|
||||
args.forEach(arg => {
|
||||
const params = arg.params || arg.command;
|
||||
const help = arg.helpText || arg.command;
|
||||
helpText += ` ${params.padEnd(20)} ${help}\n`;
|
||||
});
|
||||
|
||||
helpText += ` ${'-h --help'.padEnd(20)} Show this help message\n`;
|
||||
|
||||
this.helpContent.textContent = helpText;
|
||||
}
|
||||
createSubcommandHeader(name, description) {
|
||||
const header = document.createElement('div');
|
||||
header.className = 'subcommand-header';
|
||||
header.innerHTML = `
|
||||
<input type="text" class="subcommand-name"
|
||||
placeholder="container" value="${name}">
|
||||
<input type="text" class="subcommand-desc"
|
||||
placeholder="Manage containers" value="${description}">
|
||||
<button class="toggle-btn">▼</button>
|
||||
<button class="remove-btn">×</button>
|
||||
`;
|
||||
return header;
|
||||
}
|
||||
|
||||
getSubcommands() {
|
||||
const sections = this.subcommandContainer.querySelectorAll('.subcommand-section');
|
||||
return Array.from(sections).map(section => {
|
||||
const nameInput = section.querySelector('.subcommand-name');
|
||||
const descInput = section.querySelector('.subcommand-desc');
|
||||
const args = this.getArgumentsFromSection(section);
|
||||
|
||||
return {
|
||||
name: nameInput.value.trim(),
|
||||
description: descInput.value.trim(),
|
||||
arguments: args
|
||||
};
|
||||
}).filter(sc => sc.name);
|
||||
}
|
||||
|
||||
async generateScript() {
|
||||
const header = this.headerInput.value.trim();
|
||||
const args = this.getArguments();
|
||||
|
||||
if (args.length === 0) {
|
||||
alert('Please add at least one argument');
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
header: this.headerInput.value.trim(),
|
||||
arguments: this.getArguments(),
|
||||
subcommands: this.getSubcommands()
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/generate', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to generate script');
|
||||
}
|
||||
|
||||
const scriptCode = await response.text();
|
||||
this.generatedCode.textContent = scriptCode;
|
||||
this.outputSection.style.display = 'block';
|
||||
|
||||
// Smooth scroll to output
|
||||
this.outputSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
} catch (error) {
|
||||
alert('Error generating script: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async copyToClipboard() {
|
||||
const code = this.generatedCode.textContent;
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(code);
|
||||
this.copyBtn.textContent = 'Copied!';
|
||||
this.copyBtn.classList.add('copied');
|
||||
|
||||
setTimeout(() => {
|
||||
this.copyBtn.textContent = 'Copy';
|
||||
this.copyBtn.classList.remove('copied');
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
alert('Failed to copy to clipboard');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the application when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ArgumentBuilder();
|
||||
});
|
Reference in New Issue
Block a user