fix search by admin

This commit is contained in:
Kaoru FUZITA 2015-11-02 14:14:53 +09:00
parent a1482a9869
commit 810ede5bc3
6 changed files with 391 additions and 128 deletions

View file

@ -15,32 +15,32 @@
*/
package org.codelibs.fess.app.web.admin.searchlist;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.service.SearchService;
import org.codelibs.fess.app.web.base.FessAdminAction;
import org.codelibs.fess.entity.SearchRenderData;
import org.codelibs.fess.es.client.FessEsClient;
import org.codelibs.fess.es.client.FessEsClient.SearchConditionBuilder;
import org.codelibs.fess.exception.InvalidQueryException;
import org.codelibs.fess.exception.ResultOffsetExceededException;
import org.codelibs.fess.helper.FieldHelper;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.util.QueryResponseList;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.lastaflute.web.Execute;
import org.lastaflute.web.callback.ActionRuntime;
import org.lastaflute.web.response.HtmlResponse;
import org.lastaflute.web.response.render.RenderData;
import org.lastaflute.web.token.TxToken;
import org.lastaflute.web.util.LaRequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author codelibs
@ -49,21 +49,35 @@ import org.lastaflute.web.util.LaRequestUtil;
public class AdminSearchlistAction extends FessAdminAction {
// ===================================================================================
// Attribute
// =========
// Constant
//
private static final Logger logger = LoggerFactory
.getLogger(AdminSearchlistAction.class);
// ===================================================================================
// Attribute
// =========
@Resource
private SystemHelper systemHelper;
@Resource
protected FessEsClient fessEsClient;
@Resource
protected FieldHelper fieldHelper;
@Resource
protected QueryHelper queryHelper;
@Resource
protected JobHelper jobHelper;
@Resource
protected SearchService searchService;
@Resource
protected HttpServletRequest request;
public List<Map<String, Object>> documentItems;
public String pageSize;
@ -87,18 +101,19 @@ public class AdminSearchlistAction extends FessAdminAction {
public String execTime;
// ===================================================================================
// Hook
// ======
// Hook
// ======
@Override
protected void setupHtmlData(final ActionRuntime runtime) {
super.setupHtmlData(runtime);
runtime.registerData("helpLink", systemHelper.getHelpLink("searchList"));
runtime.registerData("helpLink",
systemHelper.getHelpLink("searchList"));
}
// ===================================================================================
// Search Execute
// ==============
// Search Execute
// ==============
@Execute
public HtmlResponse index(final SearchListForm form) {
return asHtml(path_AdminSearchlist_IndexJsp);
@ -116,7 +131,8 @@ public class AdminSearchlistAction extends FessAdminAction {
});
}
private void doSearchInternal(final RenderData data, final SearchListForm form) {
private void doSearchInternal(final RenderData data,
final SearchListForm form) {
// init pager
if (StringUtil.isBlank(form.start)) {
form.start = String.valueOf(Constants.DEFAULT_START_COUNT);
@ -141,48 +157,41 @@ public class AdminSearchlistAction extends FessAdminAction {
}
}
final int offset = Integer.parseInt(form.start);
final int size = Integer.parseInt(form.num);
try {
documentItems =
fessEsClient.getDocumentList(fieldHelper.docIndex, fieldHelper.docType, searchRequestBuilder -> {
return SearchConditionBuilder.builder(searchRequestBuilder).administrativeAccess().offset(offset).size(size)
.responseFields(queryHelper.getResponseFields()).build();
});
final WebRenderData renderData = new WebRenderData(data);
searchService.search(request, form, renderData);
} catch (final InvalidQueryException e) {
// TODO Log
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throwValidationError(e.getMessageCode(),
() -> asHtml(path_ErrorJsp));
} catch (final ResultOffsetExceededException e) {
// TODO Log
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throwValidationError(messages -> {
messages.addErrorsResultSizeExceeded(GLOBAL);
} , () -> asHtml(path_ErrorJsp));
}
final QueryResponseList queryResponseList = (QueryResponseList) documentItems;
final NumberFormat nf = NumberFormat.getInstance(LaRequestUtil.getRequest().getLocale());
nf.setMaximumIntegerDigits(2);
nf.setMaximumFractionDigits(2);
try {
nf.format((double) queryResponseList.getExecTime() / 1000);
} catch (final Exception e) {}
copyBeanToBean(documentItems, this, option -> option.include("pageSize", "currentPageNumber", "allRecordCount", "allPageCount",
"existNextPage", "existPrevPage", "currentStartRecordNumber", "currentEndRecordNumber", "pageNumberList"));
}
//@Execute(validator = false)
@Execute
public HtmlResponse search(final SearchListForm form) {
return doSearch(form);
}
//@Execute(validator = false)
@Execute
public HtmlResponse prev(final SearchListForm form) {
return doMove(form, -1);
}
//@Execute(validator = false)
@Execute
public HtmlResponse next(final SearchListForm form) {
return doMove(form, 1);
}
//@Execute(validator = false)
@Execute
public HtmlResponse move(final SearchListForm form) {
return doMove(form, 0);
}
@ -218,15 +227,14 @@ public class AdminSearchlistAction extends FessAdminAction {
}
// -----------------------------------------------------
// Confirm
// -------
// Confirm
// -------
@Execute
public HtmlResponse confirmDelete(final SearchListForm form) {
return asHtml(path_AdminSearchlist_ConfirmDeleteJsp);
}
@Execute(token = TxToken.VALIDATE)
//@Execute(validator = true, input = "index")
@Execute
public HtmlResponse delete(final SearchListForm form) {
return deleteByQuery(form);
}
@ -240,20 +248,117 @@ public class AdminSearchlistAction extends FessAdminAction {
if (!jobHelper.isCrawlProcessRunning()) {
System.currentTimeMillis();
try {
final QueryBuilder query = QueryBuilders.termQuery(fieldHelper.docIdField, docId);
fessEsClient.deleteByQuery(fieldHelper.docIndex, fieldHelper.docType, query);
final QueryBuilder query = QueryBuilders
.termQuery(fieldHelper.docIdField, docId);
fessEsClient.deleteByQuery(fieldHelper.docIndex,
fieldHelper.docType, query);
} catch (final Exception e) {
// TODO Log
}
}
}
} );
});
thread.start();
saveInfo(messages -> messages.addSuccessDeleteSolrIndex(GLOBAL));
return redirectWith(getClass(), moreUrl("search").params("query", form.query));
return redirectWith(getClass(),
moreUrl("search").params("query", form.query));
}
public boolean isSolrProcessRunning() {
return jobHelper.isCrawlProcessRunning();
}
protected static class WebRenderData extends SearchRenderData {
private final RenderData data;
WebRenderData(final RenderData data) {
this.data = data;
}
@Override
public void setDocumentItems(
final List<Map<String, Object>> documentItems) {
data.register("documentItems", documentItems);
super.setDocumentItems(documentItems);
}
@Override
public void setExecTime(final String execTime) {
data.register("execTime", execTime);
super.setExecTime(execTime);
}
@Override
public void setPageSize(final int pageSize) {
data.register("pageSize", pageSize);
super.setPageSize(pageSize);
}
@Override
public void setCurrentPageNumber(final int currentPageNumber) {
data.register("currentPageNumber", currentPageNumber);
super.setCurrentPageNumber(currentPageNumber);
}
@Override
public void setAllRecordCount(final long allRecordCount) {
data.register("allRecordCount", allRecordCount);
super.setAllRecordCount(allRecordCount);
}
@Override
public void setAllPageCount(final int allPageCount) {
data.register("allPageCount", allPageCount);
super.setAllPageCount(allPageCount);
}
@Override
public void setExistNextPage(final boolean existNextPage) {
data.register("existNextPage", existNextPage);
super.setExistNextPage(existNextPage);
}
@Override
public void setExistPrevPage(final boolean existPrevPage) {
data.register("existPrevPage", existPrevPage);
super.setExistPrevPage(existPrevPage);
}
@Override
public void setCurrentStartRecordNumber(
final long currentStartRecordNumber) {
data.register("currentStartRecordNumber", currentStartRecordNumber);
super.setCurrentStartRecordNumber(currentStartRecordNumber);
}
@Override
public void setCurrentEndRecordNumber(
final long currentEndRecordNumber) {
data.register("currentEndRecordNumber", currentEndRecordNumber);
super.setCurrentEndRecordNumber(currentEndRecordNumber);
}
@Override
public void setPageNumberList(final List<String> pageNumberList) {
data.register("pageNumberList", pageNumberList);
super.setPageNumberList(pageNumberList);
}
@Override
public void setPartialResults(final boolean partialResults) {
data.register("partialResults", partialResults);
super.setPartialResults(partialResults);
}
@Override
public void setQueryTime(final long queryTime) {
data.register("queryTime", queryTime);
super.setQueryTime(queryTime);
}
@Override
public void setSearchQuery(final String searchQuery) {
data.register("searchQuery", searchQuery);
super.setSearchQuery(searchQuery);
}
}
}

