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
27 changes: 0 additions & 27 deletions src/main/java/org/example/untitled/s3/S3Controller.java

This file was deleted.

5 changes: 2 additions & 3 deletions src/main/java/org/example/untitled/s3/S3Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,14 @@ public void deleteFile(String filename){
.key(filename));
}

public List<UploadedFile> createFile(CaseEntity caseEntity, String s3Key) {
public UploadedFile createFile(CaseEntity caseEntity, String s3Key) {
UploadedFile uploadedFile = new UploadedFile();
uploadedFile.setUploadedBy(caseEntity.getOwner());
uploadedFile.setAssociatedCase(caseEntity);
uploadedFile.setS3Key(s3Key);
int indexOfSlash = s3Key.lastIndexOf('/');
String fileName = s3Key.substring(indexOfSlash + 1);
uploadedFile.setFilename(fileName);

return List.of(uploadedFile);
return uploadedFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;


@Controller
public class UserController {

Expand Down Expand Up @@ -84,4 +85,10 @@ public String processRegister(
}
return "redirect:/login";
}

@GetMapping("/tickets/upload")
public String getUserTickets(Model model, @AuthenticationPrincipal UserDetails userDetails){
model.addAttribute("files", caseService.getUserFiles(userDetails.getUsername()));
return "upload";
}
Comment thread
FeFFe1996 marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class UploadedFile {
@Column(nullable = false)
private String filename;

@Column(nullable = true)
@Column(name = "s3key")
private String s3Key;
Comment thread
FeFFe1996 marked this conversation as resolved.

@Column(nullable = false, updatable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.example.untitled.user.service.UserService;
import org.example.untitled.usercase.AuditLog;
import org.example.untitled.usercase.CaseStatus;
import org.example.untitled.usercase.UploadedFile;
import org.example.untitled.usercase.dto.CaseEntityDto;
import org.example.untitled.usercase.dto.CommentDto;
import org.example.untitled.usercase.dto.CreateCaseRequest;
Expand Down Expand Up @@ -43,8 +44,7 @@ public class CaseController {
private final UserService userService;
private static final Logger log = LoggerFactory.getLogger(CaseController.class);

public CaseController(CaseService caseService, CommentService commentService,
AuditLogService auditLogService, UserService userService) {
public CaseController(CaseService caseService, CommentService commentService, AuditLogService auditLogService, UserService userService) {
this.caseService = caseService;
this.commentService = commentService;
this.auditLogService = auditLogService;
Expand Down Expand Up @@ -101,6 +101,7 @@ public String showTicketDetails(
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "You do not own this ticket");

List<CommentDto> comments = commentService.getCommentsByTicketId(id);
List<UploadedFile> files = caseService.getTicketFiles(id);
List<AuditLog> auditLogs = auditLogService.getLogsForCase(id);
Map<Long, String> auditUserMap = buildAuditUserMap(auditLogs);

Expand All @@ -111,6 +112,7 @@ public String showTicketDetails(
model.addAttribute("canComment", perms.canComment());
model.addAttribute("auditLogs", auditLogs);
model.addAttribute("auditUserMap", auditUserMap);
model.addAttribute("files", files);
return "ticket";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.example.untitled.usercase.repository;

import org.example.untitled.user.User;
import org.example.untitled.usercase.CaseEntity;
import org.example.untitled.usercase.UploadedFile;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UploadedFileRepository extends ListCrudRepository<UploadedFile, Long> {

List<UploadedFile> associatedCaseEntity(CaseEntity caseEntity);
Comment thread
FeFFe1996 marked this conversation as resolved.
UploadedFile getUploadedFilesByFilename(String filename);
Comment thread
FeFFe1996 marked this conversation as resolved.

List<UploadedFile> getUploadedFilesByUploadedBy(User uploadedBy);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.example.untitled.usercase.dto.CreateCommentRequest;
import org.example.untitled.usercase.mapper.CaseMapper;
import org.example.untitled.usercase.repository.CaseRepository;
import org.example.untitled.usercase.repository.UploadedFileRepository;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -34,19 +36,22 @@ public class CaseService {
private final UserRepository userRepository;
private final AuditLogService auditLogService;
private final CommentService commentService;
private final UploadedFileRepository uploadedFileRepository;
private final S3Service s3Service;

public CaseService(
CaseRepository caseRepository,
UserRepository userRepository,
CommentService commentService,
S3Service s3Service,
AuditLogService auditLogService) {
AuditLogService auditLogService,
UploadedFileRepository fileRepository) {
this.caseRepository = caseRepository;
this.userRepository = userRepository;
this.commentService = commentService;
this.auditLogService = auditLogService;
this.s3Service = s3Service;
this.uploadedFileRepository = fileRepository;
}

@Transactional
Expand All @@ -64,7 +69,9 @@ public CaseEntityDto createTicket(CreateCaseRequest request, String username) {
if (request.getFileNames() != null) {
for (String fName : request.getFileNames()) {
if (fName == null || fName.isBlank()) continue;
caseEntity.getFiles().addAll(s3Service.createFile(caseEntity, fName));
UploadedFile uploadFile = s3Service.createFile(caseEntity, fName);
uploadedFileRepository.save(uploadFile);
caseEntity.getFiles().add(uploadFile);
}
}
CaseEntity saved = caseRepository.save(caseEntity);
Expand Down Expand Up @@ -102,7 +109,9 @@ public CaseEntityDto updateTicket(Long id, CreateCaseRequest request, String use
.collect(Collectors.toSet());
for (String fName : request.getFileNames()) {
if (fName == null || fName.isBlank() || existing.contains(fName)) continue;
caseEntity.getFiles().addAll(s3Service.createFile(caseEntity, fName));
UploadedFile uploadFile = s3Service.createFile(caseEntity, fName);
uploadedFileRepository.save(uploadFile);
caseEntity.getFiles().add(uploadFile);
}
}
CaseEntity saved = caseRepository.save(caseEntity);
Expand Down Expand Up @@ -171,11 +180,25 @@ public CaseEntityDto getTicketByID(long id) {
return CaseMapper.toDto(caseEntity);
}

public List<UploadedFile> getTicketFiles(long id) {
CaseEntity caseEntity = caseRepository.findById(id)
.orElseThrow(
() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Ticket not found: " + id));

return uploadedFileRepository.associatedCaseEntity(caseEntity).stream()
.toList();
}
public User findOwnerById(long id) {
return caseRepository.findOwnerById(id);
}

public boolean isNotOwner(CaseEntityDto ticket, String username) {
return !ticket.ownerUsername().equals(username);
}

public @Nullable List<UploadedFile> getUserFiles(String username) {
User actor = userRepository.findByUsername(username)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found"));
return uploadedFileRepository.getUploadedFilesByUploadedBy(actor);
}
}
3 changes: 1 addition & 2 deletions src/main/resources/static/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,13 @@ async function uploadNewFile(){
}

async function deleteFile(fileName){
const status = document.getElementById('status');
if (window.confirm(fileName + " will be deleted! Are you sure?")) {
const res = await apiReq(`/tickets/upload/api/files/delete-url?fileName=${encodeURIComponent(fileName)}`, {method: 'DELETE'});
if (!res) return;
if (res.ok) {
await fetchAFile();
} else {
status.innerText= 'Error: ' + res.status;
console.error('Error: ' + res.status);
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/templates/edit_ticket.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<h1>Edit Ticket</h1>
<div class="form-container">

<form th:action="@{/tickets/{id}/edit(id=${ticketId})}" th:object="${ticketForm}" method="post">
<form th:action="@{/tickets/{id}/edit(id=${ticketId})}" th:object="${ticketForm}" method="POST">
<header class="ticket-header">
<div class="ticket-title">
<label for="title">Issue:</label>
Expand All @@ -23,12 +23,13 @@ <h1>Edit Ticket</h1>
<textarea th:field="*{description}" id="description"></textarea>
<span th:if="${#fields.hasErrors('description')}" th:errors="*{description}"></span>
<input type="hidden" id="fileNameHidden" th:field="*{fileNames}">
<input type="file" id="fileInput">
<input type="file" id="fileInput" multiple>
<p id="status"></p>
</div>
<div id="hidden-file-inputs"></div>
<footer class="ticket-footer">
<div class="ticket-button">
<button onclick="uploadNewFile()" type="button">Save Changes</button>
<button onclick="uploadNewFile()" type="button" id="submitBtn">Save Changes</button>
Comment thread
FeFFe1996 marked this conversation as resolved.
<a th:href="@{/user}">Cancel</a>
</div>
</footer>
Expand Down
21 changes: 20 additions & 1 deletion src/main/resources/templates/ticket.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<head>
<meta charset="UTF-8">
<title>Ticket</title>

<script th:src="@{/js/script.js}" defer></script>
<link rel="stylesheet" th:href="@{/style.css}"/>
</head>
<body>
Expand Down Expand Up @@ -58,8 +60,14 @@ <h2 class="section-title">Add Comment</h2>
th:errors="*{text}"
class="field-error"></span>
</div>
<div>
<input type="hidden" id="fileNameHidden">
<input type="file" id="fileInput" multiple>
<p id="status"></p>
</div>
<div id="hidden-file-inputs"></div>
<div style="margin-top: 12px;">
<button type="submit" class="btn">Add Comment</button>
<button onclick="uploadNewFile()" type="submit" class="btn" id="submitBtn">Add Comment</button>
</div>
</form>
</div>
Expand All @@ -77,6 +85,17 @@ <h2 class="section-title">Activity Log</h2>
</div>
</div>
</div>
<div class="show-files">
<tr th:each="file : ${files}">
<td th:text="${file.getFilename()}"></td>
<td>
<button th:data-file="${file.getS3Key()}"
onclick="downloadFile(this.getAttribute('data-file'))"
class="button">Download</button>
</td>
</tr>

</div>
Comment thread
FeFFe1996 marked this conversation as resolved.

<footer style="margin-top: 24px;">
<nav style="display: flex; gap: 10px;">
Expand Down
49 changes: 22 additions & 27 deletions src/main/resources/templates/upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,36 @@
<script th:src="@{/js/script.js}" defer></script>
</head>
<body>
<header>
<h1>File Upload</h1>
</header>
<main>
<section>
<h2>Upload File</h2>
<div>
<input type="file" id="fileInput" multiple>
<button onclick="uploadNewFile()" class="button">Upload</button>
<p id="status"></p>
<div class="page-wrapper">
<div class="page-header">
<h1>Uploaded Files</h1>
<div class="ticket-actions">
<a th:href="@{/user}" class="btn btn-secondary">user page</a>
</div>
</section>

</div>
<section>
<h2>Uploaded Files</h2>
<div th:if="${#lists.isEmpty(files)}">
<p>No files uploaded yet.</p>
</div>
<table th:if="${not #lists.isEmpty(files)}">
<table>
<thead>
<tr>
<th>File Name</th>
<th>Action</th>
</tr>
<tr>
<th>File Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr th:each="file : ${files}">
<td th:text="${file}"></td>
<td>
<button th:onclick="'downloadFile(\'' + ${file} + '\')'" class="button">Download</button>
</td>
</tr>
<tr th:each="file : ${files}">
<td th:text="${file.getFilename()}"></td>
<td>
<button th:data-file="${file.getS3Key()}"
onclick="downloadFile(this.getAttribute('data-file'))"
class="button">Download</button>
</td>
</tr>
</tbody>
</table>
</section>
<p><a th:href="@{/user}"></a></p>
</div>

</main>
Comment thread
FeFFe1996 marked this conversation as resolved.
</body>
</html>
2 changes: 1 addition & 1 deletion src/main/resources/templates/userpage.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<h1>My Tickets</h1>
<div class="ticket-actions">
<a th:href="@{/tickets/create}" class="btn">+ New ticket</a>
<a th:href="@{/tickets/upload}" class="btn btn-secondary">Upload file</a>
<a th:href="@{/tickets/upload}" class="btn btn-secondary">User Files</a>
</div>
</div>

Expand Down