Browse Source

Add delete all with this query

Kaoru FUZITA 9 years ago
parent
commit
2ff1031e43

+ 2 - 0
src/main/java/org/codelibs/fess/Constants.java

@@ -296,6 +296,8 @@ public class Constants extends CoreLibConstants {
 
 
     public static final String FACET_QUERY_PREFIX = "query:";
     public static final String FACET_QUERY_PREFIX = "query:";
 
 
+    public static final String MATCHES_ALL_QUERY = "*:*";
+
     public static final String FESS_ES_TRANSPORT_ADDRESSES = "fess.es.transport_addresses";
     public static final String FESS_ES_TRANSPORT_ADDRESSES = "fess.es.transport_addresses";
 
 
     public static final String FESS_ES_CLUSTER_NAME = "fess.es.cluster_name";
     public static final String FESS_ES_CLUSTER_NAME = "fess.es.cluster_name";

+ 36 - 0
src/main/java/org/codelibs/fess/app/service/SearchService.java

@@ -36,6 +36,7 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.web.base.login.FessLoginAssist;
 import org.codelibs.fess.app.web.base.login.FessLoginAssist;
+import org.codelibs.fess.entity.QueryContext;
 import org.codelibs.fess.entity.SearchRenderData;
 import org.codelibs.fess.entity.SearchRenderData;
 import org.codelibs.fess.entity.SearchRequestParams;
 import org.codelibs.fess.entity.SearchRequestParams;
 import org.codelibs.fess.es.client.FessEsClient;
 import org.codelibs.fess.es.client.FessEsClient;
@@ -195,6 +196,41 @@ public class SearchService {
         }
         }
     }
     }
 
 
