Fix view update: proper render methods with multiple fallbacks, DOM filtering, and parent reload
This commit is contained in:
parent
2bd0e2c9e2
commit
96cf9a42ac
|
|
@ -6,7 +6,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var _t = core._t;
|
||||
var session = require('web.session');
|
||||
var pyUtils = require('web.py_utils');
|
||||
var Domain = require('web.Domain');
|
||||
|
||||
ListRenderer.include({
|
||||
events: _.extend({}, ListRenderer.prototype.events, {
|
||||
|
|
@ -146,6 +145,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
// Store original data if first search
|
||||
if (!this._searchState.originalData) {
|
||||
this._searchState.originalData = this._captureCurrentData();
|
||||
console.log('Captured original data:', this._searchState.originalData);
|
||||
}
|
||||
|
||||
// Build and execute search
|
||||
|
|
@ -195,15 +195,34 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
* Capture current data state
|
||||
*/
|
||||
_captureCurrentData: function() {
|
||||
// Try to get current records from various locations
|
||||
if (this.state && this.state.data) {
|
||||
return {
|
||||
records: this.state.data.records ? this.state.data.records.slice() : [],
|
||||
count: this.state.count || 0,
|
||||
domain: this.state.domain ? this.state.domain.slice() : []
|
||||
};
|
||||
var data = {
|
||||
records: [],
|
||||
count: 0,
|
||||
domain: [],
|
||||
limit: 80,
|
||||
offset: 0
|
||||
};
|
||||
|
||||
// Get current records
|
||||
if (this.state) {
|
||||
if (this.state.data && this.state.data.records) {
|
||||
data.records = this.state.data.records.slice();
|
||||
}
|
||||
if (this.state.count !== undefined) {
|
||||
data.count = this.state.count;
|
||||
}
|
||||
if (this.state.domain) {
|
||||
data.domain = Array.isArray(this.state.domain) ? this.state.domain.slice() : this.state.domain;
|
||||
}
|
||||
if (this.state.limit !== undefined) {
|
||||
data.limit = this.state.limit;
|
||||
}
|
||||
if (this.state.offset !== undefined) {
|
||||
data.offset = this.state.offset;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -277,7 +296,21 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
}
|
||||
|
||||
// Combine with AND operator
|
||||
return ['&'].concat(baseDomain).concat(searchDomain);
|
||||
// Need to be careful with domain structure
|
||||
var result = [];
|
||||
|
||||
// Add AND operator if both domains exist
|
||||
if (baseDomain.length > 0 && searchDomain.length > 0) {
|
||||
result.push('&');
|
||||
}
|
||||
|
||||
// Add base domain
|
||||
result = result.concat(baseDomain);
|
||||
|
||||
// Add search domain
|
||||
result = result.concat(searchDomain);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -353,21 +386,21 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var conditions = [];
|
||||
var self = this;
|
||||
|
||||
// Escape special characters for safe search
|
||||
var safeValue = this._escapeSearchValue(value);
|
||||
var normalizedValue = this._normalizeArabic(safeValue);
|
||||
// Don't escape for now - let's keep it simple
|
||||
var searchValue = value;
|
||||
var normalizedValue = this._normalizeArabic(searchValue);
|
||||
|
||||
fields.forEach(function(field) {
|
||||
// Text-based fields
|
||||
if (['char', 'text', 'html'].includes(field.type)) {
|
||||
conditions.push([field.name, 'ilike', safeValue]);
|
||||
if (normalizedValue && normalizedValue !== safeValue) {
|
||||
conditions.push([field.name, 'ilike', searchValue]);
|
||||
if (normalizedValue && normalizedValue !== searchValue) {
|
||||
conditions.push([field.name, 'ilike', normalizedValue]);
|
||||
}
|
||||
}
|
||||
// Selection fields
|
||||
else if (field.type === 'selection') {
|
||||
conditions.push([field.name, 'ilike', safeValue]);
|
||||
conditions.push([field.name, 'ilike', searchValue]);
|
||||
}
|
||||
// Number fields
|
||||
else if (['integer', 'float', 'monetary'].includes(field.type)) {
|
||||
|
|
@ -401,14 +434,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
return domain.concat(conditions);
|
||||
},
|
||||
|
||||
/**
|
||||
* Escape special characters in search value
|
||||
*/
|
||||
_escapeSearchValue: function(value) {
|
||||
// Remove dangerous characters that might break domain
|
||||
return value.replace(/[%_\\]/g, '\\$&');
|
||||
},
|
||||
|
||||
/**
|
||||
* Execute RPC search
|
||||
*/
|
||||
|
|
@ -419,6 +444,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
|
||||
console.log('Executing RPC search...');
|
||||
console.log('Model:', model);
|
||||
console.log('Domain for RPC:', JSON.stringify(domain));
|
||||
console.log('Fields to read:', fields);
|
||||
|
||||
this._rpc({
|
||||
|
|
@ -433,6 +459,9 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
}
|
||||
}).then(function(result) {
|
||||
console.log('Search completed. Found:', result.length, 'records');
|
||||
if (result.length > 0) {
|
||||
console.log('First result:', result[0]);
|
||||
}
|
||||
self._handleSearchResults(result, searchValue);
|
||||
}).catch(function(error) {
|
||||
console.error('RPC Error:', error);
|
||||
|
|
@ -444,14 +473,15 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
},
|
||||
|
||||
/**
|
||||
* Get fields to read
|
||||
* Get fields to read - CRITICAL: Must match the original fields structure
|
||||
*/
|
||||
_getFieldsToRead: function() {
|
||||
var fields = ['id'];
|
||||
var fieldsInfo = this._getFieldsInfo();
|
||||
|
||||
if (!fieldsInfo) {
|
||||
return ['id', 'display_name'];
|
||||
// Return all fields if we can't determine
|
||||
return false; // This tells Odoo to return all fields
|
||||
}
|
||||
|
||||
// Add visible column fields
|
||||
|
|
@ -462,7 +492,8 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var fieldInfo = fieldsInfo[fieldName];
|
||||
|
||||
// Skip computed non-stored fields
|
||||
if (!fieldInfo || (fieldInfo.compute && !fieldInfo.store)) {
|
||||
if (fieldInfo && fieldInfo.compute && !fieldInfo.store) {
|
||||
console.log('Skipping computed field:', fieldName);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -476,6 +507,11 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
fields.push('display_name');
|
||||
}
|
||||
|
||||
// Add __last_update for proper record tracking
|
||||
if (fieldsInfo.__last_update) {
|
||||
fields.push('__last_update');
|
||||
}
|
||||
|
||||
return _.uniq(fields);
|
||||
},
|
||||
|
||||
|
|
@ -484,25 +520,156 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
*/
|
||||
_getSearchContext: function() {
|
||||
var context = _.extend({}, this.state.context || {}, session.user_context || {});
|
||||
// Remove active_test to include inactive records
|
||||
delete context.active_test;
|
||||
// Don't remove active_test - keep original context
|
||||
return context;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle search results
|
||||
* Handle search results - THIS IS THE CRITICAL PART
|
||||
*/
|
||||
_handleSearchResults: function(records, searchValue) {
|
||||
var count = records.length;
|
||||
console.log('Handling search results:', count, 'records');
|
||||
|
||||
if (count > 0) {
|
||||
this._updateView(records);
|
||||
// Update the view with new records
|
||||
this._updateViewWithRecords(records);
|
||||
this._showResultCount(count);
|
||||
} else {
|
||||
this._showNoResults(searchValue);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update view with search results - PROPER WAY
|
||||
*/
|
||||
_updateViewWithRecords: function(records) {
|
||||
var self = this;
|
||||
console.log('Updating view with', records.length, 'records');
|
||||
|
||||
// Method 1: Update state and trigger re-render
|
||||
if (this.state && this.state.data) {
|
||||
// Update the data
|
||||
this.state.data.records = records;
|
||||
this.state.data.count = records.length;
|
||||
this.state.count = records.length;
|
||||
|
||||
// Update res_ids if it exists
|
||||
if (this.state.res_ids) {
|
||||
this.state.res_ids = records.map(function(r) { return r.id; });
|
||||
}
|
||||
|
||||
console.log('State updated, attempting to re-render...');
|
||||
|
||||
// Try different render methods
|
||||
// Method A: Direct _renderBody
|
||||
if (typeof this._renderBody === 'function') {
|
||||
try {
|
||||
console.log('Calling _renderBody...');
|
||||
var renderPromise = this._renderBody();
|
||||
if (renderPromise && typeof renderPromise.then === 'function') {
|
||||
renderPromise.then(function() {
|
||||
console.log('_renderBody completed successfully');
|
||||
self._restoreSearchValue();
|
||||
}).catch(function(error) {
|
||||
console.error('_renderBody promise error:', error);
|
||||
self._tryAlternativeRender(records);
|
||||
});
|
||||
} else {
|
||||
console.log('_renderBody completed (non-promise)');
|
||||
self._restoreSearchValue();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('_renderBody error:', error);
|
||||
this._tryAlternativeRender(records);
|
||||
}
|
||||
} else {
|
||||
console.log('_renderBody not available, trying alternative...');
|
||||
this._tryAlternativeRender(records);
|
||||
}
|
||||
} else {
|
||||
console.error('No state.data to update');
|
||||
this._tryAlternativeRender(records);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Try alternative rendering method
|
||||
*/
|
||||
_tryAlternativeRender: function(records) {
|
||||
var self = this;
|
||||
console.log('Trying alternative render method...');
|
||||
|
||||
// Method B: Try to trigger parent update
|
||||
if (this.trigger_up) {
|
||||
console.log('Triggering update event...');
|
||||
this.trigger_up('update', {
|
||||
records: records,
|
||||
domain: this._searchState.lastSearchDomain
|
||||
});
|
||||
}
|
||||
|
||||
// Method C: Manual DOM update as last resort
|
||||
// Hide non-matching rows and show matching ones
|
||||
var recordIds = records.map(function(r) { return r.id; });
|
||||
console.log('Record IDs to show:', recordIds);
|
||||
|
||||
// First hide all rows
|
||||
this.$('.o_data_row').hide();
|
||||
|
||||
// Then show matching rows
|
||||
recordIds.forEach(function(id) {
|
||||
self.$('.o_data_row[data-id="' + id + '"]').show();
|
||||
});
|
||||
|
||||
// If no visible rows after filtering, we might need to render them
|
||||
var visibleRows = this.$('.o_data_row:visible').length;
|
||||
console.log('Visible rows after filtering:', visibleRows);
|
||||
|
||||
if (visibleRows === 0 && records.length > 0) {
|
||||
console.log('No visible rows but have records, may need full re-render');
|
||||
// The records might not be in the current DOM, need full render
|
||||
this._forceFullRender(records);
|
||||
}
|
||||
|
||||
this._restoreSearchValue();
|
||||
},
|
||||
|
||||
/**
|
||||
* Force full render of records
|
||||
*/
|
||||
_forceFullRender: function(records) {
|
||||
console.log('Forcing full render...');
|
||||
|
||||
// Store records in state
|
||||
if (this.state && this.state.data) {
|
||||
this.state.data.records = records;
|
||||
}
|
||||
|
||||
// Try to call parent's reload if available
|
||||
if (this.getParent && typeof this.getParent === 'function') {
|
||||
var parent = this.getParent();
|
||||
if (parent && parent.reload) {
|
||||
console.log('Calling parent reload...');
|
||||
parent.reload({
|
||||
offset: 0,
|
||||
limit: records.length,
|
||||
domain: this._searchState.lastSearchDomain
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Restore search value in input
|
||||
*/
|
||||
_restoreSearchValue: function() {
|
||||
if (this._searchState && this._searchState.currentValue) {
|
||||
this.$('.oe_search_input').val(this._searchState.currentValue);
|
||||
this.$('.oe_clear_search').show();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle search error
|
||||
*/
|
||||
|
|
@ -512,27 +679,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
this._fallbackToClientSearch(searchValue);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update view with search results
|
||||
*/
|
||||
_updateView: function(records) {
|
||||
// This is the tricky part - we need to update the view
|
||||
// Different versions of Odoo handle this differently
|
||||
|
||||
if (this.state && this.state.data) {
|
||||
this.state.data.records = records;
|
||||
}
|
||||
|
||||
// Try to re-render
|
||||
if (typeof this._renderBody === 'function') {
|
||||
try {
|
||||
this._renderBody();
|
||||
} catch (e) {
|
||||
console.error('Error rendering body:', e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fallback to client-side search
|
||||
*/
|
||||
|
|
@ -542,18 +688,30 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
var searchLower = value.toLowerCase();
|
||||
var normalizedSearch = this._normalizeArabic(searchLower);
|
||||
var visibleCount = 0;
|
||||
var totalCount = 0;
|
||||
|
||||
this.$('.o_data_row').each(function() {
|
||||
var $row = $(this);
|
||||
totalCount++;
|
||||
|
||||
var text = $row.text().toLowerCase();
|
||||
var normalizedText = this._normalizeArabic(text);
|
||||
|
||||
var match = text.includes(searchLower) || normalizedText.includes(normalizedSearch);
|
||||
var match = text.includes(searchLower) ||
|
||||
(normalizedText && normalizedSearch && normalizedText.includes(normalizedSearch));
|
||||
|
||||
$row.toggle(match);
|
||||
if (match) visibleCount++;
|
||||
}.bind(this));
|
||||
|
||||
this._showResultCount(visibleCount, true);
|
||||
// Remove no results message if exists
|
||||
this.$('.oe_no_results').remove();
|
||||
|
||||
if (visibleCount === 0) {
|
||||
this._showNoResults(value);
|
||||
} else {
|
||||
this._showResultCount(visibleCount, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -576,11 +734,14 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
// Restore original data
|
||||
if (this._searchState.originalData) {
|
||||
this._restoreOriginalData();
|
||||
} else {
|
||||
// Just show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}
|
||||
} else {
|
||||
// Show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}
|
||||
|
||||
// Show all rows
|
||||
this.$('.o_data_row').show();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -591,19 +752,46 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log('Restoring original data...');
|
||||
var originalData = this._searchState.originalData;
|
||||
|
||||
if (this.state && this.state.data) {
|
||||
this.state.data.records = originalData.records;
|
||||
// Restore state
|
||||
if (this.state) {
|
||||
if (this.state.data && originalData.records) {
|
||||
this.state.data.records = originalData.records;
|
||||
this.state.data.count = originalData.count || originalData.records.length;
|
||||
}
|
||||
if (originalData.count !== undefined) {
|
||||
this.state.count = originalData.count;
|
||||
}
|
||||
if (originalData.res_ids) {
|
||||
this.state.res_ids = originalData.res_ids;
|
||||
}
|
||||
}
|
||||
|
||||
// Re-render if possible
|
||||
// Re-render
|
||||
if (typeof this._renderBody === 'function') {
|
||||
try {
|
||||
this._renderBody();
|
||||
var renderPromise = this._renderBody();
|
||||
if (renderPromise && typeof renderPromise.then === 'function') {
|
||||
renderPromise.then(function() {
|
||||
console.log('Original data restored successfully');
|
||||
}).catch(function(error) {
|
||||
console.error('Error restoring original data:', error);
|
||||
// Fallback: show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}.bind(this));
|
||||
} else {
|
||||
console.log('Original data restored');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error restoring view:', e);
|
||||
// Fallback: show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}
|
||||
} else {
|
||||
// Fallback: show all rows
|
||||
this.$('.o_data_row').show();
|
||||
}
|
||||
|
||||
this._searchState.originalData = null;
|
||||
|
|
|
|||
Loading…
Reference in New Issue