Skip to content

Feature/sc 31715/sheets desktop notifications page #2410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 56 commits into
base: modularization-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
03f150b
feat(notifications): Backend changes, new param for sheets mode notif…
saengel Feb 10, 2025
1baa4ce
chore(sheets notifications): code refactor
saengel Feb 10, 2025
2e769df
feat(sheets notifications): Additional wiring for modularized base pr…
saengel Feb 10, 2025
31aa168
feat(sheets notifications): Basic wiring of URL/mod logic, CSS fixes
saengel Feb 12, 2025
062d665
chore: start refactoring TextList so that links are part of state
stevekaplan123 Mar 10, 2025
a0bdbef
chore: cleanup
stevekaplan123 Mar 11, 2025
6a4f03a
chore: get rid of commentarySectionRef and preloadAllCommentaryText w…
stevekaplan123 Mar 11, 2025
2f30357
chore: setstate textloaded to true upon successful text api call
stevekaplan123 Mar 11, 2025
2b5adf2
chore: cleanup
stevekaplan123 Mar 11, 2025
d23b817
Merge branch 'master' into bug/sc-520/second-try
stevekaplan123 Mar 31, 2025
241b610
Merge from modularization-header-main
yitzhakc Apr 1, 2025
8b49406
chore(sheets notifications): Re-applying CSS from previous commit los…
yitzhakc Apr 1, 2025
5a489b7
chore(sheets notifications): Use dynamically set active module instea…
yitzhakc Apr 1, 2025
ee707cb
Merge branch 'master' into bug/sc-520/second-try
stevekaplan123 Apr 2, 2025
113a21d
Merge branch 'master' into bug/sc-520/second-try
stevekaplan123 Apr 3, 2025
3176c02
chore: dont check null values
stevekaplan123 Apr 8, 2025
d8a4684
chore(sheets notifications): Add scope-awareness to unread_notificati…
yitzhakc Apr 10, 2025
dafc548
fix(email subscriptions): Fix order and type of parameters sent to Sa…
relyks Apr 11, 2025
74115cb
feat(sheets ConnectionsPanel): remove share settings from new editor.
YishaiGlasner Apr 28, 2025
3cadd79
fix(makeHistoryState): encode manually question mark in titles.
YishaiGlasner May 4, 2025
e3d15ff
Merge branch 'master' into bug/sc-33619/encode-question-mark-index-alt
YishaiGlasner May 4, 2025
233c69a
fix(makeHistoryState): replace all question marks.
YishaiGlasner May 4, 2025
57118fa
chore(annual impact report): Add file for 2024 impact report and crea…
relyks May 5, 2025
550549c
chore: add romanian
stevekaplan123 May 6, 2025
916a9f6
chore: add romanian string
stevekaplan123 May 6, 2025
25d81db
Merge pull request #2437 from Sefaria/bug/sc-33619/encode-question-ma…
akiva10b May 6, 2025
14e0b3a
Merge pull request #2433 from Sefaria/chore/sc-32776/remove-share-set…
akiva10b May 6, 2025
1151927
Merge branch 'master' into 2024-impact-report-link-change
relyks May 6, 2025
205f1b9
docs(AutoComplete): encode question marks in refs for urls, and retur…
YishaiGlasner May 7, 2025
3ecd91a
chore: temporarily set apiHost to prod for autocompleting in cauldron
YishaiGlasner May 7, 2025
7c27182
fix(crm): Fix order of parameters for dummy_crm too
relyks May 7, 2025
68a4084
Merge pull request #2411 from Sefaria/bug/sc-33660/hebrew-newsletter-…
akiva10b May 7, 2025
773cf21
Merge pull request #2440 from Sefaria/2024-impact-report-link-change
akiva10b May 7, 2025
59c6bf5
chore: return apiHost to "".
YishaiGlasner May 8, 2025
7bfff69
Merge pull request #2446 from Sefaria/bug/sc-33619/question-mark-in-i…
akiva10b May 8, 2025
954f77d
chore(question mark): control for question mark in templating url and…
akiva10b May 8, 2025
a160bec
Merge branch 'master' into bug/sc-520/second-try
stevekaplan123 May 11, 2025
0a7d555
fix: return topic url with ? cleaning
akiva10b May 12, 2025
a199eef
fix: don't fail on self.save when django user doesn't have mongo odject
akiva10b May 12, 2025
1cdc873
fix: add show_editor_toggle for multi env users
akiva10b May 13, 2025
cc1eee6
Merge pull request #2452 from Sefaria/fix_no_mongo_user
akiva10b May 13, 2025
fbd1a94
Merge pull request #2448 from Sefaria/fix_title_in_edit
akiva10b May 15, 2025
82542f6
fix: configure heap size in nodejs deployment
BrendanGalloway May 15, 2025
087e0fe
Merge pull request #2454 from Sefaria/node-heap-size
EliezerIsrael May 15, 2025
aaa9f97
chore(sentry): lower server rate to 1%
akiva10b May 15, 2025
d13f30d
Merge pull request #2455 from Sefaria/lower_sentry_rate
akiva10b May 15, 2025
8d19b44
Merge pull request #2381 from Sefaria/bug/sc-520/second-try
yitzhakc May 18, 2025
d952c09
Merge pull request #2444 from Sefaria/feature/sc-32313/adding-iso-cod…
yitzhakc May 18, 2025
ea4e987
chore: Update node memory requirements
EliezerIsrael May 20, 2025
6e03837
Merge pull request #2459 from Sefaria/nodemem
EliezerIsrael May 20, 2025
be4fc9f
Revert "chore: Update node memory requirements"
EliezerIsrael May 22, 2025
a2b4607
Merge pull request #2462 from Sefaria/nodemem
EliezerIsrael May 22, 2025
db035d3
feat: Clear cache in node between requests
EliezerIsrael May 22, 2025
aeb9ba4
Merge pull request #2463 from Sefaria/nodemem
EliezerIsrael May 22, 2025
f45cff4
Merge branch 'master' into modularization-main
stevekaplan123 May 25, 2025
e545158
Merge branch 'modularization-main' into feature/sc-31715/sheets-deskt…
stevekaplan123 May 25, 2025
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
9 changes: 6 additions & 3 deletions reader/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ def base_props(request):

