Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
protokollsystem
proto3
Commits
8685fc76
Commit
8685fc76
authored
Feb 26, 2017
by
Robin Sonnabend
Browse files
Todomails
parent
104cb90c
Changes
12
Hide whitespace changes
Inline
Side-by-side
migrations/versions/188f389b2286_.py
0 → 100644
View file @
8685fc76
"""empty message
Revision ID: 188f389b2286
Revises: 515d261a624b
Create Date: 2017-02-26 12:55:43.761405
"""
from
alembic
import
op
import
sqlalchemy
as
sa
# revision identifiers, used by Alembic.
revision
=
'188f389b2286'
down_revision
=
'515d261a624b'
branch_labels
=
None
depends_on
=
None
def
upgrade
():
# ### commands auto generated by Alembic - please adjust! ###
op
.
create_table
(
'todomails'
,
sa
.
Column
(
'id'
,
sa
.
Integer
(),
nullable
=
False
),
sa
.
Column
(
'name'
,
sa
.
String
(),
nullable
=
True
),
sa
.
Column
(
'mail'
,
sa
.
String
(),
nullable
=
True
),
sa
.
PrimaryKeyConstraint
(
'id'
),
sa
.
UniqueConstraint
(
'name'
)
)
# ### end Alembic commands ###
def
downgrade
():
# ### commands auto generated by Alembic - please adjust! ###
op
.
drop_table
(
'todomails'
)
# ### end Alembic commands ###
models/database.py
View file @
8685fc76
...
...
@@ -5,7 +5,7 @@ import math
from
io
import
StringIO
,
BytesIO
from
shared
import
db
from
utils
import
random_string
,
url_manager
,
get_etherpad_url
from
utils
import
random_string
,
url_manager
,
get_etherpad_url
,
split_terms
from
models.errors
import
DateNotMatchingException
import
os
...
...
@@ -326,6 +326,12 @@ class Todo(db.Model):
return
None
return
candidates
[
0
]
def
get_users
(
self
):
return
[
user
.
lower
().
strip
()
for
user
in
split_terms
(
self
.
who
,
separators
=
" ,
\t
"
)
]
def
get_state
(
self
):
return
"[Erledigt]"
if
self
.
done
else
"[Offen]"
def
get_state_plain
(
self
):
...
...
@@ -428,3 +434,20 @@ class Error(db.Model):
if
len
(
lines
)
<=
4
:
return
"
\n
"
.
join
(
lines
)
return
"
\n
"
.
join
(
lines
[:
2
],
"…"
,
lines
[
-
2
:])
class
TodoMail
(
db
.
Model
):
__tablename__
=
"todomails"
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
name
=
db
.
Column
(
db
.
String
,
unique
=
True
)
mail
=
db
.
Column
(
db
.
String
)
def
__init__
(
self
,
name
,
mail
):
self
.
name
=
name
self
.
mail
=
mail
def
__repr__
(
self
):
return
"<TodoMail(name='{}', mail='{}')>"
.
format
(
self
.
name
,
self
.
mail
)
def
get_formatted_mail
(
self
):
return
"{} <{}>"
.
format
(
self
.
name
,
self
.
mail
)
server.py
View file @
8685fc76
...
...
@@ -21,9 +21,9 @@ import math
import
config
from
shared
import
db
,
date_filter
,
datetime_filter
,
date_filter_long
,
time_filter
,
ldap_manager
,
security_manager
,
current_user
,
check_login
,
login_required
,
group_required
,
class_filter
from
utils
import
is_past
,
mail_manager
,
url_manager
,
get_first_unused_int
,
set_etherpad_text
,
get_etherpad_text
,
split_terms
,
optional_int_arg
from
models.database
import
ProtocolType
,
Protocol
,
DefaultTOP
,
TOP
,
Document
,
Todo
,
Decision
,
MeetingReminder
,
Error
from
views.forms
import
LoginForm
,
ProtocolTypeForm
,
DefaultTopForm
,
MeetingReminderForm
,
NewProtocolForm
,
DocumentUploadForm
,
KnownProtocolSourceUploadForm
,
NewProtocolSourceUploadForm
,
ProtocolForm
,
TopForm
,
SearchForm
,
NewProtocolFileUploadForm
,
NewTodoForm
,
TodoForm
from
views.tables
import
ProtocolsTable
,
ProtocolTypesTable
,
ProtocolTypeTable
,
DefaultTOPsTable
,
MeetingRemindersTable
,
ErrorsTable
,
TodosTable
,
DocumentsTable
,
DecisionsTable
,
TodoTable
,
ErrorTable
from
models.database
import
ProtocolType
,
Protocol
,
DefaultTOP
,
TOP
,
Document
,
Todo
,
Decision
,
MeetingReminder
,
Error
,
TodoMail
from
views.forms
import
LoginForm
,
ProtocolTypeForm
,
DefaultTopForm
,
MeetingReminderForm
,
NewProtocolForm
,
DocumentUploadForm
,
KnownProtocolSourceUploadForm
,
NewProtocolSourceUploadForm
,
ProtocolForm
,
TopForm
,
SearchForm
,
NewProtocolFileUploadForm
,
NewTodoForm
,
TodoForm
,
TodoMailForm
from
views.tables
import
ProtocolsTable
,
ProtocolTypesTable
,
ProtocolTypeTable
,
DefaultTOPsTable
,
MeetingRemindersTable
,
ErrorsTable
,
TodosTable
,
DocumentsTable
,
DecisionsTable
,
TodoTable
,
ErrorTable
,
TodoMailsTable
app
=
Flask
(
__name__
)
app
.
config
.
from_object
(
config
)
...
...
@@ -977,6 +977,53 @@ def delete_error(error_id):
db
.
session
.
commit
()
flash
(
"Fehler {} gelöscht."
.
format
(
name
),
"alert-success"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_errors"
))
@
app
.
route
(
"/todomails/list"
)
@
login_required
def
list_todomails
():
todomails
=
TodoMail
.
query
.
all
()
todomails_table
=
TodoMailsTable
(
todomails
)
return
render_template
(
"todomails-list.html"
,
todomails
=
todomails
,
todomails_table
=
todomails_table
)
@
app
.
route
(
"/todomail/new"
,
methods
=
[
"GET"
,
"POST"
])
@
login_required
def
new_todomail
():
form
=
TodoMailForm
()
if
form
.
validate_on_submit
():
todomail
=
TodoMail
(
form
.
name
.
data
,
form
.
mail
.
data
)
db
.
session
.
add
(
todomail
)
db
.
session
.
commit
()
flash
(
"Die Todomailzuordnung für {} wurde angelegt."
.
format
(
todomail
.
name
),
"alert-success"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_todomails"
))
return
render_template
(
"todomail-new.html"
,
form
=
form
)
@
app
.
route
(
"/todomail/edit/<int:todomail_id>"
,
methods
=
[
"GET"
,
"POST"
])
@
login_required
def
edit_todomail
(
todomail_id
):
todomail
=
TodoMail
.
query
.
filter_by
(
id
=
todomail_id
).
first
()
if
todomail
is
None
:
flash
(
"Invalide Todo-Mail-Zuordnung."
,
"alert-error"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_todomails"
))
form
=
TodoMailForm
(
obj
=
todomail
)
if
form
.
validate_on_submit
():
form
.
populate_obj
(
todomail
)
db
.
session
.
commit
()
flash
(
"Die Todo-Mail-Zuordnung wurde geändert."
,
"alert-success"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_todomails"
))
return
render_template
(
"todomail-edit.html"
,
todomail
=
todomail
,
form
=
form
)
@
app
.
route
(
"/todomail/delete/<int:todomail_id>"
)
@
login_required
def
delete_todomail
(
todomail_id
):
todomail
=
TodoMail
.
query
.
filter_by
(
id
=
todomail_id
).
first
()
if
todomail
is
None
:
flash
(
"Invalide Todomailzuordnung."
,
"alert-error"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_todomails"
))
name
=
todomail
.
name
db
.
session
.
delete
(
todomail
)
db
.
session
.
commit
()
flash
(
"Die Todo-Mail-Zuordnung für {} wurde gelöscht."
.
format
(
name
),
"alert-success"
)
return
redirect
(
request
.
args
.
get
(
"next"
)
or
url_for
(
"list_todomails"
))
@
app
.
route
(
"/login"
,
methods
=
[
"GET"
,
"POST"
])
...
...
tasks.py
View file @
8685fc76
...
...
@@ -5,7 +5,7 @@ import subprocess
import
shutil
import
tempfile
from
models.database
import
Document
,
Protocol
,
Error
,
Todo
,
Decision
,
TOP
,
DefaultTOP
,
MeetingReminder
from
models.database
import
Document
,
Protocol
,
Error
,
Todo
,
Decision
,
TOP
,
DefaultTOP
,
MeetingReminder
,
TodoMail
from
models.errors
import
DateNotMatchingException
from
server
import
celery
,
app
from
shared
import
db
,
escape_tex
,
unhyphen
,
date_filter
,
datetime_filter
,
date_filter_long
,
date_filter_short
,
time_filter
,
class_filter
...
...
@@ -324,6 +324,7 @@ def send_reminder_async(reminder_id, protocol_id):
def
send_protocol
(
protocol
):
send_protocol_async
.
delay
(
protocol
.
id
,
show_private
=
True
)
send_protocol_async
.
delay
(
protocol
.
id
,
show_private
=
False
)
send_todomails_async
.
delay
(
protocol
.
id
)
@
celery
.
task
def
send_protocol_async
(
protocol_id
,
show_private
):
...
...
@@ -338,6 +339,27 @@ def send_protocol_async(protocol_id, show_private):
]
send_mail
(
protocol
,
to_addr
,
subject
,
mail_content
,
appendix
)
@
celery
.
task
def
send_todomails_async
(
protocol_id
):
with
app
.
app_context
():
protocol
=
Protocol
.
query
.
filter_by
(
id
=
protocol_id
).
first
()
all_todos
=
Todo
.
query
.
filter
(
Todo
.
done
==
False
).
all
()
users
=
{
user
for
todo
in
all_todos
for
user
in
todo
.
get_users
()}
grouped_todos
=
{
user
:
[
todo
for
todo
in
all_todos
if
user
in
todo
.
get_users
()]
for
user
in
users
}
subject
=
"Du hast noch was zu tun!"
for
user
in
users
:
todomail
=
TodoMail
.
query
.
filter
(
TodoMail
.
name
.
ilike
(
user
)).
first
()
if
todomail
is
None
:
error
=
protocol
.
create_error
(
"Sending Todomail"
,
"Sending Todomail failed."
,
"User {} has no Todo-Mail-Assignment."
.
format
(
user
))
db
.
session
.
add
(
error
)
db
.
session
.
commit
()
continue
to_addr
=
todomail
.
get_formatted_mail
()
mail_content
=
render_template
(
"todo-mail.txt"
,
protocol
=
protocol
,
todomail
=
todomail
,
todos
=
grouped_todos
[
user
])
send_mail
(
protocol
,
to_addr
,
subject
,
mail_content
)
def
send_mail
(
protocol
,
to_addr
,
subject
,
content
,
appendix
=
None
):
if
to_addr
is
not
None
and
len
(
to_addr
.
strip
())
>
0
:
...
...
templates/layout.html
View file @
8685fc76
...
...
@@ -27,7 +27,7 @@
<div
id=
"navbar"
class=
"navbar-collapse collapse"
>
<ul
class=
"nav navbar-nav"
>
{% if check_login() %}
<li><a
href=
"{{url_for("
new_protocol
")}}"
>
Neu
es Protokoll
</a></li>
<li><a
href=
"{{url_for("
new_protocol
")}}"
>
Neu
</a></li>
{% endif %}
<li><a
href=
"{{url_for("
list_protocols
")}}"
>
Protokolle
</a></li>
{% if check_login() %}
...
...
@@ -37,6 +37,7 @@
{% if check_login() %}
<li><a
href=
"{{url_for("
list_types
")}}"
>
Typen
</a></li>
<li><a
href=
"{{url_for("
list_errors
")}}"
>
Fehler
</a></li>
<li><a
href=
"{{url_for("
list_todomails
")}}"
>
Todo Mails
</a></li>
{% endif %}
{# todo: add more links #}
</ul>
...
...
templates/todo-mail.txt
0 → 100644
View file @
8685fc76
Hallo {{todomail.name}},
Du hast für "{{protocol.protocoltype.name}}" noch offene Todos:
{% for todo in todos %}
{{todo.who}}:
{{todo.description}}
{% endfor %}
Fühle die hiermit daran erinnert!
Viele Grüße,
Dein Protokollsystem
templates/todomail-edit.html
0 → 100644
View file @
8685fc76
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}Todomail ändern{% endblock %}
{% block content %}
<div
class=
"container"
>
{{render_form(form, action_url=url_for("edit_todomail", todomail_id=todomail.id), action_text="Ändern")}}
</div>
{% endblock %}
templates/todomail-new.html
0 → 100644
View file @
8685fc76
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}Neue Todomail{% endblock %}
{% block content %}
<div
class=
"container"
>
{{render_form(form, action_url=url_for("new_todomail"), action_text="Ändern")}}
</div>
{% endblock %}
templates/todomails-list.html
0 → 100644
View file @
8685fc76
{% extends "layout.html" %}
{% from "macros.html" import render_table %}
{% block title %}Todomails{% endblock %}
{% block content %}
<div
class=
"container"
>
{{render_table(todomails_table)}}
</div>
{% endblock %}
utils.py
View file @
8685fc76
...
...
@@ -75,6 +75,7 @@ class MailManager:
or
not
self
.
username
or
not
self
.
password
or
not
self
.
from_addr
):
print
(
"Not sending mail {} to {}"
.
format
(
subject
,
to_addr
))
return
msg
=
MIMEMultipart
(
"mixed"
)
# todo: test if clients accept attachment-free mails set to multipart/mixed
msg
[
"From"
]
=
self
.
from_addr
...
...
views/forms.py
View file @
8685fc76
...
...
@@ -108,3 +108,7 @@ class TodoForm(FlaskForm):
description
=
StringField
(
"Aufgabe"
,
validators
=
[
InputRequired
(
"Bitte gib an, was erledigt werden soll."
)])
tags
=
StringField
(
"Weitere Tags"
)
done
=
BooleanField
(
"Erledigt"
)
class
TodoMailForm
(
FlaskForm
):
name
=
StringField
(
"Name"
,
validators
=
[
InputRequired
(
"Du musst den Namen angeben, der zugeordnet werden soll."
)])
mail
=
StringField
(
"Mail"
,
validators
=
[
InputRequired
(
"Du musst die Mailadresse angeben, die zugeordnet werden soll."
)])
views/tables.py
View file @
8685fc76
...
...
@@ -314,3 +314,21 @@ class DocumentsTable(Table):
if
document
.
protocol
.
protocoltype
.
has_modify_right
(
user
)
else
""
]
class
TodoMailsTable
(
Table
):
def
__init__
(
self
,
todomails
):
super
().
__init__
(
"Todo-Mail-Zuordnungen"
,
todomails
,
url_for
(
"new_todomail"
))
def
headers
(
self
):
return
[
"Name"
,
"Mail"
,
""
]
def
row
(
self
,
todomail
):
return
[
todomail
.
name
,
todomail
.
mail
,
Table
.
concat
([
Table
.
link
(
url_for
(
"edit_todomail"
,
todomail_id
=
todomail
.
id
),
"Ändern"
),
Table
.
link
(
url_for
(
"delete_todomail"
,
todomail_id
=
todomail
.
id
),
"Löschen"
,
confirm
=
"Bist du dir sicher, dass du die Todomailzuordnung {} zu {} löschen willst?"
.
format
(
todomail
.
name
,
todomail
.
mail
))
])
]
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment