Ajax search

This commit is contained in:
2022-04-04 10:24:04 +03:00
parent e27ee4f342
commit 35841c9f29
4 changed files with 45 additions and 32 deletions

View File

@ -1,7 +1,7 @@
FROM python:3.9-alpine
RUN pip install --no-cache-dir -U setuptools pip wheel && pip install --no-cache-dir Flask icalendar gunicorn
RUN pip install --no-cache-dir Flask icalendar gunicorn Unidecode
COPY . /app
WORKDIR /app
CMD ["gunicorn", "--workers=2", "--access-logfile", "-", "--log-level", "warning", "-b", "0.0.0.0:5000", "app:app"]
CMD ["gunicorn", "--workers=2", "--access-logfile", "-", "--log-level", "debug", "-b", "0.0.0.0:5000", "app:app"]
#CMD python app.py

56
app.py
View File

@ -1,22 +1,23 @@
import datetime
import json
import uuid
import logging
from collections import defaultdict
from io import BytesIO
from typing import Iterable, Mapping
from flask import Flask, request, render_template, send_file
from flask import Flask, request, render_template, send_file, jsonify
from icalendar import Calendar, Event, Alarm
from unidecode import unidecode
app = Flask(__name__)
# Source JSON created from http://vvc.gov.lv/export/sites/default/files/paplasinatais_saraksts.pdf
def generate_ical_for_mapping(cal: Mapping[datetime.date, Iterable[str]]) -> BytesIO:
ical = Calendar()
ical['VERSION'] = "2.0"
ical['PRODID'] = "NameDays"
ical["VERSION"] = "2.0"
ical["PRODID"] = "NameDays"
for date, names in sorted(cal.items(), key=lambda x: x[0]):
ev = Event()
ev.add("SUMMARY", ", ".join(sorted(names)))
@ -35,30 +36,47 @@ def generate_ical_for_mapping(cal: Mapping[datetime.date, Iterable[str]]) -> Byt
return BytesIO(ical.to_ical(True))
@app.route('/', methods=["POST", "GET"])
@app.route("/", methods=["POST", "GET"])
def calendar():
with open("vardadienas.json") as f:
vdienas = json.load(f)
names_dict = {
f"{int(month):02}_{int(day):02}_{name}": name
for month, month_data in vdienas.items()
for day, day_data in month_data.items()
for names in day_data.values()
for name in names
}
if request.method == "POST":
with open("vardadienas.json") as f:
vdienas = json.load(f)
cal = defaultdict(list)
for selected_name in request.form.getlist("words"):
if selected_name in names_dict:
month, day, name = selected_name.split("_")
month, day, name = selected_name.split("__")
vdmd = vdienas[str(int(month))][str(int(day))]
if name in vdmd["normal"] or name in vdmd["special"]:
date = datetime.date(2000, int(month), int(day))
cal[date].append(name)
if cal:
name = f"{uuid.uuid4().hex}.ics"
f = generate_ical_for_mapping(cal)
return send_file(f, mimetype="text/calendar", as_attachment=True, download_name=name)
words = ((k,v) for k,v in sorted(names_dict.items(), key=lambda x: x[1]))
return render_template("namedays.html", words=words)
return send_file(
f, mimetype="text/calendar", as_attachment=True, download_name=name
)
return render_template("namedays.html")
@app.route("/search/")
def calendar_search():
term = request.args.get("term")
results = []
if term:
term = unidecode(term.lower(), errors="preserve")
with open("mapping.json") as f:
mapping = json.load(f)
for kind in ["normal", "special"]:
words = {
"text": kind.title(),
"children": [
{"id": key, "text": value}
for key, value in mapping[kind].items()
if unidecode(value.lower(), errors="preserve").startswith(term)
],
}
if words["children"]:
results.append(words)
return jsonify({"results": results, "pagination": {"more": False}})
if __name__ == "__main__":

1
mapping.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -12,32 +12,26 @@
<div class="container">
<div class="row">
<div class="col-12">
<h1>Vārdadienu kalendāra ģenerators</h1>
<h1>Vārdadienu kalendāra ģenerators</h1>
</div>
<div class="col-12">
{%- if words %}
<form method="post">
<div class="mb-3">
<label for="idWordSelect" class="form-label">Atlasi vārdus:</label>
<select name="words" class="form-control js-example-basic-multiple" id="idWordSelect" multiple>
{%- for key, name in words %}
<option value="{{ key }}">{{ name }}</option>
{%- endfor -%}
</select>
<select name="words" class="form-control js-example-basic-multiple" id="idWordSelect" multiple></select>
</div>
<button name="submit" value="submit" class="btn btn-primary">Izveidot</button>
</form>
{% endif -%}
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function () {
$('.js-example-basic-multiple').select2();
$('.js-example-basic-multiple').select2({minimumInputLength: 2, ajax: {url: "/search/", dataType: "json", delay: 500}});
});
</script>
</body>
</html>
</html>