if request.user.is_authenticated:
profile = UserProfile(user_obj=request.user)
active_module = getattr(request, "active_module", "library")
user_data = {
"_uid": request.user.id,
"_email": request.user.email,
Expand All @@ -187,7 +188,7 @@ def base_props(request):
"blocking": profile.blockees.uids,
"calendars": get_todays_calendar_items(**_get_user_calendar_params(request)),
"notificationCount": profile.unread_notification_count(),
"notifications": profile.recent_notifications().client_contents(),
"notifications": profile.recent_notifications(scope=active_module).client_contents(),
"saved": {"loaded": False, "items": profile.get_history(saved=True, secondary=False, serialized=True, annotate=False)}, # saved is initially loaded without text annotations so it can quickly immediately mark any texts/sheets as saved, but marks as `loaded: false` so the full annotated data will be requested if the user visits the saved/history page
"last_place": profile.get_history(last_place=True, secondary=False, sheets=False, serialized=True)
}
Expand Down Expand Up @@ -1076,7 +1077,8 @@ def user_stats(request):
def notifications(request):
# Notifications content is not rendered server side
title = _("Sefaria Notifications")
notifications = UserProfile(user_obj=request.user).recent_notifications()
active_module = getattr(request, 'active_module', 'library')
notifications = UserProfile(user_obj=request.user).recent_notifications(scope=active_module)
props = {
"notifications": notifications.client_contents(),
}
Expand Down Expand Up @@ -2925,8 +2927,9 @@ def notifications_api(request):

page = int(request.GET.get("page", 0))
page_size = int(request.GET.get("page_size", 10))
scope = str(request.GET.get("scope", "library"))

