global search fixed
This commit is contained in:
parent
c98befaf26
commit
56deb56c72
@ -44,6 +44,7 @@ import cz.kamma.fabka.repository.model.PrivateMessageStats;
|
||||
import cz.kamma.fabka.repository.model.PrivateThreadRoot;
|
||||
import cz.kamma.fabka.repository.model.PrivateThreadSummary;
|
||||
import cz.kamma.fabka.repository.model.QuotedTextItem;
|
||||
import cz.kamma.fabka.repository.model.SearchResultItem;
|
||||
import cz.kamma.fabka.repository.SettingsRepository;
|
||||
import cz.kamma.fabka.repository.model.UserIcon;
|
||||
import cz.kamma.fabka.repository.UserIconRepository;
|
||||
@ -150,6 +151,48 @@ public class HttpServerApplication {
|
||||
boolean showError = "1".equals(ctx.queryParam("error"));
|
||||
Responses.html(ctx.exchange(), 200, Pages.loginPage(showError));
|
||||
});
|
||||
|
||||
router.get("/search", ctx -> {
|
||||
if (!isAuthenticated(ctx)) {
|
||||
Responses.text(ctx.exchange(), 401, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
String searchText = valueOrDefault(ctx.queryParam("stext"), "");
|
||||
String f = ctx.queryParam("fid");
|
||||
long forumId = f != null && !f.isBlank() ? parseLong(f, 0) : 0;
|
||||
|
||||
SessionData session = ctx.getSession();
|
||||
if (session == null) {
|
||||
Responses.text(ctx.exchange(), 401, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
String username = String.valueOf(session.getAttribute(AUTH_USER_KEY));
|
||||
long userId = parseLong(session.getAttribute(AUTH_USER_ID_KEY), -1L);
|
||||
|
||||
if (userId <= 0) {
|
||||
Responses.text(ctx.exchange(), 401, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
List<SearchResultItem> results = forumRepository.searchMessages(userId, searchText, forumId);
|
||||
|
||||
int loggedUsersCount = sessionManager.countSessionsWithAttribute(AUTH_USER_KEY);
|
||||
List<String> loggedUsers = sessionManager.sessionAttributeValues(AUTH_USER_KEY);
|
||||
PrivateMessageStats pmStats = privateMessageRepository.stats(userId);
|
||||
|
||||
Responses.html(ctx.exchange(), 200, Pages.searchResultsPage(
|
||||
username,
|
||||
userId,
|
||||
results,
|
||||
searchText,
|
||||
loggedUsersCount,
|
||||
loggedUsers,
|
||||
pmStats
|
||||
));
|
||||
});
|
||||
|
||||
router.get("/chat.jsp", ctx -> Responses.redirect(ctx.exchange(), "/chat"));
|
||||
router.get("/private.jsp", ctx -> {
|
||||
String oBy = ctx.queryParam("oBy");
|
||||
|
||||
@ -24,6 +24,7 @@ import cz.kamma.fabka.repository.model.ForumDetail;
|
||||
import cz.kamma.fabka.repository.model.ForumMessage;
|
||||
import cz.kamma.fabka.repository.model.ForumSummary;
|
||||
import cz.kamma.fabka.repository.model.QuotedTextItem;
|
||||
import cz.kamma.fabka.repository.model.SearchResultItem;
|
||||
import cz.kamma.fabka.repository.model.VoteStats;
|
||||
|
||||
public class ForumRepository {
|
||||
@ -282,6 +283,7 @@ public class ForumRepository {
|
||||
|
||||
out.add(new ForumMessage(
|
||||
messageId,
|
||||
forumId,
|
||||
authorIds.get(i),
|
||||
valueOrDefault(usernames.get(i), "N/A"),
|
||||
formatTs(createdTimes.get(i)),
|
||||
@ -678,6 +680,50 @@ public class ForumRepository {
|
||||
return value == null || value.isBlank() ? defaultValue : value;
|
||||
}
|
||||
|
||||
public List<SearchResultItem> searchMessages(long userId, String searchText, long forumId) {
|
||||
List<SearchResultItem> results = new ArrayList<>();
|
||||
if (searchText == null || searchText.isBlank()) {
|
||||
return results;
|
||||
}
|
||||
|
||||
String sql = "SELECT fi.id, fi.forumid, fi.created, fi.createdby, fi.text, ua.username, ua.city, ua.created as createdua, f.name FROM forum_items fi, user_accounts ua, forum f WHERE " +
|
||||
(forumId > 0 ? "fi.forumid=" + forumId + " AND " : "") +
|
||||
"MATCH (fi.text) AGAINST (? IN BOOLEAN MODE) AND fi.deleted=0 AND fi.createdby=ua.id AND f.id=fi.forumid AND f.password IN (SELECT password FROM passwords WHERE userid=?)";
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, searchText);
|
||||
ps.setLong(2, userId);
|
||||
System.out.println("[DEBUG] SEARCH SQL (forumId=" + forumId + "): " + sql);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
results.add(buildSearchResultFromResultSet(rs));
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] SEARCH_MESSAGES_SQL: searchText='" + searchText + "', forumId=" + forumId + ", count=" + results.size() + ", duration=" + durationMs + "ms");
|
||||
return results;
|
||||
}
|
||||
|
||||
private SearchResultItem buildSearchResultFromResultSet(ResultSet rs) throws Exception {
|
||||
long id = rs.getLong("id");
|
||||
long forumId = rs.getLong("forumid");
|
||||
Timestamp created = rs.getTimestamp("created");
|
||||
long createdBy = rs.getLong("createdby");
|
||||
String text = rs.getString("text");
|
||||
String username = rs.getString("username");
|
||||
String city = rs.getString("city");
|
||||
Timestamp createdua = rs.getTimestamp("createdua");
|
||||
String forumName = rs.getString("name");
|
||||
|
||||
return new SearchResultItem(id, forumId, created, createdBy, text, username, city, createdua, forumName);
|
||||
}
|
||||
|
||||
private static String formatTs(Timestamp ts) {
|
||||
if (ts == null) {
|
||||
return "N/A";
|
||||
|
||||
@ -4,6 +4,7 @@ import java.util.List;
|
||||
|
||||
public class ForumMessage {
|
||||
private final long id;
|
||||
private final long forumId;
|
||||
private final long authorId;
|
||||
private final String author;
|
||||
private final String authorJoinDate;
|
||||
@ -19,11 +20,12 @@ public class ForumMessage {
|
||||
private final QuotedTextItem quotedItem;
|
||||
private final String createdAt;
|
||||
private final String text;
|
||||
private final List<ForumAttachment> attachments;
|
||||
private List<ForumAttachment> attachments;
|
||||
private final boolean sticky;
|
||||
|
||||
public ForumMessage(
|
||||
long id,
|
||||
long forumId,
|
||||
long authorId,
|
||||
String author,
|
||||
String authorJoinDate,
|
||||
@ -43,6 +45,7 @@ public class ForumMessage {
|
||||
boolean sticky
|
||||
) {
|
||||
this.id = id;
|
||||
this.forumId = forumId;
|
||||
this.authorId = authorId;
|
||||
this.author = author;
|
||||
this.authorJoinDate = authorJoinDate;
|
||||
@ -133,4 +136,12 @@ public class ForumMessage {
|
||||
public boolean isSticky() {
|
||||
return sticky;
|
||||
}
|
||||
|
||||
public long getForumId() {
|
||||
return forumId;
|
||||
}
|
||||
|
||||
public void setAttachments(List<ForumAttachment> attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
package cz.kamma.fabka.repository.model;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class SearchResultItem {
|
||||
private final long id;
|
||||
private final long forumId;
|
||||
private final Timestamp created;
|
||||
private final long createdBy;
|
||||
private final String text;
|
||||
private final String username;
|
||||
private final String city;
|
||||
private final Timestamp createdua;
|
||||
private final String forumName;
|
||||
|
||||
public SearchResultItem(
|
||||
long id,
|
||||
long forumId,
|
||||
Timestamp created,
|
||||
long createdBy,
|
||||
String text,
|
||||
String username,
|
||||
String city,
|
||||
Timestamp createdua,
|
||||
String forumName
|
||||
) {
|
||||
this.id = id;
|
||||
this.forumId = forumId;
|
||||
this.created = created;
|
||||
this.createdBy = createdBy;
|
||||
this.text = text;
|
||||
this.username = username;
|
||||
this.city = city;
|
||||
this.createdua = createdua;
|
||||
this.forumName = forumName;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getForumId() {
|
||||
return forumId;
|
||||
}
|
||||
|
||||
public Timestamp getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public long getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public Timestamp getCreatedua() {
|
||||
return createdua;
|
||||
}
|
||||
|
||||
public String getForumName() {
|
||||
return forumName;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,6 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cz.kamma.fabka.repository.MysqlClientRepository;
|
||||
import cz.kamma.fabka.repository.model.AttachmentData;
|
||||
import cz.kamma.fabka.repository.model.ForumAttachment;
|
||||
import cz.kamma.fabka.repository.model.ForumDetail;
|
||||
import cz.kamma.fabka.repository.model.ForumDisplayView;
|
||||
@ -22,7 +21,7 @@ import cz.kamma.fabka.repository.model.PrivateMessageStats;
|
||||
import cz.kamma.fabka.repository.model.PrivateThreadRoot;
|
||||
import cz.kamma.fabka.repository.model.PrivateThreadSummary;
|
||||
import cz.kamma.fabka.repository.model.QuotedTextItem;
|
||||
import cz.kamma.fabka.repository.model.UserIcon;
|
||||
import cz.kamma.fabka.repository.model.SearchResultItem;
|
||||
|
||||
public final class Pages {
|
||||
private static final String LOGIN_TEMPLATE = readTemplate("webapp/login.html");
|
||||
@ -532,6 +531,68 @@ public final class Pages {
|
||||
.replace("{{PAGE_LINKS}}", buildPageLinks(baseLink, currentPage, totalPages));
|
||||
}
|
||||
|
||||
public static String searchResultsPage(
|
||||
String username,
|
||||
long currentUserId,
|
||||
List<SearchResultItem> results,
|
||||
String searchText,
|
||||
int loggedUsersCount,
|
||||
List<String> loggedUsers,
|
||||
PrivateMessageStats pmStats
|
||||
) {
|
||||
StringBuilder messageRows = new StringBuilder();
|
||||
if (results == null || results.isEmpty()) {
|
||||
messageRows.append("<div style='color:red'>No message found.</div>");
|
||||
} else {
|
||||
for (SearchResultItem result : results) {
|
||||
messageRows.append("<table class='tborder' cellpadding='6' cellspacing='1' border='0' width='100%' align='center'>")
|
||||
.append("<tbody>")
|
||||
.append("<tr><td class='thead'>")
|
||||
.append("<div class='normal'>")
|
||||
.append(formatTimestamp(result.getCreated()))
|
||||
.append(" - <a href='/forumdisplay?f=").append(result.getForumId()).append("'>")
|
||||
.append(escapeHtml(valueOrDefault(result.getForumName(), ""))).append("</a>")
|
||||
.append("</div></td></tr>")
|
||||
.append("<tr><td class='alt2' style='padding:0'>")
|
||||
.append("<table cellpadding='0' cellspacing='6' border='0' width='100%'><tbody><tr>")
|
||||
.append("<td valign='middle' nowrap='nowrap'><img src='/process/showimage?userIcon=yes&uid=").append(result.getCreatedBy()).append("' width='80'/></td>")
|
||||
.append("<td valign='middle' nowrap='nowrap'><div style='color: blue; font-weight:bold'><a href='#'>")
|
||||
.append(escapeHtml(result.getUsername())).append("</a></div></td>")
|
||||
.append("<td width='100%'> </td>")
|
||||
.append("<td valign='top' nowrap='nowrap'><div class='smallfont'>")
|
||||
.append("<div>Join Date: ").append(formatTimestamp(result.getCreatedua())).append("</div>")
|
||||
.append("<div>Location: ").append(escapeHtml(valueOrDefault(result.getCity(), ""))).append("</div>")
|
||||
.append("</div></td>")
|
||||
.append("</tr></tbody></table>")
|
||||
.append("</td></tr>")
|
||||
.append("<tr><td class='alt1'><div>")
|
||||
.append(LegacyMessageFormatter.convertMessageToHtml(valueOrDefault(result.getText(), ""), null, null, null))
|
||||
.append("</div></td></tr>")
|
||||
.append("</tbody></table>\n");
|
||||
}
|
||||
}
|
||||
|
||||
String body = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
|
||||
+ "<html xmlns='http://www.w3.org/1999/xhtml' dir='ltr' lang='en'><head>"
|
||||
+ "<title>kAmMa's Forum - Search Results</title>"
|
||||
+ "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>"
|
||||
+ "<meta http-equiv='Expires' content='0'/>"
|
||||
+ "<link rel='stylesheet' type='text/css' href='./css/all.css'/>"
|
||||
+ "<script type='text/javascript' src='/client.js'></script>"
|
||||
+ "</head><body>"
|
||||
+ "<div align='center'>"
|
||||
+ "<div class='page' style='width: 100%; text-align: left'>"
|
||||
+ "<div style='padding: 0px 25px 0px 25px' align='left'><br/>"
|
||||
+ renderCommonHeader(username, "Search Results", true, pmStats)
|
||||
+ "<br/>"
|
||||
+ messageRows
|
||||
+ "<br/>"
|
||||
+ renderCommonFooter(Math.max(0, loggedUsersCount), loggedUsers)
|
||||
+ "</div></div></div><br/>"
|
||||
+ "</body></html>";
|
||||
return body;
|
||||
}
|
||||
|
||||
public static String mysqlClientPage(
|
||||
String username,
|
||||
List<String> databases,
|
||||
@ -908,7 +969,7 @@ public final class Pages {
|
||||
.replace("'", "'");
|
||||
}
|
||||
|
||||
private static String readTemplate(String path) {
|
||||
private static String readTemplate(String path) {
|
||||
try (InputStream in = Pages.class.getClassLoader().getResourceAsStream(path)) {
|
||||
if (in == null) {
|
||||
throw new IllegalStateException("Template not found: " + path);
|
||||
@ -918,4 +979,13 @@ public final class Pages {
|
||||
throw new IllegalStateException("Failed to read template: " + path, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatTimestamp(java.sql.Timestamp ts) {
|
||||
if (ts == null) {
|
||||
return "N/A";
|
||||
}
|
||||
java.time.ZoneId zone = java.time.ZoneId.of("Europe/Prague");
|
||||
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
|
||||
return ts.toLocalDateTime().atZone(zone).format(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<table class='tborder' cellpadding='3' cellspacing='1' border='0'>
|
||||
<tbody><tr>
|
||||
<td class='vbmenu_control' style='font-weight:normal'>
|
||||
<form action='#' method='post'>
|
||||
<form action='/search' method='get'>
|
||||
Search in threads:
|
||||
<input type='text' class='bginput' style='font-size:11px' name='stext' tabindex='1'/>
|
||||
</form>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user