contentdb/app/blueprints/packages/advanced_search.py

104 lines
4.5 KiB
Python

# ContentDB
# Copyright (C) 2024 rubenwardy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from flask import render_template
from flask_babel import lazy_gettext, gettext
from flask_wtf import FlaskForm
from wtforms.fields.choices import SelectField, SelectMultipleField
from wtforms.fields.simple import StringField, BooleanField
from wtforms.validators import Optional
from wtforms_sqlalchemy.fields import QuerySelectMultipleField, QuerySelectField
from . import bp
from ...models import PackageType, Tag, db, ContentWarning, License, Language, MinetestRelease, Package, PackageState
def make_label(obj: Tag | ContentWarning):
translated = obj.get_translated()
if translated["description"]:
return "{}: {}".format(translated["title"], translated["description"])
else:
return translated["title"]
def get_hide_choices():
ret = [
("android_default", gettext("Android Default")),
("desktop_default", gettext("Desktop Default")),
("nonfree", gettext("Non-free")),
("wip", gettext("Work in Progress")),
("deprecated", gettext("Deprecated")),
("*", gettext("All content warnings")),
]
content_warnings = ContentWarning.query.order_by(db.asc(ContentWarning.name)).all()
tags = Tag.query.order_by(db.asc(Tag.name)).all()
ret += [(x.name, make_label(x)) for x in content_warnings + tags]
return ret
class AdvancedSearchForm(FlaskForm):
q = StringField(lazy_gettext("Query"), [Optional()])
type = SelectMultipleField(lazy_gettext("Type"), [Optional()],
choices=PackageType.choices(), coerce=PackageType.coerce)
author = StringField(lazy_gettext("Author"), [Optional()])
tag = QuerySelectMultipleField(lazy_gettext('Tags'),
query_factory=lambda: Tag.query.order_by(db.asc(Tag.name)),
get_pk=lambda a: a.name, get_label=make_label)
flag = QuerySelectMultipleField(lazy_gettext('Content Warnings'),
query_factory=lambda: ContentWarning.query.order_by(db.asc(ContentWarning.name)),
get_pk=lambda a: a.name, get_label=make_label)
license = QuerySelectMultipleField(lazy_gettext("License"), [Optional()],
query_factory=lambda: License.query.order_by(db.asc(License.name)),
allow_blank=True, blank_value="",
get_pk=lambda a: a.name, get_label=lambda a: a.name)
game = QuerySelectField(lazy_gettext("Supports Game"), [Optional()],
query_factory=lambda: Package.query.filter(Package.type == PackageType.GAME, Package.state == PackageState.APPROVED).order_by(db.asc(Package.name)),
allow_blank=True, blank_value="",
get_pk=lambda a: f"{a.author.username}/{a.name}",
get_label=lambda a: lazy_gettext("%(title)s by %(author)s", title=a.title, author=a.author.display_name))
lang = QuerySelectField(lazy_gettext("Language"),
query_factory=lambda: Language.query.order_by(db.asc(Language.title)),
allow_blank=True, blank_value="",
get_pk=lambda a: a.id, get_label=lambda a: a.title)
hide = SelectMultipleField(lazy_gettext("Hide Tags and Content Warnings"), [Optional()])
engine_version = QuerySelectField(lazy_gettext("Minetest Version"),
query_factory=lambda: MinetestRelease.query.order_by(db.asc(MinetestRelease.id)),
allow_blank=True, blank_value="",
get_pk=lambda a: a.value, get_label=lambda a: a.name)
sort = SelectField(lazy_gettext("Sort by"), [Optional()], choices=[
("", ""),
("name", lazy_gettext("Name")),
("title", lazy_gettext("Title")),
("score", lazy_gettext("Package score")),
("reviews", lazy_gettext("Reviews")),
("downloads", lazy_gettext("Downloads")),
("created_at", lazy_gettext("Created At")),
("approved_at", lazy_gettext("Approved At")),
("last_release", lazy_gettext("Last Release")),
])
order = SelectField(lazy_gettext("Order"), [Optional()], choices=[
("desc", lazy_gettext("Descending")),
("asc", lazy_gettext("Ascending")),
])
random = BooleanField(lazy_gettext("Random order"))
@bp.route("/packages/advanced-search/")
def advanced_search():
form = AdvancedSearchForm()
form.hide.choices = get_hide_choices()
return render_template("packages/advanced_search.html", form=form)