8181 flex-shrink : 0 ;
8282 background-color : var (--illinois-blue );
8383 border-color : var (--illinois-blue );
84- color : white;
84+ color : white !important ;
8585 }
8686 .copy-btn : hover {
8787 background-color : var (--illinois-blue-light );
8888 border-color : var (--illinois-blue-light );
89- color : white;
89+ color : white !important ;
9090 }
9191 .copy-btn .btn-success {
9292 background-color : # 28a745 ;
9393 border-color : # 28a745 ;
94+ color : white !important ;
95+ }
96+ .copy-btn .btn-outline-primary {
97+ background-color : var (--illinois-blue );
98+ border-color : var (--illinois-blue );
99+ color : white !important ;
100+ }
101+ .copy-btn .btn-outline-primary : hover {
102+ background-color : var (--illinois-blue-light );
103+ border-color : var (--illinois-blue-light );
104+ color : white !important ;
94105 }
95106 .metadata-section {
96107 background-color : white;
173184 .loading-spinner .active {
174185 display : inline-block;
175186 }
187+ .navbar-nav .nav-link .active {
188+ font-weight : 600 ;
189+ text-decoration : underline;
190+ }
191+ .navbar-nav .nav-link : hover {
192+ opacity : 0.8 ;
193+ }
176194 </ style >
177195</ head >
178196< body >
181199 < span class ="navbar-brand mb-0 h1 " style ="font-weight: 600; ">
182200 < i class ="bi bi-cpu "> </ i > ICRN Kernel Manager
183201 </ span >
202+ < div class ="navbar-nav flex-row ">
203+ < a class ="nav-link text-white me-3 " href ="# " id ="navViewKernels " onclick ="showView('kernels'); return false; " style ="cursor: pointer; ">
204+ < i class ="bi bi-list-ul "> </ i > View Kernels
205+ </ a >
206+ < a class ="nav-link text-white " href ="# " id ="navViewPackages " onclick ="showView('packages'); return false; " style ="cursor: pointer; ">
207+ < i class ="bi bi-box-seam "> </ i > View Packages
208+ </ a >
209+ </ div >
184210 < span class ="navbar-text text-white-50 " style ="font-size: 0.9rem; ">
185211 University of Illinois
186212 </ span >
187213 </ div >
188214 </ nav >
189215
190216 < div class ="container-fluid main-container ">
217+ <!-- Kernels View -->
218+ < div id ="kernelsView ">
191219 < div class ="row ">
192220 <!-- Left Sidebar: Language and Kernel Selection -->
193221 < div class ="col-md-2 ">
@@ -317,6 +345,32 @@ <h5 class="mb-0">Packages in Kernel</h5>
317345 </ div >
318346 </ div >
319347 </ div >
348+ </ div >
349+
350+ <!-- Packages View -->
351+ < div id ="packagesView " style ="display: none; ">
352+ < div class ="card ">
353+ < div class ="card-header ">
354+ < h5 class ="mb-0 "> Search Packages</ h5 >
355+ </ div >
356+ < div class ="card-body ">
357+ < div class ="mb-3 ">
358+ < label for ="packageSearchInput " class ="form-label "> Search for a package by name:</ label >
359+ < div class ="input-group ">
360+ < input type ="text " class ="form-control " id ="packageSearchInput "
361+ placeholder ="Enter package name (e.g., numpy, pandas, ggplot2)... "
362+ onkeyup ="handlePackageSearch(event) ">
363+ < button class ="btn btn-outline-primary " onclick ="performPackageSearch() ">
364+ < i class ="bi bi-search "> </ i > Search
365+ </ button >
366+ </ div >
367+ </ div >
368+ < div id ="packageSearchResults ">
369+ < p class ="text-muted text-center "> Enter a package name above to search</ p >
370+ </ div >
371+ </ div >
372+ </ div >
373+ </ div >
320374 </ div >
321375
322376 <!-- Bootstrap JS -->
@@ -337,6 +391,8 @@ <h5 class="mb-0">Packages in Kernel</h5>
337391 // Initialize on page load
338392 document . addEventListener ( 'DOMContentLoaded' , function ( ) {
339393 loadLanguages ( ) ;
394+ // Set kernels view as active
395+ document . getElementById ( 'navViewKernels' ) . classList . add ( 'active' ) ;
340396 } ) ;
341397
342398 // Load available languages
@@ -651,6 +707,126 @@ <h5 class="mb-0">Packages in Kernel</h5>
651707 div . textContent = text ;
652708 return div . innerHTML ;
653709 }
710+
711+ // View switching
712+ function showView ( viewName ) {
713+ // Update navigation active state
714+ document . getElementById ( 'navViewKernels' ) . classList . remove ( 'active' ) ;
715+ document . getElementById ( 'navViewPackages' ) . classList . remove ( 'active' ) ;
716+
717+ // Show/hide views
718+ if ( viewName === 'kernels' ) {
719+ document . getElementById ( 'kernelsView' ) . style . display = 'block' ;
720+ document . getElementById ( 'packagesView' ) . style . display = 'none' ;
721+ document . getElementById ( 'navViewKernels' ) . classList . add ( 'active' ) ;
722+ } else if ( viewName === 'packages' ) {
723+ document . getElementById ( 'kernelsView' ) . style . display = 'none' ;
724+ document . getElementById ( 'packagesView' ) . style . display = 'block' ;
725+ document . getElementById ( 'navViewPackages' ) . classList . add ( 'active' ) ;
726+ }
727+ }
728+
729+ // Package search functions
730+ function handlePackageSearch ( event ) {
731+ if ( event . key === 'Enter' ) {
732+ performPackageSearch ( ) ;
733+ }
734+ }
735+
736+ async function performPackageSearch ( ) {
737+ const searchInput = document . getElementById ( 'packageSearchInput' ) ;
738+ const query = searchInput . value . trim ( ) ;
739+ const resultsDiv = document . getElementById ( 'packageSearchResults' ) ;
740+
741+ if ( ! query ) {
742+ resultsDiv . innerHTML = '<p class="text-muted text-center">Please enter a package name to search</p>' ;
743+ return ;
744+ }
745+
746+ resultsDiv . innerHTML = '<div class="text-center"><span class="spinner-border spinner-border-sm"></span> Searching packages...</div>' ;
747+
748+ try {
749+ const response = await fetch ( `${ API_BASE } /packages/search?query=${ encodeURIComponent ( query ) } ` ) ;
750+ if ( ! response . ok ) {
751+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
752+ }
753+
754+ const data = await response . json ( ) ;
755+ displayPackageSearchResults ( data ) ;
756+ } catch ( error ) {
757+ console . error ( 'Error searching packages:' , error ) ;
758+ resultsDiv . innerHTML = '<div class="alert alert-danger">Error searching packages. Please try again.</div>' ;
759+ }
760+ }
761+
762+ function displayPackageSearchResults ( data ) {
763+ const resultsDiv = document . getElementById ( 'packageSearchResults' ) ;
764+
765+ if ( ! data . packages || data . packages . length === 0 ) {
766+ resultsDiv . innerHTML = `
767+ <div class="alert alert-info">
768+ <i class="bi bi-info-circle"></i> No packages found matching "${ escapeHtml ( data . query ) } "
769+ </div>
770+ ` ;
771+ return ;
772+ }
773+
774+ let html = `
775+ <div class="mb-3">
776+ <strong>Found ${ data . total_matches } package(s) matching "${ escapeHtml ( data . query ) } "</strong>
777+ </div>
778+ ` ;
779+
780+ data . packages . forEach ( pkg => {
781+ html += `
782+ <div class="card mb-3">
783+ <div class="card-header d-flex justify-content-between align-items-center">
784+ <h6 class="mb-0">
785+ <i class="bi bi-box-seam"></i> ${ escapeHtml ( pkg . name ) }
786+ </h6>
787+ <span class="badge bg-secondary">${ pkg . kernel_count } kernel(s)</span>
788+ </div>
789+ <div class="card-body">
790+ <h6 class="mb-2">Available in the following kernels:</h6>
791+ <div class="table-responsive">
792+ <table class="table table-sm table-hover">
793+ <thead>
794+ <tr>
795+ <th>Language</th>
796+ <th>Kernel Name</th>
797+ <th>Version</th>
798+ <th>Package Version</th>
799+ </tr>
800+ </thead>
801+ <tbody>
802+ ` ;
803+
804+ if ( pkg . kernels && pkg . kernels . length > 0 ) {
805+ pkg . kernels . forEach ( kernel => {
806+ html += `
807+ <tr>
808+ <td><span class="badge bg-info">${ escapeHtml ( kernel . language || 'N/A' ) } </span></td>
809+ <td>${ escapeHtml ( kernel . kernel_name || 'N/A' ) } </td>
810+ <td><span class="badge bg-secondary">${ escapeHtml ( kernel . kernel_version || 'N/A' ) } </span></td>
811+ <td>${ escapeHtml ( kernel . package_version || 'N/A' ) } </td>
812+ </tr>
813+ ` ;
814+ } ) ;
815+ } else {
816+ html += '<tr><td colspan="4" class="text-muted text-center">No kernel information available</td></tr>' ;
817+ }
818+
819+ html += `
820+ </tbody>
821+ </table>
822+ </div>
823+ </div>
824+ </div>
825+ ` ;
826+ } ) ;
827+
828+ resultsDiv . innerHTML = html ;
829+ }
654830 </ script >
655831</ body >
656832</ html >
0 commit comments