initial commit

Change-Id: I998d0a4270d2a78a22d2b456ea5dfbfe6ee3738e
This commit is contained in:
Scaffolder
2026-07-20 11:43:56 +00:00
commit 09db22bc7b
138 changed files with 28044 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'error')}">
<body>
<img src="../static/resources/images/pets.png" th:src="@{/resources/images/pets.png}" />
<!-- Title: Something happened -->
<h2 th:text="#{somethingHappened}">Something happened...</h2>
<!-- Status-specific error message -->
<p th:switch="${status}">
<span th:case="404" th:text="#{error.404}">The requested page was not found.</span>
<span th:case="500" th:text="#{error.500}">An internal server error occurred.</span>
<span th:case="*" th:text="#{error.general}">An unexpected error occurred.</span>
</p>
<!-- Exception message (for developers) -->
<p th:text="${message}">Exception message</p>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<body>
<form>
<th:block th:fragment="input (label, name, type)">
<div th:with="valid=${!#fields.hasErrors(name)}" th:class="${'form-group' + (valid ? '' : ' has-error')}"
class="form-group">
<label th:for="${name}" class="col-sm-2 control-label" th:text="${label}">Label</label>
<div class="col-sm-10">
<div th:switch="${type}">
<input th:case="'text'" class="form-control" type="text" th:field="*{__${name}__}" />
<input th:case="'date'" class="form-control" type="date" th:field="*{__${name}__}" th:min="${minVisitDate}" />
</div>
<span th:if="${valid}" class="fa fa-ok form-control-feedback" aria-hidden="true"></span>
<th:block th:if="${!valid}">
<span class="fa fa-remove form-control-feedback" aria-hidden="true"></span>
<span class="help-inline" th:errors="*{__${name}__}" th:text="#{error}">Error</span>
</th:block>
</div>
</div>
</th:block>
</form>
</body>
</html>

View File

