Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d07646d
refactor: rename class placeholder to create and add initial code
FionaSprinkles Apr 9, 2026
6419e6e
feat: add shared layout template for jte views
FionaSprinkles Apr 12, 2026
4d62e0c
style: add base styles and theme colors
FionaSprinkles Apr 12, 2026
569ce8e
config: allow public access to create and view endpoints for development
FionaSprinkles Apr 12, 2026
f5d2382
update : create with new template
FionaSprinkles Apr 12, 2026
4cf43e5
update: layout language to eng
FionaSprinkles Apr 12, 2026
f344c14
Merge remote-tracking branch 'origin/main' into feature/create-ticket…
FionaSprinkles Apr 13, 2026
9fc6bba
add /tickets to allowed endpoints for development
FionaSprinkles Apr 13, 2026
a0daf3f
Create view.jte and initial code
FionaSprinkles Apr 13, 2026
10279a5
refactor: changed endpoint
FionaSprinkles Apr 13, 2026
7c1b551
fix: bind create ticket form to DTO and enable POST submission
FionaSprinkles Apr 13, 2026
fd329e5
fix: correct ticket routing and redirect paths
FionaSprinkles Apr 13, 2026
2c9a57c
add: sign in button
FionaSprinkles Apr 13, 2026
3793994
fix: remove logging
FionaSprinkles Apr 13, 2026
876fc51
fix: preserve form input on validation errors
FionaSprinkles Apr 13, 2026
a418d19
fix:path for ticket creation link
FionaSprinkles Apr 13, 2026
bd381ef
fix:route mismatch
FionaSprinkles Apr 13, 2026
af9d886
style: remove quotes
FionaSprinkles Apr 13, 2026
3a6edb6
Merge branch 'main' into feature/create-ticket-view
FionaSprinkles Apr 13, 2026
d0564b0
chore: add .jteroot for jte template resolution
FionaSprinkles Apr 13, 2026
6826b6c
Merge branch 'main' into feature/create-ticket-view
FionaSprinkles Apr 14, 2026
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
4 changes: 4 additions & 0 deletions src/main/java/org/example/alfs/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.requestMatchers("/auth/signup").permitAll()
.requestMatchers("/auth/hash").permitAll()
.requestMatchers("/h2-console/**").permitAll()

//allow access to endpoints during development
.requestMatchers("/create", "/tickets/**", "/view/**").permitAll()
.requestMatchers("/css/**", "/js/**", "/images/**", "/static/**").permitAll()
.requestMatchers("/login", "/login-form").permitAll()
.requestMatchers("/signup", "/signup-form").permitAll()
.anyRequest().authenticated()
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/org/example/alfs/controllers/TicketController.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//TODO: Decide final routes and redirects

