Preview: LOGS_DASHBOARD_INTEGRATION.md
Size: 14.06 KB
/var/www/snow-ecom.wpress.dk/httpdocs/LOGS_DASHBOARD_INTEGRATION.md
# User Action Logs Dashboard Integration Guide
## Overview
This guide explains how to integrate the User Action Logs Dashboard with your C# Umbraco backend. The dashboard provides a comprehensive view of user activities with filtering, sorting, and Excel export functionality.
## Features
### Dashboard Features
- **Real-time Log Display**: View user action logs in a table format
- **Advanced Filtering**: Filter by action type, entity type, status, user, and date range
- **Search Functionality**: Search across user emails, booking IDs, and entity IDs
- **Pagination**: Navigate through large datasets efficiently
- **Excel Export**: Export filtered results to CSV format
- **Statistics Cards**: Overview of total logs, successful/failed actions, and active users
- **Responsive Design**: Works on desktop and mobile devices
### Log Data Captured
- User identification (ID, email)
- Action performed (SAVE, SAVE_AND_SEND, RESEND, PREVIEW, EDIT)
- Entity type (CUSTOMER, PARTICIPANT, PAYMENT, PRODUCT, PDF, EMAIL)
- Booking and page context
- Timestamp and IP address
- Success/failure status
- Detailed action data (JSON format)
- Error messages for failed actions
## Frontend Components
### 1. LogDashboard Component
**Location**: `src/app/(pages)/dashboard/_components/LogDashboard.tsx`
**Features**:
- Main dashboard interface
- Filter controls and search
- Data table with pagination
- Export functionality
- Statistics overview
### 2. Log API Service
**Location**: `src/app/services/logApiService.ts`
**Features**:
- Centralized API communication
- Filter and pagination support
- Error handling
- Type-safe interfaces
### 3. API Route
**Location**: `src/app/api/logging/userActions/route.ts`
**Features**:
- GET endpoint for fetching logs
- POST endpoint for creating logs
- Query parameter support for filtering
- Mock data for development
## Backend Integration
### 1. C# API Controller Updates
Update your existing `EC_LoggingController.cs` to support the dashboard requirements:
```csharp
[System.Web.Http.RoutePrefix("api/logging")]
public class EC_LoggingController : UmbracoApiController
{
private readonly ILog _logger;
private readonly IUserActionLogService _userActionLogService;
public EC_LoggingController(IUserActionLogService userActionLogService)
{
_logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
_userActionLogService = userActionLogService;
}
// GET: api/logging/userActions
[System.Web.Http.HttpGet]
[System.Web.Http.Route("userActions")]
public async Task<IHttpActionResult> GetUserActionLogs(
[FromUri] string action = null,
[FromUri] string entityType = null,
[FromUri] string status = null,
[FromUri] string userEmail = null,
[FromUri] string startDate = null,
[FromUri] string endDate = null,
[FromUri] int page = 1,
[FromUri] int limit = 20)
{
try
{
var filters = new LogFilters
{
Action = action,
EntityType = entityType,
Status = status,
UserEmail = userEmail,
StartDate = startDate,
EndDate = endDate,
Page = page,
Limit = limit
};
var result = await _userActionLogService.GetLogsWithFiltersAsync(filters);
return Ok(new
{
logs = result.Logs,
total = result.Total,
page = result.Page,
limit = result.Limit,
totalPages = result.TotalPages
});
}
catch (Exception ex)
{
_logger.Error("Error fetching user action logs", ex);
return InternalServerError(ex);
}
}
// POST: api/logging/userActions
[System.Web.Http.HttpPost]
[System.Web.Http.Route("userActions")]
public async Task<IHttpActionResult> CreateUserActionLog([FromBody] UserActionLog log)
{
try
{
var result = await _userActionLogService.SaveLogAsync(log);
return Ok(new { success = true, message = "Log entry created successfully" });
}
catch (Exception ex)
{
_logger.Error("Error creating user action log", ex);
return InternalServerError(ex);
}
}
}
```
### 2. Service Interface Updates
Update `IUserActionLogService.cs`:
```csharp
public interface IUserActionLogService
{
Task<LogsResult> GetLogsWithFiltersAsync(LogFilters filters);
Task<UserActionLog> SaveLogAsync(UserActionLog log);
Task<IEnumerable<UserActionLog>> GetLogsByUserEmailAsync(string userEmail);
Task<IEnumerable<UserActionLog>> GetLogsByBookingIdAsync(string bookingId);
Task<IEnumerable<UserActionLog>> GetLogsByActionTypeAsync(string actionType);
Task<IEnumerable<UserActionLog>> GetLogsByEntityTypeAsync(string entityType);
Task<IEnumerable<UserActionLog>> GetLogsByStatusAsync(string status);
Task<LogsSummary> GetLogsSummaryAsync();
}
public class LogFilters
{
public string Action { get; set; }
public string EntityType { get; set; }
public string Status { get; set; }
public string UserEmail { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public int Page { get; set; } = 1;
public int Limit { get; set; } = 20;
}
public class LogsResult
{
public IEnumerable<UserActionLog> Logs { get; set; }
public int Total { get; set; }
public int Page { get; set; }
public int Limit { get; set; }
public int TotalPages { get; set; }
}
public class LogsSummary
{
public int Total { get; set; }
public int Successful { get; set; }
public int Failed { get; set; }
public int Pending { get; set; }
public int UniqueUsers { get; set; }
public Dictionary<string, int> Actions { get; set; }
public Dictionary<string, int> EntityTypes { get; set; }
}
```
### 3. Service Implementation Updates
Update `UserActionLogService.cs`:
```csharp
public class UserActionLogService : IUserActionLogService
{
private readonly IUserActionLogRepository _repository;
public UserActionLogService(IUserActionLogRepository repository)
{
_repository = repository;
}
public async Task<LogsResult> GetLogsWithFiltersAsync(LogFilters filters)
{
var logs = await _repository.GetLogsWithFiltersAsync(filters);
var total = await _repository.GetLogsCountAsync(filters);
var totalPages = (int)Math.Ceiling((double)total / filters.Limit);
return new LogsResult
{
Logs = logs,
Total = total,
Page = filters.Page,
Limit = filters.Limit,
TotalPages = totalPages
};
}
public async Task<UserActionLog> SaveLogAsync(UserActionLog log)
{
return await _repository.InsertAsync(log);
}
// Implement other methods...
}
```
### 4. Repository Updates
Update `IUserActionLogRepository.cs`:
```csharp
public interface IUserActionLogRepository
{
Task<IEnumerable<UserActionLog>> GetLogsWithFiltersAsync(LogFilters filters);
Task<int> GetLogsCountAsync(LogFilters filters);
Task<UserActionLog> InsertAsync(UserActionLog log);
Task<IEnumerable<UserActionLog>> GetLogsByUserEmailAsync(string userEmail);
Task<IEnumerable<UserActionLog>> GetLogsByBookingIdAsync(string bookingId);
Task<IEnumerable<UserActionLog>> GetLogsByActionTypeAsync(string actionType);
Task<IEnumerable<UserActionLog>> GetLogsByEntityTypeAsync(string entityType);
Task<IEnumerable<UserActionLog>> GetLogsByStatusAsync(string status);
}
```
Update `UserActionLogRepository.cs`:
```csharp
public class UserActionLogRepository : IUserActionLogRepository
{
private readonly IDatabase _database;
public UserActionLogRepository(IDatabase database)
{
_database = database;
}
public async Task<IEnumerable<UserActionLog>> GetLogsWithFiltersAsync(LogFilters filters)
{
var sql = new Sql()
.Select("*")
.From("user_actions_log")
.Where("1=1");
if (!string.IsNullOrEmpty(filters.Action))
sql = sql.Where("action = @0", filters.Action);
if (!string.IsNullOrEmpty(filters.EntityType))
sql = sql.Where("entityType = @0", filters.EntityType);
if (!string.IsNullOrEmpty(filters.Status))
sql = sql.Where("status = @0", filters.Status);
if (!string.IsNullOrEmpty(filters.UserEmail))
sql = sql.Where("userEmail = @0", filters.UserEmail);
if (!string.IsNullOrEmpty(filters.StartDate))
sql = sql.Where("timestamp >= @0", DateTime.Parse(filters.StartDate));
if (!string.IsNullOrEmpty(filters.EndDate))
sql = sql.Where("timestamp <= @0", DateTime.Parse(filters.EndDate));
sql = sql.OrderBy("timestamp DESC")
.Append("OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY",
(filters.Page - 1) * filters.Limit, filters.Limit);
return await _database.FetchAsync<UserActionLog>(sql);
}
public async Task<int> GetLogsCountAsync(LogFilters filters)
{
var sql = new Sql()
.Select("COUNT(*)")
.From("user_actions_log")
.Where("1=1");
if (!string.IsNullOrEmpty(filters.Action))
sql = sql.Where("action = @0", filters.Action);
if (!string.IsNullOrEmpty(filters.EntityType))
sql = sql.Where("entityType = @0", filters.EntityType);
if (!string.IsNullOrEmpty(filters.Status))
sql = sql.Where("status = @0", filters.Status);
if (!string.IsNullOrEmpty(filters.UserEmail))
sql = sql.Where("userEmail = @0", filters.UserEmail);
if (!string.IsNullOrEmpty(filters.StartDate))
sql = sql.Where("timestamp >= @0", DateTime.Parse(filters.StartDate));
if (!string.IsNullOrEmpty(filters.EndDate))
sql = sql.Where("timestamp <= @0", DateTime.Parse(filters.EndDate));
return await _database.ExecuteScalarAsync<int>(sql);
}
// Implement other methods...
}
```
## Configuration
### 1. Environment Variables
Add to your `.env.local` file:
```env
NEXT_PUBLIC_API_BASE_URL=http://localhost:5000/api
```
### 2. CORS Configuration
Update your C# backend to allow requests from the frontend:
```csharp
// In your Startup.cs or Web.config
app.UseCors(builder => builder
.WithOrigins("http://localhost:3000") // Your frontend URL
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
```
### 3. Authentication (Optional)
If you need authentication, update the API service:
```typescript
// In logApiService.ts
private async getAuthHeaders() {
const token = await this.getAuthToken(); // Implement your auth logic
return {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
};
}
```
## Usage
### 1. Access the Dashboard
Navigate to `/dashboard` in your application to view the logs dashboard.
### 2. Filtering Logs
Use the filter controls to:
- Search by user email, booking ID, or entity ID
- Filter by action type (Save, Save & Send, Resend, etc.)
- Filter by entity type (Customer, Participant, Payment, etc.)
- Filter by status (Success, Failed, Pending)
- Filter by specific user
- Filter by date range
### 3. Export Data
Click the "Export Excel" button to download the filtered results as a CSV file.
### 4. Pagination
Use the pagination controls to navigate through large datasets.
## Database Schema
Ensure your database has the `user_actions_log` table with the following structure:
```sql
CREATE TABLE user_actions_log (
id BIGINT IDENTITY(1,1) PRIMARY KEY,
userId NVARCHAR(255) NOT NULL,
userEmail NVARCHAR(255) NOT NULL,
action NVARCHAR(50) NOT NULL,
entityType NVARCHAR(50) NOT NULL,
entityId NVARCHAR(255) NOT NULL,
bookingId NVARCHAR(255) NOT NULL,
pageId NVARCHAR(255) NOT NULL,
brand NVARCHAR(100) NOT NULL,
language NVARCHAR(10) NOT NULL,
actionData NVARCHAR(MAX) NOT NULL,
timestamp DATETIME2 NOT NULL,
ipAddress NVARCHAR(45),
userAgent NVARCHAR(MAX),
sessionId NVARCHAR(255),
status NVARCHAR(20) NOT NULL,
errorMessage NVARCHAR(MAX),
version NVARCHAR(50),
INDEX IX_user_actions_log_timestamp (timestamp),
INDEX IX_user_actions_log_userEmail (userEmail),
INDEX IX_user_actions_log_bookingId (bookingId),
INDEX IX_user_actions_log_action (action),
INDEX IX_user_actions_log_status (status)
);
```
## Troubleshooting
### Common Issues
1. **CORS Errors**: Ensure your C# backend allows requests from your frontend domain
2. **404 Errors**: Verify the API routes are correctly configured in your C# controller
3. **Authentication Errors**: Check if authentication is required and properly configured
4. **Database Connection**: Ensure your database connection string is correct
### Debug Mode
Enable debug mode in the frontend by setting:
```typescript
// In logApiService.ts
private debugMode = true;
```
This will log all API requests and responses to the console.
## Performance Considerations
1. **Pagination**: Always use pagination for large datasets
2. **Indexing**: Ensure proper database indexes on frequently queried columns
3. **Caching**: Consider implementing caching for frequently accessed data
4. **Batch Operations**: Use batch operations for bulk log insertions
## Security Considerations
1. **Input Validation**: Validate all input parameters on both frontend and backend
2. **SQL Injection**: Use parameterized queries (already implemented with NPoco)
3. **Authentication**: Implement proper authentication and authorization
4. **Rate Limiting**: Consider implementing rate limiting for API endpoints
5. **Data Privacy**: Ensure sensitive data is not logged or exposed
## Future Enhancements
1. **Real-time Updates**: Implement WebSocket connections for real-time log updates
2. **Advanced Analytics**: Add charts and graphs for log analysis
3. **Alert System**: Implement alerts for failed actions or unusual patterns
4. **Export Formats**: Support additional export formats (PDF, JSON)
5. **User Permissions**: Implement role-based access control for the dashboard
Directory Contents
Dirs: 5 × Files: 23