@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html th:fragment="layout (template, menu)" xmlns:th="https://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/x-icon" th:href="@{/resources/images/favicon.png}">
<title th:text="#{layoutTitle}">PetClinic :: a Spring Framework demonstration</title>
<link th:href="@{/webjars/font-awesome/css/font-awesome.min.css}" rel="stylesheet">
<link rel="stylesheet" th:href="@{/resources/css/petclinic.css}" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark" role="navigation">
<div class="container-fluid">
<a class="navbar-brand" th:href="@{/}"><span></span></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-navbar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="main-navbar" style>
<ul class="navbar-nav me-auto mb-2 mb-lg-0" th:remove="all">
<li th:fragment="menuItem (link,active,title,glyph,text)" th:class="nav-item">
<a th:class="${active==menu ? 'nav-link active' : 'nav-link'}" th:href="@{__${link}__}" th:title="${title}">
<span th:class="'fa fa-'+${glyph}" class="fa fa-home"></span>
<span th:text="${text}">Template</span>
</a>
</li>
</ul>
<ul class="nav navbar-nav me-auto">
<li th:replace="~{::menuItem ('/','home','home page','home',#{home})}">
<span class="fa fa-home" aria-hidden="true"></span>
<span th:text="#{home}">Home</span>
</li>
<li th:replace="~{::menuItem ('/owners/find','owners','find owners','search',#{findOwners})}">
<span class="fa fa-search" aria-hidden="true"></span>
<span th:text="#{findOwners}">Find owners</span>
</li>
<li th:replace="~{::menuItem ('/vets.html','vets','veterinarians','th-list',#{vets})}">
<span class="fa fa-th-list" aria-hidden="true"></span>
<span th:text="#{vets}">Veterinarians</span>
</li>
<li
th:replace="~{::menuItem ('/oups','error','trigger a RuntimeException to see how it is handled','exclamation-triangle',#{error})}">
<span class="fa exclamation-triangle" aria-hidden="true"></span>
<span th:text="#{error}">Error</span>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="container xd-container">
<th:block th:insert="${template}" />
<br />
<br />
<div class="container">
<div class="row">
<div class="col-12 text-center">
<img src="../static/images/spring-logo.svg" th:src="@{/resources/images/spring-logo.svg}"
alt="VMware Tanzu Logo" class="logo">
</div>
</div>
</div>
</div>
</div>
<script th:src="@{/webjars/bootstrap/dist/js/bootstrap.bundle.min.js}"></script>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<body>
<form>
<th:block th:fragment="select (label, name, items)">
<div th:with="valid=${!#fields.hasErrors(name)}" th:class="${'form-group' + (valid ? '' : ' has-error')}"
class="form-group">
<label th:for="${name}" class="col-sm-2 control-label" th:text="${label}">Label</label>
<div class="col-sm-10">
<select th:field="*{__${name}__}">
<option th:each="item : ${items}" th:value="${item}" th:text="${item}">dog</option>
</select>
<span th:if="${valid}" class="fa fa-ok form-control-feedback" aria-hidden="true"></span>
<th:block th:if="${!valid}">
<span class="fa fa-remove form-control-feedback" aria-hidden="true"></span>
<span class="help-inline" th:errors="*{__${name}__}" th:text="#{error}">Error</span>
</th:block>
</div>
</div>
</th:block>
</form>
</body>
</html>

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2 th:text="#{owner}">Owner</h2>
<form th:object="${owner}" class="form-horizontal" id="add-owner-form" method="post">
<div class="form-group has-feedback">
<input th:replace="~{fragments/inputField :: input (#{firstName}, 'firstName', 'text')}" />
<input th:replace="~{fragments/inputField :: input (#{lastName}, 'lastName', 'text')}" />
<input th:replace="~{fragments/inputField :: input (#{address}, 'address', 'text')}" />
<input th:replace="~{fragments/inputField :: input (#{city}, 'city', 'text')}" />
<input th:replace="~{fragments/inputField :: input (#{telephone}, 'telephone', 'text')}" />
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button th:with="text=${owner['new']} ? #{addOwner} : #{updateOwner}" class="btn btn-primary" type="submit"
th:text="${text}">Add Owner</button>
</div>
</div>
</form>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2 th:text="#{findOwners}">Find Owners</h2>
<form th:object="${owner}" th:action="@{/owners}" method="get" class="form-horizontal" id="search-owner-form">
<div class="form-group">
<div class="control-group" id="lastNameGroup">
<label class="col-sm-2 control-label" th:text="#{lastName}">Last name </label>
<div class="col-sm-10">
<input class="form-control" th:field="*{lastName}" size="30" maxlength="80" />
<span class="help-inline">
<div th:if="${#fields.hasAnyErrors()}">
<p th:each="err : ${#fields.allErrors()}" th:text="${err}">Error</p>
</div>
</span>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" th:text="#{findOwner}">Find Owner</button>
</div>
</div>
<a class="btn btn-primary" th:href="@{/owners/new}" th:text="#{addOwner}">Add Owner</a>
</form>
</body>
</html>

View File

