init
This commit is contained in:
197
app/templates/jobs/submit.html
Normal file
197
app/templates/jobs/submit.html
Normal file
@@ -0,0 +1,197 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Submit Test Job - ASF TestArena{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="submit-container">
|
||||
<h2 style="margin-bottom: 30px; color: var(--dark);">Submit New Test Job</h2>
|
||||
|
||||
<div class="step-indicator">
|
||||
<div class="step active">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-label">Branch</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-label">Scenarios</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-label">Environment</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-label">Test Mode</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">5</div>
|
||||
<div class="step-label">Review</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="branchForm">
|
||||
<div class="form-group">
|
||||
<label for="branch_name">Git Branch Name</label>
|
||||
<input type="text" id="branch_name" name="branch_name" class="form-control"
|
||||
placeholder="e.g., feature/new-feature" required>
|
||||
<small style="color: #6b7280; margin-top: 5px; display: block;">
|
||||
Enter the branch name to analyze available test scenarios
|
||||
</small>
|
||||
|
||||
<div id="branchValidation" class="branch-validation">
|
||||
<div class="loading-spinner"></div>
|
||||
<span id="validationMessage">Validating branch...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('dashboard.index') }}" class="btn" style="background: #6b7280; color: white;">Cancel</a>
|
||||
<button type="submit" id="validateBtn" class="btn btn-primary">Validate Branch</button>
|
||||
<button type="button" id="nextBtn" class="btn btn-primary" style="display: none;" onclick="proceedToStep2()">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let validatedBranch = null;
|
||||
let organizedData = {};
|
||||
let scenarioMap = {};
|
||||
|
||||
document.getElementById('branchForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
validateBranch();
|
||||
});
|
||||
|
||||
function validateBranch() {
|
||||
const branchName = document.getElementById('branch_name').value.trim();
|
||||
|
||||
if (!branchName) {
|
||||
alert('Please enter a branch name');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
const validation = document.getElementById('branchValidation');
|
||||
const message = document.getElementById('validationMessage');
|
||||
const validateBtn = document.getElementById('validateBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
|
||||
validation.className = 'branch-validation loading';
|
||||
validation.style.display = 'block';
|
||||
message.textContent = 'Validating branch...';
|
||||
validateBtn.disabled = true;
|
||||
nextBtn.style.display = 'none';
|
||||
|
||||
// Make AJAX request
|
||||
fetch('/jobs/submit/step1', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: `branch_name=${encodeURIComponent(branchName)}`
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Branch validation response:', data); // Debug log
|
||||
|
||||
if (data.success) {
|
||||
// Success
|
||||
validation.className = 'branch-validation success';
|
||||
message.textContent = data.message;
|
||||
validateBtn.style.display = 'none';
|
||||
nextBtn.style.display = 'inline-block';
|
||||
|
||||
validatedBranch = branchName;
|
||||
organizedData = data.organized_data || {};
|
||||
scenarioMap = data.scenario_map || {};
|
||||
|
||||
// Log debug info
|
||||
if (data.debug) {
|
||||
console.log('Debug info:', data.debug);
|
||||
}
|
||||
if (data.output) {
|
||||
console.log('Command output:', data.output);
|
||||
}
|
||||
} else {
|
||||
// Error
|
||||
validation.className = 'branch-validation error';
|
||||
message.textContent = data.error;
|
||||
validateBtn.disabled = false;
|
||||
nextBtn.style.display = 'none';
|
||||
|
||||
validatedBranch = null;
|
||||
organizedData = {};
|
||||
scenarioMap = {};
|
||||
|
||||
// Log debug info for troubleshooting
|
||||
console.error('Branch validation failed:', data.error);
|
||||
if (data.debug) {
|
||||
console.error('Debug info:', data.debug);
|
||||
}
|
||||
if (data.output) {
|
||||
console.error('Command output:', data.output);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// Network error
|
||||
validation.className = 'branch-validation error';
|
||||
message.textContent = 'Network error. Please try again.';
|
||||
validateBtn.disabled = false;
|
||||
nextBtn.style.display = 'none';
|
||||
|
||||
validatedBranch = null;
|
||||
availableScenarios = [];
|
||||
});
|
||||
}
|
||||
|
||||
function proceedToStep2() {
|
||||
if (!validatedBranch || Object.keys(organizedData).length === 0) {
|
||||
alert('Please validate the branch first');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create form to submit to step 2
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = '/jobs/submit/step2-validated';
|
||||
|
||||
const branchInput = document.createElement('input');
|
||||
branchInput.type = 'hidden';
|
||||
branchInput.name = 'branch_name';
|
||||
branchInput.value = validatedBranch;
|
||||
form.appendChild(branchInput);
|
||||
|
||||
const organizedDataInput = document.createElement('input');
|
||||
organizedDataInput.type = 'hidden';
|
||||
organizedDataInput.name = 'organized_data';
|
||||
organizedDataInput.value = JSON.stringify(organizedData);
|
||||
form.appendChild(organizedDataInput);
|
||||
|
||||
const scenarioMapInput = document.createElement('input');
|
||||
scenarioMapInput.type = 'hidden';
|
||||
scenarioMapInput.name = 'scenario_map';
|
||||
scenarioMapInput.value = JSON.stringify(scenarioMap);
|
||||
form.appendChild(scenarioMapInput);
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
|
||||
// Reset validation when branch name changes
|
||||
document.getElementById('branch_name').addEventListener('input', function() {
|
||||
const validation = document.getElementById('branchValidation');
|
||||
const validateBtn = document.getElementById('validateBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
|
||||
validation.style.display = 'none';
|
||||
validateBtn.style.display = 'inline-block';
|
||||
validateBtn.disabled = false;
|
||||
nextBtn.style.display = 'none';
|
||||
|
||||
validatedBranch = null;
|
||||
organizedData = {};
|
||||
scenarioMap = {};
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
268
app/templates/jobs/submit_step2.html
Normal file
268
app/templates/jobs/submit_step2.html
Normal file
@@ -0,0 +1,268 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Select Scenarios - ASF TestArena{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="submit-container">
|
||||
<h2 style="margin-bottom: 30px; color: var(--dark);">Select Test Scenarios</h2>
|
||||
|
||||
<div class="step-indicator">
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Branch</div>
|
||||
</div>
|
||||
<div class="step active">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-label">Scenarios</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-label">Environment</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-label">Test Mode</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">5</div>
|
||||
<div class="step-label">Review</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: #eff6ff; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<strong>Branch:</strong> {{ branch_name }}
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('jobs.submit_step2') }}" id="scenarioForm">
|
||||
<input type="hidden" name="branch_name" value="{{ branch_name }}">
|
||||
<input type="hidden" name="scenario_map" value="{{ scenario_map|tojson }}">
|
||||
<input type="hidden" name="selected_scenarios" id="selectedScenariosInput">
|
||||
|
||||
<div class="scenario-controls">
|
||||
<button type="button" class="btn btn-sm" onclick="selectAll()" style="background: var(--success); color: white; margin-right: 10px;">Select All</button>
|
||||
<button type="button" class="btn btn-sm" onclick="deselectAll()" style="background: var(--danger); color: white;">Deselect All</button>
|
||||
<span id="selectionCount" style="margin-left: 20px; font-weight: 600;">0 scenarios selected</span>
|
||||
</div>
|
||||
|
||||
<div class="scenario-tree">
|
||||
{% if organized_data %}
|
||||
{% for layer_name, layer_data in organized_data.items() %}
|
||||
<div class="tree-layer">
|
||||
<div class="tree-node layer-node" onclick="toggleLayer('{{ layer_name }}')">
|
||||
<span class="tree-toggle" id="toggle-{{ layer_name }}">▶</span>
|
||||
<input type="checkbox" class="layer-checkbox" id="layer-{{ layer_name }}" onchange="toggleLayerSelection('{{ layer_name }}')">
|
||||
<label for="layer-{{ layer_name }}" class="tree-label layer-label">{{ layer_name.replace('_', ' ').title() }}</label>
|
||||
</div>
|
||||
|
||||
<div class="tree-children" id="children-{{ layer_name }}" style="display: none;">
|
||||
{% if layer_data %}
|
||||
{% for stack_name, scenarios in layer_data.items() %}
|
||||
<div class="tree-stack">
|
||||
<div class="tree-node stack-node" onclick="toggleStack('{{ layer_name }}', '{{ stack_name }}')">
|
||||
<span class="tree-toggle" id="toggle-{{ layer_name }}-{{ stack_name }}">▶</span>
|
||||
<input type="checkbox" class="stack-checkbox" id="stack-{{ layer_name }}-{{ stack_name }}" onchange="toggleStackSelection('{{ layer_name }}', '{{ stack_name }}')">
|
||||
<label for="stack-{{ layer_name }}-{{ stack_name }}" class="tree-label stack-label">{{ stack_name.replace('_', ' ').title() }}</label>
|
||||
</div>
|
||||
|
||||
<div class="tree-children" id="children-{{ layer_name }}-{{ stack_name }}" style="display: none;">
|
||||
{% if scenarios %}
|
||||
{% for scenario in scenarios %}
|
||||
<div class="tree-scenario">
|
||||
<div class="tree-node scenario-node">
|
||||
<span class="tree-spacer"></span>
|
||||
<input type="checkbox" class="scenario-checkbox" id="scenario-{{ scenario }}" value="{{ scenario }}" onchange="updateSelectionCount()" data-layer="{{ layer_name }}" data-stack="{{ stack_name }}">
|
||||
<label for="scenario-{{ scenario }}" class="tree-label scenario-label">{{ scenario }}</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="tree-scenario">
|
||||
<div class="tree-node scenario-node">
|
||||
<span class="tree-spacer"></span>
|
||||
<span class="tree-label scenario-label" style="color: #9ca3af;">No scenarios found</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="tree-stack">
|
||||
<div class="tree-node stack-node">
|
||||
<span class="tree-spacer"></span>
|
||||
<span class="tree-label stack-label" style="color: #9ca3af;">No stacks found</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="tree-layer">
|
||||
<div class="tree-node layer-node">
|
||||
<span class="tree-label layer-label" style="color: #9ca3af;">No scenarios available</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('jobs.submit') }}" class="btn" style="background: #6b7280; color: white;">Back</a>
|
||||
<button type="submit" class="btn btn-primary" id="nextBtn" disabled>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let selectedScenarios = new Set();
|
||||
|
||||
function toggleLayer(layerName) {
|
||||
const children = document.getElementById(`children-${layerName}`);
|
||||
const toggle = document.getElementById(`toggle-${layerName}`);
|
||||
|
||||
if (children.style.display === 'none') {
|
||||
children.style.display = 'block';
|
||||
toggle.textContent = '▼';
|
||||
} else {
|
||||
children.style.display = 'none';
|
||||
toggle.textContent = '▶';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleStack(layerName, stackName) {
|
||||
const children = document.getElementById(`children-${layerName}-${stackName}`);
|
||||
const toggle = document.getElementById(`toggle-${layerName}-${stackName}`);
|
||||
|
||||
if (children.style.display === 'none') {
|
||||
children.style.display = 'block';
|
||||
toggle.textContent = '▼';
|
||||
} else {
|
||||
children.style.display = 'none';
|
||||
toggle.textContent = '▶';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLayerSelection(layerName) {
|
||||
const layerCheckbox = document.getElementById(`layer-${layerName}`);
|
||||
const stackCheckboxes = document.querySelectorAll(`input[id^="stack-${layerName}-"]`);
|
||||
const scenarioCheckboxes = document.querySelectorAll(`input[data-layer="${layerName}"]`);
|
||||
|
||||
// Update all stacks and scenarios in this layer
|
||||
stackCheckboxes.forEach(checkbox => {
|
||||
checkbox.checked = layerCheckbox.checked;
|
||||
checkbox.indeterminate = false;
|
||||
});
|
||||
|
||||
scenarioCheckboxes.forEach(checkbox => {
|
||||
checkbox.checked = layerCheckbox.checked;
|
||||
if (layerCheckbox.checked) {
|
||||
selectedScenarios.add(checkbox.value);
|
||||
} else {
|
||||
selectedScenarios.delete(checkbox.value);
|
||||
}
|
||||
});
|
||||
|
||||
updateSelectionCount();
|
||||
}
|
||||
|
||||
function toggleStackSelection(layerName, stackName) {
|
||||
const stackCheckbox = document.getElementById(`stack-${layerName}-${stackName}`);
|
||||
const scenarioCheckboxes = document.querySelectorAll(`input[data-layer="${layerName}"][data-stack="${stackName}"]`);
|
||||
|
||||
// Update all scenarios in this stack
|
||||
scenarioCheckboxes.forEach(checkbox => {
|
||||
checkbox.checked = stackCheckbox.checked;
|
||||
if (stackCheckbox.checked) {
|
||||
selectedScenarios.add(checkbox.value);
|
||||
} else {
|
||||
selectedScenarios.delete(checkbox.value);
|
||||
}
|
||||
});
|
||||
|
||||
updateLayerState(layerName);
|
||||
updateSelectionCount();
|
||||
}
|
||||
|
||||
function updateLayerState(layerName) {
|
||||
const layerCheckbox = document.getElementById(`layer-${layerName}`);
|
||||
const stackCheckboxes = document.querySelectorAll(`input[id^="stack-${layerName}-"]`);
|
||||
const scenarioCheckboxes = document.querySelectorAll(`input[data-layer="${layerName}"]`);
|
||||
|
||||
// Update stack states
|
||||
stackCheckboxes.forEach(stackCheckbox => {
|
||||
const stackName = stackCheckbox.id.replace(`stack-${layerName}-`, '');
|
||||
const stackScenarios = document.querySelectorAll(`input[data-layer="${layerName}"][data-stack="${stackName}"]`);
|
||||
const checkedCount = Array.from(stackScenarios).filter(cb => cb.checked).length;
|
||||
|
||||
if (checkedCount === 0) {
|
||||
stackCheckbox.checked = false;
|
||||
stackCheckbox.indeterminate = false;
|
||||
} else if (checkedCount === stackScenarios.length) {
|
||||
stackCheckbox.checked = true;
|
||||
stackCheckbox.indeterminate = false;
|
||||
} else {
|
||||
stackCheckbox.checked = false;
|
||||
stackCheckbox.indeterminate = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Update layer state
|
||||
const checkedScenarios = Array.from(scenarioCheckboxes).filter(cb => cb.checked).length;
|
||||
if (checkedScenarios === 0) {
|
||||
layerCheckbox.checked = false;
|
||||
layerCheckbox.indeterminate = false;
|
||||
} else if (checkedScenarios === scenarioCheckboxes.length) {
|
||||
layerCheckbox.checked = true;
|
||||
layerCheckbox.indeterminate = false;
|
||||
} else {
|
||||
layerCheckbox.checked = false;
|
||||
layerCheckbox.indeterminate = true;
|
||||
}
|
||||
}
|
||||
|
||||
function updateSelectionCount() {
|
||||
// Update selected scenarios set
|
||||
selectedScenarios.clear();
|
||||
document.querySelectorAll('.scenario-checkbox:checked').forEach(checkbox => {
|
||||
selectedScenarios.add(checkbox.value);
|
||||
});
|
||||
|
||||
// Update all layer states
|
||||
const layers = new Set();
|
||||
document.querySelectorAll('.scenario-checkbox').forEach(checkbox => {
|
||||
layers.add(checkbox.dataset.layer);
|
||||
});
|
||||
layers.forEach(layer => updateLayerState(layer));
|
||||
|
||||
// Update UI
|
||||
const count = selectedScenarios.size;
|
||||
document.getElementById('selectionCount').textContent = `${count} scenario${count !== 1 ? 's' : ''} selected`;
|
||||
document.getElementById('nextBtn').disabled = count === 0;
|
||||
|
||||
// Update hidden input
|
||||
document.getElementById('selectedScenariosInput').value = JSON.stringify(Array.from(selectedScenarios));
|
||||
}
|
||||
|
||||
function selectAll() {
|
||||
document.querySelectorAll('.scenario-checkbox').forEach(checkbox => {
|
||||
checkbox.checked = true;
|
||||
selectedScenarios.add(checkbox.value);
|
||||
});
|
||||
updateSelectionCount();
|
||||
}
|
||||
|
||||
function deselectAll() {
|
||||
document.querySelectorAll('.scenario-checkbox, .stack-checkbox, .layer-checkbox').forEach(checkbox => {
|
||||
checkbox.checked = false;
|
||||
checkbox.indeterminate = false;
|
||||
});
|
||||
selectedScenarios.clear();
|
||||
updateSelectionCount();
|
||||
}
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
updateSelectionCount();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
74
app/templates/jobs/submit_step3.html
Normal file
74
app/templates/jobs/submit_step3.html
Normal file
@@ -0,0 +1,74 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Select Environment - ASF TestArena{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="submit-container">
|
||||
<h2 style="margin-bottom: 30px; color: var(--dark);">Select Environment</h2>
|
||||
|
||||
<div class="step-indicator">
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Branch</div>
|
||||
</div>
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Scenarios</div>
|
||||
</div>
|
||||
<div class="step active">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-label">Environment</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-label">Test Mode</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">5</div>
|
||||
<div class="step-label">Review</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: #eff6ff; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<strong>Branch:</strong> {{ branch_name }}<br>
|
||||
<strong>Selected Scenarios:</strong> {{ scenarios|length }} scenario{{ 's' if scenarios|length != 1 else '' }}
|
||||
<details style="margin-top: 10px;">
|
||||
<summary style="cursor: pointer; color: var(--primary);">View selected scenarios</summary>
|
||||
<ul style="margin-top: 10px; padding-left: 20px;">
|
||||
{% for scenario in scenarios %}
|
||||
<li style="font-size: 12px; color: #6b7280;">{{ scenario }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('jobs.submit_step3') }}">
|
||||
<input type="hidden" name="branch_name" value="{{ branch_name }}">
|
||||
<input type="hidden" name="scenarios" value="{{ scenarios|tojson }}">
|
||||
<input type="hidden" name="scenario_map" value="{{ scenario_map|tojson }}">
|
||||
|
||||
<div class="radio-group">
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="environment" value="sensor_hub" required>
|
||||
<div>
|
||||
<strong>Sensor Hub</strong>
|
||||
<p style="font-size: 12px; color: #6b7280; margin-top: 4px;">Test on sensor hub hardware/simulator</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="environment" value="main_board" required>
|
||||
<div>
|
||||
<strong>Main Board</strong>
|
||||
<p style="font-size: 12px; color: #6b7280; margin-top: 4px;">Test on main board hardware/simulator</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn" style="background: #6b7280; color: white;" onclick="history.back()">Back</button>
|
||||
<button type="submit" class="btn btn-primary">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
80
app/templates/jobs/submit_step4.html
Normal file
80
app/templates/jobs/submit_step4.html
Normal file
@@ -0,0 +1,80 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Select Test Mode - ASF TestArena{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="submit-container">
|
||||
<h2 style="margin-bottom: 30px; color: var(--dark);">Select Test Mode</h2>
|
||||
|
||||
<div class="step-indicator">
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Branch</div>
|
||||
</div>
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Scenarios</div>
|
||||
</div>
|
||||
<div class="step completed">
|
||||
<div class="step-number">✓</div>
|
||||
<div class="step-label">Environment</div>
|
||||
</div>
|
||||
<div class="step active">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-label">Test Mode</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">5</div>
|
||||
<div class="step-label">Review</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('jobs.submit_final') }}">
|
||||
<input type="hidden" name="branch_name" value="{{ branch_name }}">
|
||||
<input type="hidden" name="scenarios" value="{{ scenarios|tojson }}">
|
||||
<input type="hidden" name="scenario_map" value="{{ scenario_map|tojson }}">
|
||||
<input type="hidden" name="environment" value="{{ environment }}">
|
||||
|
||||
<div class="radio-group">
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="test_mode" value="devbench_simulator" required>
|
||||
<div>
|
||||
<strong>Devbench Simulator</strong>
|
||||
<p style="font-size: 12px; color: #6b7280; margin-top: 4px;">Fully simulated environment</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="radio-item">
|
||||
<input type="radio" name="test_mode" value="testbench_hil" required>
|
||||
<div>
|
||||
<strong>Testbench HIL</strong>
|
||||
<p style="font-size: 12px; color: #6b7280; margin-top: 4px;">Hardware-in-the-Loop with real devices</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="margin-top: 30px;">
|
||||
<h3 style="margin-bottom: 15px; color: var(--dark);">Additional Options</h3>
|
||||
|
||||
<div style="margin-bottom: 10px;">
|
||||
<label>
|
||||
<input type="checkbox" name="keep_devbenches">
|
||||
Keep devbenches after test completion
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>
|
||||
<input type="checkbox" name="reuse_results">
|
||||
Reuse previous test results if available
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn" style="background: #6b7280; color: white;" onclick="history.back()">Back</button>
|
||||
<button type="submit" class="btn btn-success">Start Test</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user