Skip to content

Commit

Permalink
feat: What's New
Browse files Browse the repository at this point in the history
  • Loading branch information
ankush committed Apr 17, 2024
1 parent f1c8a99 commit 1855131
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 8 deletions.
2 changes: 2 additions & 0 deletions frappe/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import frappe.defaults
import frappe.desk.desk_page
from frappe.core.doctype.navbar_settings.navbar_settings import get_app_logo, get_navbar_settings
from frappe.desk.doctype.changelog_feed.changelog_feed import get_changelog_feed_items
from frappe.desk.doctype.form_tour.form_tour import get_onboarding_ui_tours
from frappe.desk.doctype.route_history.route_history import frequently_visited_links
from frappe.desk.form.load import get_meta_bundle
Expand Down Expand Up @@ -107,6 +108,7 @@ def get_bootinfo():
bootinfo.translated_doctypes = get_translated_doctypes()
bootinfo.subscription_conf = add_subscription_conf()
bootinfo.marketplace_apps = get_marketplace_apps()
bootinfo.changelog_feed = get_changelog_feed_items()

return bootinfo

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def get_next_execution(self):
next_execution = croniter(self.cron_format, last_execution).get_next(datetime)

jitter = 0
if self.frequency in ("Hourly Long", "Daily Long"):
if "Long" in self.frequency:
jitter = randint(1, 600)
return next_execution + timedelta(seconds=jitter)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_weekly_job(self):
dict(method="frappe.social.doctype.energy_point_log.energy_point_log.send_weekly_summary"),
)
job.db_set("last_execution", "2019-01-01 00:00:00")
self.assertTrue(job.is_event_due(get_datetime("2019-01-06 00:00:01")))
self.assertTrue(job.is_event_due(get_datetime("2019-01-06 00:10:01"))) # +10 min because of jitter
self.assertFalse(job.is_event_due(get_datetime("2019-01-02 00:00:06")))
self.assertFalse(job.is_event_due(get_datetime("2019-01-05 23:59:59")))

Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/user/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ def test_rate_limiting_for_reset_password(self):
res1 = c.session.post(url, data=data, verify=c.verify, headers=c.headers)
res2 = c.session.post(url, data=data, verify=c.verify, headers=c.headers)
self.assertEqual(res1.status_code, 404)
self.assertEqual(res2.status_code, 417)
self.assertEqual(res2.status_code, 429)

def test_user_rename(self):
old_name = "test_user_rename@example.com"
Expand Down
2 changes: 1 addition & 1 deletion frappe/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class InvalidSignatureError(ValidationError):


class RateLimitExceededError(ValidationError):
pass
http_status_code = 429


class CannotChangeConstantError(ValidationError):
Expand Down
3 changes: 3 additions & 0 deletions frappe/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@
"frappe.desk.form.document_follow.send_weekly_updates",
"frappe.social.doctype.energy_point_log.energy_point_log.send_weekly_summary",
"frappe.integrations.doctype.google_drive.google_drive.weekly_backup",
"frappe.desk.doctype.changelog_feed.changelog_feed.fetch_changelog_feed",
],
"monthly": [
"frappe.email.doctype.auto_email_report.auto_email_report.send_monthly",
Expand Down Expand Up @@ -455,6 +456,8 @@
"frappe.utils.sentry.add_bootinfo",
]

get_changelog_feed = "frappe.desk.doctype.changelog_feed.changelog_feed.get_feed"

export_python_type_annotations = True

# log doctype cleanups to automatically add in log settings
Expand Down
59 changes: 58 additions & 1 deletion frappe/public/js/frappe/ui/notifications/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ frappe.ui.Notifications = class Notifications {
this.body = this.dropdown_list.find(".notification-list-body");
this.panel_events = this.dropdown_list.find(".panel-events");
this.panel_notifications = this.dropdown_list.find(".panel-notifications");
this.panel_changelog_feed = this.dropdown_list.find(".panel-changelog-feed");

this.user = frappe.session.user;

Expand Down Expand Up @@ -52,11 +53,17 @@ frappe.ui.Notifications = class Notifications {
el: this.panel_notifications,
},
{
label: __("Today's Events"),
label: __("Events"),
id: "todays_events",
view: EventsView,
el: this.panel_events,
},
{
label: __("What's New"),
id: "changelog_feed",
view: ChangelogFeedView,
el: this.panel_changelog_feed,
},
];

let get_headers_html = (item) => {
Expand Down Expand Up @@ -439,3 +446,53 @@ class EventsView extends BaseNotificationsView {
this.container.html(html);
}
}

class ChangelogFeedView extends BaseNotificationsView {
make() {
this.render_changelog_feed_html(frappe.boot.changelog_feed || []);
}

render_changelog_feed_html(changelog_feed) {
let html = "";
if (changelog_feed.length) {
this.container.empty();
const get_changelog_feed_html = (changelog_feed_item) => {
const timestamp = frappe.datetime.prettyDate(
changelog_feed_item.posting_timestamp
);
const message_html = `<div class="message">
<div>${changelog_feed_item.title}</div>
<div class="notification-timestamp text-muted">
${changelog_feed_item.app_title} | ${timestamp}
</div>
</div>`;

const item_html = `<a class="recent-item notification-item"
href="${changelog_feed_item.link}"
data-name="${changelog_feed_item.title}"
target="_blank" rel="noopener noreferrer"
>
<div class="notification-body">
${message_html}
</div>
</div>
</a>`;

return item_html;
};
html = changelog_feed.map(get_changelog_feed_html).join("");
} else {
html = `<div class="notification-null-state">
<div class="text-center">
<img src="/assets/frappe/images/ui-states/notification-empty-state.svg" alt="Generic Empty State" class="null-state">
<div class="title">${__("Nothing New")}</div>
<div class="subtitle">
${__("There is nothing new to show you right now.")}
</div>
</div>
</div>
`;
}
this.container.html(html);
}
}
3 changes: 2 additions & 1 deletion frappe/public/js/frappe/ui/toolbar/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<div class="notification-list-body">
<div class="panel-notifications"></div>
<div class="panel-events"></div>
<div class="panel-changelog-feed"></div>
</div>
</div>
</li>
Expand Down Expand Up @@ -150,4 +151,4 @@
</div>
{% endif %}

</div>
</div>
3 changes: 2 additions & 1 deletion frappe/rate_limiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ def wrapper(*args, **kwargs):
value = frappe.cache.incrby(cache_key, 1)
if value > _limit:
frappe.throw(
_("You hit the rate limit because of too many requests. Please try after sometime.")
_("You hit the rate limit because of too many requests. Please try after sometime."),
frappe.RateLimitExceededError,
)

return fn(*args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion frappe/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def test_login_with_email_link(self):
# Rate limiting
for _ in range(6):
res = requests.get(_generate_temporary_login_link(user, 10))
if res.status_code == 417:
if res.status_code == 429:
break
else:
self.fail("Rate limting not working")
Expand Down

0 comments on commit 1855131

Please sign in to comment.