diff --git a/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js b/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js index a30e8843d..2fb301661 100644 --- a/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js +++ b/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js @@ -128,7 +128,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }, /** - * Handle search input keyup - FIXED FOR EMPTY SEARCH + * Handle search input keyup - ALWAYS TRIGGER SEARCH */ _onSearchKeyUp: function(e) { var self = this; @@ -145,8 +145,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Store value this._search.value = value; - // CRITICAL FIX: Always trigger search, even for empty values - // This ensures clearing the last character works properly + // ALWAYS trigger search - no exceptions this._search.timer = setTimeout(function() { self._performSearch(value); }, 500); @@ -160,7 +159,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }, /** - * Perform search - ENHANCED WITH LOOP PREVENTION + * Perform search - SIMPLIFIED AND FIXED */ _performSearch: function(value) { var self = this; @@ -171,13 +170,18 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { return Promise.resolve(); } + console.log('=== PERFORM SEARCH ==='); + console.log('Search value:', value); + console.log('Value length:', value ? value.length : 0); + // Use mutex to prevent concurrent searches return this._searchMutex.exec(function() { // Set flag to prevent loops self._searchInProgress = true; - // Clear if empty - FIXED: Proper handling of empty search + // CRITICAL FIX: Handle empty search properly if (!value || value.length === 0) { + console.log('Empty search - clearing'); return self._clearSearch().finally(function() { self._searchInProgress = false; }); @@ -190,7 +194,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { return Promise.resolve(); } - console.log('=== Starting search for:', value, '==='); + console.log('Starting server search for:', value); // Store original data on first search if (!self._search.originalData && !self._search.isFiltered) { @@ -253,137 +257,44 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { _processSearchResults: function(records) { var count = records.length; - console.log('Processing search results:', count, 'records'); + console.log('=== PROCESS SEARCH RESULTS ==='); + console.log('Records found:', count); // Update search state this._search.isFiltered = true; this._search.allFilteredRecords = records; this._search.filteredIds = records.map(function(r) { return r.id; }); + console.log('Filtered IDs:', this._search.filteredIds); + // Show count this.$('.oe_search_count').text(_t('Found: ') + count + _t(' records')).show(); if (count === 0) { this._showNoResults(); - // Update main pager for empty results - WITHOUT RELOAD this._updatePagerOnly(0); return; } - // Update the view with filtered results - this._updateViewWithFilteredData(records); + // CRITICAL FIX: Always re-render with filtered data + // Don't rely on DOM filtering - just re-render every time + this._forceRerenderWithFilteredData(records); }, /** - * CRITICAL FIX: Update view - TRY DOM FILTERING FIRST, THEN FALLBACK + * CRITICAL FIX: Always re-render with filtered data */ - _updateViewWithFilteredData: function(records) { - console.log('=== _updateViewWithFilteredData ==='); - console.log('Records count:', records.length); - console.log('Filtered IDs:', this._search.filteredIds); - - // CRITICAL FIX: Try DOM filtering first (this usually works and is fast) - var domFilterWorked = this._filterExistingRows(); - console.log('DOM filtering worked:', domFilterWorked); - - if (domFilterWorked) { - // DOM filtering worked - just update pager - this._updatePagerOnly(records.length); - return; - } - - // DOM filtering failed - need to re-render - console.log('DOM filtering failed, re-rendering with proper Odoo methods...'); - this._updateStateAndRerenderProperly(records); - }, - - /** - * CRITICAL FIX: Filter existing rows in DOM - ENHANCED - */ - _filterExistingRows: function() { - if (!this._search.filteredIds || this._search.filteredIds.length === 0) { - console.log('No filtered IDs to work with'); - return false; - } - - var self = this; - var $allRows = this.$('.o_data_row'); - var limit = this.state.limit || 80; - var visibleCount = 0; - var foundAnyMatch = false; - var availableRowIds = []; - - console.log('=== DOM Filtering Debug ==='); - console.log('Total rows in DOM:', $allRows.length); - console.log('Looking for IDs:', this._search.filteredIds); - - if ($allRows.length === 0) { - console.log('No rows in DOM to filter'); - return false; - } - - // First, collect all available row IDs for debugging - $allRows.each(function(index) { - var $row = $(this); - var rowId = self._getRowId($row); - if (rowId) { - availableRowIds.push(rowId); - } - }); - - console.log('Available row IDs in DOM:', availableRowIds); - - // Check if we have ANY matching IDs - var intersection = this._search.filteredIds.filter(function(id) { - return availableRowIds.includes(id); - }); - - console.log('Intersection (IDs that exist in DOM):', intersection); - - // If we have at least some matches, proceed with DOM filtering - if (intersection.length > 0) { - // Hide all rows first - $allRows.hide(); - - // Show matching rows up to limit - $allRows.each(function(index) { - var $row = $(this); - var rowId = self._getRowId($row); - - if (rowId && self._search.filteredIds.includes(rowId)) { - if (visibleCount < limit) { - $row.show(); - visibleCount++; - foundAnyMatch = true; - console.log('✓ Showing row', index, 'with ID', rowId); - } - } - }); - - console.log('DOM filtering completed - Visible rows:', visibleCount); - return visibleCount > 0; - } - - // No matches found - need to re-render - console.log('No matching IDs found in DOM - need to re-render'); - return false; - }, - - /** - * ENHANCED: Update state and re-render using proper Odoo methods - */ - _updateStateAndRerenderProperly: function(records) { + _forceRerenderWithFilteredData: function(records) { var self = this; var limit = this.state.limit || 80; var pageRecords = records.slice(0, limit); - console.log('=== Proper Re-rendering ==='); + console.log('=== FORCE RE-RENDER ==='); console.log('Total records:', records.length); console.log('Page records:', pageRecords.length); - // Update state with filtered data - PROPERLY + // Update state with filtered data if (this.state) { - // Store original state for restoration if (this.state.data) { this.state.data.records = pageRecords; } @@ -391,60 +302,17 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { this.state.res_ids = this._search.filteredIds; } - // Clear existing content + // Clear existing content completely this.$('tbody .o_data_row').remove(); this.$('.oe_no_results').remove(); - // Try to use Odoo's native rendering methods first, then fallback to manual - if (pageRecords.length > 0) { - var renderSuccess = this._tryOdooRenderingMethods(pageRecords); - if (!renderSuccess) { - // Fallback to manual creation with proper formatting - this._createEnhancedRows(pageRecords); - } - } else { - this._showNoResults(); - } + // Always create new rows manually with proper formatting + this._createEnhancedRows(pageRecords); // Update pager this._updatePagerOnly(records.length); }, - /** - * NEW: Try Odoo rendering methods with fallbacks - */ - _tryOdooRenderingMethods: function(records) { - try { - // Method 1: Try _renderRows - if (typeof this._renderRows === 'function') { - console.log('Trying _renderRows method'); - var $rows = this._renderRows(); - if ($rows && $rows.length > 0) { - this.$('tbody').append($rows); - console.log('✓ _renderRows succeeded'); - return true; - } - } - } catch (err) { - console.warn('_renderRows failed:', err); - } - - try { - // Method 2: Try _renderBody - if (typeof this._renderBody === 'function') { - console.log('Trying _renderBody method'); - this._renderBody(); - console.log('✓ _renderBody completed'); - return true; - } - } catch (err) { - console.warn('_renderBody failed:', err); - } - - console.log('All Odoo rendering methods failed, using manual fallback'); - return false; - }, - /** * ENHANCED: Create rows with proper Odoo formatting and event handlers */ @@ -473,9 +341,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { var self = this; var $row = $(''); - // Set proper Odoo attributes + // Set proper Odoo attributes - MULTIPLE FORMATS FOR COMPATIBILITY $row.attr('data-id', record.id); + $row.attr('data-res-id', record.id); $row.data('id', record.id); + $row.data('res-id', record.id); // CRITICAL: Add proper record data that Odoo expects var recordData = { @@ -486,6 +356,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }; $row.data('record', recordData); + console.log('Created row for record ID:', record.id); + // Add cells for each visible column using proper field rendering if (self.columns && self.columns.length > 0) { self.columns.forEach(function(col) { @@ -621,51 +493,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { } }, - /** - * Get row ID from DOM element - ENHANCED METHOD - */ - _getRowId: function($row) { - // Method 1: data-id attribute - var id = $row.attr('data-id'); - if (id && !isNaN(parseInt(id))) { - return parseInt(id); - } - - // Method 2: data-res-id attribute - id = $row.attr('data-res-id'); - if (id && !isNaN(parseInt(id))) { - return parseInt(id); - } - - // Method 3: jQuery data id - id = $row.data('id'); - if (id && !isNaN(parseInt(id))) { - return parseInt(id); - } - - // Method 4: jQuery data res-id - id = $row.data('res-id'); - if (id && !isNaN(parseInt(id))) { - return parseInt(id); - } - - // Method 5: Check for record object in data - var record = $row.data('record'); - if (record) { - if (record.res_id && !isNaN(parseInt(record.res_id))) { - return parseInt(record.res_id); - } - if (record.id && !isNaN(parseInt(record.id))) { - return parseInt(record.id); - } - if (record.data && record.data.id && !isNaN(parseInt(record.data.id))) { - return parseInt(record.data.id); - } - } - - return null; - }, - /** * SAFE PAGER UPDATE - WITHOUT RELOAD TRIGGERS */ @@ -746,7 +573,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }, /** - * Client-side search fallback - ENHANCED + * Client-side search fallback - SIMPLIFIED */ _clientSideSearch: function(value) { var self = this; @@ -756,7 +583,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { var limit = this.state.limit || 80; var matchedIds = []; - console.log('Using client-side search fallback'); + console.log('Using client-side search fallback for:', value); this.$('.o_data_row').each(function() { var $row = $(this); @@ -797,19 +624,18 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Update pager safely this._updatePagerOnly(visible); - console.log('Client-side search completed. Visible:', visible, 'IDs:', matchedIds); + console.log('Client-side search completed. Visible:', visible); }, /** - * Clear search - ENHANCED WITH LOOP PREVENTION + * Clear search - ENHANCED AND FIXED */ _clearSearch: function() { - console.log('=== Clearing search ==='); + console.log('=== CLEARING SEARCH ==='); // PREVENT LOOPS during clear if (this._searchInProgress) { - console.log('Search in progress during clear, setting flag to clear after'); - this._pendingClear = true; + console.log('Search in progress during clear, ignoring'); return Promise.resolve(); } @@ -832,7 +658,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Restore original data if (this._search.originalData) { - console.log('Restoring original data:', this._search.originalData); + console.log('Restoring original data'); // Restore state if (this.state) { @@ -886,6 +712,51 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { return promise; }, + /** + * Get row ID from DOM element - ENHANCED METHOD + */ + _getRowId: function($row) { + // Method 1: data-id attribute + var id = $row.attr('data-id'); + if (id && !isNaN(parseInt(id))) { + return parseInt(id); + } + + // Method 2: data-res-id attribute + id = $row.attr('data-res-id'); + if (id && !isNaN(parseInt(id))) { + return parseInt(id); + } + + // Method 3: jQuery data id + id = $row.data('id'); + if (id && !isNaN(parseInt(id))) { + return parseInt(id); + } + + // Method 4: jQuery data res-id + id = $row.data('res-id'); + if (id && !isNaN(parseInt(id))) { + return parseInt(id); + } + + // Method 5: Check for record object in data + var record = $row.data('record'); + if (record) { + if (record.res_id && !isNaN(parseInt(record.res_id))) { + return parseInt(record.res_id); + } + if (record.id && !isNaN(parseInt(record.id))) { + return parseInt(record.id); + } + if (record.data && record.data.id && !isNaN(parseInt(record.data.id))) { + return parseInt(record.data.id); + } + } + + return null; + }, + /** * Store original data (only once per search session) */