|
49 | 49 | .card-footer { |
50 | 50 | border-top: none !important; |
51 | 51 | } |
| 52 | +
|
| 53 | + /* Cursor pointer for clickable rows */ |
| 54 | + .event-row { |
| 55 | + cursor: pointer; |
| 56 | + } |
52 | 57 | </style> |
53 | 58 |
|
54 | 59 | <div class="container-fluid px-4"> |
|
215 | 220 | <tbody> |
216 | 221 | @foreach (var evt in Model.Stats.RecentEvents) |
217 | 222 | { |
218 | | - <tr> |
| 223 | + <tr class="event-row" style="cursor:pointer;" data-event='@Html.Raw(Json.Serialize(evt))'> |
219 | 224 | <td>@evt.EventTimestamp.ToString("g")</td> |
220 | 225 | <td> |
221 | 226 | <span class="badge rounded-pill bg-info">@evt.EntityType</span> |
|
253 | 258 | </div> |
254 | 259 | </div> |
255 | 260 |
|
| 261 | +<!-- Event Details Modal --> |
| 262 | +<div class="modal fade" id="eventDetailsModal" tabindex="-1" aria-labelledby="eventDetailsModalLabel" aria-hidden="true"> |
| 263 | + <div class="modal-dialog modal-lg"> |
| 264 | + <div class="modal-content"> |
| 265 | + <div class="modal-header"> |
| 266 | + <h5 class="modal-title" id="eventDetailsModalLabel">Event Details</h5> |
| 267 | + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
| 268 | + </div> |
| 269 | + <div class="modal-body"> |
| 270 | + <dl class="row"> |
| 271 | + <dt class="col-sm-3">Timestamp</dt> |
| 272 | + <dd class="col-sm-9" id="eventDetailTimestamp"></dd> |
| 273 | + |
| 274 | + <dt class="col-sm-3">Entity Type</dt> |
| 275 | + <dd class="col-sm-9" id="eventDetailEntityType"></dd> |
| 276 | + |
| 277 | + <dt class="col-sm-3">Event Type</dt> |
| 278 | + <dd class="col-sm-9" id="eventDetailEventType"></dd> |
| 279 | + |
| 280 | + <dt class="col-sm-3">Entity ID</dt> |
| 281 | + <dd class="col-sm-9" id="eventDetailEntityId"></dd> |
| 282 | + |
| 283 | + <dt class="col-sm-3">Actor</dt> |
| 284 | + <dd class="col-sm-9" id="eventDetailActor"></dd> |
| 285 | + |
| 286 | + <dt class="col-sm-3">Entity Data</dt> |
| 287 | + <dd class="col-sm-9"> |
| 288 | + <pre id="eventDetailEntityData" class="bg-light p-2" style="max-height: 300px; overflow-y: auto;"></pre> |
| 289 | + </dd> |
| 290 | + </dl> |
| 291 | + </div> |
| 292 | + <div class="modal-footer"> |
| 293 | + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> |
| 294 | + </div> |
| 295 | + </div> |
| 296 | + </div> |
| 297 | +</div> |
| 298 | + |
256 | 299 | @section Scripts { |
257 | 300 | <script> |
258 | 301 | document.addEventListener('DOMContentLoaded', function() { |
|
344 | 387 | } |
345 | 388 | } |
346 | 389 | }); |
| 390 | +
|
| 391 | + // Event row click handler |
| 392 | + document.querySelectorAll('.event-row').forEach(row => { |
| 393 | + row.addEventListener('click', function() { |
| 394 | + const eventData = JSON.parse(this.getAttribute('data-event')); |
| 395 | + console.log('Event object structure:', eventData); // Debug log to see property names |
| 396 | +
|
| 397 | + // Populate the modal with event data - handle different property name formats |
| 398 | + document.getElementById('eventDetailTimestamp').innerText = new Date(eventData.eventTimestamp || eventData.EventTimestamp).toLocaleString(); |
| 399 | + document.getElementById('eventDetailEntityType').innerText = eventData.entityType || eventData.EntityType || '-'; |
| 400 | + document.getElementById('eventDetailEventType').innerText = eventData.eventType || eventData.EventType || '-'; |
| 401 | + document.getElementById('eventDetailEntityId').innerText = eventData.entityId || eventData.EntityId || '-'; |
| 402 | + document.getElementById('eventDetailActor').innerText = (eventData.actorId || eventData.ActorId || '-') + ' (' + (eventData.actorType || eventData.ActorType || '-') + ')'; |
| 403 | +
|
| 404 | + // Handle entityData display with fallbacks for different property names |
| 405 | + const entityData = eventData.entityData || eventData.EntityData || eventData.data || eventData.Data; |
| 406 | + console.log('Entity data value:', entityData); |
| 407 | + console.log('Entity data type:', typeof entityData); |
| 408 | + console.log('Full event object keys:', Object.keys(eventData)); |
| 409 | + let formattedData = 'No entity data available'; |
| 410 | +
|
| 411 | + if (entityData) { |
| 412 | + try { |
| 413 | + if (typeof entityData === 'string') { |
| 414 | + // Try to parse if it's a JSON string |
| 415 | + const parsedData = JSON.parse(entityData); |
| 416 | + formattedData = JSON.stringify(parsedData, null, 2); |
| 417 | + } else { |
| 418 | + formattedData = JSON.stringify(entityData, null, 2); |
| 419 | + } |
| 420 | + } catch (e) { |
| 421 | + console.error('Error formatting entity data:', e); |
| 422 | + formattedData = String(entityData); |
| 423 | + } |
| 424 | + } |
| 425 | +
|
| 426 | + document.getElementById('eventDetailEntityData').innerText = formattedData; |
| 427 | +
|
| 428 | + // Show the modal |
| 429 | + const modal = new bootstrap.Modal(document.getElementById('eventDetailsModal')); |
| 430 | + modal.show(); |
| 431 | + }); |
| 432 | + }); |
347 | 433 | }); |
348 | 434 | </script> |
349 | 435 | } |
0 commit comments