Jottyfan 2022-10-09 20:36:08 +02:00
parent 3b33368374
commit a3df68e4f7
9 changed files with 206 additions and 5 deletions

View File

@ -18,7 +18,7 @@ apply plugin: 'war'
apply plugin: 'application' apply plugin: 'application'
group = 'de.jottyfan.camporganizer' group = 'de.jottyfan.camporganizer'
version = '0.0.2' version = '0.0.3'
sourceCompatibility = 17 sourceCompatibility = 17
mainClassName = "de.jottyfan.camporganizer.Main" mainClassName = "de.jottyfan.camporganizer.Main"

View File

@ -52,4 +52,14 @@ public interface IConfirmationService {
* @return the list of rejected bookings * @return the list of rejected bookings
*/ */
public List<BookingBean> getRejected(HttpServletRequest request); public List<BookingBean> getRejected(HttpServletRequest request);
/**
* get the result of a search for needle in the database
*
* @param needle the needle; may be a name of anything
* @param linkURL the URL of the link for clicking on the found entity
* @param request the request
* @return the result in html format (for now)
*/
public String search(String needle, String linkURL, HttpServletRequest request);
} }

View File

@ -0,0 +1,31 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
*
* @author jotty
*
*/
@Controller
public class SearchController {
@Autowired
private HttpServletRequest request;
@Autowired
private IConfirmationService service;
@GetMapping("/confirmation/search")
@ResponseBody
public String search(@PathParam(value = "needle") String needle, Model model) {
return service.search(needle, request.getRequestURI().replace("search", "person"), request);
}
}

View File

@ -4,6 +4,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE; import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON; import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
@ -127,7 +128,6 @@ public class ConfirmationGateway {
list.add(bean); list.add(bean);
} }
return list; return list;
} }
/** /**
@ -159,4 +159,48 @@ public class ConfirmationGateway {
public List<BookingBean> getRejected(String currentUser) { public List<BookingBean> getRejected(String currentUser) {
return getListWithCondition(currentUser, T_PERSON.ACCEPT.isFalse()); return getListWithCondition(currentUser, T_PERSON.ACCEPT.isFalse());
} }
/**
* get the result of the search
*
* @param needle the needle
* @param currentUser the current user
* @return a list of found beans; an empty one at least
*/
public List<BookingBean> getSearchResult(String needle, String currentUser) {
Condition condition = T_PERSON.FORENAME.containsIgnoreCase(needle)
// @formatter:off
.or(T_PERSON.SURNAME.containsIgnoreCase(needle))
.or(V_CAMP.NAME.containsIgnoreCase(needle))
.or(V_CAMP.YEAR.cast(String.class).containsIgnoreCase(needle));
// @formatter:on
SelectSeekStep1<Record7<Integer, String, String, EnumCamprole, String, Double, String>, LocalDateTime> sql = jooq
// @formatter:off
.select(T_PERSON.PK, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.LOCATION_NAME)
.from(T_PERSON)
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(condition)
.and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.and(T_PROFILE.USERNAME.eq(currentUser))
.orderBy(T_PERSON.CREATED.desc());
// @formatter:on
LOGGER.debug(sql.toString());
List<BookingBean> list = new ArrayList<>();
for (Record7<Integer, String, String, EnumCamprole, String, Double, String> r : sql.fetch()) {
Integer pkPerson = r.get(T_PERSON.PK);
String forename = r.get(T_PERSON.FORENAME);
String surname = r.get(T_PERSON.SURNAME);
EnumCamprole role = r.get(T_PERSON.CAMPROLE);
String campname = r.get(V_CAMP.NAME);
Double year = r.get(V_CAMP.YEAR);
BookingBean bean = new BookingBean(pkPerson, null, String.format("%s %4.0f", campname, year));
bean.setRole(role == null ? null : role.getLiteral());
bean.setFullname(new StringBuilder().append(forename).append(" ").append(surname).toString());
list.add(bean);
}
return list;
}
} }

View File

