ciyidogan commited on
Commit
e01b7e8
·
verified ·
1 Parent(s): 6907b62

Update flare-ui/src/app/components/activity-log/activity-log.component.ts

Browse files
flare-ui/src/app/components/activity-log/activity-log.component.ts CHANGED
@@ -5,6 +5,9 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
5
  import { MatButtonModule } from '@angular/material/button';
6
  import { MatIconModule } from '@angular/material/icon';
7
  import { MatPaginatorModule, PageEvent } from '@angular/material/paginator';
 
 
 
8
 
9
  interface ActivityLog {
10
  id: number;
@@ -33,189 +36,199 @@ interface ActivityLogResponse {
33
  MatProgressSpinnerModule,
34
  MatButtonModule,
35
  MatIconModule,
36
- MatPaginatorModule
 
 
 
37
  ],
38
  template: `
39
- <div class="activity-log-dropdown" (click)="$event.stopPropagation()">
40
- <div class="activity-header">
41
- <h3>🔔 Recent Activities</h3>
42
- <button class="close-btn" (click)="close.emit()">×</button>
43
- </div>
 
 
 
 
 
44
 
45
- <div class="activity-content">
46
  @if (loading && activities.length === 0) {
47
  <div class="loading">
48
  <mat-spinner diameter="30"></mat-spinner>
49
  </div>
50
  } @else if (activities.length === 0) {
51
- <div class="empty">No activities found</div>
 
 
 
52
  } @else {
53
- <div class="activity-list">
54
  @for (activity of activities; track activity.id) {
55
- <div class="activity-item">
56
- <div class="activity-time">{{ getRelativeTime(activity.timestamp) }}</div>
57
- <div class="activity-content">
 
 
 
58
  <strong>{{ activity.user }}</strong> {{ getActionText(activity) }}
59
  <em>{{ activity.entity_name }}</em>
60
  @if (activity.details) {
61
  <span class="details">• {{ activity.details }}</span>
62
  }
63
  </div>
64
- </div>
 
 
 
65
  }
66
- </div>
67
  }
68
- </div>
69
 
70
- <div class="activity-footer">
71
- @if (totalItems > pageSize) {
72
- <mat-paginator
73
- [length]="totalItems"
74
- [pageSize]="pageSize"
75
- [pageIndex]="currentPage - 1"
76
- [pageSizeOptions]="[10, 25, 50]"
77
- (page)="onPageChange($event)"
78
- showFirstLastButtons>
79
- </mat-paginator>
80
- } @else {
81
- <button mat-button (click)="openFullView()">
82
- <mat-icon>open_in_new</mat-icon>
83
- View All Activities
84
- </button>
85
- }
86
- </div>
87
- </div>
88
  `,
89
  styles: [`
90
  .activity-log-dropdown {
91
- position: absolute;
92
- top: 100%;
93
- right: 0;
94
- width: 400px;
95
- background: white;
96
- border: 1px solid #dee2e6;
97
- border-radius: 8px;
98
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
99
- z-index: 1000;
100
- margin-top: 0.5rem;
101
  display: flex;
102
  flex-direction: column;
103
- max-height: 600px;
104
  }
105
 
106
- .activity-header {
107
- padding: 1rem;
108
- border-bottom: 1px solid #dee2e6;
109
  display: flex;
110
  justify-content: space-between;
111
  align-items: center;
 
 
112
 
113
- h3 {
114
  margin: 0;
115
- font-size: 1.1rem;
116
- }
117
-
118
- .close-btn {
119
- background: none;
120
- border: none;
121
- font-size: 1.5rem;
122
- cursor: pointer;
123
- color: #6c757d;
124
- line-height: 1;
125
- padding: 0;
126
- width: 24px;
127
- height: 24px;
128
  display: flex;
129
  align-items: center;
130
- justify-content: center;
 
131
 
132
- &:hover {
133
- color: #333;
 
 
134
  }
135
  }
136
  }
137
 
138
- .activity-content {
139
  flex: 1;
140
  overflow-y: auto;
 
141
  min-height: 200px;
142
  max-height: 400px;
143
  }
144
 
145
  .activity-list {
146
- .activity-item {
147
- padding: 0.75rem 1rem;
148
- border-bottom: 1px solid #f0f0f0;
149
- transition: background-color 0.2s;
150
 
151
- &:hover {
152
- background-color: #f8f9fa;
153
- }
 
154
 
155
- &:last-child {
156
- border-bottom: none;
157
  }
158
 
159
  .activity-time {
160
- font-size: 0.85rem;
161
- color: #6c757d;
162
- margin-bottom: 0.25rem;
163
  }
164
 
165
- .activity-content {
166
- font-size: 0.9rem;
 
 
167
 
168
- em {
169
- color: #007bff;
170
- font-style: normal;
171
- font-weight: 500;
172
- }
 
173
 
174
- .details {
175
- color: #6c757d;
176
- font-size: 0.85rem;
177
- }
178
  }
179
  }
180
  }
181
 
182
- .activity-footer {
183
- padding: 0.5rem;
184
- border-top: 1px solid #dee2e6;
185
- display: flex;
186
- justify-content: center;
187
- align-items: center;
188
 
189
- button {
190
- width: 100%;
191
  }
192
 
193
- ::ng-deep .mat-paginator {
194
- background: transparent;
195
  width: 100%;
196
-
197
- .mat-paginator-container {
198
- padding: 0;
199
- justify-content: center;
200
- }
201
-
202
- .mat-paginator-range-label {
203
- margin: 0 8px;
204
- }
205
  }
206
  }
207
 
208
- .loading {
209
- padding: 3rem;
210
  display: flex;
211
- justify-content: center;
212
  align-items: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  }
214
 
215
- .empty {
216
- padding: 3rem;
217
- text-align: center;
218
- color: #6c757d;
 
 
 
 
 
 
 
219
  }
220
  `]
221
  })
