-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpaginated-table.service.ts
More file actions
181 lines (153 loc) · 6.15 KB
/
paginated-table.service.ts
File metadata and controls
181 lines (153 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import { computed, effect, inject, Injectable, InjectionToken, signal } from '@angular/core';
import { Table, TablePageEvent } from 'primeng/table';
import { TreeTable } from 'primeng/treetable';
import { SortMeta } from 'primeng/api';
import { KeycloakService } from '@app/core/services/keycloak/keycloak.service';
export type PaginatedTable = TreeTable | Table;
// Define a generic type for filter options
export type PaginatedFilterOption = {
name: string;
value: string;
};
// Define an injection token for filter options
export const PAGINATED_FILTER_OPTIONS_TOKEN = new InjectionToken<PaginatedFilterOption[]>('paginatedFilterOptions');
// Injection token for the localStorage key used to persist pagination state.
// Each component that provides PaginatedTableService should supply its own unique key
// via this token to prevent different tables from overwriting each other's state.
export const PAGINATION_STORAGE_KEY_TOKEN = new InjectionToken<string>('paginationStorageKey');
export interface PaginationState {
page: number;
size: number;
sortField?: string;
sortDirection?: string;
filterType?: string;
searchTerm?: string;
}
@Injectable()
export class PaginatedTableService {
private keycloakService = inject(KeycloakService);
isLoggedIn = computed(() => this.keycloakService.isLoggedIn());
// Inject filter options
filterOptions = inject<PaginatedFilterOption[]>(PAGINATED_FILTER_OPTIONS_TOKEN);
private storageKey = inject(PAGINATION_STORAGE_KEY_TOKEN);
// Pagination state
page = signal(1);
size = signal(20);
sortField = signal<string | undefined>(undefined);
sortDirection = signal<string | undefined>('desc');
searchTerm = signal<string>('');
// Active filter tracking
activeFilter = signal<PaginatedFilterOption>(this.filterOptions[0] || { name: 'All', value: 'ALL' });
// Computed pagination state for queries
paginationState = computed<PaginationState>(() => ({
page: this.page(),
size: this.size(),
sortField: this.sortField(),
sortDirection: this.sortDirection(),
filterType: this.activeFilter().value,
searchTerm: this.searchTerm() || undefined,
}));
constructor() {
// Load state from localStorage (if present) upon construction
console.log('Loading pagination state from localStorage');
this.loadPaginationFromLocalStorage();
// Whenever paginationState changes, save it to localStorage
effect(() => {
console.log('Pagination state changed:', this.paginationState());
const state = this.paginationState();
this.savePaginationToLocalStorage(state);
});
}
private loadPaginationFromLocalStorage(): void {
const storedStateStr = localStorage.getItem(this.storageKey);
if (!storedStateStr) {
console.log('No pagination state found in localStorage');
return;
}
try {
console.log('Parsing pagination state from localStorage');
const storedState: PaginationState = JSON.parse(storedStateStr);
this.page.set(storedState.page);
this.size.set(storedState.size);
if (typeof storedState.sortField === 'string') {
console.log('Setting sortField:', storedState.sortField);
this.sortField.set(storedState.sortField);
}
if (typeof storedState.sortDirection === 'string') {
console.log('Setting sortDirection:', storedState.sortDirection);
this.sortDirection.set(storedState.sortDirection);
}
if (typeof storedState.searchTerm === 'string') {
console.log('Setting searchTerm:', storedState.searchTerm);
this.searchTerm.set(storedState.searchTerm);
}
if (typeof storedState.filterType === 'string') {
const matchedFilter = this.filterOptions.find(opt => opt.value === storedState.filterType);
if (matchedFilter) {
console.log('Found matching filter:', matchedFilter);
if (!this.isLoggedIn() && ['USER_AUTHORED', 'ASSIGNED_TO_USER', 'REVIEW_REQUESTED'].includes(matchedFilter.value)) {
console.log('User is not logged in and user filter detected, fallback to the first filter.');
} else {
console.log('Setting active filter:', matchedFilter);
this.activeFilter.set(matchedFilter);
}
}
}
} catch (error) {
console.warn('Error parsing paginationState from localStorage:', error);
}
}
private savePaginationToLocalStorage(state: PaginationState): void {
localStorage.setItem(this.storageKey, JSON.stringify(state));
}
filterType(): string {
return this.activeFilter().value;
}
// Method to select a filter (similar to your existing code)
selectFilter(filter: PaginatedFilterOption): void {
this.activeFilter.set(filter);
// Reset to first page
this.page.set(1);
}
// Method to set filter by value (more convenient in some cases)
setFilterType(filterValue: string): void {
const filter = this.filterOptions.find(f => f.value === filterValue) || this.filterOptions[0];
this.selectFilter(filter);
}
// Helper method to handle search term changes
setSearchTerm(term: string | undefined): void {
this.searchTerm.set(term || '');
// Reset to first page
this.page.set(1);
}
// Clear all filters
clearFilters(): void {
this.activeFilter.set(this.filterOptions[0]);
this.searchTerm.set('');
// Reset to first page
this.page.set(1);
}
// PrimeNG table event handlers
onPage(event: TablePageEvent) {
console.log('Page event received:', event);
// Calculate the actual page number from first and rows
const calculatedPage = event.rows > 0 ? Math.floor(event.first / event.rows) + 1 : 1;
// Update both size and page
this.size.set(event.rows);
this.page.set(calculatedPage);
console.log(`Pagination updated: page=${calculatedPage}, size=${event.rows}`);
}
onSort(event: SortMeta) {
console.log('Sort event received:', event);
if (!event) {
console.warn('No sort event provided');
return;
}
this.sortField.set(event.field);
this.sortDirection.set(event.order === 1 ? 'asc' : 'desc');
}
// Check if any filter is active (other than the default)
hasActiveFilter(): boolean {
return this.activeFilter() !== this.filterOptions[0];
}
}