Merge pull request #45 from DumbWareio/fix/assets-sub-file-delete-on-edit

Add fix to file deletion on edit of assets and subassets
This commit is contained in:
Chris 2025-06-03 18:15:23 -07:00 committed by GitHub
commit 5204c1bb12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 102 deletions

View File

@ -526,16 +526,6 @@ export class ModalManager {
manualInfo.originalName || asset.manualPath.split('/').pop(),
manualInfo.size ? this.formatFileSize(manualInfo.size) : 'Unknown size'
);
const deleteBtn = manualPreview.querySelector('.delete-preview-btn');
if (deleteBtn) {
deleteBtn.onclick = () => {
if (confirm('Are you sure you want to delete this manual?')) {
manualPreview.innerHTML = '';
if (manualInput) manualInput.value = '';
this.deleteManual = true;
}
};
}
containsExistingFiles = true;
}
@ -593,16 +583,6 @@ export class ModalManager {
manualInfo.originalName || subAsset.manualPath.split('/').pop(),
manualInfo.size ? this.formatFileSize(manualInfo.size) : 'Unknown size'
);
const deleteBtn = manualPreview.querySelector('.delete-preview-btn');
if (deleteBtn) {
deleteBtn.onclick = () => {
if (confirm('Are you sure you want to delete this manual?')) {
manualPreview.innerHTML = '';
if (manualInput) manualInput.value = '';
this.deleteSubManual = true;
}
};
}
containsExistingFiles = true;
}

View File

