diff --git a/frappe/__init__.py b/frappe/__init__.py index a1391a8c90..4ac5ad90ee 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -301,6 +301,9 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None, message_log.append(json.dumps(out)) _raise_exception() +def clear_messages(): + local.message_log = [] + def throw(msg, exc=ValidationError, title=None): """Throw execption and show message (`msgprint`). @@ -994,23 +997,42 @@ def compare(val1, condition, val2): import frappe.utils return frappe.utils.compare(val1, condition, val2) -def respond_as_web_page(title, html, success=None, http_status_code=None, context=None): +def respond_as_web_page(title, html, success=None, http_status_code=None, + context=None, indicator_color=None, primary_action='/', primary_label = None): """Send response as a web page with a message rather than JSON. Used to show permission errors etc. :param title: Page title and heading. :param message: Message to be shown. :param success: Alert message. - :param http_status_code: HTTP status code.""" + :param http_status_code: HTTP status code + :param context: web template context + :param indicator_color: color of indicator in title + :param primary_action: route on primary button (default is `/`) + :param primary_label: label on primary button (defaut is "Home")""" local.message_title = title local.message = html - local.message_success = success local.response['type'] = 'page' local.response['route'] = 'message' if http_status_code: local.response['http_status_code'] = http_status_code - if context: - local.response['context'] = context + if not context: + context = {} + + if not indicator_color: + if success: + indicator_color = 'green' + elif http_status_code and http_status_code > 300: + indicator_color = 'red' + else: + indicator_color = 'blue' + + context['indicator_color'] = indicator_color + context['primary_label'] = primary_label + context['primary_action'] = primary_action + context['error_code'] = http_status_code + + local.response['context'] = context def redirect_to_message(title, html, http_status_code=None, context=None): """Redirects to /message?id=random diff --git a/frappe/app.py b/frappe/app.py index 8092b5ddc2..2cfeafb426 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -24,6 +24,7 @@ from frappe.utils import get_site_name, get_site_path from frappe.middlewares import StaticDataMiddleware from frappe.utils.error import make_error_snapshot from frappe.core.doctype.communication.comment import update_comments_in_parent_after_request +from frappe import _ local_manager = LocalManager([frappe.local]) @@ -123,6 +124,7 @@ def make_form_dict(request): def handle_exception(e): http_status_code = getattr(e, "http_status_code", 500) + return_as_message = False if (http_status_code==500 and isinstance(e, MySQLdb.OperationalError) @@ -132,17 +134,31 @@ def handle_exception(e): # code 409 represents conflict http_status_code = 508 - if frappe.local.is_ajax or 'application/json' in frappe.local.request.headers.get('Accept', ''): + if http_status_code==403: + frappe.respond_as_web_page(_("Not Permitted"), + _("You do not have enough permissions to complete the action"), + http_status_code=http_status_code, indicator_color='red') + return_as_message = True + + elif http_status_code==404: + frappe.respond_as_web_page(_("Not Found"), + _("The resource you are looking for is not available"), + http_status_code=http_status_code, indicator_color='red') + return_as_message = True + + + elif frappe.local.is_ajax or 'application/json' in frappe.local.request.headers.get('Accept', ''): response = frappe.utils.response.report_error(http_status_code) + else: traceback = "
"+frappe.get_traceback()+"" if frappe.local.flags.disable_traceback: traceback = "" frappe.respond_as_web_page("Server Error", - traceback, - http_status_code=http_status_code) - response = frappe.website.render.render("message", http_status_code=http_status_code) + traceback, http_status_code=http_status_code, + indicator_color='red') + return_as_message = True if e.__class__ == frappe.AuthenticationError: if hasattr(frappe.local, "login_manager"): @@ -152,6 +168,9 @@ def handle_exception(e): frappe.logger().error('Request Error', exc_info=True) make_error_snapshot(e) + if return_as_message: + response = frappe.website.render.render("message", http_status_code=http_status_code) + return response def after_request(rollback): diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 0421ce2a49..8b3c490bf5 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -534,15 +534,7 @@ def update_password(new_password, key=None, old_password=None): def test_password_strength(new_password, key=None, old_password=None): from frappe.utils.password_strength import test_password_strength as _test_password_strength - res = _get_user_for_update_password(key, old_password) - if not res: - return - elif res.get('message'): - return res['message'] - else: - user = res['user'] - - user_data = frappe.db.get_value('User', user, ['first_name', 'middle_name', 'last_name', 'email', 'birth_date']) + user_data = frappe.db.get_value('User', frappe.session.user, ['first_name', 'middle_name', 'last_name', 'email', 'birth_date']) if new_password: return _test_password_strength(new_password, user_inputs=user_data) @@ -586,9 +578,9 @@ def sign_up(email, full_name, redirect_to): user = frappe.db.get("User", {"email": email}) if user: if user.disabled: - return _("Registered but disabled.") + return 0, _("Registered but disabled") else: - return _("Already Registered") + return 0, _("Already Registered") else: if frappe.db.sql("""select count(*) from tabUser where HOUR(TIMEDIFF(CURRENT_TIMESTAMP, TIMESTAMP(modified)))=1""")[0][0] > 300: @@ -613,24 +605,25 @@ def sign_up(email, full_name, redirect_to): frappe.cache().hset('redirect_after_login', user.name, redirect_to) if user.flags.email_sent: - return _("Please check your email for verification") + return 1, _("Please check your email for verification") else: - return _("Please ask your administrator to verify your sign-up") + return 2, _("Please ask your administrator to verify your sign-up") @frappe.whitelist(allow_guest=True) def reset_password(user): if user=="Administrator": - return _("Not allowed to reset the password of {0}").format(user) + return 'not allowed' try: user = frappe.get_doc("User", user) user.validate_reset_password() user.reset_password(send_email=True) - return _("Password reset instructions have been sent to your email") + return frappe.msgprint(_("Password reset instructions have been sent to your email")) except frappe.DoesNotExistError: - return _("User {0} does not exist").format(user) + frappe.clear_messages() + return 'not found' def user_query(doctype, txt, searchfield, start, page_len, filters): from frappe.desk.reportview import get_match_cond diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 30ee05432a..05d982d595 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -98,7 +98,8 @@ def unsubscribe(email, name): return_unsubscribed_page(email) def return_unsubscribed_page(email): - frappe.respond_as_web_page(_("Unsubscribed"), _("{0} has been successfully unsubscribed from this list.").format(email)) + frappe.respond_as_web_page(_("Unsubscribed"), + _("{0} has been successfully unsubscribed from this list.").format(email), indicator_color='green') def create_lead(email_id): """create a lead if it does not exist""" @@ -157,7 +158,9 @@ def confirm_subscription(email): add_subscribers(_("Website"), email) frappe.db.commit() - frappe.respond_as_web_page(_("Confirmed"), _("{0} has been successfully added to our Email Group.").format(email)) + frappe.respond_as_web_page(_("Confirmed"), + _("{0} has been successfully added to the Email Group.").format(email), + indicator_color='green') def send_newsletter(newsletter): diff --git a/frappe/email/queue.py b/frappe/email/queue.py index ae4ce06687..afbb656dc0 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -218,7 +218,9 @@ def unsubscribe(doctype, name, email): return_unsubscribed_page(email, doctype, name) def return_unsubscribed_page(email, doctype, name): - frappe.respond_as_web_page(_("Unsubscribed"), _("{0} has left the conversation in {1} {2}").format(email, _(doctype), name)) + frappe.respond_as_web_page(_("Unsubscribed"), + _("{0} has left the conversation in {1} {2}").format(email, _(doctype), name), + indicator_color='green') def flush(from_test=False): """flush email queue, every time: called from scheduler""" diff --git a/frappe/handler.py b/frappe/handler.py index a96228c0b1..70bdb68cce 100755 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -30,7 +30,9 @@ def execute_cmd(cmd, from_async=False): try: method = get_attr(cmd) except: - frappe.throw('Invalid method', frappe.NotFound) + frappe.respond_as_web_page(title='Invalid Method', html='Method not found', + indicator_color='red', http_status_code=404) + return if from_async: method = method.queue @@ -79,7 +81,8 @@ def logout(): def web_logout(): frappe.local.login_manager.logout() frappe.db.commit() - frappe.respond_as_web_page("Logged Out", """""") + frappe.respond_as_web_page(_("Logged Out"), _("You have been successfully logged out"), + indicator_color='green') @frappe.whitelist(allow_guest=True) def run_custom_method(doctype, name, custom_method): diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index e68692cac7..92aa639f7a 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -148,15 +148,16 @@ def dropbox_callback(oauth_token=None, not_approved=False): close = '
' + _('Please close this window') + '
' frappe.respond_as_web_page(_("Dropbox Setup"), _("Illegal Access Token. Please try again") + close, - success=False, http_status_code=frappe.AuthenticationError.http_status_code) + indicator_color='red', + http_status_code=frappe.AuthenticationError.http_status_code) else: frappe.respond_as_web_page(_("Dropbox Setup"), _("You did not apporve Dropbox Access.") + close, - success=False, http_status_code=frappe.AuthenticationError.http_status_code) + indicator_color='red') frappe.respond_as_web_page(_("Dropbox Setup"), _("Dropbox access is approved!") + close, - success=False, http_status_code=frappe.AuthenticationError.http_status_code) + indicator_color='red') # backup process @frappe.whitelist() diff --git a/frappe/integrations/doctype/paypal_settings/paypal_settings.py b/frappe/integrations/doctype/paypal_settings/paypal_settings.py index 33f14843b1..456e775565 100644 --- a/frappe/integrations/doctype/paypal_settings/paypal_settings.py +++ b/frappe/integrations/doctype/paypal_settings/paypal_settings.py @@ -217,7 +217,7 @@ def get_express_checkout_details(token): if response.get("ACK")[0] != "Success": frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.").format(response.get("CORRELATIONID", [None])[0]), - success=False, + indicator_color='red', http_status_code=frappe.ValidationError.http_status_code) return @@ -300,5 +300,5 @@ def get_checkout_url(**kwargs): except Exception: frappe.respond_as_web_page(_("Something went wrong"), _("Looks like something is wrong with this site's Paypal configuration. Don't worry! No payment has been made from your Paypal account."), - success=False, + indicator_color='red', http_status_code=frappe.ValidationError.http_status_code) \ No newline at end of file diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index e9877636ae..04e5be8e7e 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -219,8 +219,8 @@ def get_checkout_url(**kwargs): return frappe.get_doc("Razorpay Settings").get_payment_url(**kwargs) except Exception: frappe.respond_as_web_page(_("Something went wrong"), - _("Looks like something is wrong with this site's Razorpay configuration. Don't worry! No payment has been made."), - success=False, + _("Looks like something is wrong with this site's Razorpay configuration. No payment has been made."), + indicator_color='red', http_status_code=frappe.ValidationError.http_status_code) @frappe.whitelist() diff --git a/frappe/public/css/website.css b/frappe/public/css/website.css index d24d7c6596..ea29902446 100644 --- a/frappe/public/css/website.css +++ b/frappe/public/css/website.css @@ -920,10 +920,26 @@ li .footer-child-item { } .page-card { max-width: 360px; - padding: 30px; - margin: auto; + padding: 15px; + margin: 70px auto; border: 1px solid #d1d8dd; border-radius: 4px; - margin: 30px auto; background-color: #fff; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1); +} +.page-card .page-card-head { + padding: 10px 15px; + margin: -15px; + margin-bottom: 15px; + border-bottom: 1px solid #d1d8dd; +} +.page-card .page-card-head .indicator { + color: #36414C; + font-size: 14px; +} +.page-card .page-card-head .indicator::before { + margin: 0 6px 0.5px 0px; +} +.page-card .btn { + margin-top: 30px; } diff --git a/frappe/public/less/website.less b/frappe/public/less/website.less index e8c523120c..602bba4493 100644 --- a/frappe/public/less/website.less +++ b/frappe/public/less/website.less @@ -661,10 +661,30 @@ li .footer-child-item { .page-card { max-width: 360px; - padding: 30px; - margin: auto; + padding: 15px; + margin: 70px auto; border: 1px solid @border-color; border-radius: 4px; - margin: 30px auto; - background-color: #fff; + background-color: #fff; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1); + + .page-card-head { + padding: 10px 15px; + margin: -15px; + margin-bottom: 15px; + border-bottom: 1px solid @border-color; + + .indicator { + color: @text-color; + font-size: 14px; + } + + .indicator::before { + margin: 0 6px 0.5px 0px; + } + } + + .btn { + margin-top: 30px; + } } diff --git a/frappe/templates/base.html b/frappe/templates/base.html index 655d636df2..2395281233 100644 --- a/frappe/templates/base.html +++ b/frappe/templates/base.html @@ -69,7 +69,7 @@{error}
-- {login} -
""".format(error=cstr(e.message), login=_("Login"), pathname=frappe.local.path) + frappe.local.message = cstr(e.message) frappe.local.message_title = _("Not Permitted") + frappe.local.response['context'] = dict( + indicator_color = 'red', + primary_action = '/login', + primary_label = _('Login') + ) return render_page(path), e.http_status_code def get_doctype_from_path(path): diff --git a/frappe/www/404.html b/frappe/www/404.html index 2ebd230288..9e805d726b 100644 --- a/frappe/www/404.html +++ b/frappe/www/404.html @@ -2,13 +2,18 @@ {%- block title -%}{{_("Not Found")}}{%- endblock -%} -{%- block header -%} -{{_("We are very sorry for this, but the page you are looking for is missing (this could be because of a typo in the address) or moved.")}}
+{{_("The page you are looking for is missing. This could be because it is moved or there is a typo in the link.")}}
+{{ _("Error Code: {0}").format('404') }}
+ {% endblock %} diff --git a/frappe/www/desk.html b/frappe/www/desk.html index 3bd4e8375f..dd55af0038 100644 --- a/frappe/www/desk.html +++ b/frappe/www/desk.html @@ -19,7 +19,7 @@ {%- endfor -%} -