Enhance newsletter HTML generation and UI components
- Introduce helper functions `_outlook_font` and `_outlook_link` for better formatting in Outlook-compatible HTML. - Update `create_outlook_html` to utilize new font and link functions, improving the overall appearance of the newsletter. - Modify CSS to add styles for a new copy dialog overlay and related components. - Refactor JavaScript to improve copy functionality and add a dialog for copying HTML content. - Update dashboard template to enhance user instructions for copying and downloading HTML content.
This commit is contained in:
@@ -263,6 +263,28 @@ OUTLOOK_MUTED = "#666666"
|
||||
OUTLOOK_LINK = "#0563C1"
|
||||
OUTLOOK_HEADING = "#003366"
|
||||
OUTLOOK_BORDER = "#DDDDDD"
|
||||
OUTLOOK_WHITE = "#FFFFFF"
|
||||
|
||||
|
||||
def _outlook_font(
|
||||
text: str,
|
||||
*,
|
||||
color: str = OUTLOOK_TEXT,
|
||||
size: str = "2",
|
||||
bold: bool = False,
|
||||
) -> str:
|
||||
inner = escape(text)
|
||||
if bold:
|
||||
inner = f"<b>{inner}</b>"
|
||||
return f'<font face="Arial" color="{color}" size="{size}">{inner}</font>'
|
||||
|
||||
|
||||
def _outlook_link(title: str, url: str) -> str:
|
||||
return (
|
||||
f'<a href="{escape(url)}">'
|
||||
f'<font face="Arial" color="{OUTLOOK_LINK}" size="2">{escape(title)}</font>'
|
||||
f"</a>"
|
||||
)
|
||||
|
||||
|
||||
def create_outlook_html(
|
||||
@@ -271,18 +293,18 @@ def create_outlook_html(
|
||||
display: DisplayOptions | None = None,
|
||||
category: str = "",
|
||||
) -> str:
|
||||
"""Vereinfachtes HTML für Outlook/Word – nur Tabellen und Inline-Styles."""
|
||||
"""Word/Outlook-kompatibles HTML mit font-Tags und bgcolor (überlebt Einfügen in Outlook)."""
|
||||
display = display or DEFAULT_DISPLAY
|
||||
new_articles, edited_articles = split_articles_by_type(articles)
|
||||
period_start, period_end = _period_range(days)
|
||||
created_at = datetime.now().strftime("%d.%m.%Y %H:%M")
|
||||
intro = escape(_intro_sentence(period_start, period_end))
|
||||
intro = _intro_sentence(period_start, period_end)
|
||||
subject = escape(create_subject(days, category))
|
||||
|
||||
if not new_articles and not edited_articles:
|
||||
body_rows = f"""<tr>
|
||||
<td style="padding:12px 0;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_MUTED};">
|
||||
Im gewählten Zeitraum wurden keine passenden Wiki-Änderungen gefunden.
|
||||
<td bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:12px 0;">
|
||||
{_outlook_font("Im gewählten Zeitraum wurden keine passenden Wiki-Änderungen gefunden.", color=OUTLOOK_MUTED)}
|
||||
</td>
|
||||
</tr>"""
|
||||
else:
|
||||
@@ -300,15 +322,18 @@ def create_outlook_html(
|
||||
|
||||
category_block = ""
|
||||
if category.strip():
|
||||
category_block = f"""<p style="margin:0 0 8px;font-family:{OUTLOOK_FONT};font-size:10pt;color:{OUTLOOK_MUTED};">
|
||||
<strong style="font-family:{OUTLOOK_FONT};color:{OUTLOOK_HEADING};">Filter:</strong> Kategorie {escape(category.strip())}
|
||||
</p>"""
|
||||
category_block = (
|
||||
f'<p style="margin:0 0 10px;">'
|
||||
f'{_outlook_font("Filter: ", color=OUTLOOK_HEADING, bold=True)}'
|
||||
f'{_outlook_font(f"Kategorie {category.strip()}", color=OUTLOOK_MUTED, size="1")}'
|
||||
f"</p>"
|
||||
)
|
||||
|
||||
total = len(new_articles) + len(edited_articles)
|
||||
summary_row = f"""<tr>
|
||||
<td style="padding:16px 0 0;font-family:{OUTLOOK_FONT};font-size:10pt;color:{OUTLOOK_MUTED};border-top:1px solid {OUTLOOK_BORDER};">
|
||||
<strong style="font-family:{OUTLOOK_FONT};color:{OUTLOOK_HEADING};">Zusammenfassung:</strong>
|
||||
{len(new_articles)} neu · {len(edited_articles)} bearbeitet · {total} gesamt
|
||||
<td bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:16px 0 0;border-top:1px solid {OUTLOOK_BORDER};">
|
||||
{_outlook_font("Zusammenfassung: ", color=OUTLOOK_HEADING, bold=True, size="1")}
|
||||
{_outlook_font(f"{len(new_articles)} neu · {len(edited_articles)} bearbeitet · {total} gesamt", color=OUTLOOK_MUTED, size="1")}
|
||||
</td>
|
||||
</tr>"""
|
||||
|
||||
@@ -318,48 +343,42 @@ def create_outlook_html(
|
||||
<meta charset="utf-8">
|
||||
<meta name="ProgId" content="Word.Document">
|
||||
<meta name="Generator" content="Microsoft Word 15">
|
||||
<meta name="color-scheme" content="light only">
|
||||
<meta name="supported-color-schemes" content="light">
|
||||
<title>{subject}</title>
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<w:WordDocument>
|
||||
<w:View>Print</w:View>
|
||||
<w:Zoom>100</w:Zoom>
|
||||
<w:DoNotOptimizeForBrowser/>
|
||||
</w:WordDocument>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<!--[if mso]>
|
||||
<style type="text/css">
|
||||
body, table, td, p, a, span, strong {{ font-family: Arial, sans-serif !important; }}
|
||||
body, table, td, p, a, font, span, strong {{ font-family: Arial, sans-serif !important; }}
|
||||
a {{ color: {OUTLOOK_LINK} !important; }}
|
||||
</style>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body style="margin:0;padding:16px;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};background:#FFFFFF;">
|
||||
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" style="width:600px;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};background:#FFFFFF;">
|
||||
<body bgcolor="{OUTLOOK_WHITE}" style="margin:0;padding:16px;background-color:{OUTLOOK_WHITE};">
|
||||
<table width="600" cellpadding="0" cellspacing="0" border="0" align="center" bgcolor="{OUTLOOK_WHITE}" style="width:600px;background-color:{OUTLOOK_WHITE};">
|
||||
<tr>
|
||||
<td style="padding:16px 20px;background:{OUTLOOK_HEADING};font-family:{OUTLOOK_FONT};">
|
||||
<p style="margin:0;font-family:{OUTLOOK_FONT};font-size:9pt;color:#A9C6E8;text-transform:uppercase;letter-spacing:1px;">Interner Newsletter</p>
|
||||
<p style="margin:6px 0 0;font-family:{OUTLOOK_FONT};font-size:18pt;font-weight:bold;color:#FFFFFF;">Thomas-Krenn Wiki Update</p>
|
||||
<p style="margin:4px 0 0;font-family:{OUTLOOK_FONT};font-size:11pt;color:#D9E8F8;">{escape(ORG_NAME)}</p>
|
||||
<td bgcolor="{OUTLOOK_HEADING}" style="background-color:{OUTLOOK_HEADING};padding:16px 20px;">
|
||||
{_outlook_font("Interner Newsletter", color="#A9C6E8", size="1")}<br>
|
||||
{_outlook_font("Thomas-Krenn Wiki Update", color=OUTLOOK_WHITE, size="5", bold=True)}<br>
|
||||
{_outlook_font(ORG_NAME, color="#D9E8F8", size="2")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:20px;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">
|
||||
<p style="margin:0 0 8px;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">Liebe Kolleginnen und Kollegen,</p>
|
||||
<p style="margin:0 0 12px;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">{intro}</p>
|
||||
<p style="margin:0 0 16px;font-family:{OUTLOOK_FONT};font-size:9pt;color:{OUTLOOK_MUTED};">Erstellt am: {created_at}</p>
|
||||
<td bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:20px;">
|
||||
<p style="margin:0 0 8px;">{_outlook_font("Liebe Kolleginnen und Kollegen,")}</p>
|
||||
<p style="margin:0 0 12px;">{_outlook_font(intro)}</p>
|
||||
<p style="margin:0 0 16px;">{_outlook_font(f"Erstellt am: {created_at}", color=OUTLOOK_MUTED, size="1")}</p>
|
||||
{category_block}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">
|
||||
<table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};">
|
||||
{body_rows}
|
||||
{summary_row}
|
||||
<tr>
|
||||
<td style="padding:20px 0 0;font-family:{OUTLOOK_FONT};font-size:11pt;">
|
||||
<a href="{WIKI_HOME_URL}" style="font-family:{OUTLOOK_FONT};font-size:11pt;font-weight:bold;color:{OUTLOOK_LINK};">Zum Thomas-Krenn-Wiki →</a>
|
||||
<td bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:20px 0 0;">
|
||||
<a href="{WIKI_HOME_URL}"><font face="Arial" color="{OUTLOOK_LINK}" size="2"><b>Zum Thomas-Krenn-Wiki →</b></font></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:16px 0 0;font-family:{OUTLOOK_FONT};font-size:9pt;color:{OUTLOOK_MUTED};border-top:1px solid {OUTLOOK_BORDER};">
|
||||
Automatisch erstellter interner Newsletter · Nur für den Gebrauch bei {escape(ORG_NAME)}
|
||||
<td bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:16px 0 0;border-top:1px solid {OUTLOOK_BORDER};">
|
||||
{_outlook_font(f"Automatisch erstellter interner Newsletter · Nur für den Gebrauch bei {ORG_NAME}", color=OUTLOOK_MUTED, size="1")}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -385,20 +404,19 @@ def _outlook_meta_line(item: dict[str, Any], display: DisplayOptions) -> str:
|
||||
def _outlook_article_rows(items: list[dict[str, Any]], display: DisplayOptions) -> str:
|
||||
rows: list[str] = []
|
||||
for idx, item in enumerate(items, 1):
|
||||
title = escape(item.get("title", "Ohne Titel"))
|
||||
url = escape(_article_url(item.get("title", "")))
|
||||
title = item.get("title", "Ohne Titel")
|
||||
url = _article_url(item.get("title", ""))
|
||||
meta = _outlook_meta_line(item, display)
|
||||
meta_html = ""
|
||||
if meta:
|
||||
meta_html = (
|
||||
f'<br><span style="font-family:{OUTLOOK_FONT};font-size:9pt;color:{OUTLOOK_MUTED};">'
|
||||
f"{escape(meta)}</span>"
|
||||
)
|
||||
meta_html = f"<br>{_outlook_font(meta, color=OUTLOOK_MUTED, size='1')}"
|
||||
rows.append(
|
||||
f"""<tr>
|
||||
<td width="28" valign="top" style="padding:6px 8px 10px 0;border-bottom:1px solid {OUTLOOK_BORDER};font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">{idx}.</td>
|
||||
<td valign="top" style="padding:6px 0 10px;border-bottom:1px solid {OUTLOOK_BORDER};font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_TEXT};">
|
||||
<a href="{url}" style="font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_LINK};">{title}</a>{meta_html}
|
||||
<td width="28" valign="top" bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:8px 8px 10px 0;border-bottom:1px solid {OUTLOOK_BORDER};">
|
||||
{_outlook_font(f"{idx}.")}
|
||||
</td>
|
||||
<td valign="top" bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:8px 0 10px;border-bottom:1px solid {OUTLOOK_BORDER};">
|
||||
{_outlook_link(title, url)}{meta_html}
|
||||
</td>
|
||||
</tr>"""
|
||||
)
|
||||
@@ -412,13 +430,15 @@ def _outlook_section(
|
||||
empty_text: str,
|
||||
) -> str:
|
||||
header = f"""<tr>
|
||||
<td colspan="2" style="padding:18px 0 6px;font-family:{OUTLOOK_FONT};font-size:13pt;font-weight:bold;color:{OUTLOOK_HEADING};border-bottom:2px solid {OUTLOOK_HEADING};">
|
||||
{escape(heading)} ({len(items)})
|
||||
<td colspan="2" bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:18px 0 8px;border-bottom:2px solid {OUTLOOK_HEADING};">
|
||||
{_outlook_font(f"{heading} ({len(items)})", color=OUTLOOK_HEADING, size="3", bold=True)}
|
||||
</td>
|
||||
</tr>"""
|
||||
if not items:
|
||||
return header + f"""<tr>
|
||||
<td colspan="2" style="padding:8px 0;font-family:{OUTLOOK_FONT};font-size:11pt;color:{OUTLOOK_MUTED};font-style:italic;">{escape(empty_text)}</td>
|
||||
<td colspan="2" bgcolor="{OUTLOOK_WHITE}" style="background-color:{OUTLOOK_WHITE};padding:8px 0;">
|
||||
{_outlook_font(empty_text, color=OUTLOOK_MUTED)}
|
||||
</td>
|
||||
</tr>"""
|
||||
return header + _outlook_article_rows(items, display)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user