Add logging preferences

This commit is contained in:
Andrew Dickinson 2020-04-10 21:50:37 -04:00
parent a8e74c98df
commit edaab5501b
6 changed files with 110 additions and 1 deletions

View file

@ -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

View file

@ -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": [],
}

View file

@ -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
}
}
}

View file

@ -78,6 +78,26 @@
{{ input(form.name) }}
{{ input(form.password) }}
{{ input(form.contact_email) }}
<div class="form-group">
<label for="privacy_checkboxes">{{ _("Privacy Settings") }}</label>
<div id="privacy_checkboxes" class="card card-body bg-light">
<div class="controls">
<input id="logging_enabled" type="checkbox" onchange="updatePrivacySelectFromCheckBoxes()">
<label for="logging_enabled">{{ _("Enable Project History") }}</label>
</div>
<div class="controls">
<div class="ml-4">
<input id="record_ip" type="checkbox" onchange="updatePrivacySelectFromCheckBoxes()">
<label id="record_ip_label" for="record_ip">{{ _("Record IP Adressses") }}</label>
</div>
</div>
</div>
<div class="d-none">
{{ form.logging_preferences }}
<script>updateCheckBoxesFromPrivacySelect()</script>
</div>
</div>
<div class="actions">
<button class="btn btn-primary">{{ _("Edit the project") }}</button>
<a id="delete-project" style="color:red; margin-left:10px; cursor:pointer; ">{{ _("delete") }}</a>

View file

@ -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

View file

@ -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(