diff --git a/funnel/models/__init__.py b/funnel/models/__init__.py index 90e801c59..947e26912 100644 --- a/funnel/models/__init__.py +++ b/funnel/models/__init__.py @@ -131,6 +131,7 @@ "ProjectStartingNotification", "ProjectTomorrowNotification", "ProjectUpdateNotification", + "ProjectPublishedNotification", "Proposal", "ProposalLabelProxy", "ProposalLabelProxyWrapper", diff --git a/funnel/models/__init__.pyi b/funnel/models/__init__.pyi index 6752aa5cc..198e022e5 100644 --- a/funnel/models/__init__.pyi +++ b/funnel/models/__init__.pyi @@ -176,6 +176,7 @@ from .notification_types import ( OrganizationAdminMembershipRevokedNotification, ProjectCrewMembershipNotification, ProjectCrewMembershipRevokedNotification, + ProjectPublishedNotification, ProjectStartingNotification, ProjectTomorrowNotification, ProjectUpdateNotification, @@ -354,6 +355,7 @@ __all__ = [ "ProjectRsvpStateEnum", "ProjectSponsorMembership", "ProjectStartingNotification", + "ProjectPublishedNotification", "ProjectTomorrowNotification", "ProjectUpdateNotification", "Proposal", diff --git a/funnel/models/notification_types.py b/funnel/models/notification_types.py index 1b0467e37..ef2c492e8 100644 --- a/funnel/models/notification_types.py +++ b/funnel/models/notification_types.py @@ -34,6 +34,7 @@ 'RegistrationCancellationNotification', 'RegistrationConfirmationNotification', 'ProjectStartingNotification', + 'ProjectPublishedNotification', 'ProjectTomorrowNotification', 'OrganizationAdminMembershipNotification', 'OrganizationAdminMembershipRevokedNotification', @@ -69,6 +70,15 @@ def preference_context(self) -> Account: return self.document # type: ignore[attr-defined] +class DocumentIsProfile: + """Mixin class for notifications on the profile.""" + + @property + def preference_context(self) -> Account: + """Return the document as the preference context.""" + return self.document # type: ignore[attr-defined] + + # --- Account notifications ------------------------------------------------------------ @@ -197,6 +207,21 @@ class ProjectTomorrowNotification( # This is a notification triggered without an actor +class ProjectPublishedNotification( + DocumentIsAccount, Notification[Account, Project], type='project_published' +): + """Notification of a newly published project.""" + + category = notification_categories.participant + title = __("When a project is published") + description = __( + "Notifies all members of a account when a new project is published" + ) + + roles = ['project_crew', 'account_participant'] + exclude_actor = False # Send to everyone including the actor + + # --- Comment notifications ------------------------------------------------------------ diff --git a/funnel/models/project.py b/funnel/models/project.py index 13f39d60b..31527437f 100644 --- a/funnel/models/project.py +++ b/funnel/models/project.py @@ -720,14 +720,17 @@ def _(self) -> Iterable[Account]: message=__("Submissions will be accepted until the optional closing date"), type='success', ) - def open_cfp(self) -> None: + def open_cfp(self) -> bool: """Change state to accept submissions.""" + first_opened = False # If closing date is in the past, remove it if self.cfp_end_at is not None and self.cfp_end_at <= utcnow(): self.cfp_end_at = None # If opening date is not set, set it if self.cfp_start_at is None: self.cfp_start_at = sa.func.utcnow() + first_opened = True + return first_opened @with_roles(call={'editor'}) # skipcq: PTC-W0049 @cfp_state.transition( diff --git a/funnel/templates/notifications/layout_email.html.jinja2 b/funnel/templates/notifications/layout_email.html.jinja2 index d9a3dba2c..206f9c7b0 100644 --- a/funnel/templates/notifications/layout_email.html.jinja2 +++ b/funnel/templates/notifications/layout_email.html.jinja2 @@ -355,7 +355,7 @@
@@ -365,9 +365,9 @@ 1. max-width for all clients except Desktop Windows Outlook, allowing the email to squish on narrow but never go wider than 600px. 2. MSO tags for Desktop Windows Outlook enforce a 600px width. #} -
+