Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,19 @@ public IncidentService(IncidentRepository incidentRepository, ActivityLogService
this.minioService = minioService;
}

/** Help-method for sorting **/
/**
* Help-method for sorting
**/
private Pageable withDefaultSort(Pageable pageable) {
if (pageable.isUnpaged() || pageable.getSort().isSorted()) {
return pageable;
}
return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Direction.DESC, "id"));
}

/** Create incident **/
/**
* Create incident
**/
@Transactional
public Incident createIncident(IncidentRequest incidentRequest, List<MultipartFile> files, AppUser user) {

Expand Down Expand Up @@ -99,17 +103,23 @@ public Incident createIncident(IncidentRequest incidentRequest, List<MultipartFi
}
}

/** Find all incidents (Admin) **/
/**
* Find all incidents (Admin)
**/
public Page<Incident> findAll(Pageable pageable) {
return incidentRepository.findAll(withDefaultSort(pageable));
}

/** Find your own incidents (user) **/
/**
* Find your own incidents (user)
**/
public Page<Incident> findByCreatedBy(AppUser user, Pageable pageable) {
return incidentRepository.findByCreatedBy(user, withDefaultSort(pageable));
}

/** Find assigned incidents per HANDLER **/
/**
* Find assigned incidents per HANDLER
**/
public Page<Incident> findByAssignedTo(AppUser user, Pageable pageable) {
return incidentRepository.findByAssignedTo(user, withDefaultSort(pageable));
}
Expand Down Expand Up @@ -149,6 +159,10 @@ public Incident assignIncidentToHandler(Long incidentId, String handlerId, AppUs
Incident incident = incidentRepository.findById(incidentId)
.orElseThrow(() -> new ResourceNotFoundException("Incident not found with id: " + incidentId));

if (incident.getIncidentStatus() == IncidentStatus.CLOSED) {
throw new IllegalStateException("Cannot modify a closed incident. Status: " + incident.getIncidentStatus());
}

AppUser handler = userRepository.findById(handlerId)
.orElseThrow(() -> new ResourceNotFoundException("Handler not found with id: " + handlerId));

Expand Down Expand Up @@ -191,6 +205,10 @@ public Incident unassignIncident(Long incidentId, AppUser currentUser) {
Incident incident = incidentRepository.findById(incidentId)
.orElseThrow(() -> new ResourceNotFoundException("Incident not found with id: " + incidentId));

if (incident.getIncidentStatus() == IncidentStatus.CLOSED) {
throw new IllegalStateException("Cannot modify a closed incident. Status: " + incident.getIncidentStatus());
}

AppUser previousHandler = incident.getAssignedTo();

if (previousHandler == null) {
Expand All @@ -214,14 +232,6 @@ public Incident unassignIncident(Long incidentId, AppUser currentUser) {
"Incident #" + incident.getId() + " has been unassigned from you by " + currentUser.getName(),
previousHandler, savedIncident);

if (!savedIncident.getCreatedBy().getId().equals(currentUser.getId())) {
notificationService.createNotification("Incident #" + incident.getId() + " has been unassigned from "
+ previousHandler.getName() + " by " + currentUser.getName(), savedIncident.getCreatedBy(),
savedIncident);
}

log.info("Unassigned incident {} from handler {} by admin {}", incidentId, previousHandler.getId(),
currentUser.getId());
return savedIncident;
}
}
32 changes: 22 additions & 10 deletions src/main/resources/templates/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -1220,11 +1220,25 @@ <h3>Assign Incident to Handler</h3>
const tbody = document.getElementById('incidentsTableBody');

if (!incidents || incidents.length === 0) {
tbody.innerHTML = '<tr><td colspan="8" style="text-align: center; color: #6b7280;">No incidents found</td></tr>';
tbody.innerHTML = '<tr><td colspan="8" class="loading">No incidents found</td></tr>';
return;
}

tbody.innerHTML = incidents.map(incident => `
tbody.innerHTML = incidents.map(incident => {
const isClosed = incident.incidentStatus === 'CLOSED';

let actionButton = '';
if (!isClosed) {
if (!incident.assignedTo) {
actionButton = `<button class="assign-btn" onclick="openAssignModal(${incident.id})">Assign</button>`;
} else {
actionButton = `<button class="unassign-btn" onclick="unassignIncident(${incident.id})">Unassign</button>`;
}
} else {
actionButton = `<span class="closed-badge" style="background: #4a4a4a; color: #9ca3af; padding: 0.5rem 1rem; border-radius: 0.5rem; font-size: 0.75rem;">Closed</span>`;
}

return `
<tr>
<td style="font-weight: 500;">#${incident.id}</td>
<td>
Expand All @@ -1236,21 +1250,19 @@ <h3>Assign Incident to Handler</h3>
<td style="font-size: 0.8rem;">${escapeHtml(incident.createdBy || 'Unknown')}</td>
<td>
${incident.assignedTo ?
`<span class="assigned-to">✓ ${escapeHtml(incident.assignedTo)}</span>` :
`<span class="unassigned">Unassigned</span>`
}
`<span class="assigned-to">✓ ${escapeHtml(incident.assignedTo)}</span>` :
`<span class="unassigned">Unassigned</span>`
}
</td>
<td style="font-size: 0.8rem;">${new Date(incident.createdAt).toLocaleDateString()}</td>
<td>
<div class="action-buttons">
${!incident.assignedTo ?
`<button class="assign-btn" onclick="openAssignModal(${incident.id})">Assign</button>` :
`<button class="unassign-btn" onclick="unassignIncident(${incident.id})">Unassign</button>`
}
${actionButton}
</div>
</td>
</tr>
`).join('');
`;
}).join('');
}

function renderIncidentPagination() {
Expand Down
Loading