@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2 th:text="#{ownerInformation}">Owner Information</h2>
<div th:if="${message}" class="alert alert-success" id="success-message">
<span th:text="${message}"></span>
</div>
<div th:if="${error}" class="alert alert-danger" id="error-message">
<span th:text="${error}"></span>
</div>
<table class="table table-striped" th:object="${owner}">
<tr>
<th th:text="#{name}">Name</th>
<td><b th:text="*{firstName + ' ' + lastName}"></b></td>
</tr>
<tr>
<th th:text="#{address}">Address</th>
<td th:text="*{address}"></td>
</tr>
<tr>
<th th:text="#{city}">City</th>
<td th:text="*{city}"></td>
</tr>
<tr>
<th th:text="#{telephone}">Telephone</th>
<td th:text="*{telephone}"></td>
</tr>
</table>
<a th:href="@{__${owner.id}__/edit}" class="btn btn-primary" th:text="#{editOwner}">Edit
Owner</a>
<a th:href="@{__${owner.id}__/pets/new}" class="btn btn-primary" th:text="#{addNewPet}">Add
New Pet</a>
<br />
<br />
<br />
<h2 th:text="#{petsAndVisits}">Pets and Visits</h2>
<table class="table table-striped">
<tr th:each="pet : ${owner.pets}">
<td valign="top">
<dl class="dl-horizontal">
<dt th:text="#{name}">Name</dt>
<dd th:text="${pet.name}"></dd>
<dt th:text="#{birthDate}">Birth Date</dt>
<dd th:text="${#temporals.format(pet.birthDate, 'yyyy-MM-dd')}"></dd>
<dt th:text="#{type}">Type</dt>
<dd th:text="${pet.type}"></dd>
</dl>
</td>
<td valign="top">
<table class="table-condensed">
<thead>
<tr>
<th th:text="#{visitDate}">Visit Date</th>
<th th:text="#{description}">Description</th>
</tr>
</thead>
<tr th:each="visit : ${pet.visits}">
<td th:text="${#temporals.format(visit.date, 'yyyy-MM-dd')}"></td>
<td th:text="${visit?.description}"></td>
</tr>
<tr>
<td><a th:href="@{__${owner.id}__/pets/__${pet.id}__/edit}" th:text="#{editPet}">Edit Pet</a></td>
<td><a th:href="@{__${owner.id}__/pets/__${pet.id}__/visits/new}" th:text="#{addVisit}">Add Visit</a></td>
</tr>
</table>
</td>
</tr>
</table>
<script>
// Function to hide the success and error messages after 3 seconds
function hideMessages() {
setTimeout(function () {
document.getElementById("success-message").style.display = "none";
document.getElementById("error-message").style.display = "none";
}, 3000); // 3000 milliseconds (3 seconds)
}
// Call the function to hide messages
hideMessages();
</script>
</body>
</html>

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2 th:text="#{owners}">Owners</h2>
<table id="owners" class="table table-striped">
<thead>
<tr>
<th th:text="#{name}" style="width: 150px;">Name</th>
<th th:text="#{address}" style="width: 200px;">Address</th>
<th th:text="#{city}">City</th>
<th th:text="#{telephone}" style="width: 120px">Telephone</th>
<th th:text="#{pets}">Pets</th>
</tr>
</thead>
<tbody>
<tr th:each="owner : ${listOwners}">
<td>
<a th:href="@{/owners/__${owner.id}__}" th:text="${owner.firstName + ' ' + owner.lastName}" /></a>
</td>
<td th:text="${owner.address}" />
<td th:text="${owner.city}" />
<td th:text="${owner.telephone}" />
<td><span th:text="${#strings.listJoin(owner.pets, ', ')}" /></td>
</tr>
</tbody>
</table>
<div th:if="${totalPages > 1}">
<span th:text="#{pages}">Pages:</span>
<span>[</span>
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/owners?page=' + ${i}}">[[${i}]]</a>
<span th:unless="${currentPage != i}">[[${i}]]</span>
</span>
<span>]&nbsp;</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/owners?page=1'}" th:title="#{first}" class="fa fa-fast-backward"></a>
<span th:unless="${currentPage > 1}" th:title="#{first}" class="fa fa-fast-backward"></span>
</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/owners?page=__${currentPage - 1}__'}" th:title="#{previous}"
class="fa fa-step-backward"></a>
<span th:unless="${currentPage > 1}" th:title="#{previous}" class="fa fa-step-backward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/owners?page=__${currentPage + 1}__'}" th:title="#{next}"
class="fa fa-step-forward"></a>
<span th:unless="${currentPage < totalPages}" th:title="#{next}" class="fa fa-step-forward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/owners?page=__${totalPages}__'}" th:title="#{last}"
class="fa fa-fast-forward"></a>
<span th:unless="${currentPage < totalPages}" th:title="#{last}" class="fa fa-fast-forward"></span>
</span>
</div>
</body>
</html>

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2>
<th:block th:if="${pet['new']}" th:text="#{new}">New </th:block>
<span th:text="#{pet}">Pet</span>
</h2>
<form th:object="${pet}" class="form-horizontal" method="post">
<input type="hidden" name="id" th:value="*{id}" />
<div class="form-group has-feedback">
<div class="form-group">
<label class="col-sm-2 control-label" th:text="#{owner}">Owner</label>
<div class="col-sm-10">
<span th:text="${owner?.firstName + ' ' + owner?.lastName}" />
</div>
</div>
<input th:replace="~{fragments/inputField :: input ('Name', 'name', 'text')}" />
<input th:replace="~{fragments/inputField :: input ('Birth Date', 'birthDate', 'date')}" />
<input th:replace="~{fragments/selectField :: select ('Type', 'type', ${types})}" />
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button th:with="text=${pet['new']} ? 'Add Pet' : 'Update Pet'" class="btn btn-primary" type="submit"
th:text="${text}">Add Pet</button>
</div>
</div>
</form>
</body>
</html>

