fix #1749 update search log pages

This commit is contained in:
Shinsuke Sugaya 2018-07-12 11:18:00 +09:00
parent 0c4231a3ce
commit 0c0b80732a
10 changed files with 180 additions and 89 deletions

View file

@ -48,7 +48,7 @@ public class SearchLogPager implements Serializable {
private int currentPageNumber;
public String logType;
public String logType = LOG_TYPE_SEARCH;
public String id;

View file

@ -15,17 +15,27 @@
*/
package org.codelibs.fess.app.service;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.SearchLogPager;
import org.codelibs.fess.es.log.exbhv.ClickLogBhv;
import org.codelibs.fess.es.log.exbhv.FavoriteLogBhv;
import org.codelibs.fess.es.log.exbhv.SearchLogBhv;
import org.codelibs.fess.es.log.exentity.ClickLog;
import org.codelibs.fess.es.log.exentity.FavoriteLog;
import org.codelibs.fess.es.log.exentity.SearchLog;
import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.taglib.FessFunctions;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
public class SearchLogService {
@ -77,4 +87,86 @@ public class SearchLogService {
return list;
}
public OptionalEntity<?> getSearchLog(final String logType, final String id) {
if (SearchLogPager.LOG_TYPE_CLICK.equalsIgnoreCase(logType)) {
return clickLogBhv.selectByPK(id);
} else if (SearchLogPager.LOG_TYPE_FAVORITE.equalsIgnoreCase(logType)) {
return favoriteLogBhv.selectByPK(id);
} else {
return searchLogBhv.selectByPK(id);
}
}
public Map<String, String> getSearchLogMap(final String logType, final String id) {
if (SearchLogPager.LOG_TYPE_CLICK.equalsIgnoreCase(logType)) {
return clickLogBhv.selectByPK(id).map(e -> {
Map<String, String> params = new LinkedHashMap<>();
params.put("ID", e.getId());
params.put("Query ID", e.getQueryId());
params.put("Doc ID", e.getDocId());
params.put("User Session ID", e.getUserSessionId());
params.put("URL", e.getUrl());
params.put("URL ID", e.getUrlId());
params.put("Order", toNumberString(e.getOrder()));
params.put("Query Requested Time", FessFunctions.formatDate(e.getQueryRequestedAt()));
params.put("Requested Time", FessFunctions.formatDate(e.getRequestedAt()));
return params;
}).get();
} else if (SearchLogPager.LOG_TYPE_FAVORITE.equalsIgnoreCase(logType)) {
return favoriteLogBhv.selectByPK(id).map(e -> {
Map<String, String> params = new LinkedHashMap<>();
params.put("ID", e.getId());
params.put("Query ID", e.getQueryId());
params.put("Doc ID", e.getDocId());
params.put("User Info ID", e.getUserInfoId());
params.put("URL", e.getUrl());
params.put("Created Time", FessFunctions.formatDate(e.getCreatedAt()));
params.put("Requested Time", FessFunctions.formatDate(e.getRequestedAt()));
return params;
}).get();
} else {
return searchLogBhv.selectByPK(id).map(e -> {
Map<String, String> params = new LinkedHashMap<>();
params.put("ID", e.getId());
params.put("Query ID", e.getQueryId());
params.put("User Info ID", e.getUserInfoId());
params.put("User Session ID", e.getUserSessionId());
params.put("Access Type", e.getAccessType());
params.put("Search Word", e.getSearchWord());
params.put("Requested Time", FessFunctions.formatDate(e.getRequestedAt()));
params.put("Query Time", toNumberString(e.getQueryTime()));
params.put("Response Time", toNumberString(e.getResponseTime()));
params.put("Hit Count", toNumberString(e.getHitCount()));
params.put("Offset", toNumberString(e.getQueryOffset()));
params.put("Page Size", toNumberString(e.getQueryPageSize()));
params.put("Client IP", e.getClientIp());
params.put("Referer", e.getReferer());
params.put("Languages", e.getLanguages());
params.put("Virtual Host", e.getVirtualHost());
params.put("Roles", e.getRoles() != null ? String.join(" ", e.getRoles()) : StringUtil.EMPTY);
params.put("User Agent", e.getUserAgent());
e.getSearchFieldLogList().stream().forEach(p -> {
params.put(p.getFirst(), p.getSecond());
});
return params;
}).get();
}
}
private String toNumberString(Number value) {
return value != null ? value.toString() : StringUtil.EMPTY;
}
public void deleteSearchLog(Object e) {
if (e instanceof ClickLog) {
clickLogBhv.delete((ClickLog) e);
} else if (e instanceof FavoriteLog) {
favoriteLogBhv.delete((FavoriteLog) e);
} else if (e instanceof SearchLog) {
searchLogBhv.delete((SearchLog) e);
} else {
throw new FessSystemException("Unknown log entity: " + e);
}
}
}

View file

@ -20,22 +20,19 @@ import javax.annotation.Resource;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.SearchLogPager;
import org.codelibs.fess.app.service.SearchLogService;
import org.codelibs.fess.app.web.CrudMode;
import org.codelibs.fess.app.web.base.FessAdminAction;
import org.codelibs.fess.util.RenderDataUtil;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
import org.lastaflute.web.response.render.RenderData;
import org.lastaflute.web.ruts.process.ActionRuntime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author shinsuke
*/
public class AdminSearchlogAction extends FessAdminAction {
private static final Logger logger = LoggerFactory.getLogger(AdminSearchlogAction.class);
// ===================================================================================
// Attribute
// =========
@ -111,35 +108,41 @@ public class AdminSearchlogAction extends FessAdminAction {
// -----------------------------------------------------
// Details
// -------
// @Execute
// public HtmlResponse details(final int crudMode, final String id) {
// verifyCrudMode(crudMode, CrudMode.DETAILS);
// saveToken();
// return statsService.getCrawlingInfo(id).map(entity -> {
// return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoDetailsJsp).useForm(EditForm.class, op -> {
// op.setup(form -> {
// copyBeanToBean(entity, form, copyOp -> {
// copyOp.excludeNull();
// });
// form.crudMode = crudMode;
// });
// }).renderWith(data -> {
// RenderDataUtil.register(data, "crawlingInfoParamItems", statsService.getCrawlingInfoParamList(id));
// });
// }).orElseGet(() -> {
// throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), () -> asListHtml());
// return null;
// });
// }
@Execute
public HtmlResponse details(final int crudMode, final String logType, final String id) {
verifyCrudMode(crudMode, CrudMode.DETAILS);
saveToken();
return asDetailsHtml().useForm(EditForm.class, op -> {
op.setup(form -> {
form.id = id;
form.logType = logType;
form.crudMode = crudMode;
});
}).renderWith(data -> {
RenderDataUtil.register(data, "logParamItems", searchLogService.getSearchLogMap(logType, id));
});
}
// -----------------------------------------------------
// Actually Crud
// -------------
@Execute
public HtmlResponse delete(final EditForm form) {
verifyCrudMode(form.crudMode, CrudMode.DETAILS);
validate(form, messages -> {}, () -> asDetailsHtml());
verifyToken(() -> asDetailsHtml());
searchLogService.getSearchLog(form.logType, form.id).alwaysPresent(e -> {
searchLogService.deleteSearchLog(e);
saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
});
return redirect(getClass());
}
@Execute
public HtmlResponse deleteall() {
verifyToken(() -> asListHtml());
verifyToken(this::asListHtml);
searchLogPager.clear();
// TODO delete logs
saveInfo(messages -> messages.addSuccessCrawlingInfoDeleteAll(GLOBAL));
return redirect(getClass());
}
@ -155,7 +158,7 @@ public class AdminSearchlogAction extends FessAdminAction {
if (crudMode != expectedMode) {
throwValidationError(messages -> {
messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
}, () -> asListHtml());
}, this::asListHtml);
}
}
@ -168,12 +171,12 @@ public class AdminSearchlogAction extends FessAdminAction {
RenderDataUtil.register(data, "searchLogItems", searchLogService.getSearchLogList(searchLogPager)); // page navi
}).useForm(SearchForm.class, setup -> {
setup.setup(form -> {
copyBeanToBean(searchLogPager, form, op -> op.include("id"));
copyBeanToBean(searchLogPager, form, op -> op.include("logType"));
});
});
}
private HtmlResponse asDetailsHtml() {
return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoDetailsJsp);
return asHtml(path_AdminSearchlog_AdminSearchlogDetailsJsp);
}
}