+    public int deleteByQuery(final HttpServletRequest request, final SearchRequestParams params) {
+        if (StringUtil.isNotBlank(params.getOperator())) {
+            request.setAttribute(Constants.DEFAULT_OPERATOR, params.getOperator());
+        }
+
+        final StringBuilder queryBuf = new StringBuilder(255);
+        if (StringUtil.isNotBlank(params.getQuery())) {
+            if (params.getQuery().indexOf(" OR ") >= 0) {
+                queryBuf.append('(').append(params.getQuery()).append(')');
+            } else {
+                queryBuf.append(params.getQuery());
+            }
+        }
+        if (params.getAdditional() != null) {
+            appendAdditionalQuery(params.getAdditional(), additional -> {
+                queryBuf.append(' ').append(additional);
+            });
+        }
+        params.getFields().entrySet().stream().forEach(entry -> {
+            appendQueries(queryBuf, entry.getKey(), entry.getValue());
+        });
+
+        if (params.getLanguages() != null) {
+            appendQueries(queryBuf, fessConfig.getIndexFieldLang(), params.getLanguages());
+        }
+
+        final String query = queryBuf.toString().trim();
+
+        final QueryContext queryContext = queryHelper.build(query, context -> {
+            context.skipRoleQuery();
+        });
+        return fessEsClient.deleteByQuery(fessConfig.getIndexDocumentIndex(), fessConfig.getIndexDocumentType(),
+                queryContext.getQueryBuilder());
+    }
+
     protected void storeSearchLog(final HttpServletRequest request, final LocalDateTime requestedTime, final String queryId,
     protected void storeSearchLog(final HttpServletRequest request, final LocalDateTime requestedTime, final String queryId,
             final String query, final int pageStart, final int pageSize, final QueryResponseList queryResponseList) {
             final String query, final int pageStart, final int pageSize, final QueryResponseList queryResponseList) {
 
 

+ 44 - 13
src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java

@@ -22,6 +22,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 
 
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.lang.StringUtil;
+import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.service.SearchService;
 import org.codelibs.fess.app.service.SearchService;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.entity.SearchRenderData;
 import org.codelibs.fess.entity.SearchRenderData;
@@ -109,19 +110,19 @@ public class AdminSearchlistAction extends FessAdminAction {
     // ==============
     // ==============
     @Execute
     @Execute
     public HtmlResponse index(final ListForm form) {
     public HtmlResponse index(final ListForm form) {
+        saveToken();
         validate(form, messages -> {}, () -> asHtml(path_AdminError_AdminErrorJsp));
         validate(form, messages -> {}, () -> asHtml(path_AdminError_AdminErrorJsp));
-        return asHtml(path_AdminSearchlist_AdminSearchlistJsp);
+        return asListHtml();
     }
     }
 
 
     protected HtmlResponse doSearch(final ListForm form) {
     protected HtmlResponse doSearch(final ListForm form) {
-        validate(form, messages -> {}, () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+        validate(form, messages -> {}, () -> asListHtml());
 
 
         if (StringUtil.isBlank(form.query)) {
         if (StringUtil.isBlank(form.query)) {
-            // redirect to index page
-            form.query = null;
-            return redirect(getClass());
+            // query matches on all documents.
+            form.query = Constants.MATCHES_ALL_QUERY;
         }
         }
-        return asHtml(path_AdminSearchlist_AdminSearchlistJsp).renderWith(data -> {
+        return asListHtml().renderWith(data -> {
             doSearchInternal(data, form);
             doSearchInternal(data, form);
         });
         });
     }
     }
@@ -135,7 +136,7 @@ public class AdminSearchlistAction extends FessAdminAction {
             if (logger.isDebugEnabled()) {
             if (logger.isDebugEnabled()) {
                 logger.debug(e.getMessage(), e);
                 logger.debug(e.getMessage(), e);
             }
             }
-            throwValidationError(e.getMessageCode(), () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(e.getMessageCode(), () -> asListHtml());
         } catch (final ResultOffsetExceededException e) {
         } catch (final ResultOffsetExceededException e) {
             if (logger.isDebugEnabled()) {
             if (logger.isDebugEnabled()) {
                 logger.debug(e.getMessage(), e);
                 logger.debug(e.getMessage(), e);
@@ -148,21 +149,25 @@ public class AdminSearchlistAction extends FessAdminAction {
 
 
     @Execute
     @Execute
     public HtmlResponse search(final ListForm form) {
     public HtmlResponse search(final ListForm form) {
+        saveToken();
         return doSearch(form);
         return doSearch(form);
     }
     }
 
 
     @Execute
     @Execute
     public HtmlResponse prev(final ListForm form) {
     public HtmlResponse prev(final ListForm form) {
+        saveToken();
         return doMove(form, -1);
         return doMove(form, -1);
     }
     }
 
 
     @Execute
     @Execute
     public HtmlResponse next(final ListForm form) {
     public HtmlResponse next(final ListForm form) {
+        saveToken();
         return doMove(form, 1);
         return doMove(form, 1);
     }
     }
 
 
     @Execute
     @Execute
     public HtmlResponse move(final ListForm form) {
     public HtmlResponse move(final ListForm form) {
+        saveToken();
         return doMove(form, 0);
         return doMove(form, 0);
     }
     }
 
 
@@ -185,27 +190,53 @@ public class AdminSearchlistAction extends FessAdminAction {
 
 
     @Execute
     @Execute
     public HtmlResponse delete(final DeleteForm form) {
     public HtmlResponse delete(final DeleteForm form) {
-        validate(form, messages -> {}, () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+        verifyToken(() -> asListHtml());
+        validate(form, messages -> {}, () -> asListHtml());
         final String docId = form.docId;
         final String docId = form.docId;
         if (jobHelper.isCrawlProcessRunning()) {
         if (jobHelper.isCrawlProcessRunning()) {
-            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL),
-                    () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml());
         }
         }
         try {
         try {
             final QueryBuilder query = QueryBuilders.termQuery(fessConfig.getIndexFieldDocId(), docId);
             final QueryBuilder query = QueryBuilders.termQuery(fessConfig.getIndexFieldDocId(), docId);
             fessEsClient.deleteByQuery(fessConfig.getIndexDocumentIndex(), fessConfig.getIndexDocumentType(), query);
             fessEsClient.deleteByQuery(fessConfig.getIndexDocumentIndex(), fessConfig.getIndexDocumentType(), query);
             saveInfo(messages -> messages.addSuccessDeleteDocFromIndex(GLOBAL));
             saveInfo(messages -> messages.addSuccessDeleteDocFromIndex(GLOBAL));
         } catch (final Exception e) {
         } catch (final Exception e) {
-            throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL),
-                    () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL), () -> asListHtml());
+        }
+        return asListHtml();
+    }
+
+    @Execute
+    public HtmlResponse deleteall(final ListForm form) {
+        verifyToken(() -> asListHtml());
+        validate(form, messages -> {}, () -> asListHtml());
+        if (jobHelper.isCrawlProcessRunning()) {
+            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml());
+        }
+        try {
+            searchService.deleteByQuery(request, form);
+            saveInfo(messages -> messages.addSuccessDeleteDocFromIndex(GLOBAL));
+        } catch (final InvalidQueryException e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug(e.getMessage(), e);
+            }
+            throwValidationError(e.getMessageCode(), () -> asListHtml());
         }
         }
-        return redirectWith(getClass(), moreUrl("search").params("query", form.query));
+        return asListHtml();
     }
     }
 
 
     public boolean isSolrProcessRunning() {
     public boolean isSolrProcessRunning() {
         return jobHelper.isCrawlProcessRunning();
         return jobHelper.isCrawlProcessRunning();
     }
     }
 
 
+    // ===================================================================================
+    //                                                                              JSP
+    //                                                                           =========
+
+    private HtmlResponse asListHtml() {
+        return asHtml(path_AdminSearchlist_AdminSearchlistJsp);
+    }
+
     protected static class WebRenderData extends SearchRenderData {
     protected static class WebRenderData extends SearchRenderData {
         private final RenderData data;
         private final RenderData data;
 
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/config/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
             if (searchType != null) {
                 builder.setSearchType(searchType);
                 builder.setSearchType(searchType);
             }
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             }
             if (version != null) {
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/config/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
         filterList.forEach(query -> {
             boolQuery.filter(query);
             boolQuery.filter(query);
         });
         });
-        regQ(boolQuery);
         return boolQuery;
         return boolQuery;
     }
     }
 
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/log/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
             if (searchType != null) {
                 builder.setSearchType(searchType);
                 builder.setSearchType(searchType);
             }
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             }
             if (version != null) {
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/log/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
         filterList.forEach(query -> {
             boolQuery.filter(query);
             boolQuery.filter(query);
         });
         });