@ -393,11 +393,8 @@ document.addEventListener('DOMContentLoaded', () => {
// Also add a dedicated refresh function to reload data without resetting the UI
async function refreshAllData() {
try {
const responses = await Promise.all([loadAssets(), loadSubAssets()]);
responses.forEach(async (response) => {
const responseValidation = await globalThis.validateResponse(response);
if (responseValidation.errorMessage) throw new Error(responseValidation.errorMessage);
})
const loadPromises = [loadAssets(), loadSubAssets()];
await Promise.all(loadPromises);
return true;
} catch (error) {
globalThis.logError('Error refreshing data:', error.message);
@ -407,9 +404,9 @@ document.addEventListener('DOMContentLoaded', () => {
async function saveAsset(asset) {
const saveBtn = assetForm.querySelector('.save-btn');
setButtonLoading(saveBtn, true);
try {
setButtonLoading(saveBtn, true);
const apiBaseUrl = globalThis.getApiBaseUrl();
// Get the actual edit mode from the modal manager instead of just checking for ID
const isEditMode = modalManager ? modalManager.isEditMode : false;
@ -426,46 +423,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
console.log('Edit mode determined as:', isEditMode);
// Log the current state of delete flags
console.log('Current delete flags:', {
deletePhoto: window.deletePhoto,
deleteReceipt: window.deleteReceipt,
deleteManual: window.deleteManual
});
// Handle file deletions
if (deletePhoto && assetToSave.photoPath) {
console.log(`Deleting photo: ${assetToSave.photoPath}`);
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: assetToSave.photoPath }),
credentials: 'include'
});
assetToSave.photoPath = null;
}
if (deleteReceipt && assetToSave.receiptPath) {
console.log(`Deleting receipt: ${assetToSave.receiptPath}`);
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: assetToSave.receiptPath }),
credentials: 'include'
});
assetToSave.receiptPath = null;
}
if (deleteManual && assetToSave.manualPath) {
console.log(`Deleting manual: ${assetToSave.manualPath}`);
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: assetToSave.manualPath }),
credentials: 'include'
});
assetToSave.manualPath = null;
}
console.log('After handling deletions, asset state:', {
photoPath: assetToSave.photoPath,
@ -537,9 +494,9 @@ document.addEventListener('DOMContentLoaded', () => {
async function saveSubAsset(subAsset) {
const saveBtn = subAssetForm.querySelector('.save-btn');
setButtonLoading(saveBtn, true);
try {
setButtonLoading(saveBtn, true);
const apiBaseUrl = globalThis.getApiBaseUrl();
// Get the actual edit mode from the modal manager instead of just checking for ID
const isEditMode = modalManager ? modalManager.isEditMode : false;
@ -563,34 +520,6 @@ document.addEventListener('DOMContentLoaded', () => {
throw new Error('Missing required fields for sub-asset. Check the console for details.');
}
if (deleteSubPhoto && subAsset.photoPath) {
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: subAsset.photoPath }),
credentials: 'include'
});
subAsset.photoPath = null;
}
if (deleteSubReceipt && subAsset.receiptPath) {
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: subAsset.receiptPath }),
credentials: 'include'
});
subAsset.receiptPath = null;
}
if (deleteSubManual && subAsset.manualPath) {
await fetch(`${apiBaseUrl}/api/delete-file`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: subAsset.manualPath }),
credentials: 'include'
});
subAsset.manualPath = null;
}
const response = await fetch(`${apiBaseUrl}/api/subasset`, {
method: isEditMode ? 'PUT' : 'POST',
headers: {
@ -622,7 +551,7 @@ document.addEventListener('DOMContentLoaded', () => {
refreshAssetDetails(subAsset.id, true);
} else {
// Navigate based on the saved component's context
await handleComponentNavigation(savedSubAsset);
await handleComponentNavigation({ id: savedSubAsset.id, parentId: savedSubAsset.parentId, parentSubId: savedSubAsset.parentSubId }, true);
}
// Show success message

View File

@ -618,14 +618,43 @@ app.put('/api/asset', (req, res) => {
if (index === -1) {
return res.status(404).json({ error: 'Asset not found' });
}
const oldAsset = assets[index];
// Preserve creation date
updatedAsset.createdAt = assets[index].createdAt;
// Update the modification date
updatedAsset.updatedAt = new Date().toISOString();
assets[index] = updatedAsset;
// Delete old files if new paths are provided
if (oldAsset.photoPath && updatedAsset.photoPath !== oldAsset.photoPath) {
deleteAssetFileAsync(oldAsset.photoPath);
} else if (updatedAsset.photoPath === oldAsset.photoPath) {
// If no new photoPath is provided, keep the old one
updatedAsset.photoPath = oldAsset.photoPath;
updatedAsset.photoInfo = oldAsset.photoInfo;
updatedAsset.photoPaths = oldAsset.photoPaths || [];
}
if (oldAsset.receiptPath && updatedAsset.receiptPath !== oldAsset.receiptPath) {
deleteAssetFileAsync(oldAsset.receiptPath);
} else if (updatedAsset.receiptPath === oldAsset.receiptPath) {
// If no new receiptPath is provided, keep the old one
updatedAsset.receiptPath = oldAsset.receiptPath;
updatedAsset.receiptInfo = oldAsset.receiptInfo;
updatedAsset.receiptPaths = oldAsset.receiptPaths || [];
}
if (oldAsset.manualPath && updatedAsset.manualPath !== oldAsset.manualPath) {
deleteAssetFileAsync(oldAsset.manualPath);
} else if (updatedAsset.manualPath === oldAsset.manualPath) {
// If no new manualPath is provided, keep the old one
updatedAsset.manualPath = oldAsset.manualPath;
updatedAsset.manualInfo = oldAsset.manualInfo;
updatedAsset.manualPaths = oldAsset.manualPaths || [];
}
const assetToSave = {...oldAsset, ...updatedAsset};
assets[index] = assetToSave;
if (writeJsonFile(assetsFilePath, assets)) {
if (DEBUG) {
console.log('[DEBUG] Asset edited:', { id: updatedAsset.id, name: updatedAsset.name, modelNumber: updatedAsset.modelNumber });
@ -821,13 +850,42 @@ app.put('/api/subasset', async (req, res) => {
if (index === -1) {
return res.status(404).json({ error: 'Sub-asset not found' });
}
const oldSubAsset = subAssets[index];
// Preserve creation date
updatedSubAsset.createdAt = subAssets[index].createdAt;
// Update the modification date
updatedSubAsset.updatedAt = new Date().toISOString();
subAssets[index] = updatedSubAsset;
// Delete old files if new paths are provided
if (oldSubAsset.photoPath && updatedSubAsset.photoPath !== oldSubAsset.photoPath) {
deleteAssetFileAsync(oldSubAsset.photoPath);
} else if (updatedSubAsset.photoPath === oldSubAsset.photoPath){
// If no new photoPath is provided, keep the old one
updatedSubAsset.photoPath = oldSubAsset.photoPath;
updatedSubAsset.photoInfo = oldSubAsset.photoInfo;
updatedSubAsset.photoPaths = oldSubAsset.photoPaths || [];
}
if (oldSubAsset.receiptPath && updatedSubAsset.receiptPath !== oldSubAsset.receiptPath) {
deleteAssetFileAsync(oldSubAsset.receiptPath);
} else if (updatedSubAsset.receiptPath === oldSubAsset.receiptPath){
// If no new receiptPath is provided, keep the old one
updatedSubAsset.receiptPath = oldSubAsset.receiptPath;
updatedSubAsset.receiptInfo = oldSubAsset.receiptInfo;
updatedSubAsset.receiptPaths = oldSubAsset.receiptPaths || [];
}
if (oldSubAsset.manualPath && updatedSubAsset.manualPath !== oldSubAsset.manualPath) {
deleteAssetFileAsync(oldSubAsset.manualPath);
} else if (updatedSubAsset.manualPath === oldSubAsset.manualPath){
// If no new manualPath is provided, keep the old one
updatedSubAsset.manualPath = oldSubAsset.manualPath;
updatedSubAsset.manualInfo = oldSubAsset.manualInfo;
updatedSubAsset.manualPaths = oldSubAsset.manualPaths || [];
}
const subAssetToSave = {...oldSubAsset, ...updatedSubAsset};
subAssets[index] = subAssetToSave;
if (writeJsonFile(subAssetsFilePath, subAssets)) {
if (DEBUG) {