Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project schedule notification template #1954

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions funnel/templates/notifications/layout_email.html.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,67 @@
font-weight: bold;
text-align: center;
}

.schedule {
margin: 32px 0 !important;
}
.schedule__date {
font-size: 16px !important;
margin: 0 !important;
text-align: left;
line-height: 1.5;
padding-left: 0 !important;
}
.schedule__table {
margin: 16px 0;
background-color: #fff !important;
overflow: auto;
}
.schedule__row {
overflow: auto;
border-bottom: 1pt solid rgba(132, 146, 166, 0.3) !important;
}
.schedule__row__column--header {
outline: 1px solid rgba(132, 146, 166, 0.3)
border: none !important;
background-color: #fff;
font-size: 16px;
line-height: 1.5;
align: left;
padding: 4px 16px;
width: calc(100% - 150px);
}
.schedule__row__column--time--header {
outline: 1px solid rgba(132, 146, 166, 0.3)
border: none !important;
background-color: #fff;
width: 150px;
padding: 4px 16px;
align: left;
}
.schedule__row__column {
position: relative !important;
outline: 1px solid rgba(132, 146, 166, 0.3)
}
.schedule__row__column__content__title {
width: 100% !important;
}
.schedule__row__column__content__title__duration {
position: relative !important;
background-color: transparent !important;
font-size: 16px !important;
padding: 0 !important;
margin: 0 0 4px !important;
line-height: 1.5 !important;
}
.schedule__row__column__content__title__heading,
.schedule__row__column__content__title__speaker {
font-size: 16px !important;
font-weight: normal !important;
line-height: 1.5 !important;
margin: 0 0 4px;
color: #4d5763;
}
.unsubscribe {
color: #4d5763;
text-decoration: underline;
Expand Down
74 changes: 53 additions & 21 deletions funnel/templates/notifications/macros_email.html.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,61 @@
{%- endmacro -%}

{% macro cta_button(btn_url, btn_text) %}
<tr>
<td>
<div align="center">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ btn_url }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="10%" strokecolor="#4d5763" fillcolor="#4d5763">
<w:anchorlock/>
<center style="color:#ffffff;font-family:sans-serif;font-size:15px;font-weight:bold;">{{ btn_text }}</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]> <!-->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="button-td button-td-primary">
<div>
<a class="button-a button-a-primary" href="{{ btn_url }}">{{ btn_text }}</a>
</div>
</td>
</tr>
<tr>
<td>
<div align="center">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ btn_url }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="10%" strokecolor="#4d5763" fillcolor="#4d5763">
<w:anchorlock/>
<center style="color:#ffffff;font-family:sans-serif;font-size:15px;font-weight:bold;">{{ btn_text }}</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]> <!-->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="button-td button-td-primary">
<div>
<a class="button-a button-a-primary" href="{{ btn_url }}">{{ btn_text }}</a>
</div>
</td>
</tr>
</table>
<!-- <![endif]-->
</div>
</td>
</tr>
{% endmacro %}

{% macro schedule_tables(schedule) %}
<tr>
{% for day, rooms in schedule.items() %}
<table class="schedule">
<h3 class="schedule__date">
<span>{% trans %}{{ day }}{% endtrans %}</span>
</h3>
{% for room, slots in rooms.items() %}
<tbody class="schedule__table">
<tr class="schedule__row">
<th class="schedule__row__column schedule__row__column--time--header">{% trans %}Time{% endtrans %}</th>
<th class="schedule__row__column schedule__row__column--header">{% trans %}{{ room }}{% endtrans %}</th>
</tr>
{% for slot, sessions in slots.items() %}
{% for session in sessions %}
<tr>
<td class="schedule__row__column__content__title__duration">{% trans start_time=session.startTime, end_time=session.endTime %}{{ start_time }}–{{ end_time }}{% endtrans %}</td>
<td class="schedule__row__column__content__title">
{% if session.title %}<p class="schedule__row__column__content__title__heading">{% trans title=session.title %}{{ title }}{% endtrans %}</p>{% endif %}
{% if session.speaker %}<p class="schedule__row__column__content__title__speaker">{% trans speaker=session.speaker %}{{ speaker }}{% endtrans %}</p>{% endif %}
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
{% endfor %}
</table>
<!-- <![endif]-->
</div>
</td>
{% endfor %}
</tr>
<br/>
{% endmacro %}

