Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3ea9764
[ENG-11583] Create Blank Notification Template (#11802)
Ostap-Zherebetskyi Jul 8, 2026
aae133d
[ENG-11605][ENG-11695][ENG-11696][ENG-11697][ENG-11605][ENG-11698] EN…
Ostap-Zherebetskyi Jul 9, 2026
d1048ec
[ENG-11698] Add bulk email sending with SendGrid to send_campaign_bat…
Ostap-Zherebetskyi Jul 10, 2026
fd6f778
[ENG-11702][ENG-11694][ENG-11699][ENG-11703] Notification Campaign Ad…
Ostap-Zherebetskyi Jul 15, 2026
22b2d02
[ENG-11762] Refactor filter handling in notification campaign (#11813)
Ostap-Zherebetskyi Jul 16, 2026
3e5d7c1
[ENG-11768] Update choices, add new field, check timeout and improve …
Ostap-Zherebetskyi Jul 17, 2026
8c770b2
[ENG-11764] Filter, order, skip user by activity, registration date a…
antkryt Jul 21, 2026
4fd95a0
[ENG-11769] Redo recipients page (#11821)
Ostap-Zherebetskyi Jul 21, 2026
d275049
[ENG-11791][ENG-11793] Update model to pre-calculate and sort recipie…
Ostap-Zherebetskyi Jul 23, 2026
faddad1
[ENG-11796] Unit tests on ordering/filtering user (#11829)
antkryt Jul 27, 2026
a70d6ee
[ENG-11763] Add validation for creating/starting campagin (#11828)
Ostap-Zherebetskyi Jul 27, 2026
dcfabd2
[ENG-11792] Implement campaign restart in case of catastrophe (#11831)
Ostap-Zherebetskyi Jul 27, 2026
e5c7526
Merge remote-tracking branch 'upstream/develop' into feature/project-…
cslzchen Jul 27, 2026
0ee21d2
[ENG-11797] Unit tests on updated campaign workflow - Part 1 (#11832)
antkryt Jul 29, 2026
3337e4e
[ENG-11820] Admin Campaign Page Clean-up / Polish + Optional Features…
Ostap-Zherebetskyi Jul 29, 2026
c93805b
[ENG-11847] Look into the permission issue (#11838)
Ostap-Zherebetskyi Jul 30, 2026
8bec7dd
[ENG-11797] Unit tests on updated campaign workflow - Part 2 (#11839)
antkryt Jul 30, 2026
59be6e8
[ENG-11844] Create confirmed test user with fake activity points (#11…
cslzchen Jul 30, 2026
de20f5b
[ENG-11844] Create confirmed test user with fake activity points - Pa…
cslzchen Jul 30, 2026
577be69
[ENG-11866][ENG-11524][ENG-11871] Refactor notification campaign filt…
Ostap-Zherebetskyi Jul 31, 2026
64efdc4
[ENG-11881] Time window needs to be set in seconds (#11847)
antkryt Aug 3, 2026
765b17d
[ENG-11882] Add a filter on username to include non-email usernames (…
antkryt Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion admin/notifications/forms.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,72 @@
from django import forms
from osf.models import NotificationType
from osf.models import NotificationType, NotificationCampaign
from website import settings
import json


class NotificationTypeForm(forms.ModelForm):
class Meta:
model = NotificationType
fields = '__all__'


class NotificationCampaignCreateForm(forms.ModelForm):
context = forms.CharField(
required=False,
widget=forms.Textarea(attrs={'rows': 8}),
initial='{}',
)

filters = forms.CharField(
required=False,
widget=forms.HiddenInput(),
initial='{}',
)

batch_size = forms.IntegerField(
min_value=1,
initial=settings.DEFAULT_CAMPAIGN_BATCH_SIZE,
)

max_retries = forms.IntegerField(
min_value=0,
initial=settings.DEFAULT_CAMPAIGN_MAX_RETRIES,
)

activity_threshold = forms.IntegerField(
min_value=0,
initial=settings.DEFAULT_CAMPAIGN_ACTIVITY_THRESHOLD,
help_text='Non-spam users at or above this activity total are sent in the high-activity phase.',
)

time_window = forms.IntegerField(
min_value=1,
initial=8 * 60 * 60, # 8 hours
help_text='The time in seconds before the developer reminder is sent.',
)

sendgrid_bulk = forms.BooleanField(
required=False,
initial=False,
)

class Meta:
model = NotificationCampaign
fields = (
'name',
'notification_type',
)

def clean_context(self):
value = self.cleaned_data['context'] or '{}'
try:
return json.loads(value)
except Exception as e:
raise forms.ValidationError(e)

def clean_filters(self):
value = self.cleaned_data['filters'] or '{}'
try:
return json.loads(value)
except Exception as e:
raise forms.ValidationError(e)
6 changes: 6 additions & 0 deletions admin/notifications/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@
re_path(r'types_preview/(?P<pk>\d+)/$', views.NotificationTypePreview.as_view(), name='types_preview'),
re_path(r'subscriptions/$', views.NotificationSubscriptionsList.as_view(), name='subscriptions_list'),
re_path(r'email_tasks/$', views.EmailTasksList.as_view(), name='email_tasks_list'),
re_path(r'notification_campaigns_list/$', views.NotificationCampaignsList.as_view(), name='notification_campaigns_list'),
re_path(r'notification_campaigns_detail/(?P<pk>\d+)/$', views.NotificationCampaignDetail.as_view(), name='notification_campaigns_detail'),
re_path(r'notification_campaigns_create/$', views.NotificationCampaignCreateView.as_view(), name='notification_campaigns_create'),
re_path(r'notification_campaigns_recipients_preview/$', views.NotificationCampaignsRecipientsPreview.as_view(), name='notification_campaigns_recipients_preview'),
re_path(r'notification_campaigns_recipients_list/$', views.NotificationCampaignsRecipientsView.as_view(), name='notification_campaigns_recipients_list'),
re_path(r'notification_campaigns_start/(?P<pk>\d+)/$', views.StartNotificationCampaign.as_view(), name='notification_campaigns_start'),
]
Loading
Loading