diff --git a/app/__init__.py b/app/__init__.py index 9c9b00fa..cf0732c9 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -87,6 +87,9 @@ def create_app(config_class=Config): from app.chat import bp as chat_bp app.register_blueprint(chat_bp) + from app.search import bp as search_bp + app.register_blueprint(search_bp) + def get_resource_as_string(name, charset='utf-8'): with app.open_resource(name) as f: return f.read().decode(charset) diff --git a/app/cli.py b/app/cli.py index 4c828c8b..42c5a5f6 100644 --- a/app/cli.py +++ b/app/cli.py @@ -8,6 +8,7 @@ import flask from flask import json, current_app from flask_babel import _ from sqlalchemy import or_, desc +from sqlalchemy.orm import configure_mappers from app import db import click diff --git a/app/models.py b/app/models.py index 487dfe96..6b8a36ae 100644 --- a/app/models.py +++ b/app/models.py @@ -222,6 +222,7 @@ class Topic(db.Model): machine_name = db.Column(db.String(50), index=True) name = db.Column(db.String(50)) num_communities = db.Column(db.Integer, default=0) + parent_id = db.Column(db.Integer) communities = db.relationship('Community', lazy='dynamic', backref='topic', cascade="all, delete-orphan") @@ -483,7 +484,7 @@ class User(UserMixin, db.Model): ap_inbox_url = db.Column(db.String(255)) ap_domain = db.Column(db.String(255)) - search_vector = db.Column(TSVectorType('user_name', 'bio', 'keywords')) + search_vector = db.Column(TSVectorType('user_name', 'about', 'keywords')) activity = db.relationship('ActivityLog', backref='account', lazy='dynamic', cascade="all, delete-orphan") posts = db.relationship('Post', lazy='dynamic', cascade="all, delete-orphan") post_replies = db.relationship('PostReply', lazy='dynamic', cascade="all, delete-orphan") diff --git a/app/search/__init__.py b/app/search/__init__.py new file mode 100644 index 00000000..8c2a94f6 --- /dev/null +++ b/app/search/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + +bp = Blueprint('search', __name__) + +from app.search import routes diff --git a/app/search/forms.py b/app/search/forms.py new file mode 100644 index 00000000..e69de29b diff --git a/app/search/routes.py b/app/search/routes.py new file mode 100644 index 00000000..e4a96cf8 --- /dev/null +++ b/app/search/routes.py @@ -0,0 +1,46 @@ +from flask import request, flash, json, url_for, current_app, redirect, g +from flask_login import login_required, current_user +from flask_babel import _ +from sqlalchemy import or_ + +from app.models import Post +from app.search import bp +from app.utils import moderating_communities, joined_communities, render_template, blocked_domains + + +@bp.route('/search', methods=['GET', 'POST']) +@login_required +def run_search(): + if request.args.get('q') is not None: + q = request.args.get('q') + page = request.args.get('page', 1, type=int) + low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1' + + posts = Post.query.search(q) + if current_user.ignore_bots: + posts = posts.filter(Post.from_bot == False) + if current_user.show_nsfl is False: + posts = posts.filter(Post.nsfl == False) + if current_user.show_nsfw is False: + posts = posts.filter(Post.nsfw == False) + + domains_ids = blocked_domains(current_user.id) + if domains_ids: + posts = posts.filter(or_(Post.domain_id.not_in(domains_ids), Post.domain_id == None)) + posts = posts.paginate(page=page, per_page=100 if current_user.is_authenticated and not low_bandwidth else 50, + error_out=False) + + next_url = url_for('search.run_search', page=posts.next_num, q=q) if posts.has_next else None + prev_url = url_for('search.run_search', page=posts.prev_num, q=q) if posts.has_prev and page != 1 else None + + return render_template('search/results.html', title=_('Search results for %(q)s', q=q), posts=posts, q=q, + next_url=next_url, prev_url=prev_url, + moderating_communities=moderating_communities(current_user.get_id()), + joined_communities=joined_communities(current_user.get_id()), + site=g.site) + + else: + return render_template('search/start.html', title=_('Search'), + moderating_communities=moderating_communities(current_user.get_id()), + joined_communities=joined_communities(current_user.get_id()), + site=g.site) diff --git a/app/static/structure.css b/app/static/structure.css index 19556312..39ba5112 100644 --- a/app/static/structure.css +++ b/app/static/structure.css @@ -1273,4 +1273,15 @@ fieldset legend { display: block; } +.redo_search { + display: inline; +} +.redo_search input[type=search] { + width: unset; + display: inline; + font-size: inherit; + line-height: initial; + max-width: 100%; +} + /*# sourceMappingURL=structure.css.map */ diff --git a/app/static/structure.scss b/app/static/structure.scss index fb51b917..c061882c 100644 --- a/app/static/structure.scss +++ b/app/static/structure.scss @@ -950,4 +950,15 @@ fieldset { text-align: right; margin-bottom: 10px; display: block; +} + +.redo_search { + display: inline; + input[type=search] { + width: unset; + display: inline; + font-size: inherit; + line-height: initial; + max-width: 100%; + } } \ No newline at end of file diff --git a/app/static/styles.css b/app/static/styles.css index 05b5da78..678b1cb5 100644 --- a/app/static/styles.css +++ b/app/static/styles.css @@ -477,7 +477,7 @@ div.navbar { } #outer_container { - margin-top: -4px; + margin-top: -1px; } @media (min-width: 992px) { #outer_container { diff --git a/app/static/styles.scss b/app/static/styles.scss index 1dfd8689..f28ac5dd 100644 --- a/app/static/styles.scss +++ b/app/static/styles.scss @@ -78,7 +78,7 @@ div.navbar { } #outer_container { - margin-top: -4px; + margin-top: -1px; @include breakpoint(tablet) { margin-top: 1rem; padding-top: 0.25rem; diff --git a/app/templates/search/results.html b/app/templates/search/results.html new file mode 100644 index 00000000..6ce6dd07 --- /dev/null +++ b/app/templates/search/results.html @@ -0,0 +1,79 @@ +{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %} + {% extends 'themes/' + theme() + '/base.html' %} +{% else %} + {% extends "base.html" %} +{% endif %} %} +{% from 'bootstrap/form.html' import render_form %} + +{% block app_content %} +
{{ _('No posts match your search.') }}
+ {% endfor %} +