-        regQ(boolQuery);
         return boolQuery;
         return boolQuery;
     }
     }
 
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/user/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
             if (searchType != null) {
                 builder.setSearchType(searchType);
                 builder.setSearchType(searchType);
             }
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             }
             if (version != null) {
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/user/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
         filterList.forEach(query -> {
             boolQuery.filter(query);
             boolQuery.filter(query);
         });
         });
-        regQ(boolQuery);
         return boolQuery;
         return boolQuery;
     }
     }
 
 

+ 3 - 0
src/main/java/org/codelibs/fess/helper/QueryHelper.java

@@ -40,6 +40,7 @@ import org.apache.lucene.queryparser.ext.ExtendableQueryParser;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.FuzzyQuery;
 import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TermQuery;
@@ -299,6 +300,8 @@ public class QueryHelper implements Serializable {
         } else if (query instanceof BooleanQuery) {
         } else if (query instanceof BooleanQuery) {
             final BooleanQuery booleanQuery = (BooleanQuery) query;
             final BooleanQuery booleanQuery = (BooleanQuery) query;
             return convertBooleanQuery(context, booleanQuery);
             return convertBooleanQuery(context, booleanQuery);
+        } else if (query instanceof MatchAllDocsQuery) {
+            return QueryBuilders.matchAllQuery();
         }
         }
         throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(ActionMessages.GLOBAL_PROPERTY_KEY),
         throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(ActionMessages.GLOBAL_PROPERTY_KEY),
                 "Unknown query: " + query.getClass() + " => " + query);
                 "Unknown query: " + query.getClass() + " => " + query);