View file

@ -22,7 +22,6 @@ import org.lastaflute.web.validation.theme.conversion.ValidateTypeFailure;
/**
* @author shinsuke
* @author Shunji Makino
*/
public class EditForm {
@ -37,25 +36,8 @@ public class EditForm {
@Size(max = 1000)
public String id;
@Required
@Size(max = 20)
public String sessionId;
@Size(max = 20)
public String name;
public String expiredTime;
@ValidateTypeFailure
public Long createdTime;
public void initialize() {
id = null;
sessionId = null;
name = null;
expiredTime = null;
createdTime = null;
logType = null;
}
}

View file

@ -2784,6 +2784,21 @@ public class FessLabels extends UserMessages {
/** The key of the message: Time */
public static final String LABELS_searchlog_requested_time = "{labels.searchlog_requested_time}";
/** The key of the message: Log Details */
public static final String LABELS_searchlog_configuration_details = "{labels.searchlog_configuration_details}";
/** The key of the message: Search Log */
public static final String LABELS_searchlog_configuration_link_top = "{labels.searchlog_configuration_link_top}";
/** The key of the message: Details */
public static final String LABELS_searchlog_configuration_link_details = "{labels.searchlog_configuration_link_details}";
/** The key of the message: Back */
public static final String LABELS_searchlog_configuration_button_back = "{labels.searchlog_configuration_button_back}";
/** The key of the message: Delete */
public static final String LABELS_searchlog_configuration_button_delete = "{labels.searchlog_configuration_button_delete}";
/**
* Assert the property is not null.
* @param property The value of the property. (NotNull)

View file

@ -130,12 +130,18 @@ public class FessFunctions {
}
public static String formatDate(final Date date) {
if (date == null) {
return StringUtil.EMPTY;
}
final SimpleDateFormat sdf = new SimpleDateFormat(Constants.ISO_DATETIME_FORMAT);
sdf.setTimeZone(Constants.TIMEZONE_UTC);
return sdf.format(date);
}
public static String formatDate(final LocalDateTime date) {
if (date == null) {
return StringUtil.EMPTY;
}
return date.format(DateTimeFormatter.ofPattern(Constants.ISO_DATETIME_FORMAT, Locale.ROOT));
}

View file

@ -918,3 +918,9 @@ labels.searchlog_log_type_click=Click Log
labels.searchlog_log_type_favorite=Favorite Log
labels.searchlog_log_message=Message
labels.searchlog_requested_time=Time
labels.searchlog_configuration_details=Log Details
labels.searchlog_configuration_link_top=Search Log
labels.searchlog_configuration_link_details=Details
labels.searchlog_configuration_button_back=Back
labels.searchlog_configuration_button_delete=Delete

View file

@ -918,3 +918,9 @@ labels.searchlog_log_type_click=Click Log
labels.searchlog_log_type_favorite=Favorite Log
labels.searchlog_log_message=Message
labels.searchlog_requested_time=Time
labels.searchlog_configuration_details=Log Details
labels.searchlog_configuration_link_top=Search Log
labels.searchlog_configuration_link_details=Details
labels.searchlog_configuration_button_back=Back
labels.searchlog_configuration_button_delete=Delete

View file

@ -920,3 +920,8 @@ labels.searchlog_log_type_click=クリックログ
labels.searchlog_log_type_favorite=お気に入りログ
labels.searchlog_log_message=メッセージ
labels.searchlog_requested_time=時刻
labels.searchlog_configuration_details=ログ詳細
labels.searchlog_configuration_link_top=検索ログ
labels.searchlog_configuration_link_details=詳細
labels.searchlog_configuration_button_back=戻る
labels.searchlog_configuration_button_delete=削除

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<title><la:message key="labels.admin_brand_title" /> | <la:message
key="labels.crawling_info_configuration" /></title>
key="labels.searchlog_configuration" /></title>
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
</head>
<body class="hold-transition skin-blue sidebar-mini">
@ -11,27 +11,28 @@
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
<jsp:param name="menuCategoryType" value="log" />
<jsp:param name="menuType" value="crawlingInfo" />
<jsp:param name="menuType" value="searchLog" />
</jsp:include>
<div class="content-wrapper">
<section class="content-header">
<h1>
<la:message key="labels.crawling_info_title_confirm" />
<la:message key="labels.searchlog_configuration_details" />
</h1>
<ol class="breadcrumb">
<li><la:link href="/admin/crawlinginfo">
<la:message key="labels.crawling_info_link_top" />
<li><la:link href="/admin/searchlog">
<la:message key="labels.searchlog_configuration_link_top" />
</la:link></li>
<c:if test="${crudMode == 4}">
<li class="active"><la:message
key="labels.crawling_info_link_details" /></li>
key="labels.searchlog_configuration_link_details" /></li>
</c:if>
</ol>
</section>
<section class="content">
<la:form action="/admin/crawlinginfo/">
<la:form action="/admin/searchlog/">
<la:hidden property="crudMode" />
<c:if test="${crudMode==4}">
<la:hidden property="logType" />
<la:hidden property="id" />
</c:if>
<div class="row">
@ -40,23 +41,12 @@
class="box <c:if test="${crudMode == 1}">box-success</c:if><c:if test="${crudMode == 2}">box-warning</c:if><c:if test="${crudMode == 3}">box-danger</c:if><c:if test="${crudMode == 4}">box-primary</c:if>">
<div class="box-header with-border">
<h3 class="box-title">
<c:if test="${crudMode == 1}">
<la:message key="labels.crawling_info_link_create" />
</c:if>
<c:if test="${crudMode == 2}">
<la:message key="labels.crawling_info_link_update" />
</c:if>
<c:if test="${crudMode == 3}">
<la:message key="labels.crawling_info_link_delete" />
</c:if>
<c:if test="${crudMode == 4}">
<la:message key="labels.crawling_info_link_details" />
</c:if>
<la:message key="labels.searchlog_configuration_link_details" />
</h3>
<div class="btn-group pull-right">
<la:link href="/admin/crawlinginfo"
<la:link href="/admin/searchlog"
styleClass="btn btn-primary btn-xs">
<la:message key="labels.crawling_info_link_top" />
<la:message key="labels.searchlog_configuration_link_top" />
</la:link>
</div>
</div>
@ -72,16 +62,9 @@
<%-- Form Fields --%>
<table class="table table-bordered">
<tbody>
<tr>
<th><la:message
key="labels.crawling_info_session_id" /></th>
<td><a
href="${fe:url('/admin/searchlist/search')}?q=segment:${f:u(sessionId)}">${f:h(sessionId)}</a>
<la:hidden property="sessionId" /></td>
</tr>
<c:forEach var="info" items="${crawlingInfoParamItems}">
<c:forEach var="info" items="${logParamItems}">
<tr>
<th>${f:h(info.keyMsg)}</th>
<th>${f:h(info.key)}</th>
<td>${f:h(info.value)}</td>
</tr>
</c:forEach>
@ -92,15 +75,15 @@
<div class="box-footer">
<c:if test="${crudMode == 4}">
<button type="submit" class="btn btn-default" name="back"
value="<la:message key="labels.crawling_info_button_back" />">
value="<la:message key="labels.searchlog_configuration_button_back" />">
<i class="fa fa-arrow-circle-left"></i>
<la:message key="labels.crawling_info_button_back" />
<la:message key="labels.searchlog_configuration_button_back" />
</button>
<button type="button" class="btn btn-danger" name="delete"
data-toggle="modal" data-target="#confirmToDelete"
value="<la:message key="labels.crawling_info_button_delete" />">
value="<la:message key="labels.searchlog_configuration_button_delete" />">
<i class="fa fa-trash"></i>
<la:message key="labels.crawling_info_button_delete" />
<la:message key="labels.searchlog_configuration_button_delete" />
</button>
<div class="modal modal-danger fade" id="confirmToDelete"
tabindex="-1" role="dialog">
@ -135,13 +118,6 @@
</div>
</div>
</div>
<c:if test="${running}">
<button type="submit" class="btn btn-warning" name="threaddump"
value="<la:message key="labels.crawling_info_thread_dump" />">
<i class="fa fa-bolt"></i>
<la:message key="labels.crawling_info_thread_dump" />
</button>
</c:if>
</c:if>
</div>
<!-- /.box-footer -->