feat: add member terminal trigger and align terminal panel bottom-center
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user