Add search suggestions
This commit is contained in:
		
							parent
							
								
									4586931adf
								
							
						
					
					
						commit
						2ecfe10584
					
				|  | @ -95,6 +95,14 @@ void css_route(const httplib::Request& req, httplib::Response& res) { | ||||||
|         padding-bottom: 1em; |         padding-bottom: 1em; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /* SEARCH RESULTS PAGE */ | ||||||
|  |     .searchsuggestions { | ||||||
|  |         text-align: left; | ||||||
|  |         display: inline-block; | ||||||
|  |         margin-top: .5em; | ||||||
|  |         margin-bottom: 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* ERROR PAGE */ |     /* ERROR PAGE */ | ||||||
|     .error { |     .error { | ||||||
|         text-align: center; |         text-align: center; | ||||||
|  |  | ||||||
|  | @ -4,10 +4,14 @@ | ||||||
| #include "../pixivclient.h" | #include "../pixivclient.h" | ||||||
| 
 | 
 | ||||||
| static inline Element generate_header(const httplib::Request& req, const Config& config, | static inline Element generate_header(const httplib::Request& req, const Config& config, | ||||||
|         const SearchResults& search_results, const std::string& query, const std::vector<std::string>& tags, const std::string& order); |         const SearchResults& search_results, const std::string& query, const std::vector<std::string>& tags, const std::string& order, | ||||||
|  |         const std::vector<SearchSuggestion>& search_suggestions); | ||||||
|  | static inline Element generate_search_suggestions(const httplib::Request& req, const Config& config, | ||||||
|  |         const std::vector<std::string>& tags, const std::vector<SearchSuggestion>& search_suggestions, bool open_by_default); | ||||||
| 
 | 
 | ||||||
| static std::string tags_to_string(const std::unordered_map<std::string, std::string>& tag_translations, const std::vector<std::string>& tags); | static std::string tags_to_string(const std::unordered_map<std::string, std::string>& tag_translations, const std::vector<std::string>& tags); | ||||||
| static inline std::vector<std::string> split(const std::string& str, char c); | static inline std::vector<std::string> split(const std::string& str, char c); | ||||||
|  | static inline std::string join(const std::vector<std::string>& items, char c); | ||||||
| 
 | 
 | ||||||
| void tags_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client) { | void tags_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client) { | ||||||
|     std::string query = blankie::murl::unescape(req.matches.str(1)); |     std::string query = blankie::murl::unescape(req.matches.str(1)); | ||||||
|  | @ -29,9 +33,17 @@ void tags_route(const httplib::Request& req, httplib::Response& res, const Confi | ||||||
|         serve_error(req, res, config, "500: Internal server error", "Failed to search for illusts", e.what()); |         serve_error(req, res, config, "500: Internal server error", "Failed to search for illusts", e.what()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     std::vector<SearchSuggestion> search_suggestions; | ||||||
|  |     try { | ||||||
|  |         search_suggestions = pixiv_client.get_search_suggestions(tags.back()); | ||||||
|  |     } catch (const std::exception& e) { | ||||||
|  |         res.status = 500; | ||||||
|  |         serve_error(req, res, config, "500: Internal server error", "Failed to get search suggestions", e.what()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Element body("body", { |     Element body("body", { | ||||||
|         generate_header(req, config, search_results, query, tags, order), |         generate_header(req, config, search_results, query, tags, order, search_suggestions), | ||||||
|         Element("br"), |         Element("br"), | ||||||
|         generate_illusts_pager(req, config, search_results.illusts, page, "illusts") |         generate_illusts_pager(req, config, search_results.illusts, page, "illusts") | ||||||
|     }); |     }); | ||||||
|  | @ -41,7 +53,8 @@ void tags_route(const httplib::Request& req, httplib::Response& res, const Confi | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static inline Element generate_header(const httplib::Request& req, const Config& config, | static inline Element generate_header(const httplib::Request& req, const Config& config, | ||||||
|         const SearchResults& search_results, const std::string& query, const std::vector<std::string>& tags, const std::string& order) { |         const SearchResults& search_results, const std::string& query, const std::vector<std::string>& tags, const std::string& order, | ||||||
|  |         const std::vector<SearchSuggestion>& search_suggestions) { | ||||||
|     auto sort_element = [&](const char* title, const char* new_order) { |     auto sort_element = [&](const char* title, const char* new_order) { | ||||||
|         std::string url = get_origin(req, config) + "/tags/" + blankie::murl::escape(query) + "/illustrations?order=" + new_order; |         std::string url = get_origin(req, config) + "/tags/" + blankie::murl::escape(query) + "/illustrations?order=" + new_order; | ||||||
|         Element ret("a", {{"href", std::move(url)}}, {title}); |         Element ret("a", {{"href", std::move(url)}}, {title}); | ||||||
|  | @ -56,9 +69,13 @@ static inline Element generate_header(const httplib::Request& req, const Config& | ||||||
|             Element("input", {{"name", "q"}, {"required", ""}, {"value", query}}, {}), |             Element("input", {{"name", "q"}, {"required", ""}, {"value", query}}, {}), | ||||||
|             " ", |             " ", | ||||||
|             Element("button", {"Search for illustrations"}) |             Element("button", {"Search for illustrations"}) | ||||||
|         }), |         }) | ||||||
|         Element("br") |  | ||||||
|     }); |     }); | ||||||
|  |     if (!search_suggestions.empty()) { | ||||||
|  |         header.nodes.push_back(generate_search_suggestions(req, config, tags, search_suggestions, search_results.illusts.total_illusts == 0)); | ||||||
|  |     } | ||||||
|  |     header.nodes.push_back(Element("br")); | ||||||
|  | 
 | ||||||
|     if (search_results.illusts.total_illusts != 1) { |     if (search_results.illusts.total_illusts != 1) { | ||||||
|         header.nodes.push_back("There are "); |         header.nodes.push_back("There are "); | ||||||
|         header.nodes.push_back(std::to_string(search_results.illusts.total_illusts)); |         header.nodes.push_back(std::to_string(search_results.illusts.total_illusts)); | ||||||
|  | @ -78,6 +95,39 @@ static inline Element generate_header(const httplib::Request& req, const Config& | ||||||
|     return header; |     return header; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline Element generate_search_suggestions(const httplib::Request& req, const Config& config, | ||||||
|  |         const std::vector<std::string>& tags, const std::vector<SearchSuggestion>& search_suggestions, bool open_by_default) { | ||||||
|  |     std::vector<blankie::html::Node> ul_nodes; | ||||||
|  |     ul_nodes.reserve(search_suggestions.size()); | ||||||
|  |     for (const SearchSuggestion& search_suggestion : search_suggestions) { | ||||||
|  |         std::string text = search_suggestion.tag; | ||||||
|  |         if (search_suggestion.english_tag) { | ||||||
|  |             text += " ("; | ||||||
|  |             text += *search_suggestion.english_tag; | ||||||
|  |             text += ')'; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         std::vector<std::string> new_tags = tags; | ||||||
|  |         new_tags.pop_back(); | ||||||
|  |         new_tags.push_back(search_suggestion.tag); | ||||||
|  |         std::string url = get_origin(req, config) + "/tags/" + blankie::murl::escape(join(new_tags, ' ')); | ||||||
|  | 
 | ||||||
|  |         ul_nodes.push_back(Element("li", { | ||||||
|  |             Element("a", {{"href", std::move(url)}}, {std::move(text)}) | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Element details("details", { | ||||||
|  |         Element("summary", {"Search suggestions"}), | ||||||
|  |         Element("ul", {{"class", "searchsuggestions"}}, ul_nodes) | ||||||
|  |     }); | ||||||
|  |     if (open_by_default) { | ||||||
|  |         details.attributes.push_back({"open", ""}); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return details; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static std::string tags_to_string(const std::unordered_map<std::string, std::string>& tag_translations, const std::vector<std::string>& tags) { | static std::string tags_to_string(const std::unordered_map<std::string, std::string>& tag_translations, const std::vector<std::string>& tags) { | ||||||
|  | @ -112,3 +162,16 @@ static inline std::vector<std::string> split(const std::string& str, char c) { | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static inline std::string join(const std::vector<std::string>& items, char c) { | ||||||
|  |     std::string ret; | ||||||
|  | 
 | ||||||
|  |     for (size_t i = 0; i < items.size(); i++) { | ||||||
|  |         if (i) { | ||||||
|  |             ret += c; | ||||||
|  |         } | ||||||
|  |         ret += items[i]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue