diff --git a/confarchive/model.py b/confarchive/model.py index 6fc4561..9949275 100644 --- a/confarchive/model.py +++ b/confarchive/model.py @@ -5,8 +5,9 @@ import typing import sqlalchemy import sqlalchemy.orm.decl_api -from sqlalchemy import func +from sqlalchemy import Index, func, text from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects.postgresql import TSVECTOR from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.orderinglist import ordering_list @@ -171,6 +172,22 @@ class Event(TimeStampedModel): event_type = Column(String) url = Column(String) cancelled = Column(Boolean) + search_vector = Column(TSVECTOR) + + trigger = text( + """ + CREATE TRIGGER event_vector_update BEFORE INSERT OR UPDATE + ON event FOR EACH ROW EXECUTE FUNCTION + tsvector_update_trigger(search_vector, 'pg_catalog.english', title, abstract, description); + """ + ) + + Index( + "event_search_vector_idx", + search_vector, + postgresql_using="gin", + postgresql_ops={"abstract_search_vector": "gin_trgm_ops"}, + ) conference = relationship("Conference", back_populates="events") diff --git a/main.py b/main.py index 35fe72b..b099df6 100755 --- a/main.py +++ b/main.py @@ -182,8 +182,6 @@ def search_people() -> str: @app.route("/merge", methods=["GET", "POST"]) def merge() -> str | Response: - assert app.config["ADMIN_MODE"] - if flask.request.method == "POST": search_for = flask.request.form["q"] @@ -409,8 +407,6 @@ def search_everything() -> str: @app.route("/person//delete", methods=["POST"]) def delete_person(person_id: int) -> str | Response: - assert app.config["ADMIN_MODE"] - item = model.Person.query.get(person_id) for cp in item.conferences_association: diff --git a/templates/index.html b/templates/index.html index 393876a..a02dbf0 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,58 +2,74 @@ {% block title %}Conference archive{% endblock %} -{% block content %} -
-

Conference archive

+ {% block content %} +
+
+

Conference archive

-
- 👥 - {{ "{:,d}".format(count.conference) }} conferences
- 🌍 - {{ "{:,d}".format(count.country) }} countries
- 📍 - {{ "{:,d}".format(count.venue) }} venues
- 🎤 - {{ "{:,d}".format(count.event) }} talks
- 👤 - {{ "{:,d}".format(count.person) }} speakers - top speakers
-
- -

Conferences

- - {% for item in items %} - {% if loop.first or item.start.year != loop.previtem.start.year %} -

{{ item.start.year }}

- {% endif %} - -
- 👥 - {{ item.title }} - 📅 - {{ item.start.strftime("%d %b %Y") }} -
- {% if item.venue %} - 📍 - {{ item.venue.name }} - – - {{ item.venue.city.name }}, - {{ item.venue.city.country.name }} - {{ item.venue.city.country.flag }} -
- {% endif %} {# - {% if item.series %} - 📃 Series: {{ item.series.name }} -
- {% endif %} +
+
+ + +
+ +
#} - {{ (item.end - item.start).days + 1 }} days, - {{ item.events.count() }} talks, - {{ item.people_detail.count() }} speakers
-
- {% endfor %} +
+ 👥 + {{ "{:,d}".format(count.conference) }} conferences
+ 🌍 + {{ "{:,d}".format(count.country) }} countries
+ 📍 + {{ "{:,d}".format(count.venue) }} venues
+ 🎤 + {{ "{:,d}".format(count.event) }} talks - + most common titles
+ 👤 + {{ "{:,d}".format(count.person) }} speakers + top speakers
+
-
+

Conferences

+ + {% for item in items %} + {% if loop.first or item.start.year != loop.previtem.start.year %} +

{{ item.start.year }}

+ {% endif %} + +
+ 👥 + {{ item.title }} + 📅 + {{ item.start.strftime("%d %b %Y") }} +
+ {% if item.venue %} + 📍 + {{ item.venue.name }} + – + {{ item.venue.city.name }}, + {{ item.venue.city.country.name }} + {{ item.venue.city.country.flag }} +
+ {% endif %} + {# + {% if item.series %} + 📃 Series: {{ item.series.name }} +
+ {% endif %} + #} + + {{ (item.end - item.start).days + 1 }} days, + {{ item.events.count() }} talks, + {{ item.people_detail.count() }} speakers
+
+ {% endfor %} + + +
+
{% endblock %} + + diff --git a/templates/navbar.html b/templates/navbar.html index 600cde8..c858ae0 100644 --- a/templates/navbar.html +++ b/templates/navbar.html @@ -1,6 +1,7 @@

- conferences + home + | events | speakers diff --git a/templates/person.html b/templates/person.html index d37ddde..191eaad 100644 --- a/templates/person.html +++ b/templates/person.html @@ -21,8 +21,8 @@ {% block content %} -
-
+
+
{% set photo = item.photo_filename() %} {% if photo %} @@ -45,7 +45,7 @@ {% endif %}

- {% if config.ADMIN_MODE %} + {% set search_for = item.name + ' ' + " haswbstatement:P31=Q5" %}

Search for {{ item.name }} on Wikidata

@@ -80,7 +80,6 @@

No similar names found on Wikidata

{% endif %} {% endif %} - {% endif %} {% set bio_source = item.bio_source() %} {% if bio_source %} diff --git a/templates/search_people.html b/templates/search_people.html index aabe7fe..bb1572b 100644 --- a/templates/search_people.html +++ b/templates/search_people.html @@ -17,12 +17,9 @@

- {% set count = q.count() %} - Found {{ count }} people matching '{{ search_for }}' + Found {{ q.count() }} people matching '{{ search_for }}' - {% if config.ADMIN_MODE and count %} merge - {% endif %}

    diff --git a/templates/top_speakers.html b/templates/top_speakers.html index 183d550..ff3b533 100644 --- a/templates/top_speakers.html +++ b/templates/top_speakers.html @@ -1,34 +1,40 @@ {% extends "base.html" %} {% block style %} + - + .container { + position: relative; + } {% endblock %} -{% set show_images = False %} +{% set show_images = True %} {% block title %}Conference archive{% endblock %} {% block content %} -
    +
    {% if show_images %} @@ -82,22 +88,65 @@ {% if loop.first or loop.previtem[1] != count %}

    {{ count }} conferences

    {% endif %} -
    - {% set photo = person.photo_filename() %} - +
    + 👤 - {{ person.name }}
    + {{ person.name }} ({{ count }} conferences, {{ person.event_count }} talks) {% if person.photo_filename() %}📷{% endif %} {% if person.wikidata_qid %} Wikidata {% endif %}
    - {% if photo %} - {{ person.name }} - {% endif %}
    {% endfor %}
    {% endblock %} + +{% block script %} +{% if show_images %} + +{% endif %} +{% endblock %}