feat: add member terminal trigger and align terminal panel bottom-center

This commit is contained in:
2025-09-30 21:32:30 +02:00
parent 75dc122898
commit a26ef3949a
3 changed files with 104 additions and 38 deletions

View File

@@ -23,6 +23,9 @@ class ClusterMembersComponent extends Component {
// Drawer state for desktop
this.drawer = new DrawerComponent();
// Terminal panel container (shared with drawer)
this.terminalPanelContainer = null;
// Selection state for highlighting
this.selectedMemberIp = null;
}
@@ -403,7 +406,6 @@ class ClusterMembersComponent extends Component {
const membersHTML = members.map(member => {
const statusClass = (member.status && member.status.toUpperCase() === 'ACTIVE') ? 'status-online' : 'status-offline';
const statusText = (member.status && member.status.toUpperCase() === 'ACTIVE') ? 'Online' : 'Offline';
const statusIcon = (member.status && member.status.toUpperCase() === 'ACTIVE') ? '🟢' : '🔴';
logger.debug('ClusterMembersComponent: Rendering member:', member);
@@ -433,10 +435,18 @@ class ClusterMembersComponent extends Component {
</div>
` : ''}
</div>
<div class="expand-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
<div class="member-actions">
<button class="member-terminal-btn" title="Open Terminal" aria-label="Open Terminal">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 17l6-6-6-6"></path>
<path d="M12 19h8"></path>
</svg>
</button>
<div class="expand-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</div>
</div>
</div>
<div class="member-details">
@@ -455,6 +465,7 @@ class ClusterMembersComponent extends Component {
setupMemberCards(members) {
setTimeout(() => {
this.findAllElements('.member-card').forEach((card, index) => {
const terminalBtn = card.querySelector('.member-terminal-btn');
const expandIcon = card.querySelector('.expand-icon');
const memberDetails = card.querySelector('.member-details');
const memberIp = card.dataset.memberIp;
@@ -505,6 +516,21 @@ class ClusterMembersComponent extends Component {
}
});
}
if (terminalBtn) {
this.addEventListener(terminalBtn, 'click', (e) => {
e.stopPropagation();
e.preventDefault();
try {
if (window.TerminalPanel) {
this.ensureTerminalContainer();
window.TerminalPanel.open(this.terminalPanelContainer, memberIp);
}
} catch (err) {
console.error('Failed to open member terminal:', err);
}
});
}
});
}, 100);
}
@@ -722,6 +748,20 @@ class ClusterMembersComponent extends Component {
this.selectedMemberIp = null;
}
}
ensureTerminalContainer() {
if (!this.terminalPanelContainer) {
try {
const drawer = this.drawer;
if (drawer && drawer.ensureDrawer) {
drawer.ensureDrawer();
this.terminalPanelContainer = drawer.terminalPanelContainer;
}
} catch (err) {
console.error('Failed to ensure terminal container:', err);
}
}
}
}
window.ClusterMembersComponent = ClusterMembersComponent;