feat: highlight selected node
This commit is contained in:
@@ -22,6 +22,9 @@ class ClusterMembersComponent extends Component {
|
|||||||
|
|
||||||
// Drawer state for desktop
|
// Drawer state for desktop
|
||||||
this.drawer = new DrawerComponent();
|
this.drawer = new DrawerComponent();
|
||||||
|
|
||||||
|
// Selection state for highlighting
|
||||||
|
this.selectedMemberIp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if we should use desktop drawer behavior
|
// Determine if we should use desktop drawer behavior
|
||||||
@@ -31,6 +34,9 @@ class ClusterMembersComponent extends Component {
|
|||||||
|
|
||||||
|
|
||||||
openDrawerForMember(memberIp) {
|
openDrawerForMember(memberIp) {
|
||||||
|
// Set selected member and update highlighting
|
||||||
|
this.setSelectedMember(memberIp);
|
||||||
|
|
||||||
// Get display name for drawer title
|
// Get display name for drawer title
|
||||||
let displayName = memberIp;
|
let displayName = memberIp;
|
||||||
try {
|
try {
|
||||||
@@ -68,6 +74,9 @@ class ClusterMembersComponent extends Component {
|
|||||||
</div>
|
</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
|
// Don't re-render on resume - maintain current state
|
||||||
return false;
|
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;
|
window.ClusterMembersComponent = ClusterMembersComponent;
|
||||||
@@ -5,6 +5,7 @@ class DrawerComponent {
|
|||||||
this.detailsDrawerContent = null;
|
this.detailsDrawerContent = null;
|
||||||
this.detailsDrawerBackdrop = null;
|
this.detailsDrawerBackdrop = null;
|
||||||
this.activeDrawerComponent = null;
|
this.activeDrawerComponent = null;
|
||||||
|
this.onCloseCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if we should use desktop drawer behavior
|
// 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.ensureDrawer();
|
||||||
|
this.onCloseCallback = onCloseCallback;
|
||||||
|
|
||||||
// Set drawer title
|
// Set drawer title
|
||||||
const titleEl = this.detailsDrawer.querySelector('.drawer-title');
|
const titleEl = this.detailsDrawer.querySelector('.drawer-title');
|
||||||
@@ -101,6 +103,12 @@ class DrawerComponent {
|
|||||||
closeDrawer() {
|
closeDrawer() {
|
||||||
if (this.detailsDrawer) this.detailsDrawer.classList.remove('open');
|
if (this.detailsDrawer) this.detailsDrawer.classList.remove('open');
|
||||||
if (this.detailsDrawerBackdrop) this.detailsDrawerBackdrop.classList.remove('visible');
|
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
|
// Clean up drawer elements
|
||||||
|
|||||||
@@ -3033,6 +3033,37 @@ p {
|
|||||||
animation: highlight-pulse 2s ease-in-out;
|
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 {
|
@keyframes highlight-pulse {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||||
|
|||||||
@@ -236,6 +236,33 @@
|
|||||||
display: none;
|
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 {
|
[data-theme="light"] .tabs-container {
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(255, 255, 255, 0.08);
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
|
|||||||
Reference in New Issue
Block a user