Интерфейс панели был полностью перерисован
Новый дизайн в стиле коммерческих продуктов, рассчитанный на обычного пользователя: - светлая и тёмная темы (следует системной), шрифт Inter и иконки Lucide вшиты в панель — работает без интернета; - общий каркас base.html и компоненты _ui.html вместо 14 независимых страниц; адаптивная вёрстка для телефона; - простой язык: «Работает / Выключена», «Автозапуск», «Доступ из интернета» вместо running, autostart, DNAT; технические данные убраны во вкладку «Для специалистов»; - главная: загрузка процессора, памяти и хранилища, карточки машин с главным действием и меню остальных, приветственный сценарий для первой машины; - мастер создания машины из трёх шагов с готовыми конфигурациями; - страница машины с вкладками, переключателем автозапуска и порядком загрузки кнопками; - «Сеть и доступ»: открытие SSH, сайта, RDP и т. д. из списка, ручные IP машин, понятная диагностика; - загрузка образов перетаскиванием с прогрессом и оставшимся временем; - подтверждения опасных действий в диалоге и уведомления; - раздел «Помощь»; - web/presenters.py переводит вывод virsh и /proc в данные для страниц; tests/dev_server.py запускает панель с имитацией virsh. Также: исправлено определение модели CPU на x86 («207» вместо названия процессора), история версии 0.10.0 и документация обновлены под Ubuntu 26.04 LTS, в README добавлены скриншоты. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LEUXMcdZo7b87mjkUsPgg
Этот коммит содержится в:
@@ -65,3 +65,40 @@ def test_versions_manifest_matches_version_file():
|
||||
version = (root / "VERSION").read_text().strip()
|
||||
manifest = json.loads((root / "updates" / "versions.json").read_text())
|
||||
assert version in [item["version"] for item in manifest["versions"]]
|
||||
|
||||
|
||||
def test_presenters_parse_virsh_tables():
|
||||
import presenters
|
||||
|
||||
disks = presenters.parse_domblklist(" Type Device Target Source\n------------------------------------\n file disk vda /var/lib/virtuality/images/web01.qcow2\n file cdrom sda -\n")
|
||||
assert [d["name"] for d in disks] == ["web01.qcow2", "Пусто"]
|
||||
assert disks[1]["is_cdrom"]
|
||||
nics = presenters.parse_domiflist(" Interface Type Source Model MAC\n---\n vnet0 network virtuality-nat virtio 52:54:00:aa:bb:cc\n")
|
||||
assert nics[0]["mac"] == "52:54:00:aa:bb:cc"
|
||||
info = presenters.parse_dominfo("State: shut off\nCPU(s): 4\nMax memory: 8388608 KiB\nUsed memory: 8388608 KiB\nAutostart: disable\n")
|
||||
assert (info["vcpus"], info["memory_mb"], info["autostart"]) == (4, 8192, False)
|
||||
assert presenters.vm_state("shut off")["label"] == "Выключена"
|
||||
assert presenters.format_mb(1536) == "1.5 ГБ"
|
||||
assert presenters.plural(22, "ядро", "ядра", "ядер") == "ядра"
|
||||
|
||||
|
||||
def test_update_not_offered_when_local_is_newer(tmp_path, monkeypatch, data_dirs):
|
||||
import subprocess
|
||||
|
||||
def git(*args, cwd):
|
||||
subprocess.run(["git", *args], cwd=cwd, check=True, capture_output=True)
|
||||
|
||||
remote, local = tmp_path / "remote", tmp_path / "local"
|
||||
remote.mkdir()
|
||||
git("init", "-q", "-b", "main", cwd=remote)
|
||||
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", "base", cwd=remote)
|
||||
git("clone", "-q", str(remote), str(local), cwd=tmp_path)
|
||||
(local / "VERSION").write_text("0.10.0\n")
|
||||
git("add", "VERSION", cwd=local)
|
||||
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "-m", "newer local build", cwd=local)
|
||||
monkeypatch.setattr(update_core, "SOURCE_DIR", local)
|
||||
assert update_core.check_updates(fetch=True)["has_update"] is False
|
||||
|
||||
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", "upstream", cwd=remote)
|
||||
git("reset", "-q", "--hard", "origin/main", cwd=local)
|
||||
assert update_core.check_updates(fetch=True)["has_update"] is True
|
||||
|
||||
Ссылка в новой задаче
Block a user