@Controller
@RequestMapping
@RequestMapping("/tickets")
public class TicketController {

private final TicketService ticketService;
Expand All @@ -34,23 +34,23 @@ public String createNewTicketForm(Model model) {
return "create";
}

//TODO REDIRECT, WHERE??
@PreAuthorize("hasRole('REPORTER')") // should change later for anonymous access
@PostMapping("/create")
public String createNewTicket(@ModelAttribute("ticket") @Valid TicketCreateDTO ticketCreateDTO, BindingResult bindingResult) {
public String createNewTicket(@ModelAttribute("ticket") @Valid TicketCreateDTO ticketCreateDTO, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("ticket", ticketCreateDTO);
return "create";
}

ticketService.createNewTicket(ticketCreateDTO);
TicketViewDTO ticket = ticketService.createNewTicket(ticketCreateDTO);

return "redirect:/home";
return "redirect:/tickets/" + ticket.getId();

}

//view ticket by token
//TODO, FIX SO ANONYMOUS USERS CAN USE
@GetMapping("/view/token/{token}")

@GetMapping("/token/{token}")
public String viewTicketByToken(@PathVariable String token, Model model) {

TicketViewDTO ticket = ticketService.getTicketByToken(token);
Expand All @@ -61,7 +61,7 @@ public String viewTicketByToken(@PathVariable String token, Model model) {

//view ticket by id
@PreAuthorize("hasAnyRole('ADMIN','INVESTIGATOR','REPORTER')")
@GetMapping("/view/id/{id}")
@GetMapping("/{id}")
public String viewTicketById(@PathVariable Long id, Model model) {

TicketViewDTO ticket = ticketService.getTicketById(id);
Expand All @@ -78,7 +78,7 @@ public String assignTicket(@PathVariable Long id, @Valid @ModelAttribute TicketA

ticketService.assignInvestigator(id, dto.getInvestigatorId());

return "redirect:/view/id/" + id;
return "redirect:/tickets/" + id;
}

//update status
Expand All @@ -88,7 +88,7 @@ public String updateStatus(@PathVariable Long id, @Valid @ModelAttribute TicketS

ticketService.updateTicketStatus(id, dto.getStatus());

return "redirect:/view/id/" + id;
return "redirect:/tickets/" + id;
}


Expand Down
Empty file added src/main/jte/.jteroot
Empty file.
24 changes: 24 additions & 0 deletions src/main/jte/create.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@param org.example.alfs.dto.ticket.TicketCreateDTO ticket

@template.layout(title = "Create Ticket", content = @`
<h1 class="text-2xl font-bold mb-6">Create Ticket</h1>

<form method="post" action="/tickets/create" class="space-y-4">
<input type="text"
name="title"
value="${ticket.getTitle()}"
placeholder="Title"
class="w-full border p-2 rounded"/>

<textarea
name="description"
placeholder="Description"
class="w-full border p-2 rounded h-32">${ticket.getDescription()}</textarea>

<button
type="submit"
class="bg-[#1a2b49] text-white px-4 py-2 rounded">
Create
</button>
</form>
`)
52 changes: 52 additions & 0 deletions src/main/jte/layout.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@param String title
@param gg.jte.Content content

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>${title}</title>

<!-- Tailwind -->
<script src="https://cdn.tailwindcss.com"></script>

<!-- Custom CSS -->
<link rel="stylesheet" href="/css/style.css">
</head>

<body class="min-h-screen flex flex-col">

<!-- HEADER -->
<header class="bg-[#1a2b49] text-white py-6 px-4 header-border">
<div class="max-w-5xl mx-auto flex justify-between items-center">
<h1 class="text-xl font-bold uppercase">
ALFS
whistleblower system
</h1>

<nav class="space-x-6 text-sm">
<a href="/" class="hover:text-[#b39359]">Home</a>
<a href="/tickets/create" class="hover:text-[#b39359]">Report</a>
<a href="/auth/login" class="hover:text-[#b39359]">Sign in</a>
</nav>
</div>
</header>

<!-- CONTENT -->
<main class="flex-grow max-w-5xl mx-auto w-full p-4 md:p-10">

${content}

</main>

<!-- FOOTER -->
<footer class="bg-white border-t py-6 px-4">
<div class="max-w-5xl mx-auto text-sm text-gray-600">
© ALFS
</div>
</footer>

</body>
</html>
1 change: 0 additions & 1 deletion src/main/jte/placeholder.jte

This file was deleted.

23 changes: 23 additions & 0 deletions src/main/jte/view.jte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@param org.example.alfs.dto.ticket.TicketViewDTO ticket

@template.layout(title = "View Ticket", content = @`
<h1 class="text-2xl font-bold mb-6">Ticket</h1>

<div class="card p-6 space-y-4">
<div>
<strong>ID:</strong> ${ticket.getId()}
</div>

<div>
<strong>Title:</strong> ${ticket.getTitle()}
</div>

<div>
<strong>Description:</strong> ${ticket.getDescription()}
</div>

<div>
<strong>Status:</strong> ${ticket.getStatus()}
</div>
</div>
`)
27 changes: 27 additions & 0 deletions src/main/resources/static/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

:root {
--state-blue: #1a2b49;
--state-gold: #b39359;
--state-gray: #f4f4f4;
}
body {
font-family: Georgia, serif;
background-color: var(--state-gray);
color: #333;
}
.header-border {
border-bottom: 4px solid var(--state-gold);
}
.btn-primary {
background-color: var(--state-blue);
color: white;
transition: all 0.3s ease;
}
.btn-primary:hover {
background-color: #2c4471;
}
.card {
background: white;
border: 1px solid #ddd;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
Loading