Ajax search
This commit is contained in:
@ -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
56
app.py
@ -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
1
mapping.json
Normal file
File diff suppressed because one or more lines are too long
@ -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>
|
||||
|
Reference in New Issue
Block a user