diff --git a/AppImage/ProxMenux-1.2.6.2-beta.AppImage b/AppImage/ProxMenux-1.2.6.2-beta.AppImage index be87613c..42f3653a 100755 Binary files a/AppImage/ProxMenux-1.2.6.2-beta.AppImage and b/AppImage/ProxMenux-1.2.6.2-beta.AppImage differ diff --git a/AppImage/ProxMenux-Monitor.AppImage.sha256 b/AppImage/ProxMenux-Monitor.AppImage.sha256 index 9ff437db..cf7fa00a 100644 --- a/AppImage/ProxMenux-Monitor.AppImage.sha256 +++ b/AppImage/ProxMenux-Monitor.AppImage.sha256 @@ -1 +1 @@ -814516b9d35533b39822bc8fa6452b7d3131a8734ddd8bbd14679d9d9b6bb93f ProxMenux-1.2.6.2-beta.AppImage +f8a5748d1beb986b3beafc9c4f2ce5071184fae39911bbe4927dc2ed52edb364 ProxMenux-1.2.6.2-beta.AppImage diff --git a/AppImage/components/virtual-machines.tsx b/AppImage/components/virtual-machines.tsx index e0cb0bcf..bba27570 100644 --- a/AppImage/components/virtual-machines.tsx +++ b/AppImage/components/virtual-machines.tsx @@ -5223,6 +5223,13 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => { : "bg-green-500/10 hover:bg-green-500/20 border border-green-500/30 text-green-400 hover:text-green-300" const neutralBtnCls = "border border-input bg-background text-foreground/80 hover:bg-accent hover:text-accent-foreground" const storageForBackup = applyBackupStorage || selectedBackupStorage + // A stack is updated as a whole from its main container; + // the other members only show their image. + const stackMember = ociInstance.stack && ociInstance.primary_vmid !== selectedVM.vmid + const primaryVM = (vmData || []).find((v) => v.vmid === ociInstance.primary_vmid) + const primaryLabel = primaryVM + ? `${primaryVM.name} (CT ${ociInstance.primary_vmid})` + : `CT ${ociInstance.primary_vmid}` return ( <> @@ -5262,6 +5269,29 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => { {t("vmLxc.ociUpdates.installedImage")} {installedLabel || "—"} )} + {stackMember ? ( +
+
+ + {t("vmLxc.ociUpdates.memberNote", { primary: primaryLabel, count: ociInstance.members.length })} +
+ {primaryVM && ( +
+ +
+ )} +
+ ) : ( + <> {ociInstance.stack && (
{t("vmLxc.ociUpdates.stackNote", { primary: ociInstance.primary_vmid, count: ociInstance.members.length })} @@ -5292,11 +5322,14 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => { {ociInstance.pending ? t("vmLxc.ociUpdates.recover") : t("vmLxc.ociUpdates.update")}
+ + )}
{/* Options — the backup the update keeps and the scheduled image update. */} + {!stackMember && (

{t("vmLxc.options.title")}

@@ -5494,6 +5527,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
+ )} ) })()} diff --git a/AppImage/messages/de/common.json b/AppImage/messages/de/common.json index 256e7a32..5032f316 100644 --- a/AppImage/messages/de/common.json +++ b/AppImage/messages/de/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Installiertes Image", "newImage": "Neues Image {image} verfügbar", "stackNote": "Teil einer Multi-Container-Anwendung (Haupt-CT {primary}, {count} Container): Das Update umfasst alle.", + "memberNote": "Dieser Container gehört zu einer Multi-Container-Anwendung mit dem Haupt-CT {primary} und wird nicht einzeln aktualisiert. Die Aktualisierung erfolgt über den Haupt-CT, der alle {count} Container gemeinsam aktualisiert.", + "openPrimary": "Haupt-CT öffnen", "pendingNote": "Ein Vorgang an diesem Container wurde unterbrochen; Wiederherstellen öffnet seine Wiederherstellung.", "update": "Aktualisieren", "recreate": "Neu erstellen", diff --git a/AppImage/messages/en/common.json b/AppImage/messages/en/common.json index 16de1a2f..e599b4e7 100644 --- a/AppImage/messages/en/common.json +++ b/AppImage/messages/en/common.json @@ -1214,6 +1214,8 @@ "installedImage": "Installed image", "newImage": "New image {image} available", "stackNote": "Part of a multi-container application (main CT {primary}, {count} containers): the update covers all of them.", + "memberNote": "This container belongs to a multi-container application whose main container is {primary}, and it is not updated on its own. Updates are applied from the main container, which updates all {count} containers together.", + "openPrimary": "Open the main container", "pendingNote": "An operation on this container was interrupted; Recover opens its recovery.", "update": "Update", "recreate": "Recreate", diff --git a/AppImage/messages/es/common.json b/AppImage/messages/es/common.json index 0f221010..53a5392a 100644 --- a/AppImage/messages/es/common.json +++ b/AppImage/messages/es/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Imagen instalada", "newImage": "Nueva imagen {image} disponible", "stackNote": "Forma parte de una aplicación multicontenedor (CT principal {primary}, {count} contenedores): la actualización los abarca a todos.", + "memberNote": "Este contenedor forma parte de una aplicación multicontenedor cuyo contenedor principal es {primary}, y no se actualiza de forma individual. La actualización se hace desde el contenedor principal, que actualiza a la vez los {count} contenedores.", + "openPrimary": "Abrir el contenedor principal", "pendingNote": "Una operación sobre este contenedor quedó interrumpida; Recuperar abre su recuperación.", "update": "Actualizar", "recreate": "Recrear", @@ -1200,8 +1202,8 @@ "terminalTitleUpdate": "Actualizar aplicación OCI", "terminalTitleRecreate": "Recrear aplicación OCI", "terminalDescription": "El mismo recorrido que OCI manager Apps → Gestionar aplicaciones OCI instaladas.", - "keepBackup": "Conservar el backup previo a la actualización", - "noKeepBackup": "El backup previo a la actualización no se conserva", + "keepBackup": "Conservar el backup realizado antes de actualizar", + "noKeepBackup": "No se conserva el backup realizado antes de actualizar", "keepBackupHelp": "Cada actualización hace un backup del contenedor antes de sustituir su imagen, para restaurarlo si la actualización falla. Con esta opción ese backup se conserva en el almacenamiento elegido; en Proxmox Backup Server se escribe un backup antes de actualizar.", "scheduleHelp": "Solo se actualiza la imagen, y solo cuando su registro publica una nueva.", "releaseDelayHelp": "Una imagen nueva solo se instala cuando tiene al menos esta antigüedad.", @@ -3370,7 +3372,7 @@ "groupedAppUpdates": "Notificaciones de actualización de aplicaciones agrupadas — un mensaje completo por escaneo en lugar de uno por aplicación, agrupado por LXC con las versiones instalada y disponible.", "adminTokenScope": "Ámbito administrativo — abrir un terminal del Monitor y desactivar la autenticación ahora requieren un token de administrador completo, así que un token de API de solo lectura se mantiene de solo lectura (reportado por @f3rs3n).", "ociAppTab": "Contenedores OCI en la pestaña App — un contenedor instalado por OCI manager Apps se reconoce desde su registro de instalación: la aplicación y su imagen, una imagen nueva detectada por digest y el enlace al repositorio de la imagen.", - "ociUpdatesTab": "Actualizaciones de contenedores OCI — Actualizar y Recrear abren el mismo recorrido que el menú OCI, el backup previo a la actualización puede conservarse en un almacenamiento de backups y la imagen puede actualizarse de forma programada.", + "ociUpdatesTab": "Actualizaciones de contenedores OCI — Actualizar y Recrear abren el mismo recorrido que el menú OCI, el backup realizado antes de actualizar puede conservarse en un almacenamiento de backups y la imagen puede actualizarse de forma programada.", "ociLogsTab": "Pestaña Logs para contenedores OCI — la salida de consola de la aplicación, guardada en el host y seguida en directo, con filtro y descarga. La consola de Proxmox de estos contenedores abre un shell.", "appsUpdateShortcut": "El icono de actualización de la página Apps abre el contenedor directamente en su pestaña Actualizaciones.", "webhookHttps": "Las notificaciones de Proxmox llegan al Monitor con HTTPS activado — se entregan en una dirección solo local y ya no fallan por un error de certificado.", diff --git a/AppImage/messages/fr/common.json b/AppImage/messages/fr/common.json index fe80f79c..14e7294d 100644 --- a/AppImage/messages/fr/common.json +++ b/AppImage/messages/fr/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Image installée", "newImage": "Nouvelle image {image} disponible", "stackNote": "Fait partie d'une application multi-conteneurs (CT principal {primary}, {count} conteneurs) : la mise à jour les couvre tous.", + "memberNote": "Ce conteneur fait partie d'une application multi-conteneurs dont le CT principal est {primary} et n'est pas mis à jour séparément. La mise à jour se fait depuis le CT principal, qui met à jour les {count} conteneurs ensemble.", + "openPrimary": "Ouvrir le CT principal", "pendingNote": "Une opération sur ce conteneur a été interrompue ; Récupérer ouvre sa récupération.", "update": "Mettre à jour", "recreate": "Recréer", diff --git a/AppImage/messages/it/common.json b/AppImage/messages/it/common.json index fe44d79f..cd7e7e7f 100644 --- a/AppImage/messages/it/common.json +++ b/AppImage/messages/it/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Immagine installata", "newImage": "Nuova immagine {image} disponibile", "stackNote": "Parte di un'applicazione multi-container (CT principale {primary}, {count} container): l'aggiornamento li comprende tutti.", + "memberNote": "Questo container fa parte di un'applicazione multi-container il cui CT principale è {primary} e non viene aggiornato singolarmente. L'aggiornamento si esegue dal CT principale, che aggiorna insieme tutti i {count} container.", + "openPrimary": "Apri il CT principale", "pendingNote": "Un'operazione su questo container è stata interrotta; Recupera ne apre il ripristino.", "update": "Aggiorna", "recreate": "Ricrea", diff --git a/AppImage/messages/pt/common.json b/AppImage/messages/pt/common.json index 086c0dd4..c005d441 100644 --- a/AppImage/messages/pt/common.json +++ b/AppImage/messages/pt/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Imagem instalada", "newImage": "Nova imagem {image} disponível", "stackNote": "Faz parte de uma aplicação com vários contentores (CT principal {primary}, {count} contentores): a atualização abrange todos.", + "memberNote": "Este contentor faz parte de uma aplicação com vários contentores cujo CT principal é {primary} e não é atualizado individualmente. A atualização é feita a partir do CT principal, que atualiza os {count} contentores em conjunto.", + "openPrimary": "Abrir o CT principal", "pendingNote": "Uma operação neste contentor foi interrompida; Recuperar abre a sua recuperação.", "update": "Atualizar", "recreate": "Recriar", diff --git a/AppImage/messages/sk/common.json b/AppImage/messages/sk/common.json index 52474efa..a7474034 100644 --- a/AppImage/messages/sk/common.json +++ b/AppImage/messages/sk/common.json @@ -1214,6 +1214,8 @@ "installedImage": "Nainštalovaný obraz", "newImage": "K dispozícii je nový obraz {image}", "stackNote": "Súčasť aplikácie s viacerými kontajnermi (hlavný CT {primary}, {count} kontajnerov): aktualizácia sa týka všetkých.", + "memberNote": "Tento kontajner patrí do aplikácie s viacerými kontajnermi, ktorej hlavný CT je {primary}, a neaktualizuje sa samostatne. Aktualizácia sa vykonáva z hlavného CT, ktorý aktualizuje všetkých {count} kontajnerov naraz.", + "openPrimary": "Otvoriť hlavný CT", "pendingNote": "Operácia na tomto kontajneri bola prerušená; Obnoviť otvorí jej obnovenie.", "update": "Aktualizovať", "recreate": "Znovu vytvoriť", diff --git a/AppImage/messages/sv/common.json b/AppImage/messages/sv/common.json index 88dc9c8e..a56309d1 100644 --- a/AppImage/messages/sv/common.json +++ b/AppImage/messages/sv/common.json @@ -1193,6 +1193,8 @@ "installedImage": "Installerad avbild", "newImage": "Ny avbild {image} tillgänglig", "stackNote": "Del av en applikation med flera containrar (huvud-CT {primary}, {count} containrar): uppdateringen omfattar alla.", + "memberNote": "Den här containern ingår i en applikation med flera containrar vars huvud-CT är {primary} och uppdateras inte separat. Uppdateringen görs från huvud-CT:n, som uppdaterar alla {count} containrar tillsammans.", + "openPrimary": "Öppna huvud-CT:n", "pendingNote": "En åtgärd på den här containern avbröts; Återställ öppnar dess återställning.", "update": "Uppdatera", "recreate": "Återskapa", diff --git a/web/messages/en/docs/oci-manager/monitor.json b/web/messages/en/docs/oci-manager/monitor.json index 0d121145..3826a1c0 100644 --- a/web/messages/en/docs/oci-manager/monitor.json +++ b/web/messages/en/docs/oci-manager/monitor.json @@ -118,7 +118,7 @@ } }, { - "p": "External changes, host directories and multi-container applications are handled as in the OCI menu. When the terminal closes, the image, the record and the mounts are read again." + "p": "External changes, host directories and multi-container applications are handled as in the OCI menu. In a multi-container application, the buttons and the options appear only on the main container; the other members show their image, a note that they are updated from the main container and a button that opens it. When the terminal closes, the image, the record and the mounts are read again." }, { "table": { diff --git a/web/messages/en/docs/oci-manager/storage-network.json b/web/messages/en/docs/oci-manager/storage-network.json index 68666cf9..1ba2cfd0 100644 --- a/web/messages/en/docs/oci-manager/storage-network.json +++ b/web/messages/en/docs/oci-manager/storage-network.json @@ -149,7 +149,7 @@ } }, { - "p": "The stack contract stores bridge, subnet, addresses and the relations between services. Updating or recreating a member reuses the same topology. ProxMenux Monitor opens the main container at its LAN address, not at its address on the private network." + "p": "The stack contract stores bridge, subnet, addresses and the relations between services. Updating the application reuses the same topology for every member. ProxMenux Monitor opens the main container at its LAN address, not at its address on the private network." } ] }, diff --git a/web/messages/es/docs/oci-manager/monitor.json b/web/messages/es/docs/oci-manager/monitor.json index 472a8456..c5da862f 100644 --- a/web/messages/es/docs/oci-manager/monitor.json +++ b/web/messages/es/docs/oci-manager/monitor.json @@ -118,7 +118,7 @@ } }, { - "p": "Los cambios externos, los directorios del host y las aplicaciones multicontenedor se tratan como en el menú OCI. Al cerrar la terminal se vuelven a leer la imagen, el registro y los montajes." + "p": "Los cambios externos, los directorios del host y las aplicaciones multicontenedor se tratan como en el menú OCI. En una aplicación multicontenedor, los botones y las opciones solo aparecen en el contenedor principal; los demás miembros muestran su imagen, una nota de que se actualizan desde el contenedor principal y un botón que lo abre. Al cerrar la terminal se vuelven a leer la imagen, el registro y los montajes." }, { "table": { @@ -128,7 +128,7 @@ ], "rows": [ [ - "Conservar el backup previo a la actualización", + "Conservar el backup realizado antes de actualizar", "Cada actualización hace un backup del contenedor para restaurarlo si falla. Con esta opción ese mismo backup se conserva en el almacenamiento elegido y aparece entre los backups del CT; en Proxmox Backup Server se escribe un backup antes de actualizar." ], [ diff --git a/web/messages/es/docs/oci-manager/storage-network.json b/web/messages/es/docs/oci-manager/storage-network.json index 8359ee28..800ef068 100644 --- a/web/messages/es/docs/oci-manager/storage-network.json +++ b/web/messages/es/docs/oci-manager/storage-network.json @@ -149,7 +149,7 @@ } }, { - "p": "El contrato de la pila guarda el bridge, la subred, las direcciones y las relaciones entre servicios. Actualizar o recrear un miembro reutiliza la misma topología. ProxMenux Monitor abre el contenedor principal en su dirección de la LAN, no en la de la red privada." + "p": "El contrato de la pila guarda el bridge, la subred, las direcciones y las relaciones entre servicios. La actualización de la aplicación reutiliza la misma topología en todos sus miembros. ProxMenux Monitor abre el contenedor principal en su dirección de la LAN, no en la de la red privada." } ] },