feat: highlight selected node
This commit is contained in:
@@ -22,6 +22,9 @@ class ClusterMembersComponent extends Component {
|
||||
|
||||
// Drawer state for desktop
|
||||
this.drawer = new DrawerComponent();
|
||||
|
||||
// Selection state for highlighting
|
||||
this.selectedMemberIp = null;
|
||||
}
|
||||
|
||||
// Determine if we should use desktop drawer behavior
|
||||
@@ -31,6 +34,9 @@ class ClusterMembersComponent extends Component {
|
||||
|
||||
|
||||
openDrawerForMember(memberIp) {
|
||||
// Set selected member and update highlighting
|
||||
this.setSelectedMember(memberIp);
|
||||
|
||||
// Get display name for drawer title
|
||||
let displayName = memberIp;
|
||||
try {
|
||||
@@ -68,6 +74,9 @@ class ClusterMembersComponent extends Component {
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}, null, () => {
|
||||
// Close callback - clear selection when drawer is closed
|
||||
this.clearSelectedMember();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -687,6 +696,32 @@ class ClusterMembersComponent extends Component {
|
||||
// Don't re-render on resume - maintain current state
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set selected member and update highlighting
|
||||
setSelectedMember(memberIp) {
|
||||
// Clear previous selection
|
||||
this.clearSelectedMember();
|
||||
|
||||
// Set new selection
|
||||
this.selectedMemberIp = memberIp;
|
||||
|
||||
// Add selected class to the member card
|
||||
const card = this.findElement(`[data-member-ip="${memberIp}"]`);
|
||||
if (card) {
|
||||
card.classList.add('selected');
|
||||
}
|
||||
}
|
||||
|
||||
// Clear selected member highlighting
|
||||
clearSelectedMember() {
|
||||
if (this.selectedMemberIp) {
|
||||
const card = this.findElement(`[data-member-ip="${this.selectedMemberIp}"]`);
|
||||
if (card) {
|
||||
card.classList.remove('selected');
|
||||
}
|
||||
this.selectedMemberIp = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.ClusterMembersComponent = ClusterMembersComponent;
|
||||
@@ -5,6 +5,7 @@ class DrawerComponent {
|
||||
this.detailsDrawerContent = null;
|
||||
this.detailsDrawerBackdrop = null;
|
||||
this.activeDrawerComponent = null;
|
||||
this.onCloseCallback = null;
|
||||
}
|
||||
|
||||
// Determine if we should use desktop drawer behavior
|
||||
@@ -57,8 +58,9 @@ class DrawerComponent {
|
||||
});
|
||||
}
|
||||
|
||||
openDrawer(title, contentCallback, errorCallback) {
|
||||
openDrawer(title, contentCallback, errorCallback, onCloseCallback) {
|
||||
this.ensureDrawer();
|
||||
this.onCloseCallback = onCloseCallback;
|
||||
|
||||
// Set drawer title
|
||||
const titleEl = this.detailsDrawer.querySelector('.drawer-title');
|
||||
@@ -101,6 +103,12 @@ class DrawerComponent {
|
||||
closeDrawer() {
|
||||
if (this.detailsDrawer) this.detailsDrawer.classList.remove('open');
|
||||
if (this.detailsDrawerBackdrop) this.detailsDrawerBackdrop.classList.remove('visible');
|
||||
|
||||
// Call close callback if provided
|
||||
if (this.onCloseCallback) {
|
||||
this.onCloseCallback();
|
||||
this.onCloseCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up drawer elements
|
||||
|
||||
@@ -3033,6 +3033,37 @@ p {
|
||||
animation: highlight-pulse 2s ease-in-out;
|
||||
}
|
||||
|
||||
/* Selected member card styling */
|
||||
.member-card.selected {
|
||||
border-color: #3b82f6 !important;
|
||||
border-width: 2px !important;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2), 0 8px 25px rgba(0, 0, 0, 0.2) !important;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, var(--bg-tertiary) 100%) !important;
|
||||
z-index: 10 !important;
|
||||
}
|
||||
|
||||
.member-card.selected::before {
|
||||
opacity: 0.8 !important;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(59, 130, 246, 0.05) 100%) !important;
|
||||
}
|
||||
|
||||
.member-card.selected .member-header {
|
||||
background: rgba(59, 130, 246, 0.05) !important;
|
||||
}
|
||||
|
||||
.member-card.selected .member-status {
|
||||
filter: brightness(1.2) !important;
|
||||
}
|
||||
|
||||
.member-card.selected .member-hostname {
|
||||
color: #3b82f6 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.member-card.selected .member-ip {
|
||||
color: #60a5fa !important;
|
||||
}
|
||||
|
||||
@keyframes highlight-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
|
||||
@@ -236,6 +236,33 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Selected member card styling for light theme */
|
||||
[data-theme="light"] .member-card.selected {
|
||||
border-color: #3b82f6 !important;
|
||||
border-width: 2px !important;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2), 0 8px 25px rgba(148, 163, 184, 0.15) !important;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(255, 255, 255, 0.15) 100%) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card.selected::before {
|
||||
display: block !important;
|
||||
opacity: 0.6 !important;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(59, 130, 246, 0.03) 100%) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card.selected .member-header {
|
||||
background: rgba(59, 130, 246, 0.03) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card.selected .member-hostname {
|
||||
color: #1d4ed8 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card.selected .member-ip {
|
||||
color: #3b82f6 !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .tabs-container {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
backdrop-filter: blur(20px);
|
||||
|
||||
Reference in New Issue
Block a user