notifications = NotificationSet().recent_for_user(request.user.id, limit=page_size, page=page)
notifications = NotificationSet().recent_for_user(request.user.id, limit=page_size, page=page, scope=scope)

return jsonResponse({
"notifications": notifications.client_contents(),
Expand Down
40 changes: 31 additions & 9 deletions sefaria/model/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ class Notification(abst.AbstractMongoRecord):
"suspected_spam"
]

sheets_notification_types = [
"collection add",
"follow",
"sheet like",
"sheet publish"
]

def _init_defaults(self):
self.read = False
self.read_via = None
Expand Down Expand Up @@ -326,7 +333,6 @@ def __init__(self, query=None, page=0, limit=0, sort=[["date", -1]]):
def _add_global_messages(self, uid):
"""
Add user Notification records for any new GlobalNotifications
:return:
"""
latest_id_for_user = Notification.latest_global_for_user(uid)
latest_global_id = GlobalNotification.latest_id()
Expand All @@ -336,28 +342,44 @@ def _add_global_messages(self, uid):
else:
GlobalNotificationSet({"_id": {"$gt": latest_id_for_user}}, limit=10).register_for_user(uid)

def unread_for_user(self, uid):
def _build_query_with_scope(self, uid, read=None, is_global=None, suspected_spam=None, scope='library'):
"""
Helper method to build a query with the given parameters and scope.
"""
query = {"uid": uid}
if read is not None:
query["read"] = read
if is_global is not None:
query["is_global"] = is_global
if suspected_spam is not None:
query["suspected_spam"] = suspected_spam
query["type"] = {"$in" if scope == 'sheets' else "$nin": Notification.sheets_notification_types}
return query

def unread_for_user(self, uid, scope='library'):
"""
Loads the unread notifications for uid.
"""
# Add globals ...
self._add_global_messages(uid)
self.__init__(query={"uid": uid, "read": False})
query = self._build_query_with_scope(uid, read=False, scope=scope)
self.__init__(query=query)
return self

def unread_personal_for_user(self, uid):
def unread_personal_for_user(self, uid, scope='library'):
"""
Loads the unread notifications for uid.
Loads the unread personal notifications for uid.
"""
self.__init__(query={"uid": uid, "read": False, "is_global": False, "suspected_spam": {'$in': [False, None]}})
query = self._build_query_with_scope(uid, read=False, is_global=False, suspected_spam={'$in': [False, None]}, scope=scope)
self.__init__(query=query)
return self

def recent_for_user(self, uid, page=0, limit=10):
def recent_for_user(self, uid, page=0, limit=10, scope='library'):
"""
Loads recent notifications for uid.
"""
self._add_global_messages(uid)
self.__init__(query={"uid": uid, "suspected_spam": {'$in': [False, None]}}, page=page, limit=limit)
query = self._build_query_with_scope(uid, suspected_spam={"$in": [False, None]}, scope=scope)
self.__init__(query=query, page=page, limit=limit)
return self

def mark_read(self, via="site"):
Expand Down
9 changes: 5 additions & 4 deletions sefaria/model/user_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,13 +592,14 @@ def followed_by(self, uid):
"""Returns true if this user is followed by uid"""
return uid in self.followers.uids

def recent_notifications(self):
def recent_notifications(self, scope="library"):
from sefaria.model.notification import NotificationSet
return NotificationSet().recent_for_user(self.id)
return NotificationSet().recent_for_user(self.id, scope=scope)

def unread_notification_count(self):
def unread_notification_count(self, scope="library"):
# TODO: Why do we not need to scope the notifications to the module here?
from sefaria.model.notification import NotificationSet
return NotificationSet().unread_for_user(self.id).count()
return NotificationSet().unread_for_user(self.id, scope=scope).count()

def process_history_item(self, hist, time_stamp):
action = hist.pop("action", None)
Expand Down
1 change: 1 addition & 0 deletions sefaria/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
url(r'^translations/(?P<slug>[^.]+)$', reader_views.translations_page),
url(r'^community/?$', reader_views.community_page),
url(r'^notifications/?$', reader_views.notifications),
url(r'^sheets/notifications/?$', reader_views.notifications),
url(r'^modtools/?$', reader_views.modtools),
url(r'^modtools/upload_text$', sefaria_views.modtools_upload_workflowy),
url(r'^modtools/links$', sefaria_views.links_upload_api),
Expand Down
12 changes: 8 additions & 4 deletions static/css/s2.css
Original file line number Diff line number Diff line change
Expand Up @@ -8377,14 +8377,14 @@ But not to use a display block directive that might break continuous mode for ot
}
.notification .sheetTitle,
.notification .collectionName {
--english-font: var(--english-serif-font-family);
--hebrew-font: var(--hebrew-serif-font-family);
--english-font: var(--english-sans-serif-font-family);
--hebrew-font: var(--hebrew-sans-serif-font-family);
font-size: 24px;
display: block;
}
.notification .sheetSummary {
--english-font: var(--english-serif-font-family);
--hebrew-font: var(--hebrew-serif-font-family);
--english-font: var(--english-sans-serif-font-family);
--hebrew-font: var(--hebrew-sans-serif-font-family);
color: var(--dark-grey);
font-size: 18px;
margin-top: 10px;
Expand Down Expand Up @@ -15169,6 +15169,10 @@ span.ref-link-color-3 {color: blue}
margin-top: 30px;
}

