__init__.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. """
  2. This module contains a flask blueprint for db administration stuff
  3. Templates are self-contained in this directory
  4. """
  5. from __future__ import print_function
  6. from datetime import datetime, timedelta, time
  7. from collections import defaultdict
  8. from flask import (
  9. current_app,
  10. Blueprint,
  11. render_template,
  12. jsonify,
  13. abort,
  14. request,
  15. redirect,
  16. url_for,
  17. flash,
  18. )
  19. from larigira.entrypoints_utils import get_avail_entrypoints
  20. from larigira.audiogen import get_audiogenerator
  21. from larigira.timegen_every import FrequencyAlarm
  22. from larigira.timegen import get_timegenerator, timegenerate
  23. from larigira import forms
  24. from larigira.config import get_conf
  25. from .suggestions import get_suggestions
  26. db = Blueprint(
  27. "db",
  28. __name__,
  29. url_prefix=get_conf()["ROUTE_PREFIX"] + "/db",
  30. template_folder="templates",
  31. )
  32. def request_wants_json():
  33. best = request.accept_mimetypes.best_match(["application/json", "text/html"])
  34. return (
  35. best == "application/json"
  36. and request.accept_mimetypes[best] > request.accept_mimetypes["text/html"]
  37. )
  38. def get_model():
  39. return current_app.larigira.controller.monitor.model
  40. @db.route("/")
  41. def home():
  42. return render_template("dbadmin_base.html")
  43. @db.route("/list")
  44. def events_list():
  45. model = current_app.larigira.controller.monitor.model
  46. alarms = tuple(model.get_all_alarms())
  47. events = [(alarm, model.get_actions_by_alarm(alarm)) for alarm in alarms]
  48. return render_template("list.html", events=events)
  49. @db.route("/calendar")
  50. def events_calendar():
  51. model = current_app.larigira.controller.monitor.model
  52. today = datetime.now().date()
  53. maxdays = 30
  54. # {date: {datetime: [(alarm1,actions1), (alarm2,actions2)]}}
  55. days = defaultdict(lambda: defaultdict(list))
  56. freq_threshold = get_conf()["UI_CALENDAR_FREQUENCY_THRESHOLD"]
  57. for alarm in model.get_all_alarms():
  58. if (
  59. freq_threshold
  60. and alarm["kind"] == "frequency"
  61. and FrequencyAlarm(alarm).interval < freq_threshold
  62. ):
  63. continue
  64. actions = tuple(model.get_actions_by_alarm(alarm))
  65. if not actions:
  66. continue
  67. t = datetime.fromtimestamp(int(today.strftime("%s")))
  68. for t in timegenerate(alarm, now=t, howmany=maxdays):
  69. if t is None or t > datetime.combine(
  70. today + timedelta(days=maxdays), time()
  71. ):
  72. break
  73. days[t.date()][t].append((alarm, actions))
  74. # { weeknum: [day1, day2, day3] }
  75. weeks = defaultdict(list)
  76. for d in sorted(days.keys()):
  77. weeks[d.isocalendar()[:2]].append(d)
  78. return render_template("calendar.html", days=days, weeks=weeks)
  79. @db.route("/add/time")
  80. def addtime():
  81. kinds = get_avail_entrypoints("larigira.timeform_create")
  82. def gen_info(gen):
  83. return dict(description=getattr(gen, "description", ""))
  84. info = {kind: gen_info(get_timegenerator(kind)) for kind in kinds}
  85. return render_template("add_time.html", kinds=kinds, info=info)
  86. @db.route("/edit/time/<int:alarmid>", methods=["GET", "POST"])
  87. def edit_time(alarmid):
  88. model = get_model()
  89. timespec = model.get_alarm_by_id(alarmid)
  90. kind = timespec["kind"]
  91. Form, receiver = tuple(forms.get_timeform(kind))
  92. form = Form()
  93. if request.method == "GET":
  94. form.populate_from_timespec(timespec)
  95. if request.method == "POST" and form.validate():
  96. data = receiver(form)
  97. model.update_alarm(alarmid, data)
  98. model.reload()
  99. return redirect(url_for("db.events_list", _anchor="event-%d" % alarmid))
  100. return render_template(
  101. "add_time_kind.html", form=form, kind=kind, mode="edit", alarmid=alarmid
  102. )
  103. @db.route("/add/time/<kind>", methods=["GET", "POST"])
  104. def addtime_kind(kind):
  105. Form, receiver = tuple(forms.get_timeform(kind))
  106. form = Form()
  107. if request.method == "POST" and form.validate():
  108. data = receiver(form)
  109. eid = get_model().add_alarm(data)
  110. return redirect(url_for("db.edit_event", alarmid=eid))
  111. return render_template("add_time_kind.html", form=form, kind=kind, mode="add")
  112. @db.route("/add/audio")
  113. def addaudio():
  114. kinds = get_avail_entrypoints("larigira.audioform_create")
  115. def gen_info(gen):
  116. return dict(description=getattr(gen, "description", ""))
  117. info = {kind: gen_info(get_audiogenerator(kind)) for kind in kinds}
  118. return render_template("add_audio.html", kinds=kinds, info=info)
  119. @db.route("/add/audio/<kind>", methods=["GET", "POST"])
  120. def addaudio_kind(kind):
  121. Form, receiver = tuple(forms.get_audioform(kind))
  122. form = Form()
  123. if request.method == "POST" and form.validate():
  124. data = receiver(form)
  125. model = current_app.larigira.controller.monitor.model
  126. eid = model.add_action(data)
  127. return jsonify(dict(inserted=eid, data=data))
  128. return render_template(
  129. "add_audio_kind.html", form=form, kind=kind, suggestions=get_suggestions()
  130. )
  131. @db.route("/edit/audio/<int:actionid>", methods=["GET", "POST"])
  132. def edit_audio(actionid):
  133. model = get_model()
  134. audiospec = model.get_action_by_id(actionid)
  135. kind = audiospec["kind"]
  136. Form, receiver = tuple(forms.get_audioform(kind))
  137. form = Form()
  138. if request.method == "GET":
  139. form.populate_from_audiospec(audiospec)
  140. if request.method == "POST" and form.validate():
  141. data = receiver(form)
  142. model.update_action(actionid, data)
  143. model.reload()
  144. return redirect(url_for("db.events_list"))
  145. return render_template(
  146. "add_audio_kind.html",
  147. form=form,
  148. kind=kind,
  149. mode="edit",
  150. suggestions=get_suggestions(),
  151. )
  152. @db.route("/edit/event/<alarmid>")
  153. def edit_event(alarmid):
  154. model = current_app.larigira.controller.monitor.model
  155. alarm = model.get_alarm_by_id(int(alarmid))
  156. if alarm is None:
  157. abort(404)
  158. allactions = model.get_all_actions()
  159. actions = tuple(model.get_actions_by_alarm(alarm))
  160. return render_template(
  161. "edit_event.html",
  162. alarm=alarm,
  163. all_actions=allactions,
  164. actions=actions,
  165. routeprefix=get_conf()["ROUTE_PREFIX"],
  166. )
  167. @db.route("/api/alarm/<alarmid>/actions", methods=["POST"])
  168. def change_actions(alarmid):
  169. new_actions = request.form.getlist("actions[]")
  170. if new_actions is None:
  171. new_actions = []
  172. model = current_app.larigira.controller.monitor.model
  173. ret = model.update_alarm(
  174. int(alarmid), new_fields={"actions": [int(a) for a in new_actions]}
  175. )
  176. return jsonify(dict(updated=alarmid, ret=ret))
  177. @db.route("/api/alarm/<int:alarmid>/delete", methods=["POST"])
  178. def delete_alarm(alarmid):
  179. model = current_app.larigira.controller.monitor.model
  180. try:
  181. alarm = model.get_alarm_by_id(int(alarmid))
  182. print(alarm["nick"])
  183. model.delete_alarm(alarmid)
  184. except KeyError:
  185. abort(404)
  186. if request_wants_json():
  187. return jsonify(dict(deleted=alarmid))
  188. flash("Evento %d `%s` cancellato" % (alarmid, alarm["nick"]))
  189. return redirect(url_for("db.events_list"))