-
+
@@ -18,12 +18,20 @@
> ⚠️ **AVISO CRÍTICO:** Aplicação em estágio inicial de desenvolvimento. Não use em produção — há risco de perda de dados.
-Versão atual: **0.0.7**
+Versão atual: **0.0.8**
---
## � Changelog
+### [0.0.8] — 2026-05-09
+
+#### Corrigido
+- **Botões dos modais:** botões "Marcar todos" e "Confirmar seleção" do modal de seleção de volumes (e de todos os outros dialogs modais) agora usam o sistema de design `.btn` correto, com estilos primário e secundário consistentes com o restante da interface.
+- **Exclusão de arquivos de backup em disco:** ao excluir um profile, todos os arquivos `.tar.gz` de cada backup registrado no store são deletados do disco antes de remover o registro. Em seguida, a pasta do profile (incluindo arquivos `.snar` e outros arquivos não catalogados) também é removida. A deleção agora cobre backups feitos com diferentes diretórios (ex.: após troca de Storage Location).
+
+---
+
### [0.0.7] — 2026-05-09
#### Adicionado
diff --git a/package.json b/package.json
index 5bf7640..6b58b92 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "dockerbackup-app",
- "version": "0.0.7",
+ "version": "0.0.8",
"description": "Aplicacao web para backup e restauracao de volumes Docker",
"main": "src/server.js",
"scripts": {
diff --git a/public/index.html b/public/index.html
index 33eaeb3..a441658 100644
--- a/public/index.html
+++ b/public/index.html
@@ -357,8 +357,8 @@
-
-
+
+
diff --git a/src/server.js b/src/server.js
index 5185986..dbbf85e 100644
--- a/src/server.js
+++ b/src/server.js
@@ -262,13 +262,34 @@ async function main() {
app.delete('/api/profiles/:profileId', authMiddleware, async (request, response) => {
try {
- const profile = await store.getProfile(request.params.profileId);
- await store.deleteProfile(request.params.profileId);
+ const profileId = request.params.profileId;
+ const profile = await store.getProfile(profileId);
+ const backups = await store.listBackups(profileId);
+ await store.deleteProfile(profileId);
+
+ // Deleta arquivos de backup gravados em disco usando os caminhos registrados
+ const slugifyLocal = (value) => value.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase() || 'item';
+ const deletedProfileDirs = new Set();
+ for (const backup of backups) {
+ const backupRoot = backup.backupDir;
+ if (!backupRoot) continue;
+ for (const container of backup.containers || []) {
+ if (container.archiveRelativePath) {
+ await fs.rm(path.join(backupRoot, container.archiveRelativePath), { force: true });
+ }
+ }
+ if (profile?.name) {
+ deletedProfileDirs.add(path.join(backupRoot, slugifyLocal(profile.name)));
+ }
+ }
+
+ // Limpa a pasta do profile (cobre .snar e outros arquivos não registrados no store)
if (profile?.backupDir) {
- const slugify = (value) => value.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase() || 'item';
- const profileBackupDir = path.join(profile.backupDir, slugify(profile.name));
- await fs.rm(profileBackupDir, { recursive: true, force: true });
+ deletedProfileDirs.add(path.join(profile.backupDir, slugifyLocal(profile.name)));
+ }
+ for (const dir of deletedProfileDirs) {
+ await fs.rm(dir, { recursive: true, force: true });
}
response.status(204).end();