Refactor API endpoints and update invoice generation
- Updated API calls in equipment.php, equipment_manage.php, and equipments_mass_update.php to use v2 endpoints. - Changed payload decoding from decode_payload to json_decode for consistency. - Enhanced invoice generation in factuur.php and webhook files to use a new email template and PDF structure. - Added new email and PDF templates for invoices to improve formatting and readability. - Improved marketing folder handling in marketing.php with better payload management. - Updated CSS for marketing to enhance UI interactions. - Added JavaScript checks for browser compatibility in softwaretool.php. - Adjusted user permissions in settingsprofiles.php to reflect new features.
This commit is contained in:
@@ -17,6 +17,13 @@ class MarketingFileManager {
|
||||
this.folders = []; // Store folders data
|
||||
this.loadRequestId = 0; // Track the latest load request
|
||||
|
||||
// Get permissions from PHP
|
||||
this.permissions = window.marketingPermissions || {
|
||||
canCreate: 0,
|
||||
canUpdate: 0,
|
||||
canDelete: 0
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
@@ -105,6 +112,18 @@ class MarketingFileManager {
|
||||
document.getElementById('saveEdit')?.addEventListener('click', () => {
|
||||
this.saveEdit();
|
||||
});
|
||||
|
||||
// Edit folder
|
||||
document.getElementById('saveEditFolder')?.addEventListener('click', () => {
|
||||
this.saveEditFolder();
|
||||
});
|
||||
|
||||
// Delete folder
|
||||
document.getElementById('deleteFolder')?.addEventListener('click', () => {
|
||||
if (this.selectedFolder) {
|
||||
this.deleteFolder(this.selectedFolder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bindUploadEvents() {
|
||||
@@ -317,15 +336,29 @@ class MarketingFileManager {
|
||||
const hasChildren = folder.children && folder.children.length > 0;
|
||||
const expandIcon = hasChildren ? '<i class="fa fa-chevron-right expand-icon"></i>' : '';
|
||||
|
||||
// Only show edit button if user has update permission
|
||||
const editButton = this.permissions.canUpdate === 1
|
||||
? `<button class="folder-edit-btn" title="Edit folder" data-folder-id="${folder.id}">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>`
|
||||
: '';
|
||||
|
||||
folderItem.innerHTML = `
|
||||
${expandIcon}
|
||||
<i class="fa fa-folder"></i>
|
||||
<span class="folder-name">${this.escapeHtml(folder.folder_name)}</span>
|
||||
<span class="file-count">(${folder.file_count})</span>
|
||||
${editButton}
|
||||
`;
|
||||
|
||||
folderItem.addEventListener('click', () => {
|
||||
this.selectFolder(folder.id);
|
||||
folderItem.addEventListener('click', (e) => {
|
||||
// Don't select folder if edit button was clicked
|
||||
if (e.target.closest('.folder-edit-btn')) {
|
||||
e.stopPropagation();
|
||||
this.editFolder(folder);
|
||||
} else {
|
||||
this.selectFolder(folder.id);
|
||||
}
|
||||
});
|
||||
|
||||
container.appendChild(folderItem);
|
||||
@@ -929,13 +962,20 @@ class MarketingFileManager {
|
||||
const folderId = document.getElementById('editFolder').value;
|
||||
const tags = document.getElementById('editTags').value.trim();
|
||||
|
||||
// Prepare update data
|
||||
const updateData = {
|
||||
file_id: this.selectedFile.id,
|
||||
title: title || null,
|
||||
folder_id: folderId || null,
|
||||
tags: tags ? tags.split(',').map(tag => tag.trim()).filter(tag => tag) : []
|
||||
};
|
||||
// Compare with original values to detect changes
|
||||
const originalTitle = this.selectedFile.title || '';
|
||||
const originalFolderId = this.selectedFile.folder_id || '';
|
||||
const originalTags = (this.selectedFile.tags || []).join(', ');
|
||||
|
||||
const hasChanges = title !== originalTitle ||
|
||||
folderId !== originalFolderId ||
|
||||
tags !== originalTags;
|
||||
|
||||
if (!hasChanges) {
|
||||
this.showToast('No changes detected', 'info');
|
||||
this.closeModal(document.getElementById('editModal'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
const saveBtn = document.getElementById('saveEdit');
|
||||
@@ -943,22 +983,35 @@ class MarketingFileManager {
|
||||
saveBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Saving...';
|
||||
saveBtn.disabled = true;
|
||||
|
||||
// Prepare FormData with only changed fields
|
||||
const formData = new FormData();
|
||||
formData.append('file_id', this.selectedFile.id);
|
||||
|
||||
if (title !== originalTitle) {
|
||||
formData.append('title', title);
|
||||
}
|
||||
if (folderId !== originalFolderId) {
|
||||
formData.append('folder_id', folderId);
|
||||
}
|
||||
if (tags !== originalTags) {
|
||||
formData.append('tags', tags);
|
||||
}
|
||||
|
||||
// Send update request
|
||||
fetch('./marketing.php?action=update_file', {
|
||||
fetch('index.php?page=marketing&action=marketing_update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(updateData)
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
this.showToast('File updated successfully!', 'success');
|
||||
this.closeModal(document.getElementById('editModal'));
|
||||
this.loadFiles(); // Reload to show changes
|
||||
// Reload window to reflect changes
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
} else {
|
||||
throw new Error(data.message || 'Failed to update file');
|
||||
throw new Error(data.error || data.message || 'Failed to update file');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -994,6 +1047,193 @@ class MarketingFileManager {
|
||||
this.renderUploadQueue();
|
||||
document.getElementById('startUpload').disabled = this.uploadQueue.length === 0;
|
||||
}
|
||||
|
||||
// Edit folder functionality
|
||||
editFolder(folder) {
|
||||
this.selectedFolder = folder;
|
||||
this.showEditFolderModal();
|
||||
this.populateEditFolderModal(folder);
|
||||
}
|
||||
|
||||
showEditFolderModal() {
|
||||
const modal = document.getElementById('editFolderModal');
|
||||
if (modal) {
|
||||
this.showModal(modal);
|
||||
}
|
||||
}
|
||||
|
||||
populateEditFolderModal(folder) {
|
||||
// Populate folder name
|
||||
const nameInput = document.getElementById('editFolderName');
|
||||
if (nameInput) {
|
||||
nameInput.value = folder.folder_name || '';
|
||||
}
|
||||
|
||||
// Populate parent folder select
|
||||
const parentSelect = document.getElementById('editParentFolder');
|
||||
if (parentSelect) {
|
||||
parentSelect.innerHTML = '<option value="">Root Folder</option>';
|
||||
this.addFolderOptionsExcluding(parentSelect, this.folders, folder.id);
|
||||
|
||||
// Select current parent
|
||||
if (folder.parent_id) {
|
||||
parentSelect.value = folder.parent_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate description
|
||||
const descInput = document.getElementById('editFolderDescription');
|
||||
if (descInput) {
|
||||
descInput.value = folder.description || '';
|
||||
}
|
||||
}
|
||||
|
||||
addFolderOptionsExcluding(select, folders, excludeId, level = 0) {
|
||||
// Add folders but exclude the current folder and its children
|
||||
folders.forEach(folder => {
|
||||
if (folder.id !== excludeId && !this.isFolderDescendant(folder, excludeId)) {
|
||||
const option = document.createElement('option');
|
||||
option.value = folder.id;
|
||||
option.textContent = ' '.repeat(level) + folder.folder_name;
|
||||
select.appendChild(option);
|
||||
|
||||
if (folder.children && folder.children.length > 0) {
|
||||
this.addFolderOptionsExcluding(select, folder.children, excludeId, level + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isFolderDescendant(folder, ancestorId) {
|
||||
// Check if folder is a descendant of ancestorId
|
||||
if (folder.id === ancestorId) return true;
|
||||
if (folder.children) {
|
||||
for (let child of folder.children) {
|
||||
if (this.isFolderDescendant(child, ancestorId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
saveEditFolder() {
|
||||
if (!this.selectedFolder) return;
|
||||
|
||||
const folderName = document.getElementById('editFolderName').value.trim();
|
||||
const parentId = document.getElementById('editParentFolder').value;
|
||||
const description = document.getElementById('editFolderDescription').value.trim();
|
||||
|
||||
// Compare with original values
|
||||
const originalName = this.selectedFolder.folder_name || '';
|
||||
const originalParentId = this.selectedFolder.parent_id || '';
|
||||
const originalDescription = this.selectedFolder.description || '';
|
||||
|
||||
const hasChanges = folderName !== originalName ||
|
||||
parentId !== originalParentId ||
|
||||
description !== originalDescription;
|
||||
|
||||
if (!hasChanges) {
|
||||
this.showToast('No changes detected', 'info');
|
||||
this.closeModal(document.getElementById('editFolderModal'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!folderName) {
|
||||
this.showToast('Folder name is required', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
const saveBtn = document.getElementById('saveEditFolder');
|
||||
const originalText = saveBtn.innerHTML;
|
||||
saveBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Saving...';
|
||||
saveBtn.disabled = true;
|
||||
|
||||
// Prepare FormData
|
||||
const formData = new FormData();
|
||||
formData.append('id', this.selectedFolder.id);
|
||||
|
||||
if (folderName !== originalName) {
|
||||
formData.append('folder_name', folderName);
|
||||
}
|
||||
if (parentId !== originalParentId) {
|
||||
formData.append('parent_id', parentId);
|
||||
}
|
||||
if (description !== originalDescription) {
|
||||
formData.append('description', description);
|
||||
}
|
||||
|
||||
// Send update request
|
||||
fetch('index.php?page=marketing&action=marketing_folders', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
this.showToast('Folder updated successfully!', 'success');
|
||||
// Reload window to reflect changes
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
} else {
|
||||
throw new Error(data.error || data.message || 'Failed to update folder');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Update folder error:', error);
|
||||
this.showToast('Error updating folder: ' + error.message, 'error');
|
||||
})
|
||||
.finally(() => {
|
||||
// Restore button state
|
||||
saveBtn.innerHTML = originalText;
|
||||
saveBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteFolder(folder) {
|
||||
if (!confirm(`Are you sure you want to delete the folder "${folder.folder_name}"? This action cannot be undone.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('id', folder.id);
|
||||
formData.append('delete', 'true');
|
||||
|
||||
const response = await fetch('index.php?page=marketing&action=marketing_folders', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
if (!text || text.trim() === '') {
|
||||
throw new Error('Empty response from server');
|
||||
}
|
||||
|
||||
const data = JSON.parse(text);
|
||||
|
||||
if (data && (data.success || !data.error)) {
|
||||
this.closeModal(document.getElementById('editFolderModal'));
|
||||
this.showToast('Folder deleted successfully!', 'success');
|
||||
// Reload window to reflect changes
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
} else if (data.error) {
|
||||
throw new Error(data.error);
|
||||
} else {
|
||||
throw new Error('Unexpected response format');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showToast(error.message || 'Error deleting folder', 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
|
||||
Reference in New Issue
Block a user