diff options
author | buttle <chris@gatopelao.org> | 2023-10-15 09:57:00 +0200 |
---|---|---|
committer | buttle <chris@gatopelao.org> | 2023-10-15 09:57:00 +0200 |
commit | 39036133d3e8de097877becf3bd011f50132598c (patch) | |
tree | 8c6d1dec02ce9feccf73fb936be4b5d0c773155a | |
parent | a9780148cfb58bf435e60b689f0c0d844e3d1848 (diff) | |
parent | ec241b224d0c977c16efb286849ecc247930dcee (diff) |
Merge branch 'feat/search' into develop
-rw-r--r-- | liberaforms/static/css/main-backend.css | 3 | ||||
-rw-r--r-- | liberaforms/static/js/inline_help.js | 50 | ||||
-rw-r--r-- | liberaforms/static/sass/backend/_main.scss | 3 | ||||
-rw-r--r-- | liberaforms/templates/site/partials/inline_help_menu.html | 4 | ||||
-rw-r--r-- | liberaforms/utils/inline_help.py | 82 | ||||
-rw-r--r-- | liberaforms/views/site.py | 12 |
6 files changed, 132 insertions, 22 deletions
diff --git a/liberaforms/static/css/main-backend.css b/liberaforms/static/css/main-backend.css index 4a82b36b..8c600d69 100644 --- a/liberaforms/static/css/main-backend.css +++ b/liberaforms/static/css/main-backend.css @@ -14029,6 +14029,9 @@ a.badge { .ds-inline-help .ds-inline-help-menu .nav-link:before { content: " - "; } +.ds-inline-help .ds-inline-help-menu .ds-search { + background-color: var(--lf-gray-100); +} .ds-inline-help .ds-inline-help-page { padding: 1rem; background-color: var(--lf-gray-100); diff --git a/liberaforms/static/js/inline_help.js b/liberaforms/static/js/inline_help.js index f6e10ca1..e0c5cd97 100644 --- a/liberaforms/static/js/inline_help.js +++ b/liberaforms/static/js/inline_help.js @@ -78,6 +78,7 @@ function inline_help_go_back() { function inline_help_reset() { inline_help_cache = {} inline_help_history = [] + $("input[type='search']").val("") } function inline_help_retieve_page(file_name) { return new Promise(function(resolve, reject) { @@ -115,12 +116,61 @@ function inline_help_retieve_page(file_name) { }); }) } +function search_inline_help(event) { + if (event.key == "Enter") { + do_search().then(function(data) { + delete inline_help_cache["search"]; + let search_item_pos = inline_help_history.indexOf("search"); + if (search_item_pos > -1) { + inline_help_history.splice(search_item_pos, 1) + } + var html = "" + for (let page_name of Object.keys(data.result)) { + let block = "<h2>" + page_name + "</h2>" + lines = "" + for (let line of data.result[page_name]) { + lines = lines + line + "<br />" + } + html = html + block + lines + } + _inline_help_history_push("search") + let page_title = $("input[type='search']").attr('placeholder') + ": " + $("input[type=search]").val() + inline_help_cache["search"] = {"html": html, "title": page_title } + $('#inline_help_page').html(html) + $('#inline_help_page_title').html(page_title) + }); + } +} + +function do_search() { + return new Promise(function(resolve, reject) { + $.ajax({ + url : "/site/search-help", + type: "POST", + contentType: "application/json", + data : JSON.stringify({"search_string": $("input[type=search]").val()}), + dataType: "json", + beforeSend: function(xhr, settings) { + if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) { + xhr.setRequestHeader("X-CSRFToken", csrftoken) + } + }, + success: function(data, textStatus, jqXHR) { + resolve(data) // Resolve promise and goto then() + }, + error: function(err) { + reject(err) // Reject the promise and goto catch() + } + }); + }); +} const inline_help_template = ` <div id="inline_help" class="grid ds-inline-help pt-2" style="display:none; --lf-gap: 0;"> <div class="navbar g-col-12 ds-inline-help-page-header"> <div> <a id="inline_help_back_button" href="#" onclick="js:inline_help_go_back()"" class="align-middle"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left" aria-hidden="true"><polyline points="15 18 9 12 15 6"></polyline></svg><span>%Go_back%</span></a> </div> + <div class="d-flex"> <button class="ds-button-navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHelpContent" aria-controls="navbarHelpContent" aria-expanded="false" aria-label="Toggle navigation"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-more-vertical"><circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="5" r="1"></circle><circle cx="12" cy="19" r="1"></circle></svg> diff --git a/liberaforms/static/sass/backend/_main.scss b/liberaforms/static/sass/backend/_main.scss index a061126e..b09d337c 100644 --- a/liberaforms/static/sass/backend/_main.scss +++ b/liberaforms/static/sass/backend/_main.scss @@ -51,6 +51,9 @@ content: ' - '; } } + .ds-search { + background-color: var(--lf-gray-100); + } } .ds-inline-help-page { padding: $spacer; diff --git a/liberaforms/templates/site/partials/inline_help_menu.html b/liberaforms/templates/site/partials/inline_help_menu.html index fbc3e038..37cd9692 100644 --- a/liberaforms/templates/site/partials/inline_help_menu.html +++ b/liberaforms/templates/site/partials/inline_help_menu.html @@ -21,6 +21,10 @@ </li> {% endfor %} {% endif %} + + <li class="nav-item mt-4"> + <input id="search_text" class="form-control ds-search" type="search" placeholder='{{_("Search")}}' onkeypress="search_inline_help(event)" aria-label='{{_("Search")}}'> + </li> </ul> </div> </nav> diff --git a/liberaforms/utils/inline_help.py b/liberaforms/utils/inline_help.py index 901e1d26..7851981c 100644 --- a/liberaforms/utils/inline_help.py +++ b/liberaforms/utils/inline_help.py @@ -13,6 +13,7 @@ from flask import current_app, g, render_template, jsonify, url_for from flask_babel import gettext, force_locale import flask_login from liberaforms.utils import utils +from liberaforms.utils import sanitizers from liberaforms.utils import i18n @@ -58,6 +59,63 @@ class InlineHelp(): def _external_link_icon(self): return '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-up-right"><line x1="7" y1="17" x2="17" y2="7"></line><polyline points="7 7 17 7 17 17"></polyline></svg>' + def render_markdown(self, j2_env, file_name) -> str: + #print(file_name) + template = j2_env.get_template(file_name) + markdown_help = template.render({ + "help_page": self._help_page_link, + "is_admin": self.is_admin, + "is_editor": self.is_editor, + "is_guest": self.is_guest, + "is_root_user": self.is_root_user, + "is_multilanguage_site": bool(len(g.site.custom_languages) > 1), + "_": self.translate, + "url_for": url_for, + "BASE_URL": current_app.config["BASE_URL"], + #"external_link_icon": self._external_link_icon, + "default_enabled_language": self._get_default_enabled_language, + "token_lifespan": self._token_lifespan(), + "current_user": flask_login.current_user, + "site": g.site, + "with_link": self._build_link, + "app_config": current_app.config, + "human_readable_bytes": utils.human_readable_bytes, + "mimetype_risks": self.mimetype_risks, + "i18n_docs_site_url": i18n.get_docs_site_url}) + return markdown_help + + def search(self, search_string: str) -> dict: + result: dict = {} + j2_env = Environment(loader=FileSystemLoader(self.pages_dir)) + + pages = [] + def load_pages(menu: dict): + for key, value in menu.items(): + pages.append(key) + if "sub_pages" in value and value["sub_pages"]: + load_pages(value["sub_pages"]) + + load_pages(self.menu_data["user"]) + if self.is_admin: + load_pages(self.menu_data["admin"]) + + for file_name in pages: + if file_name.startswith("_"): + continue + try: + rendered_markdown = self.render_markdown(j2_env, file_name) + for line in rendered_markdown.splitlines(): + if search_string in line: + page_name = self.get_page_label(file_name) + page_link = '<a href="#" onclick=\'inline_help_goto_page("'+file_name+'")\'>'+page_name+'</a>' + if page_link not in result: + result[page_link] = [] + text = sanitizers.remove_html_tags(markdown.markdown(line)) + result[page_link].append(text) + except: + current_app.logger.debug(f"APP - Inline help. Cannot find {file_name}") + return result + def get_page_label(self, file_name): for menu in self.menu_data.values(): for item, item_value in menu.items(): @@ -83,28 +141,8 @@ class InlineHelp(): current_app.logger.debug(f"INLINE-HELP - Cannot file help page: {file_name}") return _("Cannot find the file %(file_name)s", file_name=file_name) j2_env = Environment(loader=FileSystemLoader(self.pages_dir)) - template = j2_env.get_template(file_name) - markdown_help = template.render({ - "help_page": self._help_page_link, - "is_admin": self.is_admin, - "is_editor": self.is_editor, - "is_guest": self.is_guest, - "is_root_user": self.is_root_user, - "is_multilanguage_site": bool(len(g.site.custom_languages) > 1), - "_": self.translate, - "url_for": url_for, - "BASE_URL": current_app.config["BASE_URL"], - #"external_link_icon": self._external_link_icon, - "default_enabled_language": self._get_default_enabled_language, - "token_lifespan": self._token_lifespan(), - "current_user": flask_login.current_user, - "site": g.site, - "with_link": self._build_link, - "app_config": current_app.config, - "human_readable_bytes": utils.human_readable_bytes, - "mimetype_risks": self.mimetype_risks, - "i18n_docs_site_url": i18n.get_docs_site_url}) - html = markdown.markdown(markdown_help) + rendered_markdown = self.render_markdown(j2_env, file_name) + html = markdown.markdown(rendered_markdown) return html def get_menu(self): diff --git a/liberaforms/views/site.py b/liberaforms/views/site.py index 1aac0946..faf8e1d5 100644 --- a/liberaforms/views/site.py +++ b/liberaforms/views/site.py @@ -693,6 +693,18 @@ def get_inline_help(): return jsonify(payload), 200 +@site_bp.route('/site/search-help', methods=['POST']) +@auth.authenticated_user_required__json +def search_help(): + data = request.get_json() + search_string = data["search_string"] if "search_string" in data else None + if search_string: + inline_help = InlineHelp(g.language, flask_login.current_user.role) + result = inline_help.search(search_string) + return jsonify(result=result), 200 + return jsonify(result={}), 200 + + # RSS @site_bp.route('/feed', methods=['GET']) |