View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
<body>
<h2>
<th:block th:if="${visit['new']}" th:text="#{new}">New </th:block>
Visit
</h2>
<b th:text="#{pet}">Pet</b>
<table class="table table-striped">
<thead>
<tr>
<th th:text="#{name}">Name</th>
<th th:text="#{birthDate}">Birth Date</th>
<th th:text="#{type}">Type</th>
<th th:text="#{owner}">Owner</th>
</tr>
</thead>
<tr>
<td th:text="${pet.name}"></td>
<td th:text="${#temporals.format(pet.birthDate, 'yyyy-MM-dd')}"></td>
<td th:text="${pet.type}"></td>
<td th:text="${owner?.firstName + ' ' + owner?.lastName}"></td>
</tr>
</table>
<form th:object="${visit}" class="form-horizontal" method="post">
<div class="form-group has-feedback">
<input th:replace="~{fragments/inputField :: input ('Date', 'date', 'date')}" />
<input th:replace="~{fragments/inputField :: input ('Description', 'description', 'text')}" />
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" name="petId" th:value="${pet.id}" />
<button class="btn btn-primary" type="submit" th:text="#{addVisit}">Add Visit</button>
</div>
</div>
</form>
<br />
<b th:text="#{previousVisits}">Previous Visits</b>
<table class="table table-striped">
<tr>
<th th:text="#{date}">Date</th>
<th th:text="#{description}">Description</th>
</tr>
<tr th:if="${!visit['new']}" th:each="visit : ${pet.visits}">
<td th:text="${#temporals.format(visit.date, 'yyyy-MM-dd')}"></td>
<td th:text=" ${visit.description}"></td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'vets')}">
<body>
<h2 th:text="#{vets}">Veterinarians</h2>
<table id="vets" class="table table-striped">
<thead>
<tr>
<th th:text="#{name}">Name</th>
<th th:text="#{specialties}">Specialties</th>
</tr>
</thead>
<tbody>
<tr th:each="vet : ${listVets}">
<td th:text="${vet.firstName + ' ' + vet.lastName}"></td>
<td>
<span th:each="specialty : ${vet.specialties}" th:text="${specialty.name + ' '}" /> <span
th:if="${vet.nrOfSpecialties == 0}" th:text="#{none}">none</span>
</td>
</tr>
</tbody>
</table>
<div th:if="${totalPages > 1}">
<span th:text="#{pages}">Pages:</span>
<span>[</span>
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/vets.html?page=__${i}__'}">[[${i}]]</a>
<span th:unless="${currentPage != i}">[[${i}]]</span>
</span>
<span>]&nbsp;</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=1'}" th:title="#{first}"
class="fa fa-fast-backward"></a>
<span th:unless="${currentPage > 1}" th:title="#{first}" class="fa fa-fast-backward"></span>
</span>
<span>
<a th:if="${currentPage > 1}" th:href="@{'/vets.html?page=__${currentPage - 1}__'}" th:title="#{previous}"
class="fa fa-step-backward"></a>
<span th:unless="${currentPage > 1}" th:title="#{previous}" class="fa fa-step-backward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${currentPage + 1}__'}" th:title="#{next}"
class="fa fa-step-forward"></a>
<span th:unless="${currentPage < totalPages}" th:title="#{next}" class="fa fa-step-forward"></span>
</span>
<span>
<a th:if="${currentPage < totalPages}" th:href="@{'/vets.html?page=__${totalPages}__'}" th:title="#{last}"
class="fa fa-fast-forward"></a>
<span th:unless="${currentPage < totalPages}" th:title="#{last}" class="fa fa-fast-forward"></span>
</span>
</div>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'home')}">
<body>
<h2 th:text="#{welcome}">Welcome</h2>
<div class="row">
<div class="col-md-12">
<img class="img-responsive" src="../static/resources/images/pets.png" th:src="@{/resources/images/pets.png}" />
</div>
</div>
</body>
</html>