@@ -123,6 +123,10 @@ <h3>Filters</h3>
123123 < section class ="sidebar-section ">
124124 < h3 > Publication Indicator</ h3 >
125125 < div class ="checkbox-group ">
126+ < label class ="checkbox-label ">
127+ < input type ="checkbox " id ="show-published-with-lab ">
128+ < span > Highlight published with lab</ span >
129+ </ label >
126130 < label class ="checkbox-label ">
127131 < input type ="checkbox " id ="show-published-indicator ">
128132 < span > Highlight published on project</ span >
@@ -131,11 +135,11 @@ <h3>Publication Indicator</h3>
131135 < div class ="indicator-legend " id ="indicator-legend ">
132136 < div class ="legend-item ">
133137 < span class ="legend-swatch legend-published "> </ span >
134- < span class ="legend-label "> Published on selected project (s)</ span >
138+ < span class ="legend-label "> Has publication (s)</ span >
135139 </ div >
136140 < div class ="legend-item ">
137141 < span class ="legend-swatch legend-not-published "> </ span >
138- < span class ="legend-label "> No publications on selected project(s) </ span >
142+ < span class ="legend-label "> No publications</ span >
139143 </ div >
140144 </ div >
141145 </ section >
@@ -175,6 +179,10 @@ <h3>Group By</h3>
175179 < input type ="radio " name ="group " value ="position ">
176180 < span > Position (abstracted)</ span >
177181 </ label >
182+ < label class ="radio-label ">
183+ < input type ="radio " name ="group " value ="student_status ">
184+ < span > Students / Non-Students</ span >
185+ </ label >
178186 </ div >
179187 </ section >
180188
@@ -250,6 +258,7 @@ <h1 id="page-title">Project People Viewer</h1>
250258 const showSchoolCheckbox = document . getElementById ( 'show-school' ) ;
251259 const fullSchoolCheckbox = document . getElementById ( 'full-school' ) ;
252260 const showPublishedIndicatorCheckbox = document . getElementById ( 'show-published-indicator' ) ;
261+ const showPublishedWithLabCheckbox = document . getElementById ( 'show-published-with-lab' ) ;
253262 const hideNonPublishersCheckbox = document . getElementById ( 'hide-non-publishers' ) ;
254263 const hideCollaboratorsCheckbox = document . getElementById ( 'hide-collaborators' ) ;
255264 const onlyMyAdviseesCheckbox = document . getElementById ( 'only-my-advisees' ) ;
@@ -267,6 +276,7 @@ <h1 id="page-title">Project People Viewer</h1>
267276 showSchool : true ,
268277 fullSchool : false ,
269278 showPublishedIndicator : false ,
279+ showPublishedWithLab : false ,
270280 hideNonPublishers : false ,
271281 hideCollaborators : false ,
272282 onlyMyAdvisees : false ,
@@ -304,7 +314,7 @@ <h1 id="page-title">Project People Viewer</h1>
304314
305315 // Load group option
306316 const groupParam = params . get ( 'group' ) ;
307- if ( groupParam && [ 'none' , 'position' ] . includes ( groupParam ) ) {
317+ if ( groupParam && [ 'none' , 'position' , 'student_status' ] . includes ( groupParam ) ) {
308318 state . group = groupParam ;
309319 }
310320
@@ -324,6 +334,9 @@ <h1 id="page-title">Project People Viewer</h1>
324334 if ( params . has ( 'show_pub' ) ) {
325335 state . showPublishedIndicator = params . get ( 'show_pub' ) === '1' ;
326336 }
337+ if ( params . has ( 'show_pub_lab' ) ) {
338+ state . showPublishedWithLab = params . get ( 'show_pub_lab' ) === '1' ;
339+ }
327340 if ( params . has ( 'hide_non_pub' ) ) {
328341 state . hideNonPublishers = params . get ( 'hide_non_pub' ) === '1' ;
329342 }
@@ -380,6 +393,9 @@ <h1 id="page-title">Project People Viewer</h1>
380393 if ( state . showPublishedIndicator ) {
381394 params . set ( 'show_pub' , '1' ) ;
382395 }
396+ if ( state . showPublishedWithLab ) {
397+ params . set ( 'show_pub_lab' , '1' ) ;
398+ }
383399 if ( state . hideNonPublishers ) {
384400 params . set ( 'hide_non_pub' , '1' ) ;
385401 }
@@ -420,7 +436,8 @@ <h1 id="page-title">Project People Viewer</h1>
420436 * Updates the legend visibility based on checkbox state.
421437 */
422438 function updateLegendVisibility ( ) {
423- indicatorLegend . classList . toggle ( 'visible' , state . showPublishedIndicator ) ;
439+ indicatorLegend . classList . toggle ( 'visible' ,
440+ state . showPublishedIndicator || state . showPublishedWithLab ) ;
424441 }
425442
426443 /**
@@ -693,6 +710,48 @@ <h1 id="page-title">Project People Viewer</h1>
693710 return groups ;
694711 }
695712
713+ /**
714+ * Checks if a person's title is a student title.
715+ * @param {Object } person - Person object
716+ * @returns {boolean } True if person is a student
717+ */
718+ function isStudent ( person ) {
719+ const studentTitles = [
720+ 'High School Student' , 'Undergrad' , 'MS Student' ,
721+ 'PhD Student' , 'Medical Student'
722+ ] ;
723+ return studentTitles . includes ( person . title ) ;
724+ }
725+
726+ /**
727+ * Groups people into Students and Non-Students.
728+ * @param {Array } people - Array of people
729+ * @returns {Object } Object with 'Students' and 'Non-Students' keys
730+ */
731+ function groupPeopleByStudentStatus ( people ) {
732+ const groups = {
733+ 'Students' : [ ] ,
734+ 'Non-Students' : [ ]
735+ } ;
736+
737+ for ( const person of people ) {
738+ if ( isStudent ( person ) ) {
739+ groups [ 'Students' ] . push ( person ) ;
740+ } else {
741+ groups [ 'Non-Students' ] . push ( person ) ;
742+ }
743+ }
744+
745+ // Remove empty groups
746+ for ( const key of Object . keys ( groups ) ) {
747+ if ( groups [ key ] . length === 0 ) {
748+ delete groups [ key ] ;
749+ }
750+ }
751+
752+ return groups ;
753+ }
754+
696755 /**
697756 * Renders a single person card.
698757 * @param {Object } person - Person object
@@ -731,10 +790,13 @@ <h1 id="page-title">Project People Viewer</h1>
731790 const imageUrl = person . image_url || '/static/website/images/placeholder-person.png' ;
732791
733792 // Determine publication indicator class
793+ // "Published on project" takes priority if both are enabled
734794 let publishedClass = '' ;
735- if ( state . showPublishedIndicator ) {
795+ if ( state . showPublishedIndicator && state . selectedProjects . size > 0 ) {
736796 const hasPublished = hasPublishedOnSelectedProjects ( person ) ;
737797 publishedClass = hasPublished ? 'has-published' : 'no-publications' ;
798+ } else if ( state . showPublishedWithLab ) {
799+ publishedClass = person . has_any_publication ? 'has-published' : 'no-publications' ;
738800 }
739801
740802 // Build the card HTML
@@ -787,16 +849,21 @@ <h1 id="page-title">Project People Viewer</h1>
787849 // Sort people
788850 people = sortPeople ( people ) ;
789851
790- // Count published vs not published if indicator is on
852+ // Count published vs not published if either indicator is on
791853 let publishedCount = 0 ;
792- if ( state . showPublishedIndicator ) {
854+ let publishedLabel = '' ;
855+ if ( state . showPublishedIndicator && state . selectedProjects . size > 0 ) {
793856 publishedCount = people . filter ( p => hasPublishedOnSelectedProjects ( p ) ) . length ;
857+ publishedLabel = 'with publications on selected projects' ;
858+ } else if ( state . showPublishedWithLab ) {
859+ publishedCount = people . filter ( p => p . has_any_publication ) . length ;
860+ publishedLabel = 'with publications' ;
794861 }
795862
796863 // Update people count
797864 let countText = `${ people . length } ${ people . length === 1 ? 'person' : 'people' } ` ;
798- if ( state . showPublishedIndicator ) {
799- countText += ` (${ publishedCount } with publications on selected projects )` ;
865+ if ( publishedLabel ) {
866+ countText += ` (${ publishedCount } ${ publishedLabel } )` ;
800867 }
801868 peopleCountEl . textContent = countText ;
802869
@@ -830,6 +897,24 @@ <h2 class="people-group-title">${escapeHtml(pluralName)} (${sortedGroupPeople.le
830897 </div>
831898 ` ;
832899 }
900+ } else if ( state . group === 'student_status' ) {
901+ // Group by student vs non-student
902+ const groups = groupPeopleByStudentStatus ( people ) ;
903+
904+ for ( const [ groupName , groupPeople ] of Object . entries ( groups ) ) {
905+ if ( groupPeople . length === 0 ) continue ;
906+
907+ const sortedGroupPeople = sortPeople ( groupPeople ) ;
908+
909+ html += `
910+ <div class="people-group">
911+ <h2 class="people-group-title">${ escapeHtml ( groupName ) } (${ sortedGroupPeople . length } )</h2>
912+ <div class="people-grid">
913+ ${ sortedGroupPeople . map ( p => renderPersonCard ( p ) ) . join ( '' ) }
914+ </div>
915+ </div>
916+ ` ;
917+ }
833918 }
834919
835920 peopleContainer . innerHTML = html ;
@@ -953,13 +1038,20 @@ <h2 class="people-group-title">${escapeHtml(pluralName)} (${sortedGroupPeople.le
9531038 renderPeople ( ) ;
9541039 } ) ;
9551040
956- // Publication indicator checkbox
1041+ // Publication indicator checkbox (per project)
9571042 showPublishedIndicatorCheckbox . addEventListener ( 'change' , ( e ) => {
9581043 state . showPublishedIndicator = e . target . checked ;
9591044 saveStateToURL ( ) ;
9601045 renderPeople ( ) ;
9611046 } ) ;
9621047
1048+ // Publication indicator checkbox (with lab)
1049+ showPublishedWithLabCheckbox . addEventListener ( 'change' , ( e ) => {
1050+ state . showPublishedWithLab = e . target . checked ;
1051+ saveStateToURL ( ) ;
1052+ renderPeople ( ) ;
1053+ } ) ;
1054+
9631055 // Hide non-publishers checkbox
9641056 hideNonPublishersCheckbox . addEventListener ( 'change' , ( e ) => {
9651057 state . hideNonPublishers = e . target . checked ;
@@ -1015,6 +1107,7 @@ <h2 class="people-group-title">${escapeHtml(pluralName)} (${sortedGroupPeople.le
10151107 showSchoolCheckbox . checked = state . showSchool ;
10161108 fullSchoolCheckbox . checked = state . fullSchool ;
10171109 showPublishedIndicatorCheckbox . checked = state . showPublishedIndicator ;
1110+ showPublishedWithLabCheckbox . checked = state . showPublishedWithLab ;
10181111 hideNonPublishersCheckbox . checked = state . hideNonPublishers ;
10191112 hideCollaboratorsCheckbox . checked = state . hideCollaborators ;
10201113 onlyMyAdviseesCheckbox . checked = state . onlyMyAdvisees ;
0 commit comments