{% macro rsvp_footer(view, rsvp_linktext) %}
Expand Down
7 changes: 5 additions & 2 deletions funnel/templates/notifications/update_new_email.html.jinja2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{%- extends "notifications/layout_email.html.jinja2" -%}
{%- from "notifications/macros_email.html.jinja2" import cta_button -%}
{%- from "notifications/macros_email.html.jinja2" import cta_button, schedule_tables -%}
{%- block content -%}

<tr>
Expand All @@ -17,7 +17,10 @@
{% trans update_body=view.update.body %}{{ update_body }}{% endtrans %}
</td>
</tr>
<br/>

{# Schedule : BEGIN #}
{{ schedule_tables(schedules) }}
{# Schedule: END #}

{# Button : BEGIN #}
{{ cta_button(view.update.url_for(_external=true, **view.tracking_tags()), gettext("Read on the website") )}}
Expand Down
11 changes: 9 additions & 2 deletions funnel/views/notifications/update_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

from baseframe import _, __

from ...models import Account, NewUpdateNotification, Update
from ...models import Account, NewUpdateNotification, Project, Update
from ...transports.sms import SmsPriority, SmsTemplate
from ..helpers import shortlink
from ..notification import RenderNotification
from ..schedule import upcoming_schedule_data_with_room
from .mixins import TemplateVarMixin


Expand All @@ -33,6 +34,7 @@ class RenderNewUpdateNotification(RenderNotification):
"""Notify crew and participants when the project has a new update."""

update: Update
project: Project
aliases = {'document': 'update'}
emoji_prefix = "📰 "
reason = __(
Expand Down Expand Up @@ -62,7 +64,12 @@ def email_subject(self) -> str:
)

def email_content(self) -> str:
return render_template('notifications/update_new_email.html.jinja2', view=self)
schedules = upcoming_schedule_data_with_room(self.project)
return render_template(
'notifications/update_new_email.html.jinja2',
view=self,
schedules=schedules,
)

def sms(self) -> UpdateTemplate:
return UpdateTemplate(
Expand Down
18 changes: 17 additions & 1 deletion funnel/views/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from collections import defaultdict
from datetime import timedelta
from datetime import datetime, timedelta
from types import SimpleNamespace
from typing import TYPE_CHECKING, Any, cast

Expand Down Expand Up @@ -115,6 +115,22 @@ def schedule_data(
return schedule


def upcoming_schedule_data_with_room(project: Project) -> list[dict]:
schedule = schedule_data(project)
schedule_with_room = []
for key, day in schedule:
if datetime.strptime(key, '%y-%m-%d') >= datetime.today():
daydata_with_room: dict[str, dict[str, list]] = defaultdict(
lambda: defaultdict(list)
)
for slots in schedule[day]:
roomdata: dict[str, Any] = {'date': day, 'rooms': defaultdict(list)}
roomdata[slots.sessions.room_scoped_name].append(slots)
daydata_with_room[day]['rooms'].append(roomdata)
schedule_with_room.append(daydata_with_room)
return schedule_with_room


def schedule_ical(
project: Project, rsvp: Rsvp | None = None, future_only: bool = False
) -> bytes:
Expand Down
4 changes: 2 additions & 2 deletions sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ FLASK_CACHE_REDIS_URL=redis://${REDIS_HOST}:6379/0
# --- Database configuration
DB_HOST=localhost
# Main app database
FLASK_SQLALCHEMY_DATABASE_URI='postgresql+psycopg:///funnel'
FLASK_SQLALCHEMY_DATABASE_URI='postgresql+psycopg:///funnel_test'
# Geoname database (the use of `__` creates a dict and sets a key in the dict)
FLASK_SQLALCHEMY_BINDS__geoname='postgresql+psycopg:///geoname'
FLASK_SQLALCHEMY_BINDS__geoname='postgresql+psycopg:///geoname_testing'

# --- Email configuration
# SMTP mail server ('localhost' if Postfix is configured as a relay email server)
Expand Down
Loading