Implement debounced MAC address processing and enhance RADIUS user creation for Chrome Extension integration

This commit is contained in:
2025-12-01 12:10:43 +01:00
parent 1df61765da
commit 902bd03664
@@ -116,14 +116,9 @@ Vue.component('Cpeprovisioning', {
<tt-button text="In Radius anlegen" <tt-button text="In Radius anlegen"
@click="createRadiusUser(item)" @click="createRadiusUser(item)"
:disabled="!isValidMac(item.cpe_data.mac)" :disabled="!isValidMac(item.cpe_data.mac)"
:loading="item.isCreatingRadius"
sm sm
additional-class="btn-primary" /> additional-class="btn-primary"
<tt-button text="ACS Auto VLAN Zuweisung testen" title="Sendet Kundendaten an Chrome Extension" />
@click="testAcsVlan(item)"
:disabled="!isVlanSelected(item) || !isValidMac(item.cpe_data.mac)"
sm
additional-class="btn-info mt-2" />
</div> </div>
<div class="finish-wrapper mt-auto"> <div class="finish-wrapper mt-auto">
<label class="col-form-label col-form-label-sm">Konfig abgeschlossen</label> <label class="col-form-label col-form-label-sm">Konfig abgeschlossen</label>
@@ -180,6 +175,7 @@ Vue.component('Cpeprovisioning', {
page: 1, page: 1,
pagination: {}, pagination: {},
debouncedFetchData: null, debouncedFetchData: null,
debouncedMacHandlers: {}, // Store debounced handlers per item
extensionId: 'jglijfiddilckddlmbnlojmmlahboffh', extensionId: 'jglijfiddilckddlmbnlojmmlahboffh',
showExtensionIdModal: false, showExtensionIdModal: false,
processingMacItems: new Set() // Track items currently being processed processingMacItems: new Set() // Track items currently being processed
@@ -261,7 +257,6 @@ Vue.component('Cpeprovisioning', {
...item, ...item,
isDirty: false, isDirty: false,
isSaving: false, isSaving: false,
isCreatingRadius: false,
pop_name: item.pop_name || 'N/A', pop_name: item.pop_name || 'N/A',
owner_address: `${item.owner_street || ''} ${item.owner_housenumber || ''}, ${item.owner_zip || ''} ${item.owner_city || ''}`, owner_address: `${item.owner_street || ''} ${item.owner_housenumber || ''}, ${item.owner_zip || ''} ${item.owner_city || ''}`,
owner_phone: item.owner_phone || '', owner_phone: item.owner_phone || '',
@@ -350,8 +345,9 @@ Vue.component('Cpeprovisioning', {
console.log('[MAC Input] Current MAC value:', item.cpe_data.mac); console.log('[MAC Input] Current MAC value:', item.cpe_data.mac);
console.log('[MAC Input] Router type:', item.cpe_data.routertype); console.log('[MAC Input] Router type:', item.cpe_data.routertype);
// Check if we're already processing this item to prevent recursion
const itemKey = item.orderproduct_id; const itemKey = item.orderproduct_id;
// Check if we're already processing this item to prevent recursion
if (this.processingMacItems.has(itemKey)) { if (this.processingMacItems.has(itemKey)) {
console.log('[MAC Input] Already processing this item, returning to prevent recursion'); console.log('[MAC Input] Already processing this item, returning to prevent recursion');
return; return;
@@ -359,7 +355,18 @@ Vue.component('Cpeprovisioning', {
this.markDirty(item); this.markDirty(item);
this.processMacAddress(item); // Create a debounced handler for this item if it doesn't exist
if (!this.debouncedMacHandlers[itemKey]) {
console.log('[MAC Input] Creating debounced handler for item:', itemKey);
this.debouncedMacHandlers[itemKey] = _.debounce((itm) => {
console.log('[MAC Input] Debounced handler executing for item:', itemKey);
this.processMacAddress(itm);
}, 300); // 300ms delay to wait for barcode scanner to finish
}
// Call the debounced handler
console.log('[MAC Input] Calling debounced handler');
this.debouncedMacHandlers[itemKey](item);
}, },
handleRouterTypeChange(item) { handleRouterTypeChange(item) {
console.log('[Router Type Change] Router type changed, checking if MAC needs processing'); console.log('[Router Type Change] Router type changed, checking if MAC needs processing');
@@ -370,6 +377,10 @@ Vue.component('Cpeprovisioning', {
const routerType = item.cpe_data.routertype; const routerType = item.cpe_data.routertype;
const itemKey = item.orderproduct_id; const itemKey = item.orderproduct_id;
console.log('[MAC Process] === START processMacAddress ===');
console.log('[MAC Process] Input value:', inputValue);
console.log('[MAC Process] Router type:', routerType);
// Only process if it's a QR code format (contains dash, no colons) // Only process if it's a QR code format (contains dash, no colons)
// This prevents reprocessing already formatted MAC addresses // This prevents reprocessing already formatted MAC addresses
if (!inputValue) { if (!inputValue) {
@@ -399,6 +410,13 @@ Vue.component('Cpeprovisioning', {
// Mark this item as being processed // Mark this item as being processed
this.processingMacItems.add(itemKey); this.processingMacItems.add(itemKey);
console.log('[MAC Process] Added item to processing set:', itemKey);
// Safety timeout to ensure we don't get stuck in processing state
const safetyTimeout = setTimeout(() => {
console.log('[MAC Process] Safety timeout - removing item from processing set:', itemKey);
this.processingMacItems.delete(itemKey);
}, 2000);
try { try {
// Parse MAC from QR code // Parse MAC from QR code
@@ -407,6 +425,7 @@ Vue.component('Cpeprovisioning', {
if (!parsedMac) { if (!parsedMac) {
console.log('[MAC Process] Failed to parse MAC from QR code'); console.log('[MAC Process] Failed to parse MAC from QR code');
window.notify('error', 'Konnte MAC-Adresse nicht aus QR-Code parsen'); window.notify('error', 'Konnte MAC-Adresse nicht aus QR-Code parsen');
clearTimeout(safetyTimeout);
this.processingMacItems.delete(itemKey); this.processingMacItems.delete(itemKey);
return; return;
} }
@@ -431,8 +450,10 @@ Vue.component('Cpeprovisioning', {
// Force Vue to update the DOM // Force Vue to update the DOM
this.$nextTick(() => { this.$nextTick(() => {
console.log('[MAC Process] After nextTick, MAC value is:', item.cpe_data.mac); console.log('[MAC Process] After nextTick, MAC value is:', item.cpe_data.mac);
// Remove from processing set after DOM update // Clear safety timeout and remove from processing set
clearTimeout(safetyTimeout);
this.processingMacItems.delete(itemKey); this.processingMacItems.delete(itemKey);
console.log('[MAC Process] Removed item from processing set after nextTick:', itemKey);
}); });
// Show notification // Show notification
@@ -441,6 +462,7 @@ Vue.component('Cpeprovisioning', {
} catch (error) { } catch (error) {
console.error('[MAC Process] Error processing MAC:', error); console.error('[MAC Process] Error processing MAC:', error);
clearTimeout(safetyTimeout);
this.processingMacItems.delete(itemKey); this.processingMacItems.delete(itemKey);
} }
@@ -465,55 +487,61 @@ Vue.component('Cpeprovisioning', {
item.cpe_data = { ...item.cpe_data }; // Trigger reactivity item.cpe_data = { ...item.cpe_data }; // Trigger reactivity
} }
}, },
isVlanSelected(item) { createRadiusUser(item) {
return item.vlans && Object.values(item.vlans).some(v => v.checked); console.log('[Create Radius User] === START ===');
}, console.log('[Create Radius User] Item:', item);
async createRadiusUser(item) {
// Disable button during request
this.$set(item, 'isCreatingRadius', true);
try { // Prepare the data to send to the Chrome extension
const { data } = await axios.post(window.TT_CONFIG.CPE_PROV_API_CREATE_RADIUS_USER_URL, { const customerNumber = item.owner_customer_number || 'N/A';
mac: item.cpe_data.mac const macAddress = item.cpe_data.mac;
}); const address = item.owner_full_address || 'N/A';
const customerName = item.customer || 'N/A';
const productName = item.product_name || 'N/A';
if (data.success) { console.log('[Create Radius User] Customer Number:', customerNumber);
window.notify('success', `RADIUS User erfolgreich angelegt! Kundennr: ${data.data.customer_number}`); console.log('[Create Radius User] MAC Address:', macAddress);
console.log('RADIUS User created:', data.data); console.log('[Create Radius User] Address:', address);
} else { console.log('[Create Radius User] Customer Name:', customerName);
window.notify('error', data.message || 'Fehler beim Anlegen des RADIUS Users.'); console.log('[Create Radius User] Product Name:', productName);
window.notify('info', 'Sende Daten an Chrome Extension...');
const extensionId = this.extensionId;
const message = {
type: "CREATE_RADIUS_USER",
payload: {
customerNumber: customerNumber,
macAddress: macAddress,
address: address,
customerName: customerName,
productName: productName
} }
} catch (error) { };
const errorMsg = error.response?.data?.message || 'Ein unerwarteter Fehler ist aufgetreten.';
window.notify('error', errorMsg); console.log('[Create Radius User] Extension ID:', extensionId);
console.error('Error creating RADIUS user:', error); console.log('[Create Radius User] Message:', message);
} finally {
this.$set(item, 'isCreatingRadius', false); if (window.chrome && chrome.runtime && chrome.runtime.sendMessage) {
} try {
}, chrome.runtime.sendMessage(extensionId, message, (response) => {
async testAcsVlan(item) { if (chrome.runtime.lastError) {
const button = this.$el.querySelector(`[data-orderproduct-id="${item.orderproduct_id}"] .btn-info`); console.warn('[Create Radius User] Senden an Erweiterung fehlgeschlagen:', chrome.runtime.lastError.message);
if (button) { window.notify('warning', 'Daten konnten nicht an die Erweiterung gesendet werden. (Drücke STRG + ALT + E zum Konfigurieren)');
button.disabled = true; } else {
console.log('[Create Radius User] Erweiterung hat geantwortet:', response);
window.notify('success', 'Daten erfolgreich an Chrome Extension gesendet!');
}
});
} catch (e) {
console.error('[Create Radius User] Fehler beim Senden an die Erweiterung:', e);
window.notify('error', 'Fehler beim Senden an die Erweiterung.');
}
} else {
console.warn('[Create Radius User] Chrome Extension Messaging API nicht verfügbar.');
window.notify('warning', 'Chrome Messaging API nicht gefunden.');
} }
try { console.log('[Create Radius User] === END ===');
const { data } = await axios.post(window.TT_CONFIG.CPE_PROV_API_TEST_ACS_VLAN_URL, {
mac: item.cpe_data.mac
});
if (data.success) {
window.notify('success', `ACS VLAN Zuweisung erfolgreich: VLAN ${data.vlan_id}`);
} else {
window.notify('error', data.message || 'Fehler bei der ACS VLAN Zuweisung.');
}
} catch (error) {
window.notify('error', 'Ein unerwarteter Fehler ist aufgetreten.');
} finally {
if (button) {
button.disabled = false;
}
}
}, },
_buildSavePayload(item) { _buildSavePayload(item) {
return { return {