diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp
index 1e0fe8a26..eb43286bd 100644
--- a/src/server/internalServer.cpp
+++ b/src/server/internalServer.cpp
@@ -517,6 +517,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re
|| (patternString.empty() && ! has_geo_query) ) {
auto data = get_default_data();
data.set("pattern", encodeDiples(patternString));
+ data.set("root", m_root);
auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8");
response->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : "");
response->set_code(MHD_HTTP_NOT_FOUND);
diff --git a/static/resources_list.txt b/static/resources_list.txt
index b0b7a336a..5587111c0 100644
--- a/static/resources_list.txt
+++ b/static/resources_list.txt
@@ -32,6 +32,7 @@ skin/index.css
skin/fonts/Poppins.ttf
skin/fonts/Roboto.ttf
skin/block_external.js
+skin/search_results.css
templates/search_result.html
templates/no_search_result.html
templates/404.html
diff --git a/static/skin/search_results.css b/static/skin/search_results.css
new file mode 100644
index 000000000..8fb0a84b1
--- /dev/null
+++ b/static/skin/search_results.css
@@ -0,0 +1,87 @@
+body{
+background-color: white;
+color: #000000;
+font: small/normal Arial,Helvetica,Sans-Serif;
+margin-top: 0.5em;
+font-size: 90%;
+}
+
+a{
+color: #04c;
+}
+
+a:visited {
+color: #639
+}
+
+a:hover {
+text-decoration: underline
+}
+
+.header {
+font-size: 120%;
+}
+
+ul {
+margin:0;
+padding:0
+}
+
+.results {
+font-size: 110%;
+}
+
+.results li {
+list-style-type:none;
+margin-top: 0.5em;
+}
+
+.results a {
+font-size: 110%;
+text-decoration: underline
+}
+
+cite {
+font-style:normal;
+word-wrap:break-word;
+display: block;
+font-size: 100%;
+}
+
+.informations {
+color: #388222;
+font-size: 100%;
+}
+
+.footer {
+padding: 0;
+margin-top: 1em;
+width: 100%;
+float: left
+}
+
+.footer a, .footer span {
+display: block;
+padding: .3em .7em;
+margin: 0 .38em 0 0;
+text-align:center;
+text-decoration: none;
+}
+
+.footer a:hover {
+background: #ededed;
+}
+
+.footer ul, .footer li {
+list-style:none;
+margin: 0;
+padding: 0;
+}
+
+.footer li {
+float: left;
+}
+
+.selected {
+background: #ededed;
+}
diff --git a/static/templates/404.html b/static/templates/404.html
index 55645dbd7..2f6cf2acf 100644
--- a/static/templates/404.html
+++ b/static/templates/404.html
@@ -1,5 +1,5 @@
-
+
Content not found
diff --git a/static/templates/no_search_result.html b/static/templates/no_search_result.html
index 104708850..baa7aa2c7 100644
--- a/static/templates/no_search_result.html
+++ b/static/templates/no_search_result.html
@@ -1,99 +1,11 @@
-
-
+
Fulltext search unavailable
+
-
+
There is no article with the title "{{pattern}}"
diff --git a/test/server.cpp b/test/server.cpp
index bff14f654..4eb22e063 100644
--- a/test/server.cpp
+++ b/test/server.cpp
@@ -303,6 +303,7 @@ const char* urls404[] = {
"/ROOT/random",
"/ROOT/random?content=non-existent-book",
"/ROOT/search",
+ "/ROOT/search?content=non-existing-book&pattern=asdfqwerty",
"/ROOT/suggest",
"/ROOT/suggest?content=non-existent-book&term=abcd",
"/ROOT/catch/external",
@@ -327,11 +328,17 @@ namespace TestingOfHtmlResponses
struct ExpectedResponseData
{
- const std::string bookName, bookTitle, expectedBody;
+ const std::string expectedPageTitle;
+ const std::string expectedCssUrl;
+ const std::string bookName;
+ const std::string bookTitle;
+ const std::string expectedBody;
};
enum ExpectedResponseDataType
{
+ expected_page_title,
+ expected_css_url,
book_name,
book_title,
expected_body
@@ -344,9 +351,11 @@ ExpectedResponseData operator==(ExpectedResponseDataType t, std::string s)
{
switch (t)
{
- case book_name: return ExpectedResponseData{s, "", ""};
- case book_title: return ExpectedResponseData{"", s, ""};
- case expected_body: return ExpectedResponseData{"", "", s};
+ case expected_page_title: return ExpectedResponseData{s, "", "", "", ""};
+ case expected_css_url: return ExpectedResponseData{"", s, "", "", ""};
+ case book_name: return ExpectedResponseData{"", "", s, "", ""};
+ case book_title: return ExpectedResponseData{"", "", "", s, ""};
+ case expected_body: return ExpectedResponseData{"", "", "", "", s};
default: assert(false); return ExpectedResponseData{};
}
}
@@ -363,6 +372,8 @@ ExpectedResponseData operator&&(const ExpectedResponseData& a,
const ExpectedResponseData& b)
{
return ExpectedResponseData{
+ selectNonEmpty(a.expectedPageTitle, b.expectedPageTitle),
+ selectNonEmpty(a.expectedCssUrl, b.expectedCssUrl),
selectNonEmpty(a.bookName, b.bookName),
selectNonEmpty(a.bookTitle, b.bookTitle),
selectNonEmpty(a.expectedBody, b.expectedBody)
@@ -383,6 +394,8 @@ public:
std::string expectedResponse() const;
private:
+ std::string pageTitle() const;
+ std::string pageCssLink() const;
std::string hiddenBookNameInput() const;
std::string searchPatternInput() const;
std::string taskbarLinks() const;
@@ -392,11 +405,15 @@ std::string TestContentIn404HtmlResponse::expectedResponse() const
{
const std::string frag[] = {
R"FRAG(
-
+
- Content not found
-
+ )FRAG",
+
+ R"FRAG(
+)FRAG",
+
+ R"FRAG(
@@ -435,14 +452,36 @@ std::string TestContentIn404HtmlResponse::expectedResponse() const
};
return frag[0]
- + hiddenBookNameInput()
+ + pageTitle()
+ frag[1]
- + searchPatternInput()
+ + pageCssLink()
+ frag[2]
- + taskbarLinks()
+ + hiddenBookNameInput()
+ frag[3]
+ + searchPatternInput()
+ + frag[4]
+ + taskbarLinks()
+ + frag[5]
+ removeEOLWhitespaceMarkers(expectedBody)
- + frag[4];
+ + frag[6];
+}
+
+std::string TestContentIn404HtmlResponse::pageTitle() const
+{
+ return expectedPageTitle.empty()
+ ? "Content not found"
+ : expectedPageTitle;
+}
+
+std::string TestContentIn404HtmlResponse::pageCssLink() const
+{
+ if ( expectedCssUrl.empty() )
+ return "";
+
+ return R"(
+)";
}
std::string TestContentIn404HtmlResponse::hiddenBookNameInput() const
@@ -623,6 +662,30 @@ TEST_F(ServerTest, 404WithBodyTesting)
Cannot find content entry invalid-article
)" },
+
+ { /* url */ "/ROOT/search?content=zimfile",
+ expected_page_title=="Fulltext search unavailable" &&
+ expected_css_url=="/ROOT/skin/search_results.css" &&
+ book_name=="zimfile" &&
+ book_title=="Ray Charles" &&
+ expected_body==R"(
+
+
+ There is no article with the title ""
+ and the fulltext search engine is not available for this content.
+
+)" },
+
+ { /* url */ "/ROOT/search?content=non-existent-book&pattern=asdfqwerty",
+ expected_page_title=="Fulltext search unavailable" &&
+ expected_css_url=="/ROOT/skin/search_results.css" &&
+ expected_body==R"(
+
+
+ There is no article with the title "asdfqwerty"
+ and the fulltext search engine is not available for this content.
+
+)" },
};
for ( const auto& t : testData ) {