Merge pull request #4418 from expsa/eltayar
Fix: General Search Tree View - List Rendering After Search
This commit is contained in:
commit
0f23b29078
|
|
@ -49,7 +49,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
timer: null,
|
||||
value: '',
|
||||
active: false,
|
||||
originalData: null
|
||||
originalData: null,
|
||||
originalDomain: null,
|
||||
filteredIds: null
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -107,10 +109,13 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Store original data on first search
|
||||
// Store original data and domain on first search
|
||||
if (!this._search.originalData) {
|
||||
this._storeOriginalData();
|
||||
}
|
||||
if (!this._search.originalDomain) {
|
||||
this._search.originalDomain = this.state.domain || [];
|
||||
}
|
||||
|
||||
// Start search
|
||||
this._search.active = true;
|
||||
|
|
@ -120,8 +125,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var domain = this._buildSearchDomain(value);
|
||||
|
||||
// Add base domain if exists
|
||||
if (this.state.domain && this.state.domain.length > 0) {
|
||||
domain = ['&'].concat(this.state.domain).concat(domain);
|
||||
if (this._search.originalDomain && this._search.originalDomain.length > 0) {
|
||||
domain = ['&'].concat(this._search.originalDomain).concat(domain);
|
||||
}
|
||||
|
||||
// Get fields to read
|
||||
|
|
@ -270,33 +275,83 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Update state data
|
||||
// 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;
|
||||
|
||||
// Update IDs list
|
||||
this.state.res_ids = records.map(function(r) { return r.id; });
|
||||
this.state.res_ids = this._search.filteredIds;
|
||||
}
|
||||
|
||||
// Re-render the list body
|
||||
this._renderRecords(records);
|
||||
// Re-render the list body using the best method for Odoo 14
|
||||
this._renderFilteredRecords(records);
|
||||
},
|
||||
|
||||
/**
|
||||
* Render records - The correct way for Odoo 14
|
||||
* Render filtered records - Professional Odoo 14 compatible solution
|
||||
*/
|
||||
_renderRecords: function(records) {
|
||||
_renderFilteredRecords: function(records) {
|
||||
var self = this;
|
||||
|
||||
// Method 1: Use _renderBody if available
|
||||
// Method 1: Try to trigger reload with filtered domain (Best for Odoo 14)
|
||||
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
|
||||
this.state.domain = idDomain;
|
||||
|
||||
// Trigger parent reload with filtered domain
|
||||
this.getParent().reload({
|
||||
domain: idDomain,
|
||||
context: this.state.context,
|
||||
limit: false,
|
||||
offset: 0
|
||||
}).then(function() {
|
||||
self._afterRender();
|
||||
}).catch(function(err) {
|
||||
console.warn('Parent reload failed, trying alternative method:', err);
|
||||
self._renderRecordsAlternative(records);
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (err) {
|
||||
console.warn('Reload method failed:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2: Try direct _renderBody if available
|
||||
self._renderRecordsAlternative(records);
|
||||
},
|
||||
|
||||
/**
|
||||
* Alternative render method for filtered records
|
||||
*/
|
||||
_renderRecordsAlternative: function(records) {
|
||||
var self = this;
|
||||
|
||||
// Try _renderBody if available
|
||||
if (typeof this._renderBody === 'function') {
|
||||
try {
|
||||
// Ensure state is ready
|
||||
// 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
|
||||
this.$('tbody .o_data_row').remove();
|
||||
this.$('.oe_no_results').remove();
|
||||
|
||||
// Call render
|
||||
var result = this._renderBody();
|
||||
|
||||
|
|
@ -304,23 +359,33 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
if (result && result.then) {
|
||||
result.then(function() {
|
||||
self._afterRender();
|
||||
self._highlightSearchResults();
|
||||
}).catch(function(err) {
|
||||
console.error('Render failed:', err);
|
||||
console.error('_renderBody failed:', err);
|
||||
self._fallbackRender(records);
|
||||
});
|
||||
} else {
|
||||
self._afterRender();
|
||||
self._highlightSearchResults();
|
||||
}
|
||||
return;
|
||||
} catch (err) {
|
||||
console.error('Render error:', err);
|
||||
console.error('Alternative render error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to DOM manipulation
|
||||
// Final fallback to DOM manipulation
|
||||
this._fallbackRender(records);
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight search results (optional visual enhancement)
|
||||
*/
|
||||
_highlightSearchResults: function() {
|
||||
// Add subtle highlight to filtered rows
|
||||
this.$('.o_data_row').addClass('oe_search_filtered');
|
||||
},
|
||||
|
||||
/**
|
||||
* Fallback render using DOM manipulation
|
||||
*/
|
||||
|
|
@ -332,26 +397,55 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var $rows = this.$('.o_data_row');
|
||||
|
||||
if ($rows.length === 0) {
|
||||
// No rows in DOM, can't filter
|
||||
console.warn('No data rows found in DOM');
|
||||
// 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');
|
||||
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;
|
||||
$rows.each(function() {
|
||||
var $row = $(this);
|
||||
var rowId = self._getRowId($row);
|
||||
|
||||
if (rowId && recordIds.includes(rowId)) {
|
||||
$row.show();
|
||||
visibleCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// Show message if no visible rows
|
||||
if (this.$('.o_data_row:visible').length === 0) {
|
||||
if (visibleCount === 0) {
|
||||
this._showNoResults();
|
||||
}
|
||||
|
||||
|
|
@ -359,31 +453,45 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Get row ID from DOM element
|
||||
* Get row ID from DOM element - Enhanced version
|
||||
*/
|
||||
_getRowId: function($row) {
|
||||
// Try different methods to get ID
|
||||
|
||||
// Method 1: data-id attribute
|
||||
var id = $row.data('id');
|
||||
if (id) return parseInt(id);
|
||||
|
||||
// Method 2: Check for record object
|
||||
var record = $row.data('record');
|
||||
if (record && record.res_id) return record.res_id;
|
||||
if (record) {
|
||||
if (record.res_id) return record.res_id;
|
||||
if (record.id) return record.id;
|
||||
if (record.data && record.data.id) return record.data.id;
|
||||
}
|
||||
|
||||
// Method 3: Look in first cell with field name
|
||||
// Method 3: Look for Odoo's internal data
|
||||
if ($row[0] && $row[0].dataset) {
|
||||
if ($row[0].dataset.id) return parseInt($row[0].dataset.id);
|
||||
}
|
||||
|
||||
// Method 4: Check first cell for ID field
|
||||
var $idCell = $row.find('td[data-field="id"]');
|
||||
if ($idCell.length) {
|
||||
var idText = $idCell.text().trim();
|
||||
if (idText && !isNaN(idText)) return parseInt(idText);
|
||||
}
|
||||
|
||||
// Method 5: Extract from class or other attributes
|
||||
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);
|
||||
}
|
||||
|
||||
// Method 4: Extract from class or other attributes
|
||||
var classes = $row.attr('class') || '';
|
||||
var match = classes.match(/o_data_row_(\d+)/);
|
||||
if (match) return parseInt(match[1]);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
|
|
@ -394,6 +502,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
// Restore search value
|
||||
if (this._search && this._search.value) {
|
||||
this.$('.oe_search_input').val(this._search.value);
|
||||
this.$('.oe_clear_search').show();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -426,7 +535,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Clear search
|
||||
* Clear search and restore original view
|
||||
*/
|
||||
_clearSearch: function() {
|
||||
// Clear UI
|
||||
|
|
@ -437,6 +546,12 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
|
||||
// Clear state
|
||||
this._search.value = '';
|
||||
this._search.filteredIds = null;
|
||||
|
||||
// Restore original domain
|
||||
if (this._search.originalDomain !== null) {
|
||||
this.state.domain = this._search.originalDomain;
|
||||
}
|
||||
|
||||
// Restore original data
|
||||
if (this._search.originalData) {
|
||||
|
|
@ -445,6 +560,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
// Just show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}
|
||||
|
||||
// Remove highlight class
|
||||
this.$('.o_data_row').removeClass('oe_search_filtered');
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -456,7 +574,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
records: this.state.data && this.state.data.records ?
|
||||
this.state.data.records.slice() : [],
|
||||
count: this.state.count || 0,
|
||||
res_ids: this.state.res_ids ? this.state.res_ids.slice() : []
|
||||
res_ids: this.state.res_ids ? this.state.res_ids.slice() : [],
|
||||
limit: this.state.limit
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -467,6 +586,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
_restoreOriginalData: function() {
|
||||
if (!this._search.originalData) return;
|
||||
|
||||
var self = this;
|
||||
var orig = this._search.originalData;
|
||||
|
||||
// Restore state
|
||||
|
|
@ -476,13 +596,31 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
}
|
||||
this.state.count = orig.count;
|
||||
this.state.res_ids = orig.res_ids;
|
||||
this.state.limit = orig.limit;
|
||||
this.state.domain = this._search.originalDomain || [];
|
||||
}
|
||||
|
||||
// Re-render
|
||||
this._renderRecords(orig.records);
|
||||
// Try parent reload first 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
|
||||
}).then(function() {
|
||||
self._afterRender();
|
||||
}).catch(function() {
|
||||
// Fallback to direct render
|
||||
self._renderRecordsAlternative(orig.records);
|
||||
});
|
||||
} else {
|
||||
// Direct render
|
||||
this._renderRecordsAlternative(orig.records);
|
||||
}
|
||||
|
||||
// Clear stored data
|
||||
this._search.originalData = null;
|
||||
this._search.originalDomain = null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -517,7 +655,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Normalize Arabic text
|
||||
* Normalize Arabic text for better search
|
||||
*/
|
||||
_normalizeArabic: function(text) {
|
||||
if (!text) return '';
|
||||
|
|
|
|||
Loading…
Reference in New Issue