From 54099ad5e95df1717cde07f2eca4ca9e44971ee3 Mon Sep 17 00:00:00 2001 From: Robin Sonnabend <robin@fsmpi.rwth-aachen.de> Date: Sat, 25 Feb 2017 23:05:08 +0100 Subject: [PATCH] Protocol search --- parser.py | 2 ++ server.py | 41 +++++++++++++++++++++++++++++++---- templates/decisions-list.html | 4 ++-- templates/protocol.txt | 1 + templates/protocols-list.html | 22 ++++++++++++++++++- templates/todos-list.html | 4 ++-- utils.py | 28 ++++++++++++++++++++++++ 7 files changed, 93 insertions(+), 9 deletions(-) diff --git a/parser.py b/parser.py index 0e1a62f..edebf90 100644 --- a/parser.py +++ b/parser.py @@ -196,6 +196,8 @@ class Tag: return self.todo.render_latex(current_protocol=protocol) return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), escape_tex(self.values[0])) elif render_type == RenderType.plaintext: + if self.name == "url": + return self.values[0] return "{}: {}".format(self.name.capitalize(), self.values[0]) elif render_type == RenderType.wikitext: if self.name == "url": diff --git a/server.py b/server.py index f5c8cb1..1b087d1 100755 --- a/server.py +++ b/server.py @@ -15,7 +15,7 @@ import math import config from shared import db, date_filter, datetime_filter, date_filter_long, time_filter, ldap_manager, security_manager, current_user, check_login, login_required, group_required, class_filter -from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text +from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm, SearchForm from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable @@ -282,15 +282,48 @@ def move_default_top(type_id, top_id, diff): def list_protocols(): is_logged_in = check_login() user = current_user() + protocoltype = None + protocoltype_id = None + try: + protocoltype_id = int(request.args.get("protocoltype")) + except (ValueError, TypeError): + pass + search_term = request.args.get("search") + protocoltypes = ProtocolType.get_public_protocoltypes(user) + search_form = SearchForm(protocoltypes) + if protocoltype_id is not None: + search_form.protocoltype.data = protocoltype_id + protocoltype = ProtocolType.query.filter_by(id=protocoltype_id).first() + if search_term is not None: + search_form.search.data = search_term + protocol_query = Protocol.query + if search_term is not None: + match_target = Protocol.content_public + if protocoltype is not None and protocoltype.has_private_view_right(user): + match_target = Protocol.content_private + for term in split_terms(search_term): + protocol_query = protocol_query.filter(match_target.match("%{}%".format(term))) protocols = [ - protocol for protocol in Protocol.query.all() + protocol for protocol in protocol_query.all() if (not is_logged_in and protocol.protocoltype.is_public) or (is_logged_in and ( protocol.protocoltype.public_group in user.groups or protocol.protocoltype.private_group in user.groups))] - # TODO: sort by date and paginate + if protocoltype_id is not None and protocoltype_id != -1: + protocols = [ + protocol for protocol in protocols + if protocol.protocoltype.id == protocoltype_id + ] + protocols = sorted(protocols, key=lambda protocol: protocol.date, reverse=True) + page = _get_page() + page_count = int(math.ceil(len(protocols)) / config.PAGE_LENGTH) + if page >= page_count: + page = 0 + begin_index = page * config.PAGE_LENGTH + end_index = (page + 1) * config.PAGE_LENGTH + protocols = protocols[begin_index:end_index] protocols_table = ProtocolsTable(protocols) - return render_template("protocols-list.html", protocols=protocols, protocols_table=protocols_table) + return render_template("protocols-list.html", protocols=protocols, protocols_table=protocols_table, search_form=search_form, page=page, page_count=page_count, page_diff=config.PAGE_DIFF, protocoltype_id=protocoltype_id, search_term=search_term) @app.route("/protocol/new", methods=["GET", "POST"]) @login_required diff --git a/templates/decisions-list.html b/templates/decisions-list.html index 4d16abe..c62a083 100644 --- a/templates/decisions-list.html +++ b/templates/decisions-list.html @@ -14,14 +14,14 @@ {% if page > page_diff %} {{page_link(0, "<<")}} {% endif %} - {% for p in range(max(0, page - page_diff), min(page_count, page + page_diff)) %} + {% for p in range(max(0, page - page_diff), min(page_count, page + page_diff + 1)) %} {% if p != page %} {{page_link(p, p + 1)}} {% else %} Seite {{p + 1}} {% endif %} {% endfor %} - {% if page < page_count - page_diff %} + {% if page < page_count - page_diff - 1 %} {{page_link(page_count - 1, ">>")}} {% endif %} </div> diff --git a/templates/protocol.txt b/templates/protocol.txt index 50a816d..d255a79 100644 --- a/templates/protocol.txt +++ b/templates/protocol.txt @@ -1,5 +1,6 @@ {% for top in tree.children %} {% if top|class == "Fork" %} {{top.render(render_type=render_type, level=0, show_private=show_private, protocol=protocol)}} + {% endif %} {% endfor %} diff --git a/templates/protocols-list.html b/templates/protocols-list.html index 43d3cdb..3f8e842 100644 --- a/templates/protocols-list.html +++ b/templates/protocols-list.html @@ -1,9 +1,29 @@ {% extends "layout.html" %} -{% from "macros.html" import render_table %} +{% from "macros.html" import render_table, render_form %} {% block title %}Protokolle{% endblock %} +{% macro page_link(page, text) %} + <a href="{{url_for(request.endpoint, page=page, protocoltype=protocoltype_id, search=search_term)}}">{{text}}</a> +{% endmacro %} + {% block content %} <div class="container"> + {{render_form(search_form, class_="form-inline", action_url=url_for("list_protocols"), action_text="Suchen", labels_visible=False, method="GET")}} {{render_table(protocols_table)}} + <div class="centered"> + {% if page > page_diff %} + {{page_link(0, "<<")}} + {% endif %} + {% for p in range(max(0, page - page_diff), min(page_count, page + page_diff + 1)) %} + {% if p != page %} + {{page_link(p, p + 1)}} + {% else %} + Seite {{p + 1}} + {% endif %} + {% endfor %} + {% if page < page_count - page_diff - 1 %} + {{page_link(page_count - 1, ">>")}} + {% endif %} + </div> </div> {% endblock %} diff --git a/templates/todos-list.html b/templates/todos-list.html index c663b0c..fefb0c6 100644 --- a/templates/todos-list.html +++ b/templates/todos-list.html @@ -14,14 +14,14 @@ {% if page > page_diff %} {{page_link(0, "<<")}} {% endif %} - {% for p in range(max(0, page - page_diff), min(page_count, page + page_diff)) %} + {% for p in range(max(0, page - page_diff), min(page_count, page + page_diff + 1)) %} {% if p != page %} {{page_link(p, p + 1)}} {% else %} Seite {{p + 1}} {% endif %} {% endfor %} - {% if page < page_count - page_diff %} + {% if page < page_count - page_diff - 1 %} {{page_link(page_count - 1, ">>")}} {% endif %} </div> diff --git a/utils.py b/utils.py index 6d818bc..bd6f3ce 100644 --- a/utils.py +++ b/utils.py @@ -124,3 +124,31 @@ def set_etherpad_text(pad, text, only_if_default=True): req = requests.post(get_etherpad_import_url(pad), files=files) return req.status_code == 200 +def split_terms(text, quote_chars="\"'", separators=" \t\n"): + terms = [] + in_quote = False + last_quote_char = "" + current_term = "" + for char in text: + if in_quote: + if char != last_quote_char: + current_term += char + else: + in_quote = False + last_quote_char = "" + terms.append(current_term) + current_term = "" + else: + if char in separators: + if len(current_term) > 0: + terms.append(current_term) + current_term = "" + else: + if char in quote_chars and len(current_term) == 0: + in_quote = True + last_quote_char = char + else: + current_term += char + if len(current_term) > 0: + terms.append(current_term) + return terms -- GitLab