+ 11 - 5
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -1488,14 +1488,20 @@ public class FessLabels extends ActionMessages {
     public static final String LABELS_search_list_configuration = "{labels.search_list_configuration}";
     public static final String LABELS_search_list_configuration = "{labels.search_list_configuration}";
 
 
     /** The key of the message: Delete */
     /** The key of the message: Delete */
-    public static final String LABELS_search_list_delete_link = "{labels.search_list_delete_link}";
+    public static final String LABELS_search_list_button_delete = "{labels.search_list_button_delete}";
 
 
-    /** The key of the message: Cancel */
-    public static final String LABELS_search_list_delete_cancel = "{labels.search_list_delete_cancel}";
-
-    /** The key of the message: Do you really want to delete? ({0}) */
+    /** The key of the message: Do you really want to delete? */
     public static final String LABELS_search_list_delete_confirmation = "{labels.search_list_delete_confirmation}";
     public static final String LABELS_search_list_delete_confirmation = "{labels.search_list_delete_confirmation}";
 
 
+    /** The key of the message: Delete all with this query */
+    public static final String LABELS_search_list_button_delete_all = "{labels.search_list_button_delete_all}";
+
+    /** The key of the message: Do you really want to delete all with this query? */
+    public static final String LABELS_search_list_delete_all_confirmation = "{labels.search_list_delete_all_confirmation}";
+
+    /** The key of the message: Cancel */
+    public static final String LABELS_search_list_button_cancel = "{labels.search_list_button_cancel}";
+
     /** The key of the message: Failure URL */
     /** The key of the message: Failure URL */
     public static final String LABELS_failure_url_configuration = "{labels.failure_url_configuration}";
     public static final String LABELS_failure_url_configuration = "{labels.failure_url_configuration}";
 
 

+ 5 - 3
src/main/resources/fess_label.properties

@@ -493,9 +493,11 @@ labels.wizard_start_crawling_desc=To click "Start Crawling" button, you can star
 labels.wizard_button_start_crawling=Start Crawling
 labels.wizard_button_start_crawling=Start Crawling
 labels.wizard_button_finish=Skip
 labels.wizard_button_finish=Skip
 labels.search_list_configuration=Search
 labels.search_list_configuration=Search
-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_list_button_delete=Delete
+labels.search_list_delete_confirmation=Do you really want to delete?
+labels.search_list_button_delete_all=Delete all with this query
+labels.search_list_delete_all_confirmation=Do you really want to delete all with this query?
+labels.search_list_button_cancel=Cancel
 labels.failure_url_configuration=Failure URL
 labels.failure_url_configuration=Failure URL
 labels.failure_url_search_url=URL
 labels.failure_url_search_url=URL
 labels.failure_url_search_error_count=Error Count
 labels.failure_url_search_error_count=Error Count

+ 2 - 1
src/main/webapp/WEB-INF/view/admin/crawlinginfo/admin_crawlinginfo.jsp

@@ -55,7 +55,8 @@
 													styleClass="form-control" placeholder="${ph_session_id}"></la:text>
 													styleClass="form-control" placeholder="${ph_session_id}"></la:text>
 											</div>
 											</div>
 											<div class="form-group">
 											<div class="form-group">
-												<button type="submit" class="btn btn-primary" name="search"
+												<button type="submit" class="btn btn-primary" id="submit"
+													name="search"
 													value="<la:message key="labels.crawling_session_search" />">
 													value="<la:message key="labels.crawling_session_search" />">
 													<i class="fa fa-search"></i>
 													<i class="fa fa-search"></i>
 													<la:message key="labels.crawling_session_search" />
 													<la:message key="labels.crawling_session_search" />

+ 2 - 1
src/main/webapp/WEB-INF/view/admin/failureurl/admin_failureurl.jsp

@@ -70,7 +70,8 @@
 									</div>
 									</div>
 									<div class="form-group">
 									<div class="form-group">
 										<div class="col-sm-offset-2 col-sm-10">
 										<div class="col-sm-offset-2 col-sm-10">
-											<button type="submit" class="btn btn-primary" name="search"
+											<button type="submit" class="btn btn-primary" id="submit"
+												name="search"
 												value="<la:message key="labels.crud_button_search" />">
 												value="<la:message key="labels.crud_button_search" />">
 												<i class="fa fa-search"></i>
 												<i class="fa fa-search"></i>
 												<la:message key="labels.crud_button_search" />
 												<la:message key="labels.crud_button_search" />

+ 104 - 56
src/main/webapp/WEB-INF/view/admin/searchlist/admin_searchlist.jsp

@@ -51,8 +51,8 @@
 											placeholder="Type a search query" />
 											placeholder="Type a search query" />
 									</div>
 									</div>
 									<div class="form-group">
 									<div class="form-group">
-										<button type="submit" class="btn btn-primary" name="search"
-											value="<la:message key="labels.search"/>">
+										<button type="submit" class="btn btn-primary" id="submit"
+											name="search" value="<la:message key="labels.search"/>">
 											<i class="fa fa-search"></i>
 											<i class="fa fa-search"></i>
 											<la:message key="labels.search" />
 											<la:message key="labels.search" />
 										</button>
 										</button>
@@ -83,60 +83,17 @@
 															<a href="${doc.urlLink}">${f:h(doc.contentTitle)}</a>
 															<a href="${doc.urlLink}">${f:h(doc.contentTitle)}</a>
 														</h3>
 														</h3>
 														<div class="body col-sm-11">
 														<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>
+															${doc.contentDescription}</div>
+														<button type="button"
+															class="btn btn-xs btn-danger col-sm-1"
+															data-toggle="modal" data-target="#confirmToDelete"
+															data-docid="${f:u(doc.doc_id)}"
+															data-title="${f:h(doc.contentTitle)}"
+															data-url="${f:h(doc.urlLink)}"
+															<c:if test="${crawlerProcessRunning}">disable</c:if>>
+															<i class="fa fa-trash"></i>
+															<la:message key="labels.search_list_button_delete" />
+														</button>
 													</li>
 													</li>
 												</c:forEach>
 												</c:forEach>
 											</ol>
 											</ol>
@@ -189,8 +146,99 @@
 										</div>
 										</div>
 									</c:otherwise>
 									</c:otherwise>
 								</c:choose>
 								</c:choose>
+								<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_button_delete" />
+												</h4>
+											</div>
+											<div class="modal-body">
+												<p>
+													<la:message key="labels.search_list_delete_confirmation" />
+												</p>
+												<p>
+													<strong id="delete-doc-title"></strong><br /> <span
+														id="delete-doc-url"></span>
+												</p>
+											</div>
+											<div class="modal-footer">
+												<button type="button" class="btn btn-outline pull-left"
+													data-dismiss="modal">
+													<la:message key="labels.search_list_button_cancel" />
+												</button>
+												<la:form action="/admin/searchlist/delete">
+													<input type="hidden" name="docId" id="docId" />
+													<button type="submit" class="btn btn-outline btn-danger"
+														name="delete"
+														value="<la:message key="labels.search_list_button_delete" />">
+														<i class="fa fa-trash"></i>
+														<la:message key="labels.search_list_button_delete" />
+													</button>
+												</la:form>
+											</div>
+										</div>
+									</div>
+								</div>
 							</div>
 							</div>
 							<!-- /.box-body -->
 							<!-- /.box-body -->
+							<div class="box-footer">
+								<c:if test="${f:h(allRecordCount) > 0}">
+									<div class="row">
+										<div class="col-sm-12 center">
+											<button type="button" class="btn btn-danger"
+												data-toggle="modal" data-target="#confirmToDeleteAll">
+												<i class="fa fa-trash"></i>
+												<la:message key="labels.search_list_button_delete_all" />
+											</button>
+										</div>
+										<div class="modal modal-danger fade" id="confirmToDeleteAll"
+											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_button_delete_all" />
+														</h4>
+													</div>
+													<div class="modal-body">
+														<p>
+															<la:message
+																key="labels.search_list_delete_all_confirmation" />
+														</p>
+													</div>
+													<div class="modal-footer">
+														<la:form action="/admin/searchlist/deleteall">
+															<la:hidden property="query" />
+															<button type="button" class="btn btn-outline pull-left"
+																data-dismiss="modal">
+																<la:message key="labels.search_list_button_cancel" />
+															</button>
+															<button type="submit" class="btn btn-outline btn-danger"
+																name="deleteall"
+																value="<la:message key="labels.search_list_button_delete_all" />">
+																<i class="fa fa-trash"></i>
+																<la:message key="labels.search_list_button_delete_all" />
+															</button>
+														</la:form>
+													</div>
+												</div>
+											</div>
+										</div>
+									</div>
+								</c:if>
+							</div>
+							<!-- /.box-footer -->
 						</div>
 						</div>
 						<!-- /.box -->
 						<!-- /.box -->
 					</div>
 					</div>

+ 17 - 1
src/main/webapp/js/admin/admin.js

@@ -1,8 +1,13 @@
 $(function() {
 $(function() {
-	$('input[type="text"],select', '.login-box,section.content').first().focus();
+	$('input[type="text"],select', '.login-box,section.content').first()
+			.focus();
 
 
 	$("section.content input").keypress(function(e) {
 	$("section.content input").keypress(function(e) {
 		if (e.which == 13) {
 		if (e.which == 13) {
+			var $submitButton = $('input#submit, button#submit');
+			if ($submitButton.size() > 0) {
+				$submitButton[0].submit();
+			}
 			// ignore enter key down
 			// ignore enter key down
 			return false;
 			return false;
 		}
 		}
@@ -17,4 +22,15 @@ $(function() {
 			document.location = $(this).attr('data-href');
 			document.location = $(this).attr('data-href');
 		});
 		});
 	});
 	});
+
+	$('#confirmToDelete').on('show.bs.modal', function(event) {
+		var button = $(event.relatedTarget);
+		var docId = button.data('docid');
+		var title = button.data('title');
+		var url = button.data('url');
+
+		$(this).find('.modal-body #delete-doc-title').text(title);
+		$(this).find('.modal-body #delete-doc-url').text(url);
+		$(this).find('.modal-footer input#docId').val(docId);
+	})
 });
 });