[FIX] qemu form: tick nothing in the catalog by default
The form opened with the four main versions already ticked, so the plan showed four VMs nobody had asked for. F5 on an untouched form would have created them. Deploying is expensive and hard to undo — the list now starts empty and the choice is made, not inherited. The « * » still marks each distro's main version, and F7 ticks exactly those four in one keystroke, so nothing is lost but the presumption. With an empty list a « 0 VM · 0 vCPU » total teaches nothing, so the footer says what to do instead: tick what to deploy, F7 main versions, F6 all. Verified headless: no box ticked on open, F5 producing no spec at all, F7 giving back the four, and the ticks surviving a switch to « all architectures » (4 of 30) since identity is distro/version/arch, not rank. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7c1016552b
commit
25cc780005
2 changed files with 33 additions and 14 deletions
|
|
@ -453,33 +453,36 @@ def run_deploy_form(ctx, run_app: bool = True):
|
|||
t("Disk"),
|
||||
t("Status"),
|
||||
)
|
||||
self._reload_catalog(select_defaults=True)
|
||||
self._reload_catalog(first_load=True)
|
||||
|
||||
# -- catalogue et recalcul ------------------------------------- #
|
||||
def _entries(self):
|
||||
return catalog.get(self.arch, [])
|
||||
|
||||
def _reload_catalog(self, select_defaults=False):
|
||||
"""Recharge la liste à cocher après un changement d'architecture.
|
||||
Les cases cochées sont conservées quand la même entrée existe
|
||||
encore (l'identité est (distro, version, arch), pas le rang)."""
|
||||
def _reload_catalog(self, first_load=False):
|
||||
"""(Re)charge la liste à cocher.
|
||||
|
||||
RIEN n'est coché d'avance : déployer coûte cher, et une case
|
||||
pré-cochée ferait créer une VM que personne n'a demandée. Le « * »
|
||||
marque toujours la version principale, et F7 les coche toutes.
|
||||
|
||||
Après un changement d'architecture, les cases déjà cochées sont
|
||||
conservées quand l'entrée existe encore — l'identité est
|
||||
(distro, version, archi), pas le rang dans la liste."""
|
||||
widget = self.query_one("#f_catalog", SelectionList)
|
||||
keep = set()
|
||||
if not select_defaults:
|
||||
keep = {
|
||||
keep = (
|
||||
set()
|
||||
if first_load
|
||||
else {
|
||||
entry_key(self._entries_before[i])
|
||||
for i in widget.selected
|
||||
if i < len(self._entries_before)
|
||||
}
|
||||
)
|
||||
widget.clear_options()
|
||||
entries = self._entries()
|
||||
for i, e in enumerate(entries):
|
||||
on = (
|
||||
e.get("default", False)
|
||||
if select_defaults
|
||||
else (entry_key(e) in keep)
|
||||
)
|
||||
widget.add_option((entry_label(e), i, on))
|
||||
widget.add_option((entry_label(e), i, entry_key(e) in keep))
|
||||
self._entries_before = entries
|
||||
self._recompute()
|
||||
|
||||
|
|
@ -525,6 +528,14 @@ def run_deploy_form(ctx, run_app: bool = True):
|
|||
f"{r['disk_gb']}G",
|
||||
f"{icon}{r['note']}",
|
||||
)
|
||||
if not self.rows:
|
||||
# Rien de coché : un total à zéro n'apprend rien, on dit
|
||||
# plutôt comment remplir la liste.
|
||||
self.query_one("#totals", Static).update(
|
||||
f" {t('Tick what to deploy')} — "
|
||||
f"{t('F7 main versions · F6 all')}"
|
||||
)
|
||||
return
|
||||
n, cpus, ram, disk = plan_totals(self.rows)
|
||||
warn = ""
|
||||
if free_ram and ram > free_ram:
|
||||
|
|
|
|||
|
|
@ -1475,6 +1475,14 @@ TRANSLATIONS = {
|
|||
"fr": "toutes",
|
||||
"en": "all",
|
||||
},
|
||||
"Tick what to deploy": {
|
||||
"fr": "Cocher ce qu'on veut déployer",
|
||||
"en": "Tick what to deploy",
|
||||
},
|
||||
"F7 main versions · F6 all": {
|
||||
"fr": "F7 versions principales · F6 tout",
|
||||
"en": "F7 main versions · F6 all",
|
||||
},
|
||||
"exists - skipped": {
|
||||
"fr": "existe — ignorée",
|
||||
"en": "exists - skipped",
|
||||
|
|
|
|||
Loading…
Reference in a new issue