diff --git a/hypha/apply/activity/adapters/activity_feed.py b/hypha/apply/activity/adapters/activity_feed.py index 0c0a92817a..44e1c2ce25 100644 --- a/hypha/apply/activity/adapters/activity_feed.py +++ b/hypha/apply/activity/adapters/activity_feed.py @@ -50,6 +50,10 @@ class ActivityAdapter(AdapterBase): MESSAGES.CREATED_PROJECT: _( 'Created project with initial status of "{status}"' ), + MESSAGES.CREATED_SOW: _('Created SOW for project "{related.project}"'), + MESSAGES.EDITED_SOW: _('Edited SOW for project "{related.project}"'), + MESSAGES.CREATED_PF: _('Created project form for project "{related.project}"'), + MESSAGES.EDITED_PF: _('Edited project form for project "{related.project}"'), MESSAGES.PROJECT_TRANSITION: "handle_project_transition", MESSAGES.UPDATE_PROJECT_TITLE: _( "updated the project title from {old_title} to {source.title}" @@ -94,6 +98,10 @@ def extra_kwargs(self, message_type, source, sources, **kwargs): MESSAGES.DELETE_REVIEW_OPINION, MESSAGES.BATCH_REVIEWERS_UPDATED, MESSAGES.APPROVE_PROJECT, + MESSAGES.CREATED_SOW, + MESSAGES.EDITED_SOW, + MESSAGES.CREATED_PF, + MESSAGES.EDITED_PF, MESSAGES.REQUEST_PROJECT_CHANGE, MESSAGES.SEND_FOR_APPROVAL, MESSAGES.APPROVE_PAF, diff --git a/hypha/apply/activity/adapters/base.py b/hypha/apply/activity/adapters/base.py index 1617905464..3957b43209 100644 --- a/hypha/apply/activity/adapters/base.py +++ b/hypha/apply/activity/adapters/base.py @@ -21,6 +21,10 @@ MESSAGES.DELETE_REVIEW_OPINION: "review_opinion", MESSAGES.EDIT_REVIEW: "review", MESSAGES.CREATED_PROJECT: "submission", + MESSAGES.CREATED_SOW: "sow", + MESSAGES.EDITED_SOW: "sow", + MESSAGES.EDITED_PF: "pfp", + MESSAGES.CREATED_PF: "pfp", MESSAGES.PROJECT_TRANSITION: "old_stage", MESSAGES.APPROVE_PAF: "paf_approvals", # expect a list MESSAGES.UPDATE_PROJECT_LEAD: "old_lead", diff --git a/hypha/apply/activity/forms.py b/hypha/apply/activity/forms.py index fa8483dbc2..0d0d6c730b 100644 --- a/hypha/apply/activity/forms.py +++ b/hypha/apply/activity/forms.py @@ -1,5 +1,6 @@ from django import forms from django.db import transaction +from django.forms.widgets import Textarea from django.utils.translation import gettext_lazy as _ from django_file_form.forms import FileFormMixin @@ -24,11 +25,16 @@ class CommentForm(FileFormMixin, forms.ModelForm): class Meta: model = Activity - fields = ( - "message", - "visibility", - "assign_to", + + # Fields that should only be included when the mini comment form is used + # as the mini form can be put anywhere and associated to any object. + mini_fields = ( + "related_content_type", + "related_object_id", + "source_content_type", + "source_object_id", ) + fields = ("message", "visibility", "assign_to", *mini_fields) labels = { "visibility": _("Visible to"), "message": _("Message"), @@ -41,9 +47,10 @@ class Meta: widgets = { "visibility": forms.RadioSelect(), "message": PagedownWidget(), + **{field: forms.HiddenInput() for field in mini_fields}, } - def __init__(self, *args, user=None, has_coapplicants=False, **kwargs): + def __init__(self, *args, user=None, has_coapplicants=False, mini=False, **kwargs): super().__init__(*args, **kwargs) self.visibility_choices = self._meta.model.visibility_choices_for( user, has_coapplicants @@ -61,6 +68,15 @@ def __init__(self, *args, user=None, has_coapplicants=False, **kwargs): if not user.is_apply_staff: self.fields["assign_to"].widget = forms.HiddenInput() + if mini: + self.fields["message"].widget = Textarea( + attrs={"rows": 2, "placeholder": _("Write a comment...")} + ) + else: + # If not mini, remove the unneeded fields from the form. + for key in self.Meta.mini_fields: + del self.fields[key] + @transaction.atomic def save(self, commit=True): instance = super().save(commit=True) diff --git a/hypha/apply/activity/migrations/0096_alter_event_type.py b/hypha/apply/activity/migrations/0096_alter_event_type.py index f222ebbaf6..be8367241e 100644 --- a/hypha/apply/activity/migrations/0096_alter_event_type.py +++ b/hypha/apply/activity/migrations/0096_alter_event_type.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.17 on 2026-08-25 18:01 +# Generated by Django 5.2.17 on 2026-08-31 14:08 from django.db import migrations, models @@ -40,6 +40,10 @@ class Migration(migrations.Migration): ("DELETE_REVIEW", "deleted review"), ("DELETE_REVIEW_OPINION", "deleted review opinion"), ("CREATED_PROJECT", "created project"), + ("CREATED_SOW", "created a project SOW"), + ("EDITED_SOW", "edited a project SOW"), + ("CREATED_PF", "created a project form"), + ("EDITED_PF", "edited a project form"), ("UPDATE_PROJECT_LEAD", "updated project lead"), ("UPDATE_PROJECT_TITLE", "updated project title"), ( diff --git a/hypha/apply/activity/options.py b/hypha/apply/activity/options.py index fab645c22e..0b95a6ee72 100644 --- a/hypha/apply/activity/options.py +++ b/hypha/apply/activity/options.py @@ -36,6 +36,10 @@ class MESSAGES(TextChoices): DELETE_REVIEW = "DELETE_REVIEW", _("deleted review") DELETE_REVIEW_OPINION = "DELETE_REVIEW_OPINION", _("deleted review opinion") CREATED_PROJECT = "CREATED_PROJECT", _("created project") + CREATED_SOW = "CREATED_SOW", _("created a project SOW") + EDITED_SOW = "EDITED_SOW", _("edited a project SOW") + CREATED_PF = "CREATED_PF", _("created a project form") + EDITED_PF = "EDITED_PF", _("edited a project form") UPDATE_PROJECT_LEAD = "UPDATE_PROJECT_LEAD", _("updated project lead") UPDATE_PROJECT_TITLE = "UPDATE_PROJECT_TITLE", _("updated project title") UPDATE_PROJECT_CONTRACT_NUMBER = ( diff --git a/hypha/apply/activity/templates/activity/partials/comment_form.html b/hypha/apply/activity/templates/activity/partials/comment_form.html new file mode 100644 index 0000000000..2c677f0ef6 --- /dev/null +++ b/hypha/apply/activity/templates/activity/partials/comment_form.html @@ -0,0 +1,37 @@ +{% comment %} +Renders the sidebar comments form. + +Params: + form – the CommentForm form +{% endcomment %} + +{% load i18n static heroicons %} + +{# On error the view re-renders this whole form, so swap outerHTML on self to avoid nesting a form inside itself. A successful post returns 204 and is not swapped. #} +
diff --git a/hypha/apply/activity/templates/activity/ui/activity-action-item.html b/hypha/apply/activity/templates/activity/ui/activity-action-item.html index 25643ec769..e72b179853 100644 --- a/hypha/apply/activity/templates/activity/ui/activity-action-item.html +++ b/hypha/apply/activity/templates/activity/ui/activity-action-item.html @@ -1,7 +1,16 @@ +{% comment %} +Renders a line item of activity including the message attached to the activity & an icon based on the message. + +Params: + activity – an Activity object to render into a timeline + no_timeline - bool of should the line item be styled as a piece of a larger timeline + mini - bool that will force including only essential elements of the action item +{% endcomment %} + {% load i18n activity_tags heroicons %} {% with activity|display_for:request.user as activity_text %} -