Add option to notify users of their own web activity
Ref: ~sircmpwn/todo.sr.ht#94
This commit is contained in:
parent
68e1a17b2a
commit
bb5a0a8ccf
|
@ -239,3 +239,29 @@ select.form-control {
|
|||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move me into core.sr.ht
|
||||
details {
|
||||
padding: 0 1rem;
|
||||
margin: 0 -1rem 1rem;
|
||||
|
||||
summary {
|
||||
background: $gray-300;
|
||||
padding: 0 1rem;
|
||||
margin: 0 -1rem;
|
||||
}
|
||||
|
||||
&[open] {
|
||||
padding: 0 1rem;
|
||||
margin-left: calc(-1rem - 4px);
|
||||
border-left: 4px solid $gray-300;
|
||||
}
|
||||
}
|
||||
|
||||
.prefs {
|
||||
padding: 0.5rem 0;
|
||||
|
||||
.form-check {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ class MailHandler:
|
|||
return "550 Comment must be between 3 and 16384 characters."
|
||||
|
||||
event = add_comment(sender, ticket, text=body,
|
||||
resolution=resolution, resolve=resolve, reopen=reopen)
|
||||
resolution=resolution, resolve=resolve, reopen=reopen, from_email=True)
|
||||
TicketWebhook.deliver(TicketWebhook.Events.event_create,
|
||||
event.to_dict(),
|
||||
TicketWebhook.Subscription.ticket_id == ticket.id)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
"""Add User.notify_self
|
||||
|
||||
Revision ID: 3a9cb6757f59
|
||||
Revises: 6c714f704591
|
||||
Create Date: 2020-09-28 19:11:22.221191
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '3a9cb6757f59'
|
||||
down_revision = '6c714f704591'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('user', sa.Column('notify_self', sa.Boolean,
|
||||
nullable=False, server_default='FALSE'))
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('user', 'notify_self')
|
|
@ -1,12 +1,14 @@
|
|||
from flask import Blueprint, render_template, request, abort
|
||||
from flask import Blueprint, render_template, request, abort, redirect, url_for
|
||||
from todosrht.access import get_tracker, get_access
|
||||
from todosrht.tickets import get_participant_for_user
|
||||
from todosrht.types import Tracker, Ticket, TicketAccess
|
||||
from todosrht.types import Event, EventNotification, EventType
|
||||
from todosrht.types import User, Participant
|
||||
from srht.config import cfg
|
||||
from srht.oauth import current_user
|
||||
from srht.database import db
|
||||
from srht.oauth import current_user, loginrequired
|
||||
from srht.flask import paginate_query, session
|
||||
from srht.validation import Validation
|
||||
from sqlalchemy import and_, or_
|
||||
|
||||
html = Blueprint('html', __name__)
|
||||
|
@ -51,7 +53,7 @@ def filter_authorized_events(events):
|
|||
return events
|
||||
|
||||
@html.route("/")
|
||||
def index():
|
||||
def index_GET():
|
||||
if not current_user:
|
||||
return render_template("index.html")
|
||||
trackers = (Tracker.query
|
||||
|
@ -68,15 +70,25 @@ def index():
|
|||
.order_by(Event.created.desc()))
|
||||
events = events.limit(10).all()
|
||||
|
||||
notice = session.get("notice")
|
||||
if notice:
|
||||
del session["notice"]
|
||||
notice = session.pop("notice", None)
|
||||
prefs_updated = session.pop("prefs_updated", None)
|
||||
|
||||
return render_template("dashboard.html",
|
||||
trackers=trackers, notice=notice,
|
||||
tracker_list_msg="Your Trackers",
|
||||
more_trackers=total_trackers > limit_trackers,
|
||||
events=events, EventType=EventType)
|
||||
events=events, EventType=EventType,
|
||||
prefs_updated=prefs_updated)
|
||||
|
||||
@html.route("/", methods=["POST"])
|
||||
@loginrequired
|
||||
def index_POST():
|
||||
valid = Validation(request)
|
||||
notify_self = valid.require("notify-self")
|
||||
current_user.notify_self = notify_self == "on"
|
||||
db.session.commit()
|
||||
session["prefs_updated"] = True
|
||||
return redirect(url_for("html.index_GET"))
|
||||
|
||||
@html.route("/~<username>")
|
||||
def user_GET(username):
|
||||
|
|
|
@ -214,7 +214,7 @@ def delete_POST(owner, name):
|
|||
{ "id": tracker_id },
|
||||
UserWebhook.Subscription.user_id == owner_id)
|
||||
|
||||
return redirect(url_for("html.index"))
|
||||
return redirect(url_for("html.index_GET"))
|
||||
|
||||
@settings.route("/<owner>/<name>/settings/import-export")
|
||||
@loginrequired
|
||||
|
|
|
@ -51,6 +51,28 @@
|
|||
>
|
||||
Create new tracker {{icon("caret-right")}}
|
||||
</a>
|
||||
<details
|
||||
style="margin: -0.5rem 0 0.5rem 0"
|
||||
{% if prefs_updated %}
|
||||
open
|
||||
{% endif %}
|
||||
>
|
||||
<summary>User preferences</summary>
|
||||
<form method="POST" class="prefs">
|
||||
{{csrf_token()}}
|
||||
<label class="form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="notify-self"
|
||||
id="notify-self"
|
||||
{{ "checked" if current_user.notify_self }} />
|
||||
Notify me of my own activity
|
||||
</label>
|
||||
<button class="btn btn-primary" type="submit">
|
||||
Apply {{icon("caret-right")}}
|
||||
</button>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% if len(trackers) > 0 %}
|
||||
<h3>{{ tracker_list_msg }}</h3>
|
||||
|
|
|
@ -211,7 +211,7 @@ def _change_ticket_status(ticket, resolve, resolution, reopen):
|
|||
old_resolution, ticket.resolution)
|
||||
|
||||
def _send_comment_notifications(
|
||||
participant, ticket, event, comment, resolution):
|
||||
participant, ticket, event, comment, resolution, from_email):
|
||||
"""
|
||||
Notify users subscribed to the ticket or tracker.
|
||||
Returns a list of notified users.
|
||||
|
@ -230,7 +230,7 @@ def _send_comment_notifications(
|
|||
|
||||
for subscriber, subscription in subscriptions.items():
|
||||
_create_event_notification(subscriber, event)
|
||||
if subscriber != participant:
|
||||
if (participant.notify_self and not from_email) or subscriber != participant:
|
||||
_send_comment_notification(
|
||||
subscription, ticket, participant, event, comment, resolution)
|
||||
|
||||
|
@ -295,7 +295,8 @@ def _handle_mentions(ticket, submitter, text, notified_users, comment=None):
|
|||
|
||||
|
||||
def add_comment(submitter, ticket,
|
||||
text=None, resolve=False, resolution=None, reopen=False):
|
||||
text=None, resolve=False, resolution=None, reopen=False,
|
||||
from_email=False):
|
||||
"""
|
||||
Comment on a ticket, optionally resolve or reopen the ticket.
|
||||
"""
|
||||
|
@ -311,7 +312,7 @@ def add_comment(submitter, ticket,
|
|||
return None
|
||||
event = _create_comment_event(ticket, submitter, comment, status_change)
|
||||
notified_participants = _send_comment_notifications(
|
||||
submitter, ticket, event, comment, resolution)
|
||||
submitter, ticket, event, comment, resolution, from_email)
|
||||
|
||||
if comment and comment.text:
|
||||
_handle_mentions(
|
||||
|
@ -406,7 +407,7 @@ def assign(ticket, assignee, assigner):
|
|||
assigner_participant = get_participant_for_user(assigner)
|
||||
|
||||
subscription = get_or_create_subscription(ticket, assignee_participant)
|
||||
if assigner != assignee:
|
||||
if assigner.notify_self or assigner != assignee:
|
||||
notify_assignee(subscription, ticket, assigner, assignee)
|
||||
|
||||
event = Event()
|
||||
|
@ -500,8 +501,8 @@ def submit_ticket(tracker, submitter, title, description,
|
|||
# Send notifications
|
||||
for sub in all_subscriptions.values():
|
||||
_create_event_notification(sub.participant, event)
|
||||
# Notify submitter for tickets created by email
|
||||
if from_email or sub.participant != submitter:
|
||||
# Always notify submitter for tickets created by email
|
||||
if from_email or submitter.notify_self or sub.participant != submitter:
|
||||
_send_new_ticket_notification(sub, ticket, from_email_id)
|
||||
|
||||
_handle_mentions(
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from srht.database import Base
|
||||
from srht.oauth import ExternalUserMixin
|
||||
from srht.oauth import ExternalOAuthTokenMixin
|
||||
import sqlalchemy as sa
|
||||
|
||||
class User(Base, ExternalUserMixin):
|
||||
pass
|
||||
notify_self = sa.Column(sa.Boolean, nullable=False, server_default="FALSE")
|
||||
|
||||
class OAuthToken(Base, ExternalOAuthTokenMixin):
|
||||
pass
|
||||
|
|
|
@ -52,6 +52,13 @@ class Participant(Base):
|
|||
return self.external_id
|
||||
assert False
|
||||
|
||||
@property
|
||||
def notify_self(self):
|
||||
if self.participant_type == ParticipantType.user:
|
||||
return self.user.notify_self
|
||||
else:
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
|
Loading…
Reference in New Issue