@@ -269,16 +282,15 @@ export class ActivityLogComponent implements OnInit {
269
  getRelativeTime(timestamp: string): string {
270
  const date = new Date(timestamp);
271
  const now = new Date();
272
- const diff = now.getTime() - date.getTime();
273
-
274
- const minutes = Math.floor(diff / 60000);
275
- const hours = Math.floor(diff / 3600000);
276
- const days = Math.floor(diff / 86400000);
277
 
278
- if (minutes < 1) return 'just now';
279
- if (minutes < 60) return `${minutes} min ago`;
280
- if (hours < 24) return `${hours} hour${hours > 1 ? 's' : ''} ago`;
281
- if (days < 7) return `${days} day${days > 1 ? 's' : ''} ago`;
282
 
283
  return date.toLocaleDateString();
284
  }
@@ -304,4 +316,16 @@ export class ActivityLogComponent implements OnInit {
304
 
305
  return actions[activity.action] || activity.action.toLowerCase().replace(/_/g, ' ');
306
  }
 
 
 
 
 
 
 
 
 
 
 
 
307
  }
 
5
  import { MatButtonModule } from '@angular/material/button';
6
  import { MatIconModule } from '@angular/material/icon';
7
  import { MatPaginatorModule, PageEvent } from '@angular/material/paginator';
8
+ import { MatListModule } from '@angular/material/list';
9
+ import { MatCardModule } from '@angular/material/card';
10
+ import { MatDividerModule } from '@angular/material/divider';
11
 
12
  interface ActivityLog {
13
  id: number;
 
36
  MatProgressSpinnerModule,
37
  MatButtonModule,
38
  MatIconModule,
39
+ MatPaginatorModule,
40
+ MatListModule,
41
+ MatCardModule,
42
+ MatDividerModule
43
  ],
44
  template: `
45
+ <mat-card class="activity-log-dropdown" (click)="$event.stopPropagation()">
46
+ <mat-card-header>
47
+ <mat-card-title>
48
+ <mat-icon>notifications</mat-icon>
49
+ Recent Activities
50
+ </mat-card-title>
51
+ <button mat-icon-button (click)="close.emit()">
52
+ <mat-icon>close</mat-icon>
53
+ </button>
54
+ </mat-card-header>
55
 
56
+ <mat-card-content>
57
  @if (loading && activities.length === 0) {
58
  <div class="loading">
59
  <mat-spinner diameter="30"></mat-spinner>
60
  </div>
61
  } @else if (activities.length === 0) {
62
+ <div class="empty">
63
+ <mat-icon>inbox</mat-icon>
64
+ <p>No activities found</p>
65
+ </div>
66
  } @else {
67
+ <mat-list class="activity-list">
68
  @for (activity of activities; track activity.id) {
69
+ <mat-list-item>
70
+ <mat-icon matListItemIcon>{{ getActivityIcon(activity.action) }}</mat-icon>
71
+ <div matListItemTitle>
72
+ <span class="activity-time">{{ getRelativeTime(activity.timestamp) }}</span>
73
+ </div>
74
+ <div matListItemLine>
75
  <strong>{{ activity.user }}</strong> {{ getActionText(activity) }}
76
  <em>{{ activity.entity_name }}</em>
77
  @if (activity.details) {
78
  <span class="details">• {{ activity.details }}</span>
79
  }
80
  </div>
81
+ </mat-list-item>
82
+ @if (!$last) {
83
+ <mat-divider></mat-divider>
84
+ }
85
  }
86
+ </mat-list>
87
  }
88
+ </mat-card-content>
89
 
90
+ <mat-card-actions *ngIf="totalItems > pageSize">
91
+ <mat-paginator
92
+ [length]="totalItems"
93
+ [pageSize]="pageSize"
94
+ [pageIndex]="currentPage - 1"
95
+ [pageSizeOptions]="[10, 25, 50]"
96
+ (page)="onPageChange($event)"
97
+ showFirstLastButtons>
98
+ </mat-paginator>
99
+ </mat-card-actions>
100
+
101
+ <mat-card-actions *ngIf="totalItems <= pageSize && activities.length > 0">
102
+ <button mat-button (click)="openFullView()" class="full-width">
103
+ <mat-icon>open_in_new</mat-icon>
104
+ View All Activities
105
+ </button>
106
+ </mat-card-actions>
107
+ </mat-card>
108
  `,
