feat: smistamento file non-CAD, rinomina cartelle speciali, guida utente
- Aggiunge cartella __SALTATI: i file non-CAD vengono ora copiati in __SALTATI invece di essere ignorati (folderProcessor, zipProcessor) - Rinomina cartella duplicati in __DUPLICATI per coerenza con le altre cartelle speciali (__NON_SMISTATI, __SALTATI) - Aggiunge pulsante "Anteprima saltati" in UI con anteprima e pulizia - Aggiunge guida utente HTML/CSS in renderer/docs/ con sidebar navigabile - Aggiunge menu Help > Documentazione che apre la guida in una finestra - Imposta DEFAULT_DESTINATION a X:\
This commit is contained in:
4
main.js
4
main.js
@@ -8,8 +8,10 @@ const {
|
||||
resolveUnroutedDir,
|
||||
listUnroutedFiles,
|
||||
listDuplicateFiles,
|
||||
listSkippedFiles,
|
||||
clearUnroutedFiles,
|
||||
clearDuplicateFiles,
|
||||
clearSkippedFiles,
|
||||
} = require('./services/unrouted');
|
||||
|
||||
const CAD_EXTENSIONS = ['prt', 'asm', 'dwr'];
|
||||
@@ -209,5 +211,7 @@ ipcMain.handle('open-unrouted-folder', async () => {
|
||||
|
||||
ipcMain.handle('list-unrouted-files', async () => listUnroutedFiles());
|
||||
ipcMain.handle('list-duplicates-files', async () => listDuplicateFiles());
|
||||
ipcMain.handle('list-skipped-files', async () => listSkippedFiles());
|
||||
ipcMain.handle('clear-unrouted-files', async () => clearUnroutedFiles());
|
||||
ipcMain.handle('clear-duplicates-files', async () => clearDuplicateFiles());
|
||||
ipcMain.handle('clear-skipped-files', async () => clearSkippedFiles());
|
||||
|
||||
@@ -11,6 +11,8 @@ contextBridge.exposeInMainWorld('api', {
|
||||
openUnroutedFolder: () => ipcRenderer.invoke('open-unrouted-folder'),
|
||||
listUnroutedFiles: () => ipcRenderer.invoke('list-unrouted-files'),
|
||||
listDuplicatesFiles: () => ipcRenderer.invoke('list-duplicates-files'),
|
||||
listSkippedFiles: () => ipcRenderer.invoke('list-skipped-files'),
|
||||
clearUnroutedFiles: () => ipcRenderer.invoke('clear-unrouted-files'),
|
||||
clearDuplicatesFiles: () => ipcRenderer.invoke('clear-duplicates-files'),
|
||||
clearSkippedFiles: () => ipcRenderer.invoke('clear-skipped-files'),
|
||||
});
|
||||
|
||||
@@ -277,6 +277,7 @@
|
||||
<div class="rule-row single-row preview-actions">
|
||||
<button id="openUnroutedBtn" class="browse">Anteprima non smistati</button>
|
||||
<button id="openDuplicatesBtn" class="browse">Anteprima duplicati</button>
|
||||
<button id="openSkippedBtn" class="browse">Anteprima saltati</button>
|
||||
</div>
|
||||
<div class="rule-status" id="destinationStatus"></div>
|
||||
</section>
|
||||
|
||||
@@ -7,6 +7,7 @@ const browseDestinationBtn = document.getElementById('browseDestinationBtn');
|
||||
const saveDestinationBtn = document.getElementById('saveDestinationBtn');
|
||||
const openUnroutedBtn = document.getElementById('openUnroutedBtn');
|
||||
const openDuplicatesBtn = document.getElementById('openDuplicatesBtn');
|
||||
const openSkippedBtn = document.getElementById('openSkippedBtn');
|
||||
const destinationStatus = document.getElementById('destinationStatus');
|
||||
const previewOverlay = document.getElementById('previewOverlay');
|
||||
const closePreviewBtn = document.getElementById('closePreviewBtn');
|
||||
@@ -29,6 +30,7 @@ function setDestinationLoading(isLoading) {
|
||||
saveDestinationBtn.disabled = isLoading;
|
||||
openUnroutedBtn.disabled = isLoading;
|
||||
openDuplicatesBtn.disabled = isLoading;
|
||||
openSkippedBtn.disabled = isLoading;
|
||||
clearPreviewBtn.disabled = isLoading;
|
||||
}
|
||||
|
||||
@@ -60,18 +62,14 @@ function hidePreview() {
|
||||
}
|
||||
|
||||
async function loadPreviewData(kind) {
|
||||
if (kind === 'duplicates') {
|
||||
return window.api.listDuplicatesFiles();
|
||||
}
|
||||
|
||||
if (kind === 'duplicates') return window.api.listDuplicatesFiles();
|
||||
if (kind === 'skipped') return window.api.listSkippedFiles();
|
||||
return window.api.listUnroutedFiles();
|
||||
}
|
||||
|
||||
async function clearPreviewData(kind) {
|
||||
if (kind === 'duplicates') {
|
||||
return window.api.clearDuplicatesFiles();
|
||||
}
|
||||
|
||||
if (kind === 'duplicates') return window.api.clearDuplicatesFiles();
|
||||
if (kind === 'skipped') return window.api.clearSkippedFiles();
|
||||
return window.api.clearUnroutedFiles();
|
||||
}
|
||||
|
||||
@@ -248,7 +246,22 @@ openDuplicatesBtn.addEventListener('click', async () => {
|
||||
destinationStatus.textContent = 'Caricamento anteprima duplicati...';
|
||||
|
||||
const result = await window.api.listDuplicatesFiles();
|
||||
showPreview('duplicates', 'Anteprima duplicati', result, 'Nessun file presente in duplicati.');
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
openSkippedBtn.addEventListener('click', async () => {
|
||||
try {
|
||||
setDestinationLoading(true);
|
||||
destinationStatus.textContent = 'Caricamento anteprima saltati...';
|
||||
|
||||
const result = await window.api.listSkippedFiles();
|
||||
showPreview('skipped', 'Anteprima __SALTATI', result, 'Nessun file presente in __SALTATI.');
|
||||
destinationStatus.textContent = `Anteprima caricata (${result.files?.length || 0} file).`;
|
||||
} catch (error) {
|
||||
destinationStatus.textContent = `Errore: ${error.message}`;
|
||||
@@ -263,8 +276,11 @@ clearPreviewBtn.addEventListener('click', async () => {
|
||||
}
|
||||
|
||||
const isDuplicates = currentPreviewKind === 'duplicates';
|
||||
const isSkipped = currentPreviewKind === 'skipped';
|
||||
const confirmMessage = isDuplicates
|
||||
? 'Confermi la pulizia della cartella duplicati?'
|
||||
? 'Confermi la pulizia della cartella __DUPLICATI?'
|
||||
: isSkipped
|
||||
? 'Confermi la pulizia della cartella saltati?'
|
||||
: 'Confermi la pulizia della cartella non smistati?';
|
||||
|
||||
if (!window.confirm(confirmMessage)) {
|
||||
@@ -277,9 +293,11 @@ clearPreviewBtn.addEventListener('click', async () => {
|
||||
|
||||
const clearResult = await clearPreviewData(currentPreviewKind);
|
||||
const refreshed = await loadPreviewData(currentPreviewKind);
|
||||
const title = isDuplicates ? 'Anteprima duplicati' : 'Anteprima __NON_SMISTATI';
|
||||
const title = isDuplicates ? 'Anteprima __DUPLICATI' : isSkipped ? 'Anteprima __SALTATI' : 'Anteprima __NON_SMISTATI';
|
||||
const emptyMessage = isDuplicates
|
||||
? 'Nessun file presente in duplicati.'
|
||||
? 'Nessun file presente in __DUPLICATI.'
|
||||
: isSkipped
|
||||
? 'Nessun file presente in __SALTATI.'
|
||||
: 'Nessun file presente in __NON_SMISTATI.';
|
||||
|
||||
showPreview(currentPreviewKind, title, refreshed, emptyMessage);
|
||||
|
||||
@@ -3,7 +3,7 @@ const path = require('path');
|
||||
const { getDestinationDecision, getCadInfo } = require('./router');
|
||||
const { buildDestinationIndex } = require('./destinationIndex');
|
||||
const { buildExistingCadKeyIndex, toCadKey } = require('./duplicateIndex');
|
||||
const { prepareUnroutedTarget, prepareDuplicateTarget } = require('./unrouted');
|
||||
const { prepareUnroutedTarget, prepareDuplicateTarget, getSkippedTarget } = require('./unrouted');
|
||||
|
||||
function parseNumericVersion(version) {
|
||||
const rawVersion = String(version || '').trim();
|
||||
@@ -86,7 +86,10 @@ async function processFolder(folder, config) {
|
||||
|
||||
const cadInfo = getCadInfo(file);
|
||||
if (!cadInfo) {
|
||||
const skippedTarget = await getSkippedTarget(file);
|
||||
await fs.copy(fullPath, skippedTarget.destinationPath);
|
||||
result.skipped += 1;
|
||||
result.copied += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ const { getCadInfo } = require('./router');
|
||||
|
||||
const PRIMARY_UNROUTED_DIR = '/cadroute/__NON_SMISTATI';
|
||||
const HOME_UNROUTED_DIR = path.join(os.homedir(), '.cadroute', '__NON_SMISTATI');
|
||||
const PRIMARY_DUPLICATES_DIR = '/cadroute/duplicati';
|
||||
const HOME_DUPLICATES_DIR = path.join(os.homedir(), '.cadroute', 'duplicati');
|
||||
const PRIMARY_DUPLICATES_DIR = '/cadroute/__DUPLICATI';
|
||||
const HOME_DUPLICATES_DIR = path.join(os.homedir(), '.cadroute', '__DUPLICATI');
|
||||
const PRIMARY_SKIPPED_DIR = '/cadroute/__SALTATI';
|
||||
const HOME_SKIPPED_DIR = path.join(os.homedir(), '.cadroute', '__SALTATI');
|
||||
|
||||
const SPECIAL_TARGETS = {
|
||||
unrouted: {
|
||||
@@ -17,6 +19,10 @@ const SPECIAL_TARGETS = {
|
||||
primary: PRIMARY_DUPLICATES_DIR,
|
||||
fallback: HOME_DUPLICATES_DIR,
|
||||
},
|
||||
skipped: {
|
||||
primary: PRIMARY_SKIPPED_DIR,
|
||||
fallback: HOME_SKIPPED_DIR,
|
||||
},
|
||||
};
|
||||
|
||||
const resolvedDirs = new Map();
|
||||
@@ -178,6 +184,22 @@ async function prepareDuplicateTarget(fileName) {
|
||||
return prepareSpecialTarget('duplicates', fileName);
|
||||
}
|
||||
|
||||
async function resolveSkippedDir() {
|
||||
return resolveTargetDir('skipped');
|
||||
}
|
||||
|
||||
async function getSkippedTarget(fileName) {
|
||||
return getTarget('skipped', fileName);
|
||||
}
|
||||
|
||||
async function listSkippedFiles() {
|
||||
return listTargetFiles('skipped');
|
||||
}
|
||||
|
||||
async function clearSkippedFiles() {
|
||||
return clearTargetFiles('skipped');
|
||||
}
|
||||
|
||||
async function listFilesRecursively(rootDir) {
|
||||
const files = [];
|
||||
|
||||
@@ -251,16 +273,22 @@ async function clearDuplicateFiles() {
|
||||
module.exports = {
|
||||
getUnroutedTarget,
|
||||
getDuplicateTarget,
|
||||
getSkippedTarget,
|
||||
prepareUnroutedTarget,
|
||||
prepareDuplicateTarget,
|
||||
resolveUnroutedDir,
|
||||
resolveDuplicatesDir,
|
||||
resolveSkippedDir,
|
||||
listUnroutedFiles,
|
||||
listDuplicateFiles,
|
||||
listSkippedFiles,
|
||||
clearUnroutedFiles,
|
||||
clearDuplicateFiles,
|
||||
clearSkippedFiles,
|
||||
PRIMARY_UNROUTED_DIR,
|
||||
HOME_UNROUTED_DIR,
|
||||
PRIMARY_DUPLICATES_DIR,
|
||||
HOME_DUPLICATES_DIR,
|
||||
PRIMARY_SKIPPED_DIR,
|
||||
HOME_SKIPPED_DIR,
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ const { pipeline } = require('stream/promises');
|
||||
const { getDestinationDecision, getCadInfo } = require('./router');
|
||||
const { buildDestinationIndex } = require('./destinationIndex');
|
||||
const { buildExistingCadKeyIndex, toCadKey } = require('./duplicateIndex');
|
||||
const { prepareUnroutedTarget, prepareDuplicateTarget } = require('./unrouted');
|
||||
const { prepareUnroutedTarget, prepareDuplicateTarget, getSkippedTarget } = require('./unrouted');
|
||||
|
||||
function parseNumericVersion(version) {
|
||||
const rawVersion = String(version || '').trim();
|
||||
@@ -82,8 +82,10 @@ async function processZip(zipPath, config) {
|
||||
|
||||
const cadInfo = getCadInfo(baseName);
|
||||
if (!cadInfo) {
|
||||
const skippedTarget = await getSkippedTarget(baseName);
|
||||
await pipeline(entry, fs.createWriteStream(skippedTarget.destinationPath));
|
||||
result.skipped += 1;
|
||||
entry.autodrain();
|
||||
result.copied += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user