|
426 | 426 |
|
427 | 427 | $('.dt-import-step-content').html(step3Html); |
428 | 428 |
|
429 | | - // Initialize field mappings from suggested mappings |
430 | | - Object.entries(mappingSuggestions).forEach(([index, mapping]) => { |
431 | | - if (mapping.suggested_field) { |
432 | | - this.fieldMappings[index] = { |
433 | | - field_key: mapping.suggested_field, |
434 | | - column_index: parseInt(index), |
435 | | - }; |
436 | | - } |
437 | | - }); |
438 | | - |
439 | | - // Show field-specific options for auto-suggested fields after DOM is ready |
440 | | - setTimeout(() => { |
| 429 | + // Initialize field mappings from suggested mappings ONLY if no existing mappings |
| 430 | + if (Object.keys(this.fieldMappings).length === 0) { |
| 431 | + // Initialize from suggestions for first-time display |
441 | 432 | Object.entries(mappingSuggestions).forEach(([index, mapping]) => { |
442 | 433 | if (mapping.suggested_field) { |
| 434 | + this.fieldMappings[index] = { |
| 435 | + field_key: mapping.suggested_field, |
| 436 | + column_index: parseInt(index), |
| 437 | + }; |
| 438 | + } |
| 439 | + }); |
| 440 | + } |
| 441 | + |
| 442 | + // Restore existing field mappings to the dropdowns and read actual dropdown values |
| 443 | + setTimeout(() => { |
| 444 | + // First, restore any existing user mappings to the dropdowns |
| 445 | + Object.entries(this.fieldMappings).forEach(([columnIndex, mapping]) => { |
| 446 | + const $select = $( |
| 447 | + `.field-mapping-select[data-column-index="${columnIndex}"]`, |
| 448 | + ); |
| 449 | + if ($select.length && mapping.field_key) { |
| 450 | + $select.val(mapping.field_key); |
443 | 451 | this.showFieldSpecificOptions( |
444 | | - parseInt(index), |
445 | | - mapping.suggested_field, |
| 452 | + parseInt(columnIndex), |
| 453 | + mapping.field_key, |
446 | 454 | ); |
447 | 455 | } |
448 | 456 | }); |
| 457 | + |
| 458 | + // Read the actual dropdown values to ensure mappings match what's displayed |
| 459 | + // This handles cases where suggestions were auto-selected but user wants different behavior |
| 460 | + const actualMappings = {}; |
| 461 | + $('.field-mapping-select').each((index, select) => { |
| 462 | + const $select = $(select); |
| 463 | + const columnIndex = $select.data('column-index'); |
| 464 | + const fieldKey = $select.val(); |
| 465 | + |
| 466 | + // Only create mapping if a field is actually selected (not empty) |
| 467 | + if (fieldKey && fieldKey !== '' && fieldKey !== 'create_new') { |
| 468 | + actualMappings[columnIndex] = { |
| 469 | + field_key: fieldKey, |
| 470 | + column_index: parseInt(columnIndex), |
| 471 | + }; |
| 472 | + } |
| 473 | + }); |
| 474 | + |
| 475 | + // Update field mappings to match actual dropdown state |
| 476 | + this.fieldMappings = actualMappings; |
| 477 | + console.log( |
| 478 | + 'DT Import: Field mappings synchronized with dropdown state:', |
| 479 | + this.fieldMappings, |
| 480 | + ); |
| 481 | + |
| 482 | + // Update the summary after mappings are initialized |
| 483 | + this.updateMappingSummary(); |
449 | 484 | }, 100); |
450 | 485 |
|
451 | 486 | this.updateNavigation(); |
452 | | - this.updateMappingSummary(); |
453 | 487 | } |
454 | 488 |
|
455 | 489 | createColumnMappingCard(columnIndex, mapping) { |
|
465 | 499 | .map((sample) => `<li>${this.escapeHtml(sample)}</li>`) |
466 | 500 | .join(''); |
467 | 501 |
|
| 502 | + // Check if there's an existing user mapping for this column |
| 503 | + const existingMapping = this.fieldMappings[columnIndex]; |
| 504 | + const selectedField = existingMapping |
| 505 | + ? existingMapping.field_key |
| 506 | + : mapping.suggested_field; // Restore auto-mapping |
| 507 | + |
468 | 508 | return ` |
469 | 509 | <div class="column-mapping-card" data-column-index="${columnIndex}"> |
470 | 510 | <div class="column-header"> |
471 | 511 | <h4>${this.escapeHtml(mapping.column_name)}</h4> |
472 | 512 | ${ |
473 | | - mapping.confidence > 0 |
| 513 | + mapping.confidence > 0 && !existingMapping |
474 | 514 | ? ` |
475 | 515 | <div class="confidence-indicator confidence-${confidenceClass}"> |
476 | 516 | ${mapping.confidence}% confidence |
|
489 | 529 | <label>Map to field:</label> |
490 | 530 | <select class="field-mapping-select" data-column-index="${columnIndex}"> |
491 | 531 | <option value="">-- Do not import --</option> |
492 | | - ${this.getFieldOptions(mapping.suggested_field)} |
| 532 | + ${this.getFieldOptions(selectedField)} |
493 | 533 | <option value="create_new">+ Create New Field</option> |
494 | 534 | </select> |
495 | 535 | |
|
537 | 577 | return; |
538 | 578 | } |
539 | 579 |
|
540 | | - // Store mapping |
541 | | - if (fieldKey) { |
| 580 | + console.log( |
| 581 | + `DT Import: Column ${columnIndex} field mapping changed to: "${fieldKey}"`, |
| 582 | + ); |
| 583 | + |
| 584 | + // Store mapping - properly handle empty values for "do not import" |
| 585 | + if (fieldKey && fieldKey !== '') { |
542 | 586 | this.fieldMappings[columnIndex] = { |
543 | 587 | field_key: fieldKey, |
544 | 588 | column_index: columnIndex, |
545 | 589 | }; |
| 590 | + console.log( |
| 591 | + `DT Import: Added mapping for column ${columnIndex} -> ${fieldKey}`, |
| 592 | + ); |
546 | 593 | } else { |
| 594 | + // When "do not import" is selected (empty value), remove the mapping entirely |
547 | 595 | delete this.fieldMappings[columnIndex]; |
| 596 | + console.log( |
| 597 | + `DT Import: Removed mapping for column ${columnIndex} (do not import)`, |
| 598 | + ); |
548 | 599 | } |
549 | 600 |
|
| 601 | + console.log('DT Import: Current field mappings:', this.fieldMappings); |
| 602 | + |
550 | 603 | // Show field-specific options if needed |
551 | 604 | this.showFieldSpecificOptions(columnIndex, fieldKey); |
552 | 605 | this.updateMappingSummary(); |
|
821 | 874 | return; |
822 | 875 | } |
823 | 876 |
|
| 877 | + console.log( |
| 878 | + 'DT Import: Saving field mappings to server:', |
| 879 | + this.fieldMappings, |
| 880 | + ); |
824 | 881 | this.showProcessing('Saving field mappings...'); |
825 | 882 |
|
826 | 883 | fetch(`${dtImport.restUrl}${this.sessionId}/mapping`, { |
|
838 | 895 | this.hideProcessing(); |
839 | 896 |
|
840 | 897 | if (data.success) { |
| 898 | + console.log('DT Import: Field mappings saved successfully'); |
841 | 899 | this.showStep4(); |
842 | 900 | } else { |
843 | 901 | this.showError(data.message || 'Failed to save mappings'); |
|
955 | 1013 | return '<p>No data to preview.</p>'; |
956 | 1014 | } |
957 | 1015 |
|
| 1016 | + // Get only the headers for fields that are actually being imported |
| 1017 | + // The preview data from the server only contains fields that have mappings |
958 | 1018 | const headers = Object.keys(rows[0].data); |
| 1019 | + |
| 1020 | + if (headers.length === 0) { |
| 1021 | + return '<p>No fields selected for import. Please go back and configure field mappings.</p>'; |
| 1022 | + } |
| 1023 | + |
959 | 1024 | const headerHtml = headers |
960 | 1025 | .map((header) => `<th>${this.escapeHtml(header)}</th>`) |
961 | 1026 | .join(''); |
|
1010 | 1075 | `; |
1011 | 1076 | } |
1012 | 1077 |
|
| 1078 | + getColumnIndexForField(fieldKey) { |
| 1079 | + // Find the column index that maps to this field |
| 1080 | + for (const [columnIndex, mapping] of Object.entries(this.fieldMappings)) { |
| 1081 | + if (mapping.field_key === fieldKey) { |
| 1082 | + return parseInt(columnIndex); |
| 1083 | + } |
| 1084 | + } |
| 1085 | + return null; |
| 1086 | + } |
| 1087 | + |
1013 | 1088 | executeImport() { |
1014 | 1089 | if (this.isProcessing) return; |
1015 | 1090 |
|
|
0 commit comments