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 e674ab1dc..fbf0da500 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 @@ -51,7 +51,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { active: false, originalData: null, originalDomain: null, - filteredIds: null + filteredIds: null, + isSearching: false // Flag to prevent input clearing }; }, @@ -73,6 +74,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Store value this._search.value = value; + // Require at least 2 characters or empty to search + if (value.length === 1) { + return; // Don't search for single character + } + // Debounce search this._search.timer = setTimeout(function() { self._performSearch(value); @@ -117,6 +123,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { this._search.originalDomain = this.state.domain || []; } + // Set searching flag + this._search.isSearching = true; + // Start search this._search.active = true; this._showLoading(true); @@ -132,14 +141,16 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Get fields to read var fields = this._getReadFields(); - // Execute search + // Execute search with pagination + var limit = this.state.limit || 80; // Use current page limit + this._rpc({ model: this.state.model, method: 'search_read', args: [domain], kwargs: { fields: fields, - limit: false, + limit: false, // Get all records for count context: this.state.context || {} } }).then(function(results) { @@ -149,7 +160,10 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { self._clientSideSearch(value); }).finally(function() { self._search.active = false; + self._search.isSearching = false; self._showLoading(false); + // Restore search value after search completes + self._restoreSearchInput(); }); }, @@ -267,7 +281,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { var self = this; var count = records.length; - // Show count + // Show count - KEEP IT VISIBLE this.$('.oe_search_count').text(_t('Found: ') + count + _t(' records')).show(); if (count === 0) { @@ -278,43 +292,50 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Store filtered IDs for later use this._search.filteredIds = records.map(function(r) { return r.id; }); - // Update state data properly - if (this.state && this.state.data) { - this.state.data.records = records; - this.state.count = count; - this.state.res_ids = this._search.filteredIds; - } - - // Re-render the list body using the best method for Odoo 14 - this._renderFilteredRecords(records); + // Re-render the list with pagination + this._renderFilteredRecordsWithPagination(records); }, /** - * Render filtered records - Professional Odoo 14 compatible solution + * Render filtered records with proper pagination */ - _renderFilteredRecords: function(records) { + _renderFilteredRecordsWithPagination: function(records) { var self = this; - // Method 1: Try to trigger reload with filtered domain (Best for Odoo 14) + // Get current limit (default 80) + var limit = this.state.limit || 80; + var offset = 0; + + // Get IDs for filtered records + var filteredIds = records.map(function(r) { return r.id; }); + + // Create domain to filter by IDs + var idDomain = [['id', 'in', filteredIds]]; + + // Try to use parent's reload method with proper pagination if (this.getParent() && typeof this.getParent().reload === 'function') { try { - // Create domain to filter by IDs - var idDomain = [['id', 'in', this._search.filteredIds]]; - - // Update state domain temporarily + // Update state temporarily + var originalDomain = this.state.domain; this.state.domain = idDomain; - // Trigger parent reload with filtered domain + // Store total count for pagination + this.state.count = records.length; + + // Reload with pagination settings this.getParent().reload({ domain: idDomain, context: this.state.context, - limit: false, - offset: 0 + limit: limit, // Keep original pagination limit + offset: offset }).then(function() { - self._afterRender(); + // Restore search input and count + self._restoreSearchInput(); + self.$('.oe_search_count').text(_t('Found: ') + records.length + _t(' records')).show(); }).catch(function(err) { - console.warn('Parent reload failed, trying alternative method:', err); - self._renderRecordsAlternative(records); + console.warn('Parent reload failed:', err); + // Fallback method + self._renderRecordsWithPagination(records, limit, offset); }); return; @@ -323,67 +344,63 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { } } - // Method 2: Try direct _renderBody if available - self._renderRecordsAlternative(records); + // Fallback: render with pagination + this._renderRecordsWithPagination(records, limit, offset); }, /** - * Alternative render method for filtered records + * Render records with pagination (fallback) */ - _renderRecordsAlternative: function(records) { + _renderRecordsWithPagination: function(records, limit, offset) { var self = this; - // Try _renderBody if available + // Get records for current page + var pageRecords = records.slice(offset, offset + limit); + + // Update state + if (this.state && this.state.data) { + this.state.data.records = pageRecords; + this.state.count = records.length; // Total count + this.state.res_ids = pageRecords.map(function(r) { return r.id; }); + } + + // Try to render using _renderBody if (typeof this._renderBody === 'function') { try { - // Update state properly - if (this.state && this.state.data) { - // Store current state - var originalCount = this.state.count; - var originalLimit = this.state.limit; - - // Update for filtered records - this.state.data.records = records; - this.state.count = records.length; - this.state.limit = false; // Show all filtered records - } - - // Remove existing rows to force full re-render + // Remove existing rows this.$('tbody .o_data_row').remove(); this.$('.oe_no_results').remove(); - // Call render + // Render new rows var result = this._renderBody(); - // Handle promise if (result && result.then) { result.then(function() { - self._afterRender(); - self._highlightSearchResults(); - }).catch(function(err) { - console.error('_renderBody failed:', err); - self._fallbackRender(records); + self._restoreSearchInput(); + self.$('.oe_search_count').text(_t('Found: ') + records.length + _t(' records')).show(); }); } else { - self._afterRender(); - self._highlightSearchResults(); + self._restoreSearchInput(); + self.$('.oe_search_count').text(_t('Found: ') + records.length + _t(' records')).show(); } - return; } catch (err) { - console.error('Alternative render error:', err); + console.error('Render error:', err); + this._fallbackRender(pageRecords); } + } else { + this._fallbackRender(pageRecords); } - - // Final fallback to DOM manipulation - this._fallbackRender(records); }, /** - * Highlight search results (optional visual enhancement) + * Restore search input value */ - _highlightSearchResults: function() { - // Add subtle highlight to filtered rows - this.$('.o_data_row').addClass('oe_search_filtered'); + _restoreSearchInput: function() { + // Don't restore if we're clearing + if (this._search && this._search.value && !this._search.isClearing) { + this.$('.oe_search_input').val(this._search.value); + this.$('.oe_clear_search').show(); + } }, /** @@ -397,63 +414,39 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { var $rows = this.$('.o_data_row'); if ($rows.length === 0) { - // Try to force re-render if no rows in DOM - if (this._search.originalData && this._search.originalData.records.length > 0) { - // Restore original data first - this.state.data.records = this._search.originalData.records; - - // Try to render all rows - if (typeof this._renderBody === 'function') { - this._renderBody().then(function() { - // Now filter the rendered rows - setTimeout(function() { - self._filterDOMRows(recordIds); - }, 100); - }); - return; - } - } - - console.warn('No data rows found in DOM and cannot re-render'); + console.warn('No data rows found in DOM'); return; } - // Filter existing DOM rows - this._filterDOMRows(recordIds); - }, - - /** - * Filter DOM rows by IDs - */ - _filterDOMRows: function(recordIds) { - var self = this; - var $rows = this.$('.o_data_row'); - // Hide all rows first $rows.hide(); - // Show matching rows - var visibleCount = 0; + // Show matching rows (limited to page size) + var shown = 0; + var limit = this.state.limit || 80; + $rows.each(function() { + if (shown >= limit) return false; // Stop if reached limit + var $row = $(this); var rowId = self._getRowId($row); if (rowId && recordIds.includes(rowId)) { $row.show(); - visibleCount++; + shown++; } }); // Show message if no visible rows - if (visibleCount === 0) { + if (shown === 0) { this._showNoResults(); } - this._afterRender(); + this._restoreSearchInput(); }, /** - * Get row ID from DOM element - Enhanced version + * Get row ID from DOM element */ _getRowId: function($row) { // Method 1: data-id attribute @@ -480,32 +473,14 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { if (idText && !isNaN(idText)) return parseInt(idText); } - // Method 5: Extract from class or other attributes + // Method 5: Extract from class var classes = $row.attr('class') || ''; var match = classes.match(/o_data_row_(\d+)/); if (match) return parseInt(match[1]); - // Method 6: Try to find ID in any cell text that looks like an ID - var $firstCell = $row.find('td.o_data_cell:first'); - if ($firstCell.length) { - var cellData = $firstCell.data(); - if (cellData && cellData.id) return parseInt(cellData.id); - } - return null; }, - /** - * After render tasks - */ - _afterRender: function() { - // Restore search value - if (this._search && this._search.value) { - this.$('.oe_search_input').val(this._search.value); - this.$('.oe_clear_search').show(); - } - }, - /** * Client-side search fallback */ @@ -513,8 +488,14 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { var searchLower = value.toLowerCase(); var normalized = this._normalizeArabic(searchLower); var visible = 0; + var limit = this.state.limit || 80; this.$('.o_data_row').each(function() { + if (visible >= limit) { + $(this).hide(); + return true; // Continue but hide excess rows + } + var $row = $(this); var text = $row.text().toLowerCase(); var match = text.includes(searchLower) || text.includes(normalized); @@ -523,21 +504,26 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { if (match) visible++; }); - // Update count + // Update count - KEEP VISIBLE var msg = visible > 0 ? - _t('Showing: ') + visible + _t(' visible records') : + _t('Found: ') + visible + _t(' records') : _t('No records found'); this.$('.oe_search_count').text(msg).show(); if (visible === 0) { this._showNoResults(); } + + this._restoreSearchInput(); }, /** * Clear search and restore original view */ _clearSearch: function() { + // Set clearing flag + this._search.isClearing = true; + // Clear UI this.$('.oe_search_input').val(''); this.$('.oe_clear_search').hide(); @@ -553,16 +539,21 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { this.state.domain = this._search.originalDomain; } - // Restore original data + // Restore original data with proper pagination if (this._search.originalData) { - this._restoreOriginalData(); + this._restoreOriginalDataWithPagination(); } else { - // Just show all rows - this.$('.o_data_row').show(); + // Just show all rows respecting pagination + var $rows = this.$('.o_data_row'); + var limit = this.state.limit || 80; + + $rows.each(function(index) { + $(this).toggle(index < limit); + }); } - // Remove highlight class - this.$('.o_data_row').removeClass('oe_search_filtered'); + // Remove clearing flag + this._search.isClearing = false; }, /** @@ -575,15 +566,16 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { this.state.data.records.slice() : [], count: this.state.count || 0, res_ids: this.state.res_ids ? this.state.res_ids.slice() : [], - limit: this.state.limit + limit: this.state.limit, + offset: this.state.offset || 0 }; } }, /** - * Restore original data + * Restore original data with pagination */ - _restoreOriginalData: function() { + _restoreOriginalDataWithPagination: function() { if (!this._search.originalData) return; var self = this; @@ -591,31 +583,54 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { // Restore state if (this.state) { - if (this.state.data) { - this.state.data.records = orig.records; - } - this.state.count = orig.count; - this.state.res_ids = orig.res_ids; - this.state.limit = orig.limit; this.state.domain = this._search.originalDomain || []; + this.state.count = orig.count; + this.state.limit = orig.limit; + this.state.offset = orig.offset; } - // Try parent reload first for clean restore + // Try parent reload for clean restore if (this.getParent() && typeof this.getParent().reload === 'function') { this.getParent().reload({ domain: this._search.originalDomain || [], context: this.state.context, limit: orig.limit, - offset: 0 + offset: orig.offset }).then(function() { - self._afterRender(); + // Clear search data + self._search.originalData = null; + self._search.originalDomain = null; }).catch(function() { - // Fallback to direct render - self._renderRecordsAlternative(orig.records); + // Fallback + self._restoreOriginalRecords(orig); }); } else { - // Direct render - this._renderRecordsAlternative(orig.records); + this._restoreOriginalRecords(orig); + } + }, + + /** + * Restore original records (fallback) + */ + _restoreOriginalRecords: function(orig) { + // Update state + if (this.state && this.state.data) { + this.state.data.records = orig.records; + this.state.count = orig.count; + this.state.res_ids = orig.res_ids; + } + + // Re-render + if (typeof this._renderBody === 'function') { + this._renderBody(); + } else { + // Show original rows with pagination + var $rows = this.$('.o_data_row'); + var limit = orig.limit || 80; + + $rows.each(function(index) { + $(this).toggle(index < limit); + }); } // Clear stored data @@ -628,9 +643,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { */ _showLoading: function(show) { this.$('.oe_search_loading').toggle(show); - if (show) { - this.$('.oe_search_count').hide(); - } + // Don't hide count when loading }, /**