Implement mail tracker system
* Implement mail tracking Signed-off-by: Victor "multun" Collod <victor.collod@prologin.org> * Implement task merging * Add a mail tracker title format pattern * Autocomplete task names * Fix comment display * Track notification answers * Add a socket timeout for the mail worker A mail worker is a long running application. And sometimes, the IMAP server just hangs for hours for no apparent reason. imaplib doesn't enable setting a timeout, and setting it globally seems fine. * Only validate the merge form when submitted * Redirect to the new form when merging * Prettier task edit UI * Make task merging optional * Test mail tracking * Update documentation for mail tracking * Update dependencies * Add the TODO_COMMENT_CLASSES setting * Fix dependencies install order * Remove debug leftovers, improve documentation * Fail on missing from_address
This commit is contained in:
parent
d0212b8a55
commit
c7ad961ef3
28 changed files with 1069 additions and 136 deletions
|
@ -2,9 +2,7 @@
|
|||
|
||||
<form action="" name="add_task" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
|
||||
<div id="AddEditTask" class="collapse mt-3">
|
||||
<div class="mt-3">
|
||||
<div class="form-group">
|
||||
<label for="id_title" name="title">Task</label>
|
||||
<input type="text" class="form-control" id="id_title" name="title" required placeholder="Task title"
|
||||
|
@ -33,12 +31,15 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="id_notify">Notify</label>
|
||||
<input type="checkbox" checked="checked" class="form-control" id="id_notify" name="notify" aria-describedby="inputNotifyHelp"
|
||||
value="{{ form.notify.text }}">
|
||||
<small id="inputNotifyHelp" class="form-text text-muted">
|
||||
Email notifications will only be sent if task is assigned to someone other than yourself.
|
||||
</small>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" aria-describedby="inputNotifyHelp" checked="checked" id="id_notify">
|
||||
<label class="form-check-label" for="id_notify">
|
||||
Notify
|
||||
</label>
|
||||
<small id="inputNotifyHelp" class="form-text text-muted">
|
||||
Email notifications will only be sent if task is assigned to someone other than yourself.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="priority"
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
data-toggle="collapse" data-target="#AddEditTask">Add Task</button>
|
||||
|
||||
{# Task edit / new task form #}
|
||||
{% include 'todo/include/task_edit.html' %}
|
||||
<div id="AddEditTask" class="collapse">
|
||||
{% include 'todo/include/task_edit.html' %}
|
||||
</div>
|
||||
<hr />
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -2,50 +2,63 @@
|
|||
|
||||
{% block title %}Task:{{ task.title }}{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
<style>
|
||||
.select2 {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
min-width: 0 !important;
|
||||
}
|
||||
</style>
|
||||
{{ form.media }}
|
||||
{{ merge_form.media }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<h3 class="card-title">{{ task.title }}</h3>
|
||||
{% if task.note %}
|
||||
<p class="card-text">{{ task.note|safe|urlize|linebreaks }}</p>
|
||||
{% endif %}
|
||||
<div class="card-deck">
|
||||
<div class="card col-sm-8">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">{{ task.title }}</h3>
|
||||
{% if task.note %}
|
||||
<div class="card-text">{{ task.note|safe|urlize|linebreaks }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<div class="mb-2">
|
||||
|
||||
<button
|
||||
class="btn btn-sm btn-primary"
|
||||
id="EditTaskButton"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#AddEditTask"
|
||||
>
|
||||
<div class="card col-sm-4 p-0">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<button
|
||||
class="btn btn-sm btn-primary"
|
||||
id="EditTaskButton"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#TaskEdit">
|
||||
Edit Task
|
||||
</button>
|
||||
</button>
|
||||
|
||||
<form method="post" action="{% url "todo:task_toggle_done" task.id %}" role="form" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<div style="display:inline;">
|
||||
<button class="btn btn-info btn-sm" type="submit" name="toggle_done">
|
||||
{% if task.completed %} Mark Not Done {% else %} Mark Done {% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="post" action="{% url "todo:delete_task" task.id %}" role="form" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<div style="display:inline;">
|
||||
<button class="btn btn-danger btn-sm" type="submit" name="submit_delete">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<ul class="list-group">
|
||||
<form method="post" action="{% url "todo:task_toggle_done" task.id %}" role="form" class="d-inline">
|
||||
{% csrf_token %}
|
||||
<div style="display:inline;">
|
||||
<button class="btn btn-info btn-sm" type="submit" name="toggle_done">
|
||||
{% if task.completed %} Mark Not Done {% else %} Mark Done {% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="post" action="{% url "todo:delete_task" task.id %}" role="form" class="d-inline">
|
||||
{% csrf_token %}
|
||||
<div style="display:inline;">
|
||||
<button class="btn btn-danger btn-sm" type="submit" name="submit_delete">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Assigned to:</strong>
|
||||
{% if task.assigned_to %} {{ task.assigned_to.get_full_name }} {% else %} Anyone {% endif %}
|
||||
|
@ -77,35 +90,65 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="TaskEdit">
|
||||
<div id="TaskEdit" class="collapse">
|
||||
{# Task edit / new task form #}
|
||||
{% include 'todo/include/task_edit.html' %}
|
||||
{% if merge_form is not None %}
|
||||
<form action="" method="post">
|
||||
<div class="card border-danger">
|
||||
<div class="card-header">Merge task</div>
|
||||
<div class="card-body">
|
||||
<div class="">
|
||||
<p>Merging is a destructive operation. This task will not exist anymore, and comments will be moved to the target task.</p>
|
||||
{% csrf_token %}
|
||||
{% for field in merge_form.visible_fields %}
|
||||
<p>
|
||||
{{ field.errors }}
|
||||
{{ field }}
|
||||
</p>
|
||||
{% endfor %}
|
||||
<input class="d-inline btn btn-sm btn-outline-danger" type="submit" name="merge_task_into" value="Merge">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h5>Add comment</h5>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" name="comment-body" rows="3"></textarea>
|
||||
</div>
|
||||
<input class="btn btn-sm btn-primary" type="submit" name="add_comment" value="Add Comment">
|
||||
</form>
|
||||
<div class="mt-3">
|
||||
<h5>Add comment</h5>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" name="comment-body" rows="3"></textarea>
|
||||
</div>
|
||||
<input class="btn btn-sm btn-primary" type="submit" name="add_comment" value="Add Comment">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="task_comments mt-4">
|
||||
{% if comment_list %}
|
||||
<h5>Comments on this task</h5>
|
||||
{% for comment in comment_list %}
|
||||
<p>
|
||||
<strong>{{ comment.author.first_name }}
|
||||
{{ comment.author.last_name }},
|
||||
<div class="mb-3 card">
|
||||
<div class="card-header">
|
||||
<div class="float-left">
|
||||
{% if comment.email_message_id %}
|
||||
<span class="badge badge-warning">email</span>
|
||||
{% endif %}
|
||||
{{ comment.author_text }}
|
||||
</div>
|
||||
<span class="float-right d-inline-block text-muted">
|
||||
{{ comment.date|date:"F d Y P" }}
|
||||
</strong>
|
||||
</p>
|
||||
{{ comment.body|safe|urlize|linebreaks }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="{{ comment_classes | join:" " }} card-body">
|
||||
{{ comment.body|safe|urlize|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h5>No comments (yet).</h5>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue