98 lines
3.2 KiB
HTML
98 lines
3.2 KiB
HTML
{% extends "base.html" %}
|
||
{% block content %}
|
||
|
||
<!-- Step 1: Start New Session -->
|
||
<div class="panel" id="step1">
|
||
<h2>New Conversion Session</h2>
|
||
|
||
<form id="session-form" onsubmit="startSession(event)">
|
||
<div class="form-group">
|
||
<label for="vmid">VM ID *</label>
|
||
<input type="number" id="vmid" name="vmid" required
|
||
placeholder="e.g. 21050" min="21000" max="21100">
|
||
<span class="hint">Range 21000–21100. Must be unique on the Proxmox host.</span>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="source-type">Source Type</label>
|
||
<select id="source-type" onchange="toggleSourceInput(event)">
|
||
<option value="upload">File Upload</option>
|
||
<option value="url">Download from URL</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group" id="upload-group">
|
||
<label for="source-file">Source File (.vmdk / .7z / .zip / .tar.gz)</label>
|
||
<input type="file" id="source-file" name="source_file"
|
||
accept=".vmdk,.vhd,.vhdx,.7z,.zip,.tar.gz,.tgz,.tar,.gz">
|
||
</div>
|
||
|
||
<div class="form-group hidden" id="url-group">
|
||
<label for="source-url">Download URL</label>
|
||
<input type="url" id="source-url" name="source_url"
|
||
placeholder="https://example.com/image.7z">
|
||
</div>
|
||
|
||
<button type="submit" id="start-btn">Analyse Source Image</button>
|
||
</form>
|
||
|
||
<div id="session-status" class="hidden" style="margin-top:1rem;"></div>
|
||
</div>
|
||
|
||
<!-- Step 2: Analysis Result (populated by JavaScript) -->
|
||
<div id="analysis-section"></div>
|
||
|
||
<script>
|
||
function toggleSourceInput(e) {
|
||
const type = e.target.value;
|
||
document.getElementById('upload-group').classList.toggle('hidden', type !== 'upload');
|
||
document.getElementById('url-group').classList.toggle('hidden', type !== 'url');
|
||
}
|
||
|
||
async function startSession(e) {
|
||
e.preventDefault();
|
||
const btn = document.getElementById('start-btn');
|
||
const status = document.getElementById('session-status');
|
||
btn.disabled = true;
|
||
status.classList.remove('hidden');
|
||
status.innerHTML = '<div class="spinner"></div> Analysing source image...';
|
||
|
||
const formData = new FormData();
|
||
formData.append('vmid', document.getElementById('vmid').value);
|
||
|
||
const sourceType = document.getElementById('source-type').value;
|
||
formData.append('source_type', sourceType);
|
||
|
||
if (sourceType === 'upload') {
|
||
const fileInput = document.getElementById('source-file');
|
||
if (fileInput.files.length > 0) {
|
||
formData.append('source_file', fileInput.files[0]);
|
||
} else {
|
||
status.innerHTML = '<div class="error">Please select a file.</div>';
|
||
btn.disabled = false;
|
||
return;
|
||
}
|
||
} else {
|
||
const url = document.getElementById('source-url').value.trim();
|
||
if (!url) {
|
||
status.innerHTML = '<div class="error">Please enter a URL.</div>';
|
||
btn.disabled = false;
|
||
return;
|
||
}
|
||
formData.append('source_url', url);
|
||
}
|
||
|
||
try {
|
||
const resp = await fetch('/session/start', { method: 'POST', body: formData });
|
||
const html = await resp.text();
|
||
document.getElementById('analysis-section').innerHTML = html;
|
||
status.classList.add('hidden');
|
||
} catch (err) {
|
||
status.innerHTML = `<div class="error">Failed: ${err.message}</div>`;
|
||
} finally {
|
||
btn.disabled = false;
|
||
}
|
||
}
|
||
</script>
|
||
|
||
{% endblock %}
|