[design] Redesign, cleanup Login, Message pages (#2564)
* [cleanup] login, message pages * [style] cleanups * [cleanup] * [cleanup] update password * [fix] name for web form (fixes edit-profile)
This commit is contained in:
parent
1d2a91c393
commit
042e2b09cb
25 changed files with 384 additions and 253 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = "<pre>"+frappe.get_traceback()+"</pre>"
|
||||
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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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"""
|
||||
|
|
|
|||
|
|
@ -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", """<p><a href="/index" class="text-muted">Back to Home</a></p>""")
|
||||
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):
|
||||
|
|
|
|||
|
|
@ -148,15 +148,16 @@ def dropbox_callback(oauth_token=None, not_approved=False):
|
|||
close = '<p class="text-muted">' + _('Please close this window') + '</p>'
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
<div data-html-block="hero">
|
||||
{%- block hero -%}{%- endblock -%}
|
||||
</div>
|
||||
<div class="container" data-html-block="content">
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/* login-css */
|
||||
|
||||
footer {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.hero-and-content {
|
||||
/*background-color: #f5f7fa;*/
|
||||
background-color: #fafbfc;
|
||||
|
||||
.page-sidebar, #wrap-footer, .page-header {
|
||||
display: none;
|
||||
|
|
@ -13,20 +13,6 @@ footer {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: #7575ff;
|
||||
}
|
||||
|
||||
.icon-facebook, .icon-facebook-sign{
|
||||
color: #3b5998;
|
||||
}
|
||||
.icon-google-plus, .icon-google-plus-sign{
|
||||
color: #C63D2D;
|
||||
}
|
||||
.icon-github, .icon-github-sign{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.icon-twitter, .icon-twitter-sign{
|
||||
color: #00a0d1;
|
||||
}
|
||||
|
|
@ -39,8 +25,11 @@ footer {
|
|||
background-color: #7575ff;
|
||||
}
|
||||
|
||||
.form-signin {
|
||||
|
||||
section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-signin .form-signin-heading,
|
||||
.form-signin .checkbox {
|
||||
margin-bottom: 10px;
|
||||
|
|
@ -55,7 +44,7 @@ footer {
|
|||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding: 6px;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.form-signin .form-control:focus {
|
||||
|
|
@ -66,6 +55,26 @@ footer {
|
|||
margin: 10px;
|
||||
}
|
||||
|
||||
.social-logins .fa {
|
||||
margin-right: 5px;
|
||||
color: #8D99A6;
|
||||
}
|
||||
|
||||
.form-footer {
|
||||
margin-top: -45px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-footer, .form-footer a, .form-footer h6 {
|
||||
font-size: 12px;
|
||||
color: #8D99A6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-footer .btn-default {
|
||||
color: #36414C;
|
||||
}
|
||||
|
||||
h5 {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
|
@ -73,44 +82,11 @@ h5 {
|
|||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
h5 span {
|
||||
background: #fff;
|
||||
padding: 0 15px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
h5:before {
|
||||
background: #ddd;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 1px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
}
|
||||
h5:before {
|
||||
left: 0;
|
||||
}
|
||||
.login_header{
|
||||
font-size: 30px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
margin: 10px 0px 30px 0px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
p{
|
||||
p {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.btn-login, .btn-signup, .btn-forgot {
|
||||
background: #7575ff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 400;
|
||||
.login-content .btn {
|
||||
font-size: 14px;
|
||||
margin-top: 45px;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ login.bind_events = function() {
|
|||
args.redirect_to = get_url_arg("redirect-to") || '';
|
||||
args.full_name = ($("#signup_fullname").val() || "").trim();
|
||||
if(!args.email || !valid_email(args.email) || !args.full_name) {
|
||||
frappe.msgprint(__("Valid email and name required"));
|
||||
login.set_indicator(__("Valid email and name required"), 'red');
|
||||
return false;
|
||||
}
|
||||
login.call(args);
|
||||
|
|
@ -46,21 +46,21 @@ login.bind_events = function() {
|
|||
args.cmd = "frappe.core.doctype.user.user.reset_password";
|
||||
args.user = ($("#forgot_email").val() || "").trim();
|
||||
if(!args.user) {
|
||||
frappe.msgprint(__("Valid Login id required."));
|
||||
login.set_indicator(__("Valid Login id required."), 'red');
|
||||
return false;
|
||||
}
|
||||
login.call(args);
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".btn-ldpa-login").on("click", function(){
|
||||
$(".btn-ldap-login").on("click", function(){
|
||||
var args = {};
|
||||
args.cmd = "{{ ldap_settings.method }}";
|
||||
args.usr = ($("#login_email").val() || "").trim();
|
||||
args.pwd = $("#login_password").val();
|
||||
args.device = "desktop";
|
||||
if(!args.usr || !args.pwd) {
|
||||
frappe.msgprint(__("Both login and password required"));
|
||||
login.set_indicator(__("Both login and password required"), 'red');
|
||||
return false;
|
||||
}
|
||||
login.call(args);
|
||||
|
|
@ -75,32 +75,49 @@ login.route = function() {
|
|||
login[route]();
|
||||
}
|
||||
|
||||
login.reset_sections = function(hide) {
|
||||
if(hide || hide===undefined) {
|
||||
$("section").toggle(false);
|
||||
}
|
||||
$('section .indicator').each(function() {
|
||||
$(this).removeClass().addClass('indicator').addClass('blue')
|
||||
.text($(this).attr('data-text'));
|
||||
});
|
||||
}
|
||||
|
||||
login.login = function() {
|
||||
$("form").toggle(false);
|
||||
$(".form-login").toggle(true);
|
||||
login.reset_sections();
|
||||
$(".for-login").toggle(true);
|
||||
}
|
||||
|
||||
login.forgot = function() {
|
||||
$("form").toggle(false);
|
||||
$(".form-forgot").toggle(true);
|
||||
login.reset_sections();
|
||||
$(".for-forgot").toggle(true);
|
||||
}
|
||||
|
||||
login.signup = function() {
|
||||
$("form").toggle(false);
|
||||
$(".form-signup").toggle(true);
|
||||
login.reset_sections();
|
||||
$(".for-signup").toggle(true);
|
||||
}
|
||||
|
||||
|
||||
// Login
|
||||
login.call = function(args) {
|
||||
login.call = function(args, callback) {
|
||||
login.set_indicator(__('Verifying...'), 'blue');
|
||||
return frappe.call({
|
||||
type: "POST",
|
||||
args: args,
|
||||
callback: callback,
|
||||
freeze: true,
|
||||
statusCode: login.login_handlers
|
||||
});
|
||||
}
|
||||
|
||||
login.set_indicator = function(message, color) {
|
||||
$('section:visible .indicator')
|
||||
.removeClass().addClass('indicator').addClass(color).text(message)
|
||||
}
|
||||
|
||||
login.login_handlers = (function() {
|
||||
var get_error_handler = function(default_message) {
|
||||
return function(xhr, data) {
|
||||
|
|
@ -110,7 +127,7 @@ login.login_handlers = (function() {
|
|||
|
||||
var message = default_message;
|
||||
if (data._server_messages) {
|
||||
message = ($.map(JSON.parse(data._server_messages || '[]'), function() {
|
||||
message = ($.map(JSON.parse(data._server_messages || '[]'), function(v) {
|
||||
// temp fix for messages sent as dict
|
||||
try {
|
||||
return JSON.parse(v).message;
|
||||
|
|
@ -120,15 +137,22 @@ login.login_handlers = (function() {
|
|||
}) || []).join('<br>') || default_message;
|
||||
}
|
||||
|
||||
frappe.msgprint(message);
|
||||
if(message===default_message) {
|
||||
login.set_indicator(message, 'red');
|
||||
} else {
|
||||
login.reset_sections(false);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
var login_handlers = {
|
||||
200: function(data) {
|
||||
if(data.message=="Logged In") {
|
||||
login.set_indicator(__("Success"), 'green');
|
||||
window.location.href = get_url_arg("redirect-to") || data.home_page;
|
||||
} else if(data.message=="No App") {
|
||||
login.set_indicator(__("Success"), 'green');
|
||||
if(localStorage) {
|
||||
var last_visited =
|
||||
localStorage.getItem("last_visited")
|
||||
|
|
@ -145,11 +169,26 @@ login.login_handlers = (function() {
|
|||
} else {
|
||||
window.location.href = data.home_page;
|
||||
}
|
||||
} else if(["#signup", "#forgot"].indexOf(window.location.hash)!==-1) {
|
||||
frappe.msgprint(data.message);
|
||||
} else if(window.location.hash === '#forgot') {
|
||||
console.log(data.message);
|
||||
if(data.message==='not found') {
|
||||
login.set_indicator(__("Not a valid user"), 'red');
|
||||
} else if (data.message=='not allowed') {
|
||||
login.set_indicator(__("Not Allowed"), 'red');
|
||||
}
|
||||
|
||||
|
||||
} else if(window.location.hash === '#signup') {
|
||||
if(cint(data.message[0])==0) {
|
||||
login.set_indicator(data.message[1], 'red');
|
||||
} else {
|
||||
login.set_indicator(__('Success'), 'green');
|
||||
frappe.msgprint(data.message[1])
|
||||
}
|
||||
//login.set_indicator(__(data.message), 'green');
|
||||
}
|
||||
},
|
||||
401: get_error_handler(__("Invalid Login")),
|
||||
401: get_error_handler(__("Invalid Login. Try again.")),
|
||||
417: get_error_handler(__("Oops! Something went wrong"))
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -144,13 +144,10 @@ def get_context(context):
|
|||
if not frappe.form_dict.name and not frappe.form_dict.new:
|
||||
self.build_as_list(context)
|
||||
else:
|
||||
name = None
|
||||
if frappe.session.user != 'Guest':
|
||||
name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name")
|
||||
if frappe.session.user != 'Guest' and not frappe.form_dict.name:
|
||||
frappe.form_dict.name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name")
|
||||
|
||||
if name:
|
||||
frappe.form_dict.name = name
|
||||
else:
|
||||
if not frappe.form_dict.name:
|
||||
# only a single doc allowed and no existing doc, hence new
|
||||
frappe.form_dict.new = 1
|
||||
|
||||
|
|
|
|||
|
|
@ -120,10 +120,10 @@ $.extend(frappe, {
|
|||
}
|
||||
|
||||
if(data.exc) {
|
||||
if(opts.btn) {
|
||||
$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-danger" : "text-danger");
|
||||
setTimeout(function() { $(opts.btn).removeClass("btn-danger text-danger"); }, 1000);
|
||||
}
|
||||
// if(opts.btn) {
|
||||
// $(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-danger" : "text-danger");
|
||||
// setTimeout(function() { $(opts.btn).removeClass("btn-danger text-danger"); }, 1000);
|
||||
// }
|
||||
try {
|
||||
var err = JSON.parse(data.exc);
|
||||
if($.isArray(err)) {
|
||||
|
|
@ -135,10 +135,10 @@ $.extend(frappe, {
|
|||
}
|
||||
|
||||
} else{
|
||||
if(opts.btn) {
|
||||
$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-success" : "text-success");
|
||||
setTimeout(function() { $(opts.btn).removeClass("btn-success text-success"); }, 1000);
|
||||
}
|
||||
// if(opts.btn) {
|
||||
// $(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-success" : "text-success");
|
||||
// setTimeout(function() { $(opts.btn).removeClass("btn-success text-success"); }, 1000);
|
||||
// }
|
||||
}
|
||||
if(opts.msg && data.message) {
|
||||
$(opts.msg).html(data.message).toggle(true);
|
||||
|
|
|
|||
|
|
@ -218,11 +218,13 @@ def clear_cache(path=None):
|
|||
|
||||
def render_403(e, pathname):
|
||||
path = "message"
|
||||
frappe.local.message = """<p><strong>{error}</strong></p>
|
||||
<p>
|
||||
<a href="/login?redirect-to=/{pathname}" class="btn btn-primary">{login}</a>
|
||||
</p>""".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):
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@
|
|||
|
||||
{%- block title -%}{{_("Not Found")}}{%- endblock -%}
|
||||
|
||||
{%- block header -%}
|
||||
<h1 class="text-danger" style="margin-top: 100px;">{{_("Page missing or moved")}}</h1>
|
||||
{%- endblock -%}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<div class="404-content" style="margin-bottom: 100px;">
|
||||
<p>{{_("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.")}}</p>
|
||||
<div class='page-card'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator darkgrey'>{{_("Page Missing or Moved")}}</span>
|
||||
</div>
|
||||
<p>{{_("The page you are looking for is missing. This could be because it is moved or there is a typo in the link.")}}</p>
|
||||
<div><a href='/' class='btn btn-primary btn-xs'>{{ _("Home") }}</a></div>
|
||||
</div>
|
||||
<p class='text-muted text-center small' style='margin-top: -20px;'>{{ _("Error Code: {0}").format('404') }}</p>
|
||||
<style>
|
||||
.hero-and-content {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
{%- endfor -%}
|
||||
</head>
|
||||
<body>
|
||||
<div class="centered splash" style="width: 200px; height: 200px;">
|
||||
<div class="centered splash" style="width: 100px; height: 100px;">
|
||||
<img src="{{ splash_image or "/assets/frappe/images/frappe-bird-thin.svg" }}">
|
||||
</div>
|
||||
<div class="main-section">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{% block header %}
|
||||
<h2 class="text-danger">
|
||||
<i class="fa fa-exclamation-sign"></i> Oops, a server error has occured
|
||||
<i class="fa fa-exclamation-sign"></i> Uncaught Server Exception
|
||||
</h2>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,92 +8,101 @@
|
|||
|
||||
{% block page_content %}
|
||||
<!-- {{ for_test }} -->
|
||||
<section class='for-login'>
|
||||
<div class="login-content page-card" style="margin-top: 20px;">
|
||||
<form class="form-signin form-login" role="form">
|
||||
<div class="page-card-head">
|
||||
<span class="indicator blue" data-text="{{ _("Sign In") }}"></span>
|
||||
</div>
|
||||
|
||||
<div class="login-content page-card">
|
||||
<form class="form-signin form-login" role="form">
|
||||
<input type="text" id="login_email"
|
||||
class="form-control" placeholder="{{ _('Email address') }}" required autofocus>
|
||||
|
||||
<div class="login_header">Sign In</div>
|
||||
<input type="password" id="login_password"
|
||||
class="form-control" placeholder="{{ _('Password') }}" required>
|
||||
|
||||
<input type="text" id="login_email"
|
||||
class="form-control" placeholder="{{ _('Email address') }}" required autofocus>
|
||||
<button class="btn btn-sm btn-primary btn-block btn-login" type="submit">
|
||||
{{ _("Sign in") }}</button>
|
||||
|
||||
<input type="password" id="login_password"
|
||||
class="form-control" placeholder="{{ _('Password') }}" required>
|
||||
{% if ldap_settings.enabled %}
|
||||
<button class="btn btn-sm btn-default btn-block btn-login btn-ldap-login">
|
||||
{{ _("Login with LDAP") }}</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
<div class='form-footer'>
|
||||
|
||||
<div>
|
||||
<!-- <p style="float:left" class="text-center small"><input type="checkbox" value="remember-me"> Remember me </p> -->
|
||||
<p style="float:right" class="text-center small"><a href="#forgot">{{ _("Forgot Password?") }}</a></p>
|
||||
</div>
|
||||
<div class='social-logins'>
|
||||
{%- if social_login -%}
|
||||
<h6>{{ _("Or login with") }}</h6>
|
||||
|
||||
<button class="btn btn-lg btn-default btn-block btn-login" type="submit">{{ _("Sign in") }}</button>
|
||||
<div class='social-logins'>
|
||||
|
||||
{%- if social_login -%}
|
||||
<h5><span>{{ _("Or login with") }}</span></h5>
|
||||
|
||||
|
||||
<p class="text-center" style="margin-top: 15px">
|
||||
<p class="text-center" style="margin-top: 15px">
|
||||
{%- if facebook_login is defined %}
|
||||
<a href="{{ facebook_login }}" class="no-decoration btn-social btn-facebook">
|
||||
<i class="fa fa-facebook fa-2x"></i></a>
|
||||
<a href="{{ facebook_login }}"
|
||||
class="btn btn-default btn-xs btn-social btn-facebook">
|
||||
<i class="fa fa-facebook-official"></i> {{ _("Facebook") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if google_login is defined %}
|
||||
<a href="{{ google_login }}" class="no-decoration btn-social btn-google">
|
||||
<i class="fa fa-google-plus fa-2x"></i></a>
|
||||
<a href="{{ google_login }}" class="btn btn-default btn-xs btn-social btn-google">
|
||||
<i class="fa fa-google-plus"></i> {{ _("Google") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if github_login is defined %}
|
||||
<a href="{{ github_login }}" class="no-decoration btn-social btn-github">
|
||||
<i class="fa fa-github fa-2x"></i></a>
|
||||
<a href="{{ github_login }}" class="btn btn-default btn-xs btn-social btn-github">
|
||||
<i class="fa fa-github"></i> {{ _("GitHub") }}</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if frappe_login is defined %}
|
||||
<a href="{{ frappe_login }}" class="no-decoration">
|
||||
<img src="/assets/frappe/images/favicon.png"></a>
|
||||
<a href="{{ frappe_login }}" class="btn btn-default btn-xs btn-social">
|
||||
<img style='width: 16px; height: 16px;'
|
||||
src="/assets/frappe/images/favicon.png"> {{ _("Frappe") }}</a>
|
||||
{%- endif -%}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
{% if ldap_settings.enabled %}
|
||||
<p>
|
||||
<button class="btn btn-lg btn-default btn-block btn-login btn-ldpa-login">
|
||||
{{ _("Login via LDAP") }}</button>
|
||||
</p>
|
||||
{% endif %}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
|
||||
{%- if not disable_signup -%}
|
||||
<p class="text-center">
|
||||
<a href="#signup" style="margin-top: -2px;">{{ _("Dont have an account? Sign up") }}</a>
|
||||
</p>
|
||||
{%- endif -%}
|
||||
<p class="text-center">
|
||||
<a href="#forgot">{{ _("Forgot Password?") }}</a></p>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 25px">
|
||||
{%- if not disable_signup -%}
|
||||
<p class="text-center">
|
||||
{{ _("Dont have an account? ") }} <a class="btn btn-default" href="#signup" style="margin-top: -2px;">{{ _("Sign up.") }}</a>
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class='padding'></div>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
<section class='for-signup'>
|
||||
<div class="login-content page-card" style="margin-top: 20px;">
|
||||
<form class="form-signin form-signup hide" role="form">
|
||||
<div class="page-card-head">
|
||||
<span class="indicator blue" data-text="{{ _("Sign Up") }}"></span>
|
||||
</div>
|
||||
<input type="text" id="signup_fullname"
|
||||
class="form-control" placeholder="{{ _('Full Name') }}" required autofocus>
|
||||
<input type="email" id="signup_email"
|
||||
class="form-control" placeholder="{{ _('Email address') }}" required>
|
||||
<br>
|
||||
<button class="btn btn-lg btn-default btn-block btn-signup" type="submit">{{ _("Sign up") }}</button>
|
||||
<p class="text-center small">
|
||||
{{ _("Have an account? ") }} <a href="#login" class="blue">{{ _("Login") }}</a>
|
||||
</p>
|
||||
<button class="btn btn-sm btn-primary btn-block btn-signup" type="submit">{{ _("Sign up") }}</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class='form-footer'>
|
||||
<a href="#login" class="blue">{{ _("Have an account? Login") }}</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class='for-forgot'>
|
||||
<div class="login-content page-card" style="margin-top: 20px;">
|
||||
<form class="form-signin form-forgot hide" role="form">
|
||||
<div class="page-card-head">
|
||||
<span class="indicator blue" data-text="{{ _("Forgot Password") }}"></span></div>
|
||||
<input type="email" id="forgot_email"
|
||||
class="form-control" placeholder="{{ _('Email address') }}" required autofocus>
|
||||
<br>
|
||||
<button class="btn btn-lg btn-default btn-block btn-forgot" type="submit">{{ _("Send Password") }}</button>
|
||||
<p class="text-center small">
|
||||
<br><a href="#login" class="blue">{{ _("Back to Login") }}</a>
|
||||
</p>
|
||||
<button class="btn btn-sm btn-primary btn-block btn-forgot" type="submit">{{ _("Send Password") }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class='form-footer'>
|
||||
<a href="#login">{{ _("Back to Login") }}</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ def get_context(context):
|
|||
if get_oauth_keys(provider):
|
||||
context["{provider}_login".format(provider=provider)] = get_oauth2_authorize_url(provider)
|
||||
context["social_login"] = True
|
||||
|
||||
|
||||
ldap_settings = get_ldap_settings()
|
||||
context["ldap_settings"] = ldap_settings
|
||||
|
||||
|
||||
return context
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils.user import get_fullname_and_avatar
|
||||
import frappe.www.list
|
||||
|
||||
no_cache = 1
|
||||
|
|
|
|||
|
|
@ -2,17 +2,22 @@
|
|||
|
||||
{% block title %}{{ title or _("Message") }}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% if header is defined -%}
|
||||
<h1>{{ header }}</h1>
|
||||
{%- endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<div class="message-content" style="min-height: 200px;">
|
||||
<div>
|
||||
{{ message or _("No Message") }}
|
||||
<div class='page-card'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator {{ indicator_color }}'>{{ title or _("Message") }}</span>
|
||||
</div>
|
||||
<p>{{ message or "" }}</p>
|
||||
<div><a href='{{ primary_action or "/" }}' class='btn btn-primary btn-sm'>
|
||||
{{ primary_label or _("Home") }}</a></div>
|
||||
</div>
|
||||
{% if error_code %}
|
||||
<p class='text-muted text-center small' style='margin-top: -20px;'>{{ _("Error Code: {0}").format(error_code) }}</p>
|
||||
{% endif %}
|
||||
<style>
|
||||
.hero-and-content {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -2,29 +2,32 @@
|
|||
|
||||
{% block title %} {{_("Reset Password")}} {% endblock %}
|
||||
|
||||
{% block header %}<h1>{{_("Reset Password")}}</h1>{% endblock %}
|
||||
{% block page_content %}
|
||||
|
||||
<div class="row" style="margin-top: 40px; margin-bottom: 20px">
|
||||
<div class="col-sm-6">
|
||||
<form id="reset-password">
|
||||
<div class="form-group">
|
||||
<input id="old_password" type="password"
|
||||
class="form-control" placeholder="{{ _("Old Password") }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="new_password" type="password"
|
||||
class="form-control" placeholder="{{ _("New Password") }}">
|
||||
<span class="password-strength-indicator indicator"></span>
|
||||
</div>
|
||||
<p class='password-strength-message text-muted small hidden'></p>
|
||||
<div class="form-group">
|
||||
<button type="submit" id="update"
|
||||
class="btn btn-primary">{{_("Update")}}</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="page-card">
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator blue'>{{ _("Reset Password") }}</span>
|
||||
</div>
|
||||
<form id="reset-password">
|
||||
<div class="form-group">
|
||||
<input id="old_password" type="password"
|
||||
class="form-control" placeholder="{{ _("Old Password") }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="new_password" type="password"
|
||||
class="form-control" placeholder="{{ _("New Password") }}">
|
||||
<span class="password-strength-indicator indicator"></span>
|
||||
</div>
|
||||
<p class='password-strength-message text-muted small hidden'></p>
|
||||
<button type="submit" id="update"
|
||||
class="btn btn-primary">{{_("Update")}}</button>
|
||||
</form>
|
||||
</div>
|
||||
<style>
|
||||
.hero-and-content {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
|
|
@ -62,17 +65,25 @@ frappe.ready(function() {
|
|||
method: "frappe.core.doctype.user.user.update_password",
|
||||
btn: $("#update"),
|
||||
args: args,
|
||||
callback: function(r) {
|
||||
$("input").val("");
|
||||
if(r.message) {
|
||||
frappe.msgprint(__("Password Updated"));
|
||||
setTimeout(function() {
|
||||
window.location.href = r.message;
|
||||
}, 2000);
|
||||
statusCode: {
|
||||
401: function() {
|
||||
$('.page-card-head .indicator').removeClass().addClass('indicator red')
|
||||
.text(__('Invalid Password'));
|
||||
},
|
||||
200: function(r) {
|
||||
$("input").val("");
|
||||
strength_indicator.addClass('hidden');
|
||||
strength_message.addClass('hidden');
|
||||
$('.page-card-head .indicator')
|
||||
.removeClass().addClass('indicator green')
|
||||
.html(_('Password Updated'));
|
||||
if(r.message) {
|
||||
frappe.msgprint(__("Password Updated"));
|
||||
setTimeout(function() {
|
||||
window.location.href = r.message;
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
if(r.exc) {
|
||||
frappe.msgprint(r.exc);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -106,23 +117,32 @@ frappe.ready(function() {
|
|||
method: 'frappe.core.doctype.user.user.test_password_strength',
|
||||
args: args,
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.entropy) {
|
||||
var score = r.message.score,
|
||||
feedback = r.message.feedback;
|
||||
// console.log(r.message);
|
||||
},
|
||||
statusCode: {
|
||||
401: function() {
|
||||
$('.page-card-head .indicator').removeClass().addClass('indicator red')
|
||||
.text(__('Invalid Password'));
|
||||
},
|
||||
200: function(r) {
|
||||
if (r.message && r.message.entropy) {
|
||||
var score = r.message.score,
|
||||
feedback = r.message.feedback;
|
||||
|
||||
feedback.crack_time_display = r.message.crack_time_display;
|
||||
feedback.score = score;
|
||||
feedback.crack_time_display = r.message.crack_time_display;
|
||||
feedback.score = score;
|
||||
|
||||
if (score < 2) {
|
||||
set_strength_indicator('red', feedback);
|
||||
} else if (score < 4) {
|
||||
set_strength_indicator('yellow', feedback);
|
||||
} else {
|
||||
set_strength_indicator('green', feedback);
|
||||
if (score < 2) {
|
||||
set_strength_indicator('red', feedback);
|
||||
} else if (score < 4) {
|
||||
set_strength_indicator('yellow', feedback);
|
||||
} else {
|
||||
set_strength_indicator('green', feedback);
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log(r.message);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue