wire disk budget step + VM provisioning into installer wizard
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="./disk-budget-step.js"></script>
|
||||
<script src="./wizard.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -44,6 +44,12 @@ const state = {
|
||||
email: '',
|
||||
caName: 'DashCaddy Local CA'
|
||||
},
|
||||
// Disk budget / VM sandbox configuration
|
||||
diskBudget: {
|
||||
preset: 'balanced',
|
||||
diskSizeGB: 30,
|
||||
customSizeGB: 30
|
||||
},
|
||||
// Detected network IPs
|
||||
network: {
|
||||
lanIP: '',
|
||||
@@ -91,6 +97,7 @@ const steps = [
|
||||
{ id: 'welcome', title: 'Welcome' },
|
||||
{ id: 'dependencies', title: 'Dependencies' },
|
||||
{ id: 'folder', title: 'Install Path' },
|
||||
{ id: 'disk', title: 'Storage' },
|
||||
{ id: 'tier', title: 'Tier' },
|
||||
{ id: 'access', title: 'Access' },
|
||||
{ id: 'dns', title: 'DNS' },
|
||||
@@ -179,7 +186,7 @@ function setupEventListeners() {
|
||||
state.result.dashboardUrl = data.dashboardUrl;
|
||||
state.result.installPath = data.installPath;
|
||||
state.result.health = data.health || null;
|
||||
state.currentStep = 8; // Move to complete step
|
||||
state.currentStep = 9; // Move to complete step
|
||||
render();
|
||||
});
|
||||
|
||||
@@ -207,6 +214,21 @@ function setupEventListeners() {
|
||||
state.uninstall.error = data.error;
|
||||
render();
|
||||
});
|
||||
|
||||
// VM provisioning progress / error listeners
|
||||
window.electronAPI.onVMProgress((data) => {
|
||||
if (state.installation.status === 'running') {
|
||||
state.installation.progress = Math.min(data.progress || 0, 5);
|
||||
state.installation.currentTask = data.task || 'Provisioning sandboxed virtual disk...';
|
||||
render();
|
||||
}
|
||||
});
|
||||
|
||||
window.electronAPI.onVMError((data) => {
|
||||
state.installation.status = 'error';
|
||||
state.installation.error = data.error || 'VM provisioning failed';
|
||||
render();
|
||||
});
|
||||
}
|
||||
|
||||
// Navigation
|
||||
@@ -219,7 +241,7 @@ function nextStep() {
|
||||
case 1: // Dependencies
|
||||
checkDependencies();
|
||||
break;
|
||||
case 7: // Installation
|
||||
case 8: // Installation
|
||||
startInstallation();
|
||||
break;
|
||||
}
|
||||
@@ -420,6 +442,33 @@ async function startInstallation() {
|
||||
render();
|
||||
|
||||
try {
|
||||
// ── Provision sandboxed VM disk before installation ─────────
|
||||
if (state.diskBudget && state.diskBudget.diskSizeGB) {
|
||||
state.installation.currentTask = 'Provisioning sandboxed virtual disk...';
|
||||
state.installation.progress = 1;
|
||||
render();
|
||||
|
||||
const domain = state.domainMode === 'public'
|
||||
? state.domain.publicDomain
|
||||
: state.domainMode === 'custom-tld'
|
||||
? state.domain.tld
|
||||
: null;
|
||||
|
||||
const vmResult = await window.electronAPI.vmProvision({
|
||||
diskSizeGB: state.diskBudget.diskSizeGB,
|
||||
installPath: state.paths.install,
|
||||
apiPort: state.branding.apiPort,
|
||||
domain
|
||||
});
|
||||
|
||||
if (!vmResult || !vmResult.success) {
|
||||
throw new Error((vmResult && vmResult.error) || 'VM provisioning failed');
|
||||
}
|
||||
state.installation.completedTasks.push('Virtual disk provisioned');
|
||||
state.installation.progress = 5;
|
||||
render();
|
||||
}
|
||||
|
||||
await window.electronAPI.runInstallation({
|
||||
installPath: state.paths.install,
|
||||
dockerDataPath: state.paths.dockerData,
|
||||
@@ -511,12 +560,13 @@ function renderCurrentStep() {
|
||||
case 0: return renderWelcome();
|
||||
case 1: return renderDependencies();
|
||||
case 2: return renderFolderSelection();
|
||||
case 3: return renderTierSelection();
|
||||
case 4: return renderAccessMode();
|
||||
case 5: return renderDNSConfiguration();
|
||||
case 6: return renderDashboardSetup();
|
||||
case 7: return renderInstallation();
|
||||
case 8: return renderComplete();
|
||||
case 3: return renderDiskBudgetStep();
|
||||
case 4: return renderTierSelection();
|
||||
case 5: return renderAccessMode();
|
||||
case 6: return renderDNSConfiguration();
|
||||
case 7: return renderDashboardSetup();
|
||||
case 8: return renderInstallation();
|
||||
case 9: return renderComplete();
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
@@ -1125,7 +1175,7 @@ function renderComplete() {
|
||||
function renderFooter() {
|
||||
const isFirst = state.currentStep === 0;
|
||||
const isLast = state.currentStep === steps.length - 1;
|
||||
const isInstalling = state.currentStep === 7 && state.installation.status === 'running';
|
||||
const isInstalling = state.currentStep === 8 && state.installation.status === 'running';
|
||||
|
||||
// Determine if user can proceed
|
||||
let canProceed = true;
|
||||
@@ -1136,7 +1186,7 @@ function renderFooter() {
|
||||
case 2: // Folder
|
||||
canProceed = !!state.paths.install;
|
||||
break;
|
||||
case 4: // Access mode
|
||||
case 5: // Access mode
|
||||
if (state.domainMode === 'public') {
|
||||
canProceed = !!state.domain.publicDomain && !!state.domain.email;
|
||||
} else if (state.domainMode === 'custom-tld') {
|
||||
@@ -1165,7 +1215,7 @@ function renderFooter() {
|
||||
|
||||
// Button text
|
||||
let nextLabel = 'Next';
|
||||
if (state.currentStep === 6) nextLabel = 'Install';
|
||||
if (state.currentStep === 7) nextLabel = 'Install';
|
||||
|
||||
return `
|
||||
<div class="step-footer">
|
||||
|
||||
Reference in New Issue
Block a user