fix(installer): split the database page so every field is reachable
Some checks failed
CI / backend (push) Failing after 6s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 7s

Trimming the description brought the Username box back and left Password off the
bottom. CreateInputQueryPage stacks its fields below the description and neither
scrolls nor shrinks, so a field that does not fit is drawn past the surface and
simply never appears - no error, no scrollbar. Sizing the description against a
pixel budget that varies with DPI and font scaling is guesswork, and it had now
failed twice.

Connection details (host, port, database) and sign-in (username, password) are
now two pages of three and two fields. Both fit under any reasonable
description, at any scaling, without anyone having to estimate.

The upgrade hint about leaving the password blank moves to the sign-in page,
where the password field actually is. ShouldSkipPage hides both pages for the
bundled-database option, and the stage arguments read the values from their new
homes.
This commit is contained in:
cproudlock
2026-08-04 12:51:39 -04:00
parent e650eb0220
commit 5f18ca27a1

View File

@@ -181,6 +181,7 @@ Filename: "{win}\Sysnative\WindowsPowerShell\v1.0\powershell.exe"; \
var
DbChoicePage: TInputOptionWizardPage;
DbDetailsPage: TInputQueryWizardPage;
DbCredsPage: TInputQueryWizardPage;
SitePage: TInputQueryWizardPage;
PreflightPage: TWizardPage;
BannerPanel: TPanel;
@@ -414,17 +415,28 @@ begin
DbDetailsPage.Add('Host:', False);
DbDetailsPage.Add('Port:', False);
DbDetailsPage.Add('Database:', False);
DbDetailsPage.Add('Username:', False);
DbDetailsPage.Add('Password:', True);
DbDetailsPage.Values[0] := '127.0.0.1';
DbDetailsPage.Values[1] := '3306';
DbDetailsPage.Values[2] := 'shopdb_flask';
DbDetailsPage.Values[3] := 'shopdb';
// SPLIT ACROSS TWO PAGES on purpose. CreateInputQueryPage stacks its fields
// below the description and does not scroll or shrink: with five fields the
// last one is drawn past the bottom of the surface and simply does not appear.
// Trimming the description bought one field back and lost the next, which is
// guessing at a pixel budget that varies with DPI and font. Three fields and
// two fields both fit under any reasonable description, at any scaling.
DbCredsPage := CreateInputQueryPage(DbDetailsPage.ID,
'Existing database', 'Sign-in',
'The account the application uses to reach that database. It needs full ' +
'rights on it, and nothing outside it.');
DbCredsPage.Add('Username:', False);
DbCredsPage.Add('Password:', True);
DbCredsPage.Values[0] := 'shopdb';
// How the application is published. Offered only when the bundle actually
// carries a subpath SPA build - Vite compiles the base path in, so this can
// never be a pure runtime switch.
DeployPage := CreateInputOptionPage(DbDetailsPage.ID,
DeployPage := CreateInputOptionPage(DbCredsPage.ID,
'Address', 'How should people reach ShopDB-Flask?',
'Both options serve the same application. The second needs no new DNS name '
+ 'and no port number, because it rides this server''s existing address.',
@@ -860,8 +872,20 @@ begin
begin
MsgBox('Enter the database host.', mbError, MB_OK);
Result := False;
end;
end;
end;
if CurPageID = DbCredsPage.ID then
begin
if not UseBundledDb then
begin
if DbCredsPage.Values[0] = '' then
begin
MsgBox('Enter the username the application connects with.', mbError, MB_OK);
Result := False;
end
else if (DbDetailsPage.Values[4] = '') and
else if (DbCredsPage.Values[1] = '') and
(not FileExists(InstalledDir + '.env')) then
begin
// Only required on a FRESH install. On an upgrade, blank means "keep the
@@ -920,7 +944,7 @@ begin
Creds := Copy(Existing, 1, Pos('@', Existing) - 1);
Rest := Copy(Existing, Pos('@', Existing) + 1, Length(Existing));
if Pos(':', Creds) > 0 then
DbDetailsPage.Values[3] := Copy(Creds, 1, Pos(':', Creds) - 1);
DbCredsPage.Values[0] := Copy(Creds, 1, Pos(':', Creds) - 1);
if Pos(':', Rest) > 0 then
begin
DbDetailsPage.Values[0] := Copy(Rest, 1, Pos(':', Rest) - 1);
@@ -936,10 +960,13 @@ begin
end;
// Password intentionally left blank: blank means "keep the current
// one", so an upgrade never needs the operator to know it.
DbDetailsPage.Values[4] := '';
DbCredsPage.Values[1] := '';
DbDetailsPage.SubCaptionLabel.Caption :=
'These are the settings this server is using now. Leave the password '
+ 'blank to keep the current one.';
'These are the settings this server is using now.';
// The hint belongs where the password field actually is - it moved to
// the next page when this one was split.
DbCredsPage.SubCaptionLabel.Caption :=
'Leave the password blank to keep the one this server already uses.';
end;
end;
@@ -990,7 +1017,7 @@ begin
end;
// The bundled path generates its own credentials, so asking for them would be
// meaningless - and any value typed here would be silently ignored.
Result := (PageID = DbDetailsPage.ID) and UseBundledDb;
Result := ((PageID = DbDetailsPage.ID) or (PageID = DbCredsPage.ID)) and UseBundledDb;
end;
// Runs from ssPostInstall, NOT PrepareToInstall.
@@ -1066,10 +1093,10 @@ begin
// PowerShell transcripts. The installer shreds the file after reading it.
// No password typed on an upgrade means "leave .env alone" - so send no
// password file, and the installer keeps the existing DATABASE_URL.
if DbDetailsPage.Values[4] <> '' then
if DbCredsPage.Values[1] <> '' then
begin
PwFile := ExpandConstant('{tmp}\dbpw.txt');
SaveStringToFile(PwFile, DbDetailsPage.Values[4] + #13#10, False);
SaveStringToFile(PwFile, DbCredsPage.Values[1] + #13#10, False);
end
else
PwFile := '';
@@ -1077,7 +1104,7 @@ begin
' -DbHost "' + DbDetailsPage.Values[0] + '"' +
' -DbPort ' + DbDetailsPage.Values[1] +
' -DbName "' + DbDetailsPage.Values[2] + '"' +
' -DbUser "' + DbDetailsPage.Values[3] + '"';
' -DbUser "' + DbCredsPage.Values[0] + '"';
if PwFile <> '' then Args := Args + ' -DbPasswordFile "' + PwFile + '"';
end;