|
1 | | -import { Component, inject, OnInit, signal } from '@angular/core'; |
| 1 | +import { Component, ViewChild, AfterViewInit, signal, computed, effect, inject, OnInit } from '@angular/core'; |
2 | 2 | import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; |
3 | | -import { UserService } from '@core/services/user.service'; |
4 | | -import { DatePipe, NgFor } from '@angular/common'; |
| 3 | +import { MatTableDataSource } from '@angular/material/table'; |
| 4 | +import { MatPaginator, MatPaginatorModule, PageEvent } from '@angular/material/paginator'; |
| 5 | +import { MatSort, MatSortModule } from '@angular/material/sort'; |
| 6 | +import { UserService } from "@core/services/user.service"; |
| 7 | +import { MatTableModule } from '@angular/material/table'; |
| 8 | +import { MatFormFieldModule } from '@angular/material/form-field'; |
| 9 | +import { MatInputModule } from '@angular/material/input'; |
| 10 | +import { DatePipe, NgFor, NgIf } from '@angular/common'; |
| 11 | + |
| 12 | +// Define the ActivityLog interface |
| 13 | +interface ActivityLog { |
| 14 | + username: string; |
| 15 | + email: string; |
| 16 | + activity: string; |
| 17 | + endpoint: string; |
| 18 | + timestamp: Date; |
| 19 | +} |
5 | 20 |
|
6 | 21 | @Component({ |
7 | 22 | selector: 'app-activity-log', |
8 | 23 | templateUrl: './activity-log.component.html', |
9 | | - styleUrls: ['./activity-log.component.scss'], |
10 | 24 | standalone: true, |
11 | 25 | imports: [ |
12 | 26 | ReactiveFormsModule, |
| 27 | + MatTableModule, |
| 28 | + MatPaginatorModule, |
| 29 | + MatSortModule, |
| 30 | + MatFormFieldModule, |
| 31 | + MatInputModule, |
13 | 32 | DatePipe, |
14 | | - NgFor |
| 33 | + NgIf |
15 | 34 | ] |
16 | 35 | }) |
17 | | -export class ActivityLogComponent implements OnInit { |
| 36 | +export class ActivityLogComponent implements AfterViewInit, OnInit { |
18 | 37 | private fb = inject(FormBuilder); |
19 | | - private userService = inject(UserService); |
| 38 | + private activityLogService = inject(UserService); |
| 39 | + |
| 40 | + // Signals |
| 41 | + activityLogs = signal<ActivityLog[]>([]); |
| 42 | + totalRecords = signal<number>(0); |
| 43 | + loading = signal<boolean>(false); |
| 44 | + error = signal<string | null>(null); |
| 45 | + pageSize = signal<number>(5); |
| 46 | + pageIndex = signal<number>(0); |
| 47 | + |
| 48 | + // Material table related properties |
| 49 | + displayedColumns = ['username', 'email', 'activity', 'endpoint', 'timestamp']; |
| 50 | + dataSource = signal(new MatTableDataSource<ActivityLog>([])); |
| 51 | + |
| 52 | + // Form for API filtering |
| 53 | + filterForm = this.fb.group({ |
| 54 | + username: [''], |
| 55 | + email: [''] |
| 56 | + }); |
20 | 57 |
|
21 | | - filterForm!: FormGroup; |
22 | | - activityLogs = signal<any[]>([]); |
| 58 | + @ViewChild(MatPaginator) paginator!: MatPaginator; |
| 59 | + @ViewChild(MatSort) sort!: MatSort; |
23 | 60 |
|
24 | | - ngOnInit(): void { |
25 | | - this.filterForm = this.fb.group({ |
26 | | - username: [''], |
27 | | - email: [''] |
| 61 | + constructor() { |
| 62 | + // Effect to update the dataSource when activityLogs changes |
| 63 | + effect(() => { |
| 64 | + const currentLogs = this.activityLogs(); |
| 65 | + this.totalRecords.set(currentLogs.length); |
| 66 | + |
| 67 | + // Manually handle pagination since datasource pagination is not working |
| 68 | + const start = this.pageIndex() * this.pageSize(); |
| 69 | + const end = start + this.pageSize(); |
| 70 | + const paginatedData = currentLogs.slice(start, end); |
| 71 | + |
| 72 | + const dataSourceValue = new MatTableDataSource<ActivityLog>(paginatedData); |
| 73 | + |
| 74 | + if (this.sort) { |
| 75 | + dataSourceValue.sort = this.sort; |
| 76 | + } |
| 77 | + |
| 78 | + this.dataSource.set(dataSourceValue); |
| 79 | + }); |
| 80 | + } |
| 81 | + |
| 82 | + ngOnInit() { |
| 83 | + // Initialize by loading all logs |
| 84 | + this.loadActivityLogs(); |
| 85 | + } |
| 86 | + |
| 87 | + ngAfterViewInit() { |
| 88 | + // Ensure sort is applied after view initialization |
| 89 | + setTimeout(() => { |
| 90 | + if (this.sort) { |
| 91 | + const dataSourceValue = this.dataSource(); |
| 92 | + dataSourceValue.sort = this.sort; |
| 93 | + this.dataSource.set(dataSourceValue); |
| 94 | + } |
28 | 95 | }); |
29 | 96 | } |
30 | 97 |
|
31 | | - onFilter(): void { |
32 | | - const { username, email } = this.filterForm.value; |
33 | | - this.userService.getActivityLogs(username, email).subscribe({ |
| 98 | + // Handle pagination events |
| 99 | + handlePageEvent(event: PageEvent) { |
| 100 | + this.pageSize.set(event.pageSize); |
| 101 | + this.pageIndex.set(event.pageIndex); |
| 102 | + } |
| 103 | + |
| 104 | + loadActivityLogs() { |
| 105 | + this.loading.set(true); |
| 106 | + this.error.set(null); |
| 107 | + |
| 108 | + this.activityLogService.getActivityLogs().subscribe({ |
| 109 | + next: (logs) => { |
| 110 | + this.activityLogs.set(logs); |
| 111 | + this.pageIndex.set(0); // Reset to first page |
| 112 | + this.loading.set(false); |
| 113 | + }, |
| 114 | + error: (err) => { |
| 115 | + console.error('Error loading activity logs', err); |
| 116 | + this.error.set('Failed to load activity logs. Please try again.'); |
| 117 | + this.loading.set(false); |
| 118 | + } |
| 119 | + }); |
| 120 | + } |
| 121 | + |
| 122 | + onFilter() { |
| 123 | + const usernameValue = this.filterForm.get('username')?.value; |
| 124 | + const emailValue = this.filterForm.get('email')?.value; |
| 125 | + |
| 126 | + this.loading.set(true); |
| 127 | + this.error.set(null); |
| 128 | + |
| 129 | + this.activityLogService.getActivityLogs(usernameValue, emailValue).subscribe({ |
34 | 130 | next: (logs) => { |
35 | 131 | this.activityLogs.set(logs); |
| 132 | + this.pageIndex.set(0); // Reset to first page |
| 133 | + this.loading.set(false); |
| 134 | + }, |
| 135 | + error: (err) => { |
| 136 | + console.error('Error filtering activity logs', err); |
| 137 | + this.error.set('Failed to filter activity logs. Please try again.'); |
| 138 | + this.loading.set(false); |
36 | 139 | } |
37 | 140 | }); |
38 | 141 | } |
| 142 | + |
| 143 | + // Client-side filtering for the Material table |
| 144 | + applyFilter(event: Event) { |
| 145 | + const filterValue = (event.target as HTMLInputElement).value; |
| 146 | + const filteredLogs = this.activityLogs().filter(log => |
| 147 | + Object.values(log).some(val => |
| 148 | + val && val.toString().toLowerCase().includes(filterValue.toLowerCase()) |
| 149 | + ) |
| 150 | + ); |
| 151 | + |
| 152 | + // Update filtered records |
| 153 | + const start = this.pageIndex() * this.pageSize(); |
| 154 | + const end = start + this.pageSize(); |
| 155 | + const paginatedData = filteredLogs.slice(start, end); |
| 156 | + |
| 157 | + const dataSourceValue = new MatTableDataSource<ActivityLog>(paginatedData); |
| 158 | + this.totalRecords.set(filteredLogs.length); |
| 159 | + this.pageIndex.set(0); // Reset to first page |
| 160 | + |
| 161 | + if (this.sort) { |
| 162 | + dataSourceValue.sort = this.sort; |
| 163 | + } |
| 164 | + |
| 165 | + this.dataSource.set(dataSourceValue); |
| 166 | + } |
39 | 167 | } |
0 commit comments