diff --git a/verse/app.py b/verse/app.py index 529db20..8c9c355 100644 --- a/verse/app.py +++ b/verse/app.py @@ -8,6 +8,8 @@ from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from flask_wtf.csrf import CSRFProtect + + APP = Flask(__name__, static_folder="static") db = SQLAlchemy() migrate = Migrate() @@ -46,6 +48,7 @@ def create_app(): migrate.init_app(APP, db, render_as_batch=True) bcrypt.init_app(APP) + @APP.context_processor def inject_title(): return dict(title=APP.config["title"]) diff --git a/verse/search/forms/searchform.py b/verse/search/forms/searchform.py index 8925c53..d32296a 100644 --- a/verse/search/forms/searchform.py +++ b/verse/search/forms/searchform.py @@ -4,3 +4,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, validators from wtforms.validators import Length from wtforms.widgets import TextArea + +class SearchForm(FlaskForm): + searchfield = StringField("Search distribusi-verse archive") + submit = SubmitField("Search") diff --git a/verse/search/search.py b/verse/search/search.py index 83a40b0..8129d08 100644 --- a/verse/search/search.py +++ b/verse/search/search.py @@ -1,8 +1,41 @@ import os - +from flask import Blueprint, render_template from whoosh.fields import * from whoosh.index import open_dir from whoosh.qparser import QueryParser +from search.forms.searchform import SearchForm + +searchpages = Blueprint( + "search", + __name__, + template_folder="templates/search", + static_folder="static", +) SCRIPT_DIR = os.path.dirname(__file__) -DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../data")) +SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + +@searchpages.route("/", methods=["GET", "POST"]) +def searchpage(): + searchform = SearchForm() + found_distribusis = [] + if searchform.validate_on_submit(): + found_distribusis = search(searchform.searchfield.data) + template = render_template( + "search.html", + searchform=searchform, + found_distribusis=found_distribusis, + ) + return template + + +def search(searchinput): + """search and get search result titles and return them as distribusi ids""" + ix = open_dir(SEARCH_DATA_DIR) + with ix.searcher() as searcher: + query = QueryParser("content", ix.schema).parse(searchinput) + search_results = searcher.search(query) + found_distribusis = [] + for result in search_results: + found_distribusis.append(result["title"]) + return found_distribusis diff --git a/verse/search/search_index.py b/verse/search/search_index.py new file mode 100644 index 0000000..11d75d4 --- /dev/null +++ b/verse/search/search_index.py @@ -0,0 +1,47 @@ +import os +from whoosh.fields import * +from whoosh.index import create_in +from whoosh.qparser import QueryParser +from models.distribusi_model import Distribusis +import flask_apscheduler + + +SCRIPT_DIR = os.path.dirname(__file__) +SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + +def init_search_index(APP): + scheduler = flask_apscheduler.APScheduler() + scheduler.api_enabled = False + scheduler.init_app(APP) + scheduler.start() + index_distribusis(APP) + index_distribusi_files(APP) + + @scheduler.task("interval", id="update", minutes=60) + def update_search_index(): + index_distribusis(APP) + index_distribusi_files(APP) + + +def index_distribusis(APP): + schema = Schema( + title=TEXT(stored=True), path=ID(stored=True), content=TEXT + ) + ix = create_in(SEARCH_DATA_DIR, schema) + writer = ix.writer() + distribusis = _visible_distribusis(APP) + for distribusi in distribusis: + writer.add_document(title=distribusi.distribusiname, path="/a", content=distribusi.description) + writer.commit() + + +def index_distribusi_files(APP): + APP.logger.info("searching distribusi files not implemented yet.") + + +def _visible_distribusis(APP): + with APP.app_context(): + distribusis = Distribusis.query.filter( + Distribusis.visible.isnot(False) + ).all() + return distribusis diff --git a/verse/search/templates/search/search.html b/verse/search/templates/search/search.html index 6925b8d..a4261cc 100644 --- a/verse/search/templates/search/search.html +++ b/verse/search/templates/search/search.html @@ -1,3 +1,23 @@ {% extends "base/base.html" %} {% block main %} +
+
+ {{ searchform.csrf_token }} +
+ {{ searchform.searchfield.label }} + {{ searchform.searchfield }} + {% for message in searchform.searchfield.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ searchform.submit }} +
+
+
+ {% for found_distribusis in found_distribusis %} +

{{found_distribusis}}

+ {% endfor %} +
+
{% endblock %} diff --git a/verse/start.py b/verse/start.py index 75de5be..f5bf472 100644 --- a/verse/start.py +++ b/verse/start.py @@ -26,6 +26,8 @@ from statuspengguna.forgotpassword import forgot_password from statuspengguna.helper import UserHelper from statuspengguna.loginuser import login_section from statuspengguna.registeruser import register_user +from search.search import searchpages +from search.search_index import init_search_index APP = create_app() stash_page = Blueprint("stash_page", __name__, static_folder="stash") @@ -36,7 +38,8 @@ APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(admin_page, url_prefix="/admin") APP.register_blueprint(distribusikan, url_prefix="/distribusikan") - +APP.register_blueprint(searchpages, url_prefix="/search") +init_search_index(APP) @APP.before_request def session_handler():