feat(forum): email + visual highlight for @mentions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- parse_mentions_and_notify now sends email to mentioned user (separate from forum subscription emails — fires on every mention) - parse_forum_markdown accepts current_user_name; mentions matching the viewer get extra .forum-mention-self class - topic.html passes current_user.name to filter; .forum-mention-self styled with amber background + bold + ring Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dc6c711264
commit
836594079f
@ -200,6 +200,13 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.forum-mention-self {
|
||||||
|
background: #fde68a;
|
||||||
|
color: #78350f;
|
||||||
|
font-weight: 700;
|
||||||
|
box-shadow: 0 0 0 1px #f59e0b;
|
||||||
|
}
|
||||||
|
|
||||||
/* User stats tooltip */
|
/* User stats tooltip */
|
||||||
.user-stats-trigger {
|
.user-stats-trigger {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -1105,7 +1112,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="topic-content" id="topicContent">{{ topic.content|forum_markdown }}</div>
|
<div class="topic-content" id="topicContent">{{ topic.content|forum_markdown(current_user.name if current_user.is_authenticated else None) }}</div>
|
||||||
|
|
||||||
<!-- Reactions bar for topic -->
|
<!-- Reactions bar for topic -->
|
||||||
<div class="reactions-bar" id="topicReactions" data-content-type="topic" data-content-id="{{ topic.id }}">
|
<div class="reactions-bar" id="topicReactions" data-content-type="topic" data-content-id="{{ topic.id }}">
|
||||||
@ -1235,7 +1242,7 @@
|
|||||||
{% if reply.is_deleted %}
|
{% if reply.is_deleted %}
|
||||||
<div class="reply-content deleted-notice">[Ta odpowiedź została usunięta]</div>
|
<div class="reply-content deleted-notice">[Ta odpowiedź została usunięta]</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="reply-content">{{ reply.content|forum_markdown }}</div>
|
<div class="reply-content">{{ reply.content|forum_markdown(current_user.name if current_user.is_authenticated else None) }}</div>
|
||||||
|
|
||||||
{% if reply.attachments %}
|
{% if reply.attachments %}
|
||||||
<div class="reply-attachments-container">
|
<div class="reply-attachments-container">
|
||||||
|
|||||||
@ -19,7 +19,7 @@ def _autolink(text):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_forum_markdown(text):
|
def parse_forum_markdown(text, current_user_name=None):
|
||||||
"""
|
"""
|
||||||
Convert markdown text to safe HTML.
|
Convert markdown text to safe HTML.
|
||||||
|
|
||||||
@ -81,12 +81,18 @@ def parse_forum_markdown(text):
|
|||||||
text
|
text
|
||||||
)
|
)
|
||||||
|
|
||||||
# @mentions - highlight them
|
# @mentions - highlight them; mark self-mentions with extra class
|
||||||
text = re.sub(
|
self_variants = set()
|
||||||
r'@([\w.\-]+)',
|
if current_user_name:
|
||||||
r'<span class="forum-mention">@\1</span>',
|
norm = current_user_name.strip().lower()
|
||||||
text
|
self_variants = {norm.replace(' ', '.'), norm.replace(' ', '_'), norm.replace(' ', '')}
|
||||||
)
|
|
||||||
|
def _render_mention(m):
|
||||||
|
handle = m.group(1).lower()
|
||||||
|
cls = 'forum-mention forum-mention-self' if handle in self_variants else 'forum-mention'
|
||||||
|
return f'<span class="{cls}">@{m.group(1)}</span>'
|
||||||
|
|
||||||
|
text = re.sub(r'@([\w.\-]+)', _render_mention, text)
|
||||||
|
|
||||||
# Now process block structure (lists, quotes, paragraphs)
|
# Now process block structure (lists, quotes, paragraphs)
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
|
|||||||
@ -621,6 +621,7 @@ def parse_mentions_and_notify(content, author_id, author_name, topic_id, content
|
|||||||
|
|
||||||
if user:
|
if user:
|
||||||
mentioned_user_ids.append(user.id)
|
mentioned_user_ids.append(user.id)
|
||||||
|
action_url = f'/forum/{topic_id}{"#reply-" + str(content_id) if content_type == "reply" else ""}'
|
||||||
create_notification(
|
create_notification(
|
||||||
user_id=user.id,
|
user_id=user.id,
|
||||||
title=f"@{author_name} wspomniał o Tobie",
|
title=f"@{author_name} wspomniał o Tobie",
|
||||||
@ -628,9 +629,53 @@ def parse_mentions_and_notify(content, author_id, author_name, topic_id, content
|
|||||||
notification_type='message',
|
notification_type='message',
|
||||||
related_type=f'forum_{content_type}',
|
related_type=f'forum_{content_type}',
|
||||||
related_id=content_id,
|
related_id=content_id,
|
||||||
action_url=f'/forum/{topic_id}{"#reply-" + str(content_id) if content_type == "reply" else ""}'
|
action_url=action_url
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Send email notification to mentioned user
|
||||||
|
try:
|
||||||
|
from email_service import send_email, _email_v3_wrap
|
||||||
|
base_url = "https://nordabiznes.pl"
|
||||||
|
full_url = base_url + action_url
|
||||||
|
preview = (content[:200] + '...') if len(content) > 200 else content
|
||||||
|
where = 'odpowiedzi' if content_type == 'reply' else 'temacie'
|
||||||
|
subject = f"{author_name} wspomniał o Tobie na forum"
|
||||||
|
body_text = f"""{author_name} wspomniał o Tobie w {where} na forum Norda Biznes.
|
||||||
|
|
||||||
|
"{preview}"
|
||||||
|
|
||||||
|
Zobacz: {full_url}
|
||||||
|
|
||||||
|
---
|
||||||
|
Norda Biznes Partner - https://nordabiznes.pl
|
||||||
|
"""
|
||||||
|
html_content = f'''
|
||||||
|
<p style="margin:0 0 16px; color:#1e293b; font-size:16px;">Cześć <strong>{user.name or ''}</strong>!</p>
|
||||||
|
<p style="margin:0 0 24px; color:#475569; font-size:15px; line-height:1.5;"><strong>{author_name}</strong> wspomniał o Tobie w {where} na forum:</p>
|
||||||
|
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" style="background:#fef3c7; border-left: 4px solid #f59e0b; border-radius: 0 8px 8px 0; margin-bottom:28px;">
|
||||||
|
<tr><td style="padding: 16px 20px;">
|
||||||
|
<p style="margin:0; color:#475569; font-size:14px; font-style:italic; line-height:1.6;">{preview}</p>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" style="margin-bottom:20px;">
|
||||||
|
<tr><td align="center" style="padding: 8px 0;">
|
||||||
|
<a href="{full_url}" style="display:inline-block; padding:16px 40px; background: linear-gradient(135deg, #1e3a8a, #172554); color:#ffffff; text-decoration:none; border-radius:8px; font-size:15px; font-weight:600;">Zobacz na forum →</a>
|
||||||
|
</td></tr>
|
||||||
|
</table>'''
|
||||||
|
body_html = _email_v3_wrap('Wspomniano o Tobie', 'Norda Biznes Partner', html_content)
|
||||||
|
send_email(
|
||||||
|
to=[user.email],
|
||||||
|
subject=subject,
|
||||||
|
body_text=body_text,
|
||||||
|
body_html=body_html,
|
||||||
|
email_type='forum_mention',
|
||||||
|
recipient_name=user.name or ''
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to send mention email to {user.email}: {e}")
|
||||||
|
|
||||||
return mentioned_user_ids
|
return mentioned_user_ids
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user