I write a pop message for display immediate after login.
when I run the following in the bench console.
Apps in this namespace:
frappe, erpnext, hrms, payments, education, agriculture, healthcare, pdf_on_submit, my_print, chat, late_minutes, icfosserp, icfoss_dashboard, custom_dashboard_app, asset_sla, frappe_whatsapp, mytask
In [1]: from late_minutes.login_reminder import check_recent_absents
…:
…: class FakeLoginManager:
…: user = “arunad@icfoss.org”
…:
…: check_recent_absents(FakeLoginManager())
In [2]:
It works as in the screenshot
But when I log out and again logged in , it does not shown…
My hooks.py are as follows
on_login = “late_minutes.login_reminder.check_recent_absents”
app_include_js = “/assets/late_minutes/js/desk.js”
I request all of you to help me if any one knew the solution.
2 Likes
@ArunaDevraj
You can achieve this by overriding the frappe.Application
class in your custom app’s desk.js
. Specifically, override the startup()
method to display your dialog box right after login. Here’s how I did it:
frappe.Application = class Application {
constructor() {
this.startup();
}
startup() {
this.show_reminder_dialog();
}
show_reminder_dialog() {
frappe.msgprint({
title: __("Reminder"),
message: __("You have recent absents. Please check your attendance."),
indicator: "orange"
});
}
}
This works because startup()
is called once immediately after login and page load.
Just using on_login
in hooks.py
doesn’t guarantee your dialog appears on the front end — it’s server-side.
I added this to my app’s public/js/desk.js
, and included it via app_include_js
in hooks.py
.
@Sudhanshu
But it is only a static message.
I want realtime message
my desk.js is as following
console.log(“
Custom JS file from late_minutes loaded”);
let maxWaitTime = 10000; // 10 seconds max wait
let waited = 0;
const interval = 500;
const waitForSocket = setInterval(() => {
if (frappe.realtime && frappe.realtime.on) {
clearInterval(waitForSocket);
console.log(“
frappe.realtime is ready”);
frappe.realtime.on("login_popup", function (data) {
// Support both string or object format
let message = typeof data === "string" ? data : (data?.message || null);
if (message) {
console.log("✅ Received login_popup:", message);
// ✅ Delay execution until UI is ready
frappe.after_ajax(() => {
setTimeout(() => {
frappe.msgprint({
title: __("Attendance Reminder"),
message: message,
indicator: "orange"
});
}, 300); // Small delay to ensure UI is stable
});
} else {
console.warn("⚠️ Received login_popup without a valid message:", data);
}
});
} else {
waited += interval;
if (waited >= maxWaitTime) {
clearInterval(waitForSocket);
console.error("❌ frappe.realtime not ready after 10 seconds");
}
}
}, interval);
@ArunaDevraj
If frappe.realtime
isn’t working reliably, you can simply call your API after login and check the condition yourself.
Just add this in your desk.js
file:
frappe.after_ajax(() => {
frappe.call('late_minutes.api.get_login_popup_message')
.then(r => {
const message = r.message;
if (message) {
frappe.msgprint({
title: __("Attendance Reminder"),
message: message,
indicator: "orange"
});
}
});
});
This will fetch the real-time message based on current data
You can handle all your logic server-side in the API (like checking recent absents, holidays, etc.)
In short:
in my original code
you can just do frappe call
write your logic in python
if conditions satisfy then show dialog box
@Sudhanshu
Thank you, dear bro… I got it… Thank you for your valuable support.