Skip to content

Commit 696de4b

Browse files
committed
Refactor upload file handling to improve folder structure and enhance UI interactions
1 parent 61d68d5 commit 696de4b

File tree

2 files changed

+113
-49
lines changed

2 files changed

+113
-49
lines changed

synapse-electron/src/app.js

Lines changed: 113 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,16 +1385,35 @@ Parent ID: ${item.parent_id || 'N/A'}
13851385
const parentMap = new Map();
13861386
const rootItems = [];
13871387

1388-
// Create virtual folders for directory structure
1389-
files.forEach(file => {
1388+
// Separate files and folders
1389+
const actualFiles = files.filter(item => item.type === 'file');
1390+
const actualFolders = files.filter(item => item.type === 'folder');
1391+
1392+
// First, add all actual folders to the maps
1393+
actualFolders.forEach(folder => {
1394+
const normalizedPath = folder.relative_path.replace(/\\/g, '/');
1395+
if (!itemsMap.has(normalizedPath)) {
1396+
const folderObj = {
1397+
...folder,
1398+
id: `folder_${folder.path}`,
1399+
name: folder.name,
1400+
type: 'folder',
1401+
path: normalizedPath,
1402+
isVirtual: false
1403+
};
1404+
itemsMap.set(normalizedPath, folderObj);
1405+
}
1406+
});
1407+
1408+
// Create virtual folders for any missing parent directories of files
1409+
actualFiles.forEach(file => {
13901410
// Handle both Windows (\) and Unix (/) path separators
13911411
const pathParts = file.relative_path.replace(/\\/g, '/').split('/').filter(part => part.length > 0);
13921412

1393-
// Create all parent directories as virtual folders
1413+
// Create all parent directories as virtual folders (only if they don't already exist as actual folders)
13941414
let currentPath = '';
13951415
for (let i = 0; i < pathParts.length - 1; i++) {
13961416
const part = pathParts[i];
1397-
const parentPath = currentPath;
13981417
currentPath = currentPath ? `${currentPath}/${part}` : part;
13991418

14001419
if (!itemsMap.has(currentPath)) {
@@ -1406,19 +1425,29 @@ Parent ID: ${item.parent_id || 'N/A'}
14061425
isVirtual: true
14071426
};
14081427
itemsMap.set(currentPath, virtualFolder);
1428+
}
1429+
}
1430+
});
14091431

1410-
if (parentPath) {
1411-
if (!parentMap.has(parentPath)) {
1412-
parentMap.set(parentPath, []);
1413-
}
1414-
parentMap.get(parentPath).push(virtualFolder);
1415-
} else {
1416-
rootItems.push(virtualFolder);
1417-
}
1432+
// Now build the hierarchy relationships
1433+
itemsMap.forEach((item, path) => {
1434+
const pathParts = path.split('/');
1435+
if (pathParts.length === 1) {
1436+
// Root level item
1437+
rootItems.push(item);
1438+
} else {
1439+
// Find parent
1440+
const parentPath = pathParts.slice(0, -1).join('/');
1441+
if (!parentMap.has(parentPath)) {
1442+
parentMap.set(parentPath, []);
14181443
}
1444+
parentMap.get(parentPath).push(item);
14191445
}
1446+
});
14201447

1421-
// Add the file itself
1448+
// Add files to their parent directories
1449+
actualFiles.forEach(file => {
1450+
const pathParts = file.relative_path.replace(/\\/g, '/').split('/').filter(part => part.length > 0);
14221451
const fileName = pathParts[pathParts.length - 1];
14231452
const fileObj = {
14241453
...file,
@@ -1447,19 +1476,44 @@ Parent ID: ${item.parent_id || 'N/A'}
14471476
const itemElement = this.createUploadTreeItem(item, level);
14481477
container.appendChild(itemElement);
14491478

1450-
// Add children if this is a folder
1451-
if (item.type === 'folder' && parentMap.has(item.path)) {
1479+
// Add children if this is a folder and it has children
1480+
if (item.type === 'folder') {
1481+
const children = parentMap.get(item.path) || [];
14521482
const childrenContainer = document.createElement('div');
14531483
childrenContainer.className = 'tree-children';
1454-
childrenContainer.id = `upload-children-${item.id}`;
1484+
// Create a safe ID by replacing problematic characters
1485+
const safeId = item.id.replace(/[^a-zA-Z0-9_-]/g, '_');
1486+
childrenContainer.id = `upload-children-${safeId}`;
14551487
childrenContainer.style.display = 'block'; // Start expanded like download tree
14561488

1457-
this.createUploadTreeElements(
1458-
parentMap.get(item.path),
1459-
childrenContainer,
1460-
parentMap,
1461-
level + 1
1462-
);
1489+
if (children.length > 0) {
1490+
this.createUploadTreeElements(
1491+
children,
1492+
childrenContainer,
1493+
parentMap,
1494+
level + 1
1495+
);
1496+
} else {
1497+
// Handle empty folders - add a placeholder or just leave empty
1498+
// The folder will still be expandable but show as empty
1499+
const emptyMessage = document.createElement('div');
1500+
emptyMessage.className = 'tree-item empty-folder level-' + (level + 1);
1501+
emptyMessage.innerHTML = `
1502+
<div class="tree-item-content upload-compact" style="opacity: 0.6; font-style: italic;">
1503+
<span style="margin-left: 20px;">Empty folder</span>
1504+
</div>
1505+
`;
1506+
childrenContainer.appendChild(emptyMessage);
1507+
}
1508+
1509+
// Update the toggle button class based on whether folder has children
1510+
const toggleButton = itemElement.querySelector('.tree-toggle');
1511+
if (toggleButton) {
1512+
if (children.length === 0) {
1513+
toggleButton.classList.remove('expanded');
1514+
toggleButton.classList.add('leaf');
1515+
}
1516+
}
14631517

14641518
container.appendChild(childrenContainer);
14651519
}
@@ -1478,7 +1532,7 @@ Parent ID: ${item.parent_id || 'N/A'}
14781532
if (item.type === 'folder') {
14791533
// For folders: "Folder Name (folder)" - we'll add count later if needed
14801534
content = `
1481-
<button class="tree-toggle expanded" onclick="window.synapseApp.toggleUploadFolder('${item.id}')">
1535+
<button class="tree-toggle expanded" data-folder-id="${this.escapeHtml(item.id)}">
14821536
</button>
14831537
<div class="tree-item-content upload-compact">
14841538
<i class="fas fa-folder tree-item-icon folder"></i>
@@ -1492,20 +1546,32 @@ Parent ID: ${item.parent_id || 'N/A'}
14921546
<button class="tree-toggle leaf">
14931547
</button>
14941548
<div class="tree-item-content upload-compact">
1495-
<input type="checkbox" class="item-checkbox" data-id="${item.id}">
1549+
<input type="checkbox" class="item-checkbox" data-id="${this.escapeHtml(item.id)}">
14961550
<i class="fas fa-file tree-item-icon file"></i>
14971551
<span class="upload-item-info">${this.escapeHtml(item.name)} <span class="item-meta">(${sizeStr})</span></span>
14981552
</div>
14991553
`;
1554+
}
15001555

1556+
itemDiv.innerHTML = content;
1557+
1558+
// Add event listeners instead of inline onclick handlers
1559+
if (item.type === 'folder') {
1560+
const toggleButton = itemDiv.querySelector('.tree-toggle');
1561+
if (toggleButton) {
1562+
toggleButton.addEventListener('click', () => {
1563+
this.toggleUploadFolder(item.id);
1564+
});
1565+
}
1566+
} else {
1567+
// Add event listener for file checkbox
15011568
itemDiv.addEventListener('change', (e) => {
15021569
if (e.target.classList.contains('item-checkbox')) {
15031570
this.handleUploadFileSelection(item.id, e.target.checked);
15041571
}
15051572
});
15061573
}
15071574

1508-
itemDiv.innerHTML = content;
15091575
return itemDiv;
15101576
}
15111577

@@ -1545,8 +1611,17 @@ Parent ID: ${item.parent_id || 'N/A'}
15451611
}
15461612

15471613
toggleUploadFolder(itemId) {
1548-
const toggleButton = document.querySelector(`#upload-files-tree .tree-item[data-id="${itemId}"] .tree-toggle`);
1549-
const childrenDiv = document.getElementById(`upload-children-${itemId}`);
1614+
// Find the tree item and toggle button using the dataset id
1615+
const treeItem = document.querySelector(`#upload-files-tree .tree-item[data-id="${CSS.escape(itemId)}"]`);
1616+
if (!treeItem) {
1617+
console.warn('Could not find tree item for ID:', itemId);
1618+
return;
1619+
}
1620+
1621+
const toggleButton = treeItem.querySelector('.tree-toggle');
1622+
// Create the same safe ID used when creating the container
1623+
const safeId = itemId.replace(/[^a-zA-Z0-9_-]/g, '_');
1624+
const childrenDiv = document.getElementById(`upload-children-${safeId}`);
15501625

15511626
if (toggleButton && childrenDiv) {
15521627
const isExpanded = toggleButton.classList.contains('expanded');
@@ -1560,6 +1635,8 @@ Parent ID: ${item.parent_id || 'N/A'}
15601635
toggleButton.classList.add('expanded');
15611636
childrenDiv.style.display = 'block';
15621637
}
1638+
} else {
1639+
console.warn('Could not find toggle button or children container for ID:', itemId, 'Safe ID:', safeId);
15631640
}
15641641
}
15651642

@@ -1569,7 +1646,8 @@ Parent ID: ${item.parent_id || 'N/A'}
15691646
if (!toggle.classList.contains('leaf')) {
15701647
const treeItem = toggle.closest('.tree-item');
15711648
const itemId = treeItem.dataset.id;
1572-
const childrenContainer = document.getElementById(`upload-children-${itemId}`);
1649+
const safeId = itemId.replace(/[^a-zA-Z0-9_-]/g, '_');
1650+
const childrenContainer = document.getElementById(`upload-children-${safeId}`);
15731651
if (childrenContainer) {
15741652
childrenContainer.style.display = 'block';
15751653
toggle.classList.remove('collapsed');
@@ -1585,7 +1663,8 @@ Parent ID: ${item.parent_id || 'N/A'}
15851663
if (!toggle.classList.contains('leaf')) {
15861664
const treeItem = toggle.closest('.tree-item');
15871665
const itemId = treeItem.dataset.id;
1588-
const childrenContainer = document.getElementById(`upload-children-${itemId}`);
1666+
const safeId = itemId.replace(/[^a-zA-Z0-9_-]/g, '_');
1667+
const childrenContainer = document.getElementById(`upload-children-${safeId}`);
15891668
if (childrenContainer) {
15901669
childrenContainer.style.display = 'none';
15911670
toggle.classList.remove('expanded');
@@ -1595,18 +1674,6 @@ Parent ID: ${item.parent_id || 'N/A'}
15951674
});
15961675
}
15971676

1598-
collapseAllUploadFolders() {
1599-
const toggles = document.querySelectorAll('#upload-files-tree .tree-toggle');
1600-
toggles.forEach(toggle => {
1601-
const folderElement = toggle.closest('.tree-item');
1602-
const childrenContainer = folderElement.nextElementSibling;
1603-
if (childrenContainer && childrenContainer.classList.contains('tree-children')) {
1604-
childrenContainer.style.display = 'none';
1605-
toggle.textContent = '▶';
1606-
}
1607-
});
1608-
}
1609-
16101677
formatFileSize(bytes) {
16111678
if (!bytes) return '';
16121679
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
@@ -1629,10 +1696,11 @@ Parent ID: ${item.parent_id || 'N/A'}
16291696
}
16301697

16311698
try {
1632-
// Get selected file data
1633-
const selectedFileData = this.uploadFileItems.filter(file =>
1634-
this.selectedUploadFiles.has(`file_${file.path}`)
1635-
);
1699+
// Get selected file data - handle both old and new ID formats
1700+
const selectedFileData = this.uploadFileItems.filter(file => {
1701+
const fileId = `file_${file.path}`;
1702+
return this.selectedUploadFiles.has(fileId) || this.selectedUploadFiles.has(file.id);
1703+
});
16361704

16371705
const result = await window.electronAPI.bulkUpload({
16381706
parent_id: parentId,

synapse-electron/src/index.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
<link rel="stylesheet" href="styles.css">
88
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
99
<!-- JSTree CSS and JS -->
10-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/themes/default/style.min.css">
11-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
12-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/jstree.min.js"></script>
13-
<!-- JSTree for enhanced tree functionality -->
1410
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.15/themes/default/style.min.css">
1511
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
1612
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.15/jstree.min.js"></script>

0 commit comments

Comments
 (0)