View file

@ -16,18 +16,30 @@
package org.codelibs.fess.app.web.admin.searchlist;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.SearchRequestParams;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.util.ComponentUtil;
/**
* @author codelibs
* @author Keiichi Watanabe
*/
public class SearchListForm implements Serializable {
//public class SearchListForm implements Serializable {
public class SearchListForm implements SearchRequestParams, Serializable {
private static final long serialVersionUID = 1L;
//@Maxbytelength(maxbytelength = 1000)
public String query;
public String sort;
//@Digits(integer=10, fraction=0)
public String start;
@ -37,9 +49,114 @@ public class SearchListForm implements Serializable {
//@Digits(integer=10, fraction=0)
public String num;
public String[] lang;
//@Required(target = "confirmDelete,delete")
public String docId;
//@Required(target = "confirmDelete")
public String url;
@Override
public String getQuery() {
return query;
}
public Map<String, String[]> fields = new HashMap<>();
public String additional[];
//@Maxbytelength(maxbytelength = 10)
public String op;
@Override
public String getOperator() {
return op;
}
@Override
public String[] getAdditional() {
return additional;
}
@Override
public Map<String, String[]> getFields() {
return fields;
}
// geo
public GeoInfo geo;
// facet
public FacetInfo facet;
private int startPosition = -1;
private int pageSize = -1;
@Override
public int getStartPosition() {
if (startPosition != -1) {
return startPosition;
}
final QueryHelper queryHelper = ComponentUtil.getQueryHelper();
if (StringUtil.isBlank(start)) {
startPosition = queryHelper.getDefaultStart();
} else {
try {
startPosition = Integer.parseInt(start);
} catch (final NumberFormatException e) {
startPosition = queryHelper.getDefaultStart();
}
}
start = String.valueOf(startPosition);
return startPosition;
}
@Override
public int getPageSize() {
if (pageSize != -1) {
return pageSize;
}
final QueryHelper queryHelper = ComponentUtil.getQueryHelper();
if (StringUtil.isBlank(num)) {
pageSize = queryHelper.getDefaultPageSize();
} else {
try {
pageSize = Integer.parseInt(num);
if (pageSize > queryHelper.getMaxPageSize() || pageSize <= 0) {
pageSize = queryHelper.getMaxPageSize();
}
} catch (final NumberFormatException e) {
pageSize = queryHelper.getDefaultPageSize();
}
}
num = String.valueOf(pageSize);
return pageSize;
}
@Override
public String[] getLanguages() {
return lang;
}
@Override
public GeoInfo getGeoInfo() {
return geo;
}
@Override
public FacetInfo getFacetInfo() {
return facet;
}
@Override
public String getSort() {
return sort;
}
}

View file

@ -526,7 +526,7 @@ labels.crawling_session_name=Name
labels.crawling_session_created_time=Created
labels.crawling_session_expired_time=Expired
labels.crawling_session_delete_all_link=Delete All
labels.crawling_session_delete_all_confirmation=Do you want to delete all?
labels.crawling_session_delete_all_confirmation=Do you really want to delete all?
labels.crawling_session_delete_all_cancel=Cancel
labels.crawling_session_CrawlerStatus=Crawling Status
labels.crawling_session_CrawlerStartTime=Start Time (Crawling)
@ -734,7 +734,7 @@ labels.design_file_errorNotFound=Error Page (Not Found)
labels.design_file_errorSystem=Error Page (System Error)
labels.design_file_errorRedirect=Error Page (Redirect)
labels.design_file_errorBadRequest=Error Page (BadRequest)
labels.design_delete_confirmation=Do you want to delete it?
labels.design_delete_confirmation=Do you really want to delete it?
labels.design_title_edit_content=Edit Page View File
labels.design_button_update=Update
labels.design_button_back=Back
@ -808,6 +808,8 @@ labels.search_list_index_page=Type a search query.
labels.search_list_title_confirm_delete=Delete Confirmation
labels.search_list_url=URL
labels.search_list_delete_link=Delete
labels.search_list_delete_cancel=Cancel
labels.search_list_delete_confirmation=Do you really want to delete? ({0})
labels.search_log_configuration=Search Log
labels.search_log_search_word_search=Search Word
labels.search_log_user_code_search=User ID
@ -822,7 +824,7 @@ labels.search_log_client_ip=IP
labels.search_log_link_details=Details
labels.search_log_link_delete=Delete
labels.search_log_delete_all_link=Delete All
labels.search_log_delete_all_confirmation=Do you want to delete all?
labels.search_log_delete_all_confirmation=Do you really want to delete all?
labels.search_log_sort_up=(Up)
labels.search_log_sort_down=(Down)
labels.search_log_download_csv=Download(CSV)
@ -852,7 +854,7 @@ labels.failure_url_url=URL
labels.failure_url_last_access_time=Last Access
labels.failure_url_link_confirm=Confirm
labels.failure_url_delete_all_link=Delete All
labels.failure_url_delete_all_confirmation=Do you want to delete all?
labels.failure_url_delete_all_confirmation=Do you really want to delete all?
labels.failure_url_delete_all_cancel=Cancel
labels.failure_url_error_count=Error Count
labels.failure_url_title_confirm=Failure URL Details
@ -932,7 +934,7 @@ labels.user_info_edit_code=User ID
labels.user_info_edit_createddate=Created
labels.user_info_edit_lastupdated=Last Accessed
labels.user_info_delete_all_link=Delete All
labels.user_info_delete_all_confirmation=Do you want to delete all?
labels.user_info_delete_all_confirmation=Do you really want to delete all?
labels.favorite_log_title=Popular URL
labels.favorite_log_configuration=Popular URL
labels.favorite_log_user_code_search=User ID
@ -943,7 +945,7 @@ labels.favorite_log_created_time=Submitted
labels.favorite_log_link_details=Details
labels.favorite_log_link_delete=Delete
labels.favorite_log_delete_all_link=Delete All
labels.favorite_log_delete_all_confirmation=Do you want to delete it?
labels.favorite_log_delete_all_confirmation=Do you really want to delete it?
labels.favorite_log_download_csv=Download (CSV)
labels.favorite_log_search_term=Term
labels.favorite_log_title_confirm=Details
@ -1011,7 +1013,7 @@ labels.joblog_title_confirm=Confirm Job Log
labels.joblog_title_details=Job Log Details
labels.joblog_title_list=Job Log List
labels.joblog_delete_all_link=Delete All
labels.joblog_delete_all_confirmation=Do you want to delete all?
labels.joblog_delete_all_confirmation=Do you really want to delete all?
labels.dict_configuration=Dictionary List
labels.dict_list_title=Dictionary List
labels.dict_list_link=Dictionaries

View file

@ -29,29 +29,14 @@
</section>
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="col-xs-12">
<div class="box box-primary">
<%-- Box Header --%>
<div class="box-header with-border">
<h3 class="box-title">
<la:message key="labels.search_list_configuration" />
</h3>
<la:form styleClass="form-inline">
<div class="form-group">
<label class="sr-only" for="sessionIdSearchBtn"></label>
<la:text styleClass="query form-control" property="query" title="Search"
size="50" maxlength="1000"
placeholder="Type a search query" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" name="search"
value="<la:message key="labels.search"/>">
<la:message key="labels.search" />
</button>
</div>
</la:form>
</div>
<%-- Box Body --%>
<div class="box-body">
@ -62,22 +47,27 @@
</la:info>
<la:errors />
</div>
<la:form action="search" styleClass="form-inline">
<div class="form-group">
<label class="sr-only" for="sessionIdSearchBtn"></label>
<la:text styleClass="query form-control" property="query"
title="Search" size="50" maxlength="1000"
placeholder="Type a search query" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" name="search"
value="<la:message key="labels.search"/>">
<la:message key="labels.search" />
</button>
</div>
</la:form>
<%-- List --%>
<c:choose>
<c:when test="${allRecordCount == null}">
<div id="subheader"></div>
<div id="result">
<%--
<p>
<la:message key="labels.search_list_index_page" />
</p>
--%>
</div>
</c:when>
<c:when test="${f:h(allRecordCount) != 0}">
<div id="subheader">
<p>
<c:when test="${f:h(allRecordCount) > 0}">
<div id="subheader" class="row top10">
<div class="col-xs-12">
<la:message key="labels.search_result_status"
arg0="${f:h(query)}" arg1="${f:h(allRecordCount)}"
arg2="${f:h(currentStartRecordNumber)}"
@ -86,40 +76,78 @@
<la:message key="labels.search_result_time"
arg0="${f:h(execTime)}" />
</c:if>
</p>
</div>
<div id="result">
<div>
<ol>
<c:forEach var="doc" varStatus="s" items="${documentItems}">
<li>
<h3 class="title">
<a href="${doc.urlLink}">${f:h(doc.contentTitle)}</a>
</h3>
<div class="body">
${doc.contentDescription}
<div style="text-align: right;">
<c:if test="${!crawlerProcessRunning}">
<la:link
href="confirmDelete?query=${f:u(query)}&docId=${f:u(doc.docId)}&url=${f:u(doc.url)}">
<la:message key="labels.search_list_delete_link" />
</la:link>
</c:if>
<c:if test="${crawlerProcessRunning}">
<la:message key="labels.search_list_delete_link" />
</c:if>
</div>
</div>
</li>
</c:forEach>
</ol>
</div>
</div>
<div class="row center">
<div class="pagination">
<ul>
<div id="result">
<ol class="row">
<c:forEach var="doc" varStatus="s" items="${documentItems}">
<li class="col-sm-12">
<h3 class="title">
<a href="${doc.urlLink}">${f:h(doc.contentTitle)}</a>
</h3>
<div class="body col-sm-11">
${doc.contentDescription}</div> <c:if
test="${!crawlerProcessRunning}">
<button type="button"
class="btn btn-xs btn-danger col-sm-1"
data-toggle="modal" data-target="#confirmToDelete">
<i class="fa fa-trash"></i>
<la:message key="labels.search_list_delete_link" />
</button>
<div class="modal modal-danger fade" id="confirmToDelete"
tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">
<la:message key="labels.search_list_delete_link" />
</h4>
</div>
<div class="modal-body">
<p>
<la:message
key="labels.search_list_delete_confirmation"
arg0="${f:h(doc.urlLink)}" />
</p>
</div>
<div class="modal-footer">
<button type="button"
class="btn btn-outline pull-left"
data-dismiss="modal">
<la:message key="labels.search_list_delete_cancel" />
</button>
<la:form action="delete">
<%-- TODO: doc_id --%>
<la:hidden property="docId"
value="${f:u(doc.doc_id)}" />
<la:hidden property="query"
value="${f:u(query)}" />
<button type="submit"
class="btn btn-outline btn-danger">
<i class="fa fa-trash"></i>
<la:message key="labels.search_list_delete_link" />
</button>
</la:form>
</div>
</div>
</div>
</div>
</c:if> <c:if test="${crawlerProcessRunning}">
<div class="col-sm-1">
<la:message key="labels.search_list_delete_link" />
</div>
</c:if>
</li>
</c:forEach>
</ol>
</div>
<div class="row">
<div class="col-sm-12 text-center">
<ul class="pagination pagination-sm">
<c:if test="${existPrePage}">
<li class="prev"><la:link
href="prev?query=${f:u(query)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}&labelTypeValue=${f:u(labelTypeValue)}">
@ -153,25 +181,22 @@
</c:if>
</ul>
</div>
<div>
<span> ${currentPageNumber}/${allPageCount}
(${allRecordCount}) </span>
</div>
</div>
</c:when>
<c:otherwise>
<div id="subheader"></div>
<div id="result">
<p>
<la:message key="labels.did_not_match" arg0="${f:h(query)}" />
</p>
<div id="result" class="row top10">
<div class="col-sm-12">
<p class="callout callout-info">
<la:message key="labels.did_not_match" arg0="${f:h(query)}" />
</p>
</div>
</div>
</c:otherwise>
</c:choose>
<%-- Box Footer --%>
<div class="box-footer"></div>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
</section>

View file

@ -6,7 +6,7 @@
<section class="sidebar">
<!-- search form -->
<form action="/admin/searchList/search" method="get"
<form action="<%=request.getContextPath()%>/admin/searchlist/search" method="post"
class="sidebar-form">
<div class="input-group">
<input type="text" name="query" id="query" class="form-control"
@ -20,7 +20,6 @@
</span>
</div>
</form>
<!-- /.search form -->
<!-- Sidebar Menu -->
<ul class="sidebar-menu">

View file

@ -38,11 +38,26 @@
font-size: 13px;
}
button>i {
button>i, a.btn>i {
margin-right: 0.2em;
}
.content-wrapper iframe {
border: 0;
width: 100%;
}
#result ol {
list-style: none !important;
padding-left: 0;
}
#result ol li {
margin-bottom: 0;
}
#result .title {
margin: 1.0em 0 0.5em 0;
font-size: 130%;
font-weight: 600;
}