@ -50,4 +50,14 @@ public class ConfirmationService implements IConfirmationService {
public List<BookingBean> getRejected(HttpServletRequest request) { public List<BookingBean> getRejected(HttpServletRequest request) {
return gateway.getRejected(getCurrentUser(request)); return gateway.getRejected(getCurrentUser(request));
} }
@Override
public String search(String needle, String linkURL, HttpServletRequest request) {
StringBuilder buf = new StringBuilder("<table class=\"table table-striped\"><thead><tr><th>Name</th><th>Freizeit</th><th>Rolle</th></tr><tbody>");
for (BookingBean bean : gateway.getSearchResult(needle, getCurrentUser(request))) {
buf.append(String.format("<tr><td><a href=\"%s/%d\">%s</a></td><td>%s</td><td>%s</td></tr>", linkURL, bean.getPkPerson(), bean.getFullname(), bean.getCamp(), bean.getRolename()));
}
buf.append("</tbody></table>");
return buf.toString();
}
} }

View File

@ -0,0 +1,84 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class FoundBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer fkPerson;
private String forename;
private String surname;
private String campname;
private Integer year;
/**
* @return the forename
*/
public String getForename() {
return forename;
}
/**
* @param forename the forename to set
*/
public void setForename(String forename) {
this.forename = forename;
}
/**
* @return the surname
*/
public String getSurname() {
return surname;
}
/**
* @param surname the surname to set
*/
public void setSurname(String surname) {
this.surname = surname;
}
/**
* @return the campname
*/
public String getCampname() {
return campname;
}
/**
* @param campname the campname to set
*/
public void setCampname(String campname) {
this.campname = campname;
}
/**
* @return the year
*/
public Integer getYear() {
return year;
}
/**
* @param year the year to set
*/
public void setYear(Integer year) {
this.year = year;
}
public Integer getFkPerson() {
return fkPerson;
}
public void setFkPerson(Integer fkPerson) {
this.fkPerson = fkPerson;
}
}

View File

@ -0,0 +1,9 @@
class MyAjax {
constructor(url) {
this.url = url;
}
call(destdivid, needle) {
$("[id='" + destdivid + "']").load(this.url + '?needle=' + encodeURI(needle));
}
}

View File

@ -157,10 +157,22 @@
</div> </div>
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header" id="searchpanel"> <h2 class="accordion-header" id="searchpanel">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#searchdiv" aria-expanded="true" aria-control="searchdiv">Suchmaske</button> <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#searchdiv" aria-expanded="true" aria-control="searchdiv">Suchmaske (einzelne Begriffe)</button>
</h2> </h2>
<div id="searchdiv" class="accordion-collapse collapse dist8" aria-labelled="searchpanel" data-bs-parent="#mainacc">TODO: add an ajax based search field for persons to directly edit <div id="searchdiv" class="accordion-collapse collapse dist8" aria-labelled="searchpanel" data-bs-parent="#mainacc">
them</div> <script th:inline="javascript">
/*<![CDATA[*/
var searchUrl = /*[[@{/confirmation/search}]]*/ '?';
var myAjax = new MyAjax(searchUrl);
/*]]>*/
</script>
<input type="text" placeholder="bitte Suchtext eingeben" class="form-control" onchange="myAjax.call('searchresult', this.value)" />
<div id="searchresult">
Die Suche ist eine einfache Textsuche. Bestenfalls sollte nur ein Begriff zum Suchen verwendet werden, also z.B. nur der Vor- ODER der Nachname, nicht beides.<br />
Es werden nur wenige Felder in der Datenbank durchsucht: Vorname, Nachname, Freizeitname und Freizeitjahr.<br />
Die Suche wird nach dem Verlassen des Suchtext-Eingabefeldes aktiviert.
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -14,6 +14,7 @@
<script th:src="@{/webjars/select2/4.0.13/js/select2.full.min.js}"></script> <script th:src="@{/webjars/select2/4.0.13/js/select2.full.min.js}"></script>
<script th:src="@{/js/dataTables.de.js}"></script> <script th:src="@{/js/dataTables.de.js}"></script>
<script th:src="@{/js/mytoggle.js}"></script> <script th:src="@{/js/mytoggle.js}"></script>
<script th:src="@{/js/myAjax.js}"></script>
<meta th:replace="${libs}"></meta> <meta th:replace="${libs}"></meta>
</head> </head>
<body> <body>