109
  styles: [`
110
  .activity-log-dropdown {
111
+ width: 450px;
112
+ max-height: 600px;
 
 
 
 
 
 
 
 
113
  display: flex;
114
  flex-direction: column;
115
+ overflow: hidden;
116
  }
117
 
118
+ mat-card-header {
 
 
119
  display: flex;
120
  justify-content: space-between;
121
  align-items: center;
122
+ padding: 16px;
123
+ background-color: #f5f5f5;
124
 
125
+ mat-card-title {
126
  margin: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  display: flex;
128
  align-items: center;
129
+ gap: 8px;
130
+ font-size: 18px;
131
 
132
+ mat-icon {
133
+ font-size: 24px;
134
+ width: 24px;
135
+ height: 24px;
136
  }
137
  }
138
  }
139
 
140
+ mat-card-content {
141
  flex: 1;
142
  overflow-y: auto;
143
+ padding: 0;
144
  min-height: 200px;
145
  max-height: 400px;
146
  }
147
 
148
  .activity-list {
149
+ padding: 0;
 
 
 
150
 
151
+ mat-list-item {
152
+ height: auto;
153
+ min-height: 72px;
154
+ padding: 12px 16px;
155
 
156
+ &:hover {
157
+ background-color: #f5f5f5;
158
  }
159
 
160
  .activity-time {
161
+ font-size: 12px;
162
+ color: #666;
 
163
  }
164
 
165
+ strong {
166
+ color: #1976d2;
167
+ margin-right: 4px;
168
+ }
169
 
170
+ em {
171
+ color: #673ab7;
172
+ font-style: normal;
173
+ font-weight: 500;
174
+ margin: 0 4px;
175
+ }
176
 
177
+ .details {
178
+ color: #666;
179
+ font-size: 12px;
180
+ margin-left: 4px;
181
  }
182
  }
183
  }
184
 
185
+ mat-card-actions {
186
+ padding: 0;
187
+ margin: 0;
 
 
 
188
 
189
+ mat-paginator {
190
+ background: transparent;
191
  }
192
 
193
+ .full-width {
 
194
  width: 100%;
195
+ margin: 0;
 
 
 
 
 
 
 
 
196
  }
197
  }
198
 
199
+ .loading, .empty {
200
+ padding: 60px 20px;
201
  display: flex;
202
+ flex-direction: column;
203
  align-items: center;
204
+ justify-content: center;
205
+ color: #666;
206
+
207
+ mat-icon {
208
+ font-size: 48px;
209
+ width: 48px;
210
+ height: 48px;
211
+ color: #e0e0e0;
212
+ margin-bottom: 16px;
213
+ }
214
+
215
+ p {
216
+ margin: 0;
217
+ font-size: 14px;
218
+ }
219
  }
220
 
221
+ ::ng-deep {
222
+ .mat-mdc-list-item-unscoped-content {
223
+ display: block;
224
+ }
225
+
226
+ .mat-mdc-paginator {
227
+ .mat-mdc-paginator-container {
228
+ padding: 8px;
229
+ justify-content: center;
230
+ }
231
+ }
232
  }
233
  `]
234
  })
 
282
  getRelativeTime(timestamp: string): string {
283
  const date = new Date(timestamp);
284
  const now = new Date();
285
+ const diffMs = now.getTime() - date.getTime();
286
+ const diffMins = Math.floor(diffMs / 60000);
287
+ const diffHours = Math.floor(diffMs / 3600000);
288
+ const diffDays = Math.floor(diffMs / 86400000);
 
289
 
290
+ if (diffMins < 1) return 'just now';
291
+ if (diffMins < 60) return `${diffMins} min ago`;
292
+ if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
293
+ if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
294
 
295
  return date.toLocaleDateString();
296
  }
 
316
 
317
  return actions[activity.action] || activity.action.toLowerCase().replace(/_/g, ' ');
318
  }
319
+
320
+ getActivityIcon(action: string): string {
321
+ if (action.includes('CREATE')) return 'add_circle';
322
+ if (action.includes('UPDATE')) return 'edit';
323
+ if (action.includes('DELETE')) return 'delete';
324
+ if (action.includes('ENABLE')) return 'check_circle';
325
+ if (action.includes('DISABLE')) return 'cancel';
326
+ if (action.includes('PUBLISH')) return 'publish';
327
+ if (action.includes('IMPORT')) return 'cloud_upload';
328
+ if (action.includes('PASSWORD')) return 'lock';
329
+ return 'info';
330
+ }
331
  }