Skip to content

Add ability to send a notification email on review of community libra…#6050

Open
marcellamaki wants to merge 1 commit into
learningequality:hotfixesfrom
marcellamaki:send-notification-email
Open

Add ability to send a notification email on review of community libra…#6050
marcellamaki wants to merge 1 commit into
learningequality:hotfixesfrom
marcellamaki:send-notification-email

Conversation

@marcellamaki

Copy link
Copy Markdown
Member

Summary

This implements a very basic notification email to support communication around community library submissions. It seems from a lack of updates/edits to reviewed channels that users maybe were not seeing their notifications. This repurposes existing strings (therefore, we may want to make future edits to the wording to be more detailed/informative), to send an update about accepted community library channels or requesting edits/updates.

References

Fixes #5993

Reviewer guidance

I think code review here is best, and then manual QA on hotfixes to confirm email end to end. I did some testing of this using assistance from Claude, but it was a bit of a workaround, and I think testing more fully (to a real email address) will be more helpful than trying to replicate that during PR review.

AI usage

Implemented with Claude -- wrote up a spec together with me reviewing and providing inputs and guidance. Claude implementation, and then manual code review and testing in the browser and confirming logged outputs and email functions.

@marcellamaki
marcellamaki requested a review from rtibblesbot July 21, 2026 21:31
@rtibblesbot

rtibblesbot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🔵 Review posted

Last updated: 2026-07-21 21:44 UTC

@rtibblesbot rtibblesbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6050 adds a resolution-notification email (approved / requires changes) to the community-library resolve flow, cleanly mirroring the channel_published_email pattern and well covered by tests.

One blocking concern plus a few smaller notes:

  • blocking — introduces six net-new Django gettext strings on the non-default hotfixes branch, whereas issue #5993 scoped this to reusing existing strings. See models.py:3064. Confirm the branch/translation tradeoff is intentional.
  • suggestion — email is sent before the approval side-effects; a send failure could leave an APPROVED-but-not-added state (viewset:349).
  • suggestionname reimplements User.get_full_name() (models.py:3077).
  • nitpickblocktrans wrapping a bare variable adds noise to the catalog (template:12, and the same at line 21).

CI pending. Manual QA was required for this PR but did not run — UI/email rendering was not visually verified.


@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

How was this generated?

Ran a phased review pipeline over the pull request diff:

  • Classified the diff to select review passes (core, frontend, backend) and whether manual QA was required
  • Core review pass checked correctness, design, architecture, testing, completeness, and DRY/SRP/Rule-of-Three principles
  • Specialized frontend/backend review passes applied framework-specific lenses where those files changed
  • For UI changes: manual QA and an accessibility audit against a live dev server, when available
  • Checked CI status and linked issue acceptance criteria
  • Synthesized one review from those passes and chose the verdict from the findings, CI status, and QA evidence

is_approved = self.status == community_library_submission.STATUS_APPROVED

if is_approved:
subject_text = _("Your Community Library submission has been approved")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: This email introduces six net-new Django gettext strings — the two subjects here (3064/3066) plus five template strings ("Available in Community Library", "Your previously submitted version needs changes…", "Notes from the reviewer", "Thanks for using Kolibri Studio!", "The Learning Equality Team"). None exist in locale/en/LC_MESSAGES/django.po; the matching frontend contentcuration-messages.json text is a separate ($tr) catalog. Two issues: (1) linked issue #5993 scoped this to reusing existing strings, but in the Django catalog these are new; (2) this PR targets hotfixes, not unstable, so new strings miss the normal extraction/translation cycle and will ship English-only until forward-merged. If English-only on the hotfix is an accepted P1 tradeoff, that's fine — please confirm it's intentional and that extraction also happens on unstable.

)

submission.notify_update_to_channel_editors()
submission.send_resolution_email()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: send_resolution_email() runs before the approval side-effects (_mark_previous_pending_submissions_as_superseded / _add_to_community_library / mark_channel_version_as_distributable). email_user only swallows the two Postmark recipient exceptions; any other send/render error propagates. With no transaction.atomic here and ATOMIC_REQUESTS unset, serializer.save() has already committed APPROVED — a send failure would 500 and leave the submission approved but never added to the community library. Move the send after the state-mutation block so a mail failure is the least-damaging failure point.

message = render_to_string(
"community_library/submission_resolved_email.html",
{
"name": f"{self.author.first_name} {self.author.last_name}".strip(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: f"{self.author.first_name} {self.author.last_name}".strip() duplicates User.get_full_name(). Use self.author.get_full_name().

{% autoescape off %}
<p>{% blocktrans with name=name %}Hello {{ name }},{% endblocktrans %}</p>

<p><a href="{{ channel_url }}" target="_blank">{% blocktrans with channel_name=channel.name %}{{ channel_name }}{% endblocktrans %}</a> ({{ channel_url }})</p>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: {% blocktrans with channel_name=channel.name %}{{ channel_name }}{% endblocktrans %} emits a msgid of just the placeholder — nothing for a translator to act on. Plain {{ channel.name }} is equivalent. Same at line 21 for feedback_notes. Matches the existing channel_published_email.html, so take it or leave it.

channel_id=self.submission.channel.id,
)

self.assertEqual(len(mail.outbox), 1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Both paths assert against the real locmem mail backend — recipient, subject, body copy, channel name, and feedback notes — rather than mocking the mail layer. Solid end-to-end coverage of the new path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants