mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-06 13:01:50 +02:00
Add logging preferences
This commit is contained in:
parent
a8e74c98df
commit
edaab5501b
6 changed files with 110 additions and 1 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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": [],
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue