From d529e34249f64d8dbe32acd2d0e128903e7b8750 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Mon, 16 Mar 2026 10:27:12 +0100 Subject: [PATCH] feat(ui): anteprima duplicati/non smistati con pulizia cartella confermata --- main.js | 11 +++- preload.js | 3 ++ renderer/index.html | 31 +++++++++--- renderer/renderer.js | 116 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 136 insertions(+), 25 deletions(-) diff --git a/main.js b/main.js index 6bfff93..3160a5f 100644 --- a/main.js +++ b/main.js @@ -4,7 +4,13 @@ const fs = require('fs-extra'); const { processFolder } = require('./services/folderProcessor'); const { processZip } = require('./services/zipProcessor'); -const { resolveUnroutedDir, listUnroutedFiles } = require('./services/unrouted'); +const { + resolveUnroutedDir, + listUnroutedFiles, + listDuplicateFiles, + clearUnroutedFiles, + clearDuplicateFiles, +} = require('./services/unrouted'); const CAD_EXTENSIONS = ['prt', 'asm', 'dwr']; const DEFAULT_DESTINATION = './output/cad'; @@ -182,3 +188,6 @@ ipcMain.handle('open-unrouted-folder', async () => { }); ipcMain.handle('list-unrouted-files', async () => listUnroutedFiles()); +ipcMain.handle('list-duplicates-files', async () => listDuplicateFiles()); +ipcMain.handle('clear-unrouted-files', async () => clearUnroutedFiles()); +ipcMain.handle('clear-duplicates-files', async () => clearDuplicateFiles()); diff --git a/preload.js b/preload.js index 8729748..0dcdc68 100644 --- a/preload.js +++ b/preload.js @@ -10,4 +10,7 @@ contextBridge.exposeInMainWorld('api', { updateDestination: (destination) => ipcRenderer.invoke('update-destination', { destination }), openUnroutedFolder: () => ipcRenderer.invoke('open-unrouted-folder'), listUnroutedFiles: () => ipcRenderer.invoke('list-unrouted-files'), + listDuplicatesFiles: () => ipcRenderer.invoke('list-duplicates-files'), + clearUnroutedFiles: () => ipcRenderer.invoke('clear-unrouted-files'), + clearDuplicatesFiles: () => ipcRenderer.invoke('clear-duplicates-files'), }); diff --git a/renderer/index.html b/renderer/index.html index 19ca720..dfeeea1 100644 --- a/renderer/index.html +++ b/renderer/index.html @@ -133,6 +133,11 @@ margin-top: 10px; } + .rule-row.preview-actions { + grid-template-columns: auto auto; + justify-content: start; + } + .rule-label { font-size: 13px; color: var(--muted); @@ -195,11 +200,21 @@ gap: 10px; } + .preview-header-actions { + display: flex; + gap: 8px; + align-items: center; + } + .preview-header h2 { margin: 0; font-size: 18px; } + .danger { + background: #b91c1c; + } + .preview-meta { font-size: 12px; color: var(--muted); @@ -259,22 +274,26 @@ -
+
+
Pronto.
-
+
-

Anteprima __NON_SMISTATI

- +

Anteprima

+
+ + +
-
-
Nessun dato.
+
+
Nessun dato.
diff --git a/renderer/renderer.js b/renderer/renderer.js index 4fc9fa7..c5530f8 100644 --- a/renderer/renderer.js +++ b/renderer/renderer.js @@ -6,13 +6,17 @@ const destinationInput = document.getElementById('destinationInput'); const browseDestinationBtn = document.getElementById('browseDestinationBtn'); const saveDestinationBtn = document.getElementById('saveDestinationBtn'); const openUnroutedBtn = document.getElementById('openUnroutedBtn'); +const openDuplicatesBtn = document.getElementById('openDuplicatesBtn'); const destinationStatus = document.getElementById('destinationStatus'); -const unroutedPreviewOverlay = document.getElementById('unroutedPreviewOverlay'); -const closeUnroutedPreviewBtn = document.getElementById('closeUnroutedPreviewBtn'); -const unroutedPreviewMeta = document.getElementById('unroutedPreviewMeta'); -const unroutedPreviewList = document.getElementById('unroutedPreviewList'); +const previewOverlay = document.getElementById('previewOverlay'); +const closePreviewBtn = document.getElementById('closePreviewBtn'); +const clearPreviewBtn = document.getElementById('clearPreviewBtn'); +const previewTitle = document.getElementById('previewTitle'); +const previewMeta = document.getElementById('previewMeta'); +const previewList = document.getElementById('previewList'); const defaultDropZoneText = 'Trascina qui una cartella o un file .zip'; let isProcessing = false; +let currentPreviewKind = null; function setLoading(isLoading) { folderBtn.disabled = isLoading; @@ -24,6 +28,8 @@ function setDestinationLoading(isLoading) { browseDestinationBtn.disabled = isLoading; saveDestinationBtn.disabled = isLoading; openUnroutedBtn.disabled = isLoading; + openDuplicatesBtn.disabled = isLoading; + clearPreviewBtn.disabled = isLoading; } function formatBytes(bytes) { @@ -34,20 +40,39 @@ function formatBytes(bytes) { return `${(value / (1024 * 1024 * 1024)).toFixed(1)} GB`; } -function showUnroutedPreview(payload) { +function showPreview(kind, title, payload, emptyMessage) { const files = payload?.files || []; const directory = payload?.directory || ''; const lines = files.length ? files.map((file) => `- ${file.relativePath} | ${formatBytes(file.size)}`).join('\n') - : 'Nessun file presente in __NON_SMISTATI.'; + : emptyMessage; - unroutedPreviewMeta.textContent = `cartella: ${directory} | file totali: ${files.length}`; - unroutedPreviewList.textContent = lines; - unroutedPreviewOverlay.classList.add('visible'); + currentPreviewKind = kind; + previewTitle.textContent = title; + previewMeta.textContent = `cartella: ${directory} | file totali: ${files.length}`; + previewList.textContent = lines; + previewOverlay.classList.add('visible'); } -function hideUnroutedPreview() { - unroutedPreviewOverlay.classList.remove('visible'); +function hidePreview() { + currentPreviewKind = null; + previewOverlay.classList.remove('visible'); +} + +async function loadPreviewData(kind) { + if (kind === 'duplicates') { + return window.api.listDuplicatesFiles(); + } + + return window.api.listUnroutedFiles(); +} + +async function clearPreviewData(kind) { + if (kind === 'duplicates') { + return window.api.clearDuplicatesFiles(); + } + + return window.api.clearUnroutedFiles(); } function renderResult(title, result) { @@ -64,6 +89,7 @@ function renderResult(title, result) { `copiati: ${result.copied ?? 0}`, `saltati: ${result.skipped ?? 0}`, `non smistati: ${result.unrouted ?? 0}`, + `duplicati: ${result.duplicates ?? 0}`, '', 'dettagli (max 20):', detailsText, @@ -202,7 +228,12 @@ openUnroutedBtn.addEventListener('click', async () => { destinationStatus.textContent = 'Caricamento anteprima non smistati...'; const result = await window.api.listUnroutedFiles(); - showUnroutedPreview(result); + showPreview( + 'unrouted', + 'Anteprima __NON_SMISTATI', + result, + 'Nessun file presente in __NON_SMISTATI.' + ); destinationStatus.textContent = `Anteprima caricata (${result.files?.length || 0} file).`; } catch (error) { destinationStatus.textContent = `Errore: ${error.message}`; @@ -211,16 +242,65 @@ openUnroutedBtn.addEventListener('click', async () => { } }); -closeUnroutedPreviewBtn.addEventListener('click', hideUnroutedPreview); -unroutedPreviewOverlay.addEventListener('click', (event) => { - if (event.target === unroutedPreviewOverlay) { - hideUnroutedPreview(); +openDuplicatesBtn.addEventListener('click', async () => { + try { + setDestinationLoading(true); + destinationStatus.textContent = 'Caricamento anteprima duplicati...'; + + const result = await window.api.listDuplicatesFiles(); + showPreview('duplicates', 'Anteprima duplicati', result, 'Nessun file presente in duplicati.'); + destinationStatus.textContent = `Anteprima caricata (${result.files?.length || 0} file).`; + } catch (error) { + destinationStatus.textContent = `Errore: ${error.message}`; + } finally { + setDestinationLoading(false); + } +}); + +clearPreviewBtn.addEventListener('click', async () => { + if (!currentPreviewKind) { + return; + } + + const isDuplicates = currentPreviewKind === 'duplicates'; + const confirmMessage = isDuplicates + ? 'Confermi la pulizia della cartella duplicati?' + : 'Confermi la pulizia della cartella non smistati?'; + + if (!window.confirm(confirmMessage)) { + return; + } + + try { + setDestinationLoading(true); + destinationStatus.textContent = 'Pulizia cartella in corso...'; + + const clearResult = await clearPreviewData(currentPreviewKind); + const refreshed = await loadPreviewData(currentPreviewKind); + const title = isDuplicates ? 'Anteprima duplicati' : 'Anteprima __NON_SMISTATI'; + const emptyMessage = isDuplicates + ? 'Nessun file presente in duplicati.' + : 'Nessun file presente in __NON_SMISTATI.'; + + showPreview(currentPreviewKind, title, refreshed, emptyMessage); + destinationStatus.textContent = `Cartella pulita: ${clearResult.directory}`; + } catch (error) { + destinationStatus.textContent = `Errore: ${error.message}`; + } finally { + setDestinationLoading(false); + } +}); + +closePreviewBtn.addEventListener('click', hidePreview); +previewOverlay.addEventListener('click', (event) => { + if (event.target === previewOverlay) { + hidePreview(); } }); window.addEventListener('keydown', (event) => { - if (event.key === 'Escape' && unroutedPreviewOverlay.classList.contains('visible')) { - hideUnroutedPreview(); + if (event.key === 'Escape' && previewOverlay.classList.contains('visible')) { + hidePreview(); } });