@@ -428,6 +428,7 @@ async function renderDashboard() {
428428 < div class ="page " id ="page-pterodactyl "> </ div >
429429 < div class ="page " id ="page-account "> </ div >
430430 < div class ="page " id ="page-server-detail "> </ div >
431+ < div class ="page " id ="page-log "> </ div >
431432 </ main >
432433 </ div >
433434
@@ -499,6 +500,8 @@ function navigateTo(page) {
499500 else if ( param === 'links' ) renderAccountLinks ( ) ;
500501 else if ( param === 'dangerous' ) renderDangerous ( ) ;
501502 else renderAccount ( ) ;
503+ } else if ( basePage === 'log' ) {
504+ renderLog ( ) ;
502505 }
503506 }
504507
@@ -539,6 +542,8 @@ window.addEventListener('popstate', () => {
539542 else if ( param === 'links' ) renderAccountLinks ( ) ;
540543 else if ( param === 'dangerous' ) renderDangerous ( ) ;
541544 else renderAccount ( ) ;
545+ } else if ( basePage === 'log' ) {
546+ renderLog ( ) ;
542547 }
543548 }
544549} ) ;
@@ -697,6 +702,63 @@ function getActionLabel(action) {
697702 return labels [ action ] || action ;
698703}
699704
705+ async function renderLog ( pageNum ) {
706+ const el = $ ( '#page-log' ) ;
707+ pageNum = pageNum || 1 ;
708+ const limit = 50 ;
709+ const offset = ( pageNum - 1 ) * limit ;
710+
711+ el . innerHTML = html `
712+ < div class ="page-header ">
713+ < h1 class ="page-title "> Activity Log</ h1 >
714+ < p class ="page-subtitle "> All account activity</ p >
715+ </ div >
716+ < div class ="card " style ="margin-bottom:20px ">
717+ < div id ="log-list ">
718+ < div style ="text-align:center;padding:24px;color:var(--text-secondary) "> < span class ="spinner "> </ span > Loading...</ div >
719+ </ div >
720+ </ div >
721+ ` ;
722+
723+ try {
724+ const data = await api ( `/activity?limit=${ limit } &offset=${ offset } ` ) ;
725+ const list = $ ( '#log-list' ) ;
726+
727+ if ( data . activities . length === 0 ) {
728+ list . innerHTML = '<div class="activity-empty">No activity found.</div>' ;
729+ return ;
730+ }
731+
732+ const pageInfo = data . totalPages > 1 ? html `
733+ < div class ="log-pagination ">
734+ < button class ="btn btn-ghost btn-sm " onclick ="renderLog(${ pageNum - 1 } ) " ${ pageNum <= 1 ? 'disabled' : '' } > Previous</ button >
735+ < span class ="log-pagination-info "> Page ${ data . page } of ${ data . totalPages } (${ data . total } total)</ span >
736+ < button class ="btn btn-ghost btn-sm " onclick ="renderLog(${ pageNum + 1 } ) " ${ pageNum >= data . totalPages ? 'disabled' : '' } > Next</ button >
737+ </ div >
738+ ` : '' ;
739+
740+ list . innerHTML = html `
741+ ${ pageInfo }
742+ < div class ="activity-list ">
743+ ${ data . activities . map ( a => html `
744+ < div class ="activity-item ">
745+ < div class ="activity-icon activity-icon- ${ a . action } "> ${ activityIcons [ a . action ] || '' } </ div >
746+ < div class ="activity-content ">
747+ < div class ="activity-action "> ${ getActionLabel ( a . action ) } </ div >
748+ < div class ="activity-details "> ${ a . details || '' } </ div >
749+ </ div >
750+ < div class ="activity-time "> ${ formatRelativeTime ( a . created_at ) } </ div >
751+ </ div >
752+ ` ) . join ( '' ) }
753+ </ div >
754+ ${ pageInfo }
755+ ` ;
756+ } catch ( err ) {
757+ const list = $ ( '#log-list' ) ;
758+ if ( list ) list . innerHTML = '<div class="activity-empty">Could not load activity log.</div>' ;
759+ }
760+ }
761+
700762async function renderActivity ( ) {
701763 const el = $ ( '#page-overview' ) ;
702764 let activitySection = $ ( '#activity-section' ) ;
@@ -718,24 +780,36 @@ async function renderActivity() {
718780 }
719781
720782 try {
721- const data = await api ( '/activity' ) ;
783+ const data = await api ( '/activity?limit=5 ' ) ;
722784 const list = $ ( '#activity-list' ) ;
723785
724786 if ( data . activities . length === 0 ) {
725787 list . innerHTML = '<div class="activity-empty">No activity yet. Create a server to get started.</div>' ;
726788 return ;
727789 }
728790
729- list . innerHTML = data . activities . slice ( 0 , 10 ) . map ( a => html `
730- < div class ="activity-item ">
731- < div class ="activity-icon activity-icon- ${ a . action } "> ${ activityIcons [ a . action ] || '' } </ div >
732- < div class ="activity-content ">
733- < div class ="activity-action "> ${ getActionLabel ( a . action ) } </ div >
734- < div class ="activity-details "> ${ a . details || '' } </ div >
735- </ div >
736- < div class ="activity-time "> ${ formatRelativeTime ( a . created_at ) } </ div >
791+ const showCount = Math . min ( 4 , data . activities . length ) ;
792+ const hasMore = data . total > 4 ;
793+
794+ list . innerHTML = html `
795+ < div class ="activity-list ${ hasMore ? ' activity-list-truncated' : '' } ">
796+ ${ data . activities . slice ( 0 , showCount ) . map ( a => html `
797+ < div class ="activity-item ">
798+ < div class ="activity-icon activity-icon- ${ a . action } "> ${ activityIcons [ a . action ] || '' } </ div >
799+ < div class ="activity-content ">
800+ < div class ="activity-action "> ${ getActionLabel ( a . action ) } </ div >
801+ < div class ="activity-details "> ${ a . details || '' } </ div >
802+ </ div >
803+ < div class ="activity-time "> ${ formatRelativeTime ( a . created_at ) } </ div >
804+ </ div >
805+ ` ) . join ( '' ) }
737806 </ div >
738- ` ) . join ( '' ) ;
807+ ${ hasMore ? html `
808+ < div class ="activity-more-overlay ">
809+ < a class ="btn btn-primary btn-sm " onclick ="navigateTo('log') " style ="margin-top:12px;width:auto "> View all logs</ a >
810+ </ div >
811+ ` : '' }
812+ ` ;
739813 } catch ( err ) {
740814 const list = $ ( '#activity-list' ) ;
741815 if ( list ) list . innerHTML = '<div class="activity-empty">Could not load activity.</div>' ;
0 commit comments