From edaab5501b9ac4c2c179d1258d4546f0a9520af4 Mon Sep 17 00:00:00 2001 From: Andrew Dickinson Date: Fri, 10 Apr 2020 21:50:37 -0400 Subject: [PATCH] Add logging preferences --- ihatemoney/forms.py | 10 ++++++- ihatemoney/models.py | 3 +++ ihatemoney/static/js/ihatemoney.js | 43 ++++++++++++++++++++++++++++++ ihatemoney/templates/forms.html | 20 ++++++++++++++ ihatemoney/utils.py | 34 +++++++++++++++++++++++ ihatemoney/web.py | 1 + 6 files changed, 110 insertions(+), 1 deletion(-) diff --git a/ihatemoney/forms.py b/ihatemoney/forms.py index 88afd296..9d17cb40 100644 --- a/ihatemoney/forms.py +++ b/ihatemoney/forms.py @@ -23,7 +23,7 @@ from jinja2 import Markup import email_validator from ihatemoney.models import Project, Person -from ihatemoney.utils import slugify, eval_arithmetic_expression +from ihatemoney.utils import slugify, eval_arithmetic_expression, LoggingMode def strip_filter(string): @@ -89,6 +89,12 @@ class EditProjectForm(FlaskForm): name = StringField(_("Project name"), validators=[DataRequired()]) password = StringField(_("Private code"), validators=[DataRequired()]) contact_email = StringField(_("Email"), validators=[DataRequired(), Email()]) + logging_preferences = SelectField( + _("Logging Preferences"), + choices=LoggingMode.choices(), + coerce=LoggingMode.coerce, + default=LoggingMode.default(), + ) def save(self): """Create a new project with the information given by this form. @@ -100,6 +106,7 @@ class EditProjectForm(FlaskForm): id=self.id.data, password=generate_password_hash(self.password.data), contact_email=self.contact_email.data, + logging_preference=self.logging_preferences.data, ) return project @@ -108,6 +115,7 @@ class EditProjectForm(FlaskForm): project.name = self.name.data project.password = generate_password_hash(self.password.data) project.contact_email = self.contact_email.data + project.logging_preference = self.logging_preferences.data return project diff --git a/ihatemoney/models.py b/ihatemoney/models.py index 4d32fd97..8a823f2e 100644 --- a/ihatemoney/models.py +++ b/ihatemoney/models.py @@ -7,6 +7,7 @@ from flask import g, current_app from debts import settle from sqlalchemy import orm from sqlalchemy.sql import func +from ihatemoney.utils import LoggingMode from itsdangerous import ( TimedJSONWebSignatureSerializer, URLSafeSerializer, @@ -27,6 +28,7 @@ class Project(db.Model): name = db.Column(db.UnicodeText) password = db.Column(db.String(128)) contact_email = db.Column(db.String(128)) + logging_preference = db.Column(db.Enum(LoggingMode), default=LoggingMode.default()) members = db.relationship("Person", backref="project") query_class = ProjectQuery @@ -37,6 +39,7 @@ class Project(db.Model): "id": self.id, "name": self.name, "contact_email": self.contact_email, + "logging_preference": self.logging_preference.value, "members": [], } diff --git a/ihatemoney/static/js/ihatemoney.js b/ihatemoney/static/js/ihatemoney.js index c240dc1a..8a7145df 100644 --- a/ihatemoney/static/js/ihatemoney.js +++ b/ihatemoney/static/js/ihatemoney.js @@ -5,3 +5,46 @@ function selectCheckboxes(value){ els[i].checked = value; } } + +function updateCheckBoxesFromPrivacySelect() { + var history_checkbox = document.getElementById('logging_enabled'); + var record_ip_checkbox = document.getElementById('record_ip'); + var record_ip_checkbox_text = document.getElementById("record_ip_label"); + var select_input = document.getElementById("logging_preferences"); + + if (select_input.selectedIndex === 0) { + history_checkbox.checked = false; + record_ip_checkbox.checked = false; + record_ip_checkbox.disabled = true; + record_ip_checkbox_text.classList.add("text-muted"); + } else if (select_input.selectedIndex === 1 || select_input.selectedIndex === 2) { + history_checkbox.checked = true; + record_ip_checkbox.disabled = false; + record_ip_checkbox_text.classList.remove("text-muted"); + if (select_input.selectedIndex === 2) { + record_ip_checkbox.checked = true + } + } +} + +function updatePrivacySelectFromCheckBoxes() { + var history_checkbox = document.getElementById('logging_enabled'); + var record_ip_checkbox = document.getElementById('record_ip'); + var record_ip_checkbox_text = document.getElementById("record_ip_label"); + var select_input = document.getElementById("logging_preferences"); + + if (!history_checkbox.checked) { + record_ip_checkbox.checked = false; + record_ip_checkbox.disabled = true; + record_ip_checkbox_text.classList.add("text-muted"); + select_input.selectedIndex = 0 + } else { + record_ip_checkbox.disabled = false; + record_ip_checkbox_text.classList.remove("text-muted"); + if (record_ip_checkbox.checked){ + select_input.selectedIndex = 2 + } else { + select_input.selectedIndex = 1 + } + } +} \ No newline at end of file diff --git a/ihatemoney/templates/forms.html b/ihatemoney/templates/forms.html index bec70184..7401a80b 100644 --- a/ihatemoney/templates/forms.html +++ b/ihatemoney/templates/forms.html @@ -78,6 +78,26 @@ {{ input(form.name) }} {{ input(form.password) }} {{ input(form.contact_email) }} +
+ +
+
+ + +
+
+
+ + +
+
+
+
+ {{ form.logging_preferences }} + +
+
+
{{ _("delete") }} diff --git a/ihatemoney/utils.py b/ihatemoney/utils.py index 126b9dee..ad2a40b8 100644 --- a/ihatemoney/utils.py +++ b/ihatemoney/utils.py @@ -2,6 +2,7 @@ import re import os import ast import operator +from enum import Enum from io import BytesIO, StringIO @@ -257,3 +258,36 @@ def same_bill(bill1, bill2): if bill1[a] != bill2[a]: return False return True + + +class FormEnum(Enum): + """Extend builtin Enum class to be seamlessly compatible with WTForms""" + + @classmethod + def choices(cls): + return [(choice, choice.name) for choice in cls] + + @classmethod + def coerce(cls, item): + """Coerce a str or int representation into an Enum object""" + if isinstance(item, cls): + return item + + # If item is not already a Enum object then it must be + # a string or int corresponding to an ID (e.g. '0' or 1) + # Either int() or cls() will correctly throw a TypeError if this + # is not the case + return cls(int(item)) + + def __str__(self): + return str(self.value) + + +class LoggingMode(FormEnum): + DISABLED = 0 + ENABLED = 1 + RECORD_IP = 2 + + @classmethod + def default(cls): + return cls.ENABLED diff --git a/ihatemoney/web.py b/ihatemoney/web.py index 1b80ab62..55b4fd65 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -391,6 +391,7 @@ def edit_project(): return redirect(url_for(".list_bills")) else: edit_form.name.data = g.project.name + edit_form.logging_preferences.data = g.project.logging_preference edit_form.contact_email.data = g.project.contact_email return render_template(