refactor(rendering): restore NodeDetails active tab; keyed partial updates by IP; add escapeHtml in base Component and use in members; simplify ApiClient methods by removing redundant try/catch
This commit is contained in:
@@ -285,22 +285,11 @@ class ClusterMembersComponent extends Component {
|
||||
|
||||
// Check if we should skip rendering during view switches
|
||||
shouldSkipRender() {
|
||||
// Skip rendering if we're in the middle of a view switch
|
||||
const isViewSwitching = document.querySelectorAll('.view-content.active').length === 0;
|
||||
if (isViewSwitching) {
|
||||
console.log('ClusterMembersComponent: View switching in progress, skipping render');
|
||||
// Rely on lifecycle flags controlled by App
|
||||
if (!this.isMounted || this.isPaused) {
|
||||
logger.debug('ClusterMembersComponent: Not mounted or paused, skipping render');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip rendering if the component is not visible
|
||||
const isVisible = this.container.style.display !== 'none' &&
|
||||
this.container.style.opacity !== '0' &&
|
||||
this.container.classList.contains('active');
|
||||
if (!isVisible) {
|
||||
console.log('ClusterMembersComponent: Component not visible, skipping render');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -308,11 +297,12 @@ class ClusterMembersComponent extends Component {
|
||||
updateMembersPartially(newMembers, previousMembers) {
|
||||
console.log('ClusterMembersComponent: Performing partial update to preserve UI state');
|
||||
|
||||
// Update only the data that changed, preserving expanded states and active tabs
|
||||
newMembers.forEach((newMember, index) => {
|
||||
const prevMember = previousMembers[index];
|
||||
// Build previous map by IP for stable diffs
|
||||
const prevByIp = new Map((previousMembers || []).map(m => [m.ip, m]));
|
||||
newMembers.forEach((newMember) => {
|
||||
const prevMember = prevByIp.get(newMember.ip);
|
||||
if (prevMember && this.hasMemberChanged(newMember, prevMember)) {
|
||||
this.updateMemberCard(newMember, index);
|
||||
this.updateMemberCard(newMember);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -325,7 +315,7 @@ class ClusterMembersComponent extends Component {
|
||||
}
|
||||
|
||||
// Update a specific member card without re-rendering the entire component
|
||||
updateMemberCard(member, index) {
|
||||
updateMemberCard(member) {
|
||||
const card = this.findElement(`[data-member-ip="${member.ip}"]`);
|
||||
if (!card) return;
|
||||
|
||||
@@ -451,9 +441,9 @@ class ClusterMembersComponent extends Component {
|
||||
<div class="member-status ${statusClass}">
|
||||
${statusIcon}
|
||||
</div>
|
||||
<div class="member-hostname">${member.hostname || 'Unknown Device'}</div>
|
||||
<div class="member-hostname">${this.escapeHtml(member.hostname || 'Unknown Device')}</div>
|
||||
</div>
|
||||
<div class="member-ip">${member.ip || 'No IP'}</div>
|
||||
<div class="member-ip">${this.escapeHtml(member.ip || 'No IP')}</div>
|
||||
<div class="member-latency">
|
||||
<span class="latency-label">Latency:</span>
|
||||
<span class="latency-value">${member.latency ? member.latency + 'ms' : 'N/A'}</span>
|
||||
@@ -462,7 +452,7 @@ class ClusterMembersComponent extends Component {
|
||||
${member.labels && Object.keys(member.labels).length ? `
|
||||
<div class="member-row-2">
|
||||
<div class="member-labels">
|
||||
${Object.entries(member.labels).map(([key, value]) => `<span class=\"label-chip\">${key}: ${value}</span>`).join('')}
|
||||
${Object.entries(member.labels).map(([key, value]) => `<span class=\"label-chip\">${this.escapeHtml(key)}: ${this.escapeHtml(value)}</span>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
@@ -807,8 +797,8 @@ class NodeDetailsComponent extends Component {
|
||||
}
|
||||
|
||||
renderNodeDetails(nodeStatus, tasks, capabilities) {
|
||||
// Always start with 'status' tab, don't restore previous state
|
||||
const activeTab = 'status';
|
||||
// Use persisted active tab from the view model, default to 'status'
|
||||
const activeTab = (this.viewModel && typeof this.viewModel.get === 'function' && this.viewModel.get('activeTab')) || 'status';
|
||||
console.log('NodeDetailsComponent: Rendering with activeTab:', activeTab);
|
||||
|
||||
const html = `
|
||||
|
||||
Reference in New Issue
Block a user