.notificationUserName {
color: var(--midrash-green) !important;
}

.emptyNotificationsTitle{
font-family: Roboto;
font-size: 16px;
Expand Down
18 changes: 8 additions & 10 deletions static/js/NotificationsPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class NotificationsPanel extends Component {
}
}
getMoreNotifications() {
$.getJSON("/api/notifications?page=" + this.state.page, this.loadMoreNotifications);
const activeModule = Sefaria.activeModule;
$.getJSON(`/api/notifications?page=${this.state.page}&scope=${activeModule}`, this.loadMoreNotifications);
this.setState({loading: true});
}
loadMoreNotifications(data) {
Expand Down Expand Up @@ -81,13 +82,10 @@ class NotificationsPanel extends Component {
<InterfaceText>Notifications</InterfaceText>
</h1>
</div>
{(Sefaria._uid) ? (
Sefaria.notificationCount > 0 && notifications
) : (
<LoginPrompt fullPanel={true} />
)}
{!Sefaria._uid && <LoginPrompt fullPanel={true} />}
</div>
{Sefaria._uid && Sefaria.notificationCount < 1 && <EmptyNotificationsMessage /> }
{Sefaria._uid && notifications.length < 1 && <EmptyNotificationsMessage /> }
{Sefaria._uid && notifications.length > 0 && notifications}
</div>
<NavSidebar sidebarModules={sidebarModules} />
</div>
Expand Down Expand Up @@ -167,7 +165,7 @@ const Notification = ({imageUrl, imageLink, topLine, date, body}) => {
const SheetPublishNotification = ({date, content}) => {
const topLine = (
<>
<a href={content.profileUrl}>{content.name}</a>&nbsp;
<a href={content.profileUrl} className="notificationUserName">{content.name}</a>&nbsp;
<InterfaceText>published a new sheet</InterfaceText>
</>
);
Expand Down Expand Up @@ -197,7 +195,7 @@ const SheetPublishNotification = ({date, content}) => {
const SheetLikeNotification = ({date, content}) => {
const topLine = (
<>
<a href={content.profileUrl}>{content.name}</a>&nbsp;
<a href={content.profileUrl} className="notificationUserName">{content.name}</a>&nbsp;
<InterfaceText>liked your sheet</InterfaceText>
</>
);
Expand All @@ -223,7 +221,7 @@ const FollowNotification = ({date, content}) => {

const topLine = (
<>
<a href={content.profileUrl}>{content.name}</a>&nbsp;
<a href={content.profileUrl} className="notificationUserName">{content.name}</a>&nbsp;
<InterfaceText>is now following you</InterfaceText>
</>
);
Expand Down
Loading