Merge branch 'hotfix'
This commit is contained in:
commit
fd06f8ea9c
28 changed files with 291 additions and 80 deletions
|
|
@ -35,6 +35,7 @@ before_script:
|
|||
- echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
|
||||
|
||||
- cd ~/frappe-bench
|
||||
- npm install babel-core less chokidar babel-preset-es2015 babel-preset-es2016 babel-preset-es2017 babel-preset-babili
|
||||
- bench use test_site
|
||||
- bench reinstall --yes
|
||||
- bench start &
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json
|
|||
from .exceptions import *
|
||||
from .utils.jinja import get_jenv, get_template, render_template
|
||||
|
||||
__version__ = '8.0.55'
|
||||
__version__ = '8.0.56'
|
||||
__title__ = "Frappe Framework"
|
||||
|
||||
local = Local()
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ def application(request):
|
|||
elif frappe.request.path.startswith('/private/files/'):
|
||||
response = frappe.utils.response.download_private_file(request.path)
|
||||
|
||||
elif frappe.local.request.method in ('GET', 'HEAD'):
|
||||
elif frappe.local.request.method in ('GET', 'HEAD', 'POST'):
|
||||
response = frappe.website.render.render()
|
||||
|
||||
else:
|
||||
|
|
@ -122,6 +122,7 @@ def make_form_dict(request):
|
|||
frappe.local.form_dict.pop("_")
|
||||
|
||||
def handle_exception(e):
|
||||
response = None
|
||||
http_status_code = getattr(e, "http_status_code", 500)
|
||||
return_as_message = False
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,9 @@ class LoginManager:
|
|||
if not (user and pwd):
|
||||
self.fail('Incomplete login details', user=user)
|
||||
|
||||
if cint(frappe.db.get_value("System Settings", "System Settings", "allow_login_using_mobile_number")):
|
||||
user = frappe.db.get_value("User", filters={"mobile_no": user}, fieldname="name") or user
|
||||
|
||||
self.check_if_enabled(user)
|
||||
self.user = self.check_password(user, pwd)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const build_map = make_build_map();
|
|||
// command line args
|
||||
const action = process.argv[2] || '--build';
|
||||
|
||||
if (!['--build', '--watch'].includes(action)) {
|
||||
if (['--build', '--watch'].indexOf(action) === -1) {
|
||||
console.log('Invalid argument: ', action);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ def bundle(no_compress, make_copy=False, verbose=False):
|
|||
make_asset_dirs(make_copy=make_copy)
|
||||
|
||||
# new nodejs build system
|
||||
command = 'node ../apps/frappe/frappe/build.js --build'
|
||||
command = 'node --use_strict ../apps/frappe/frappe/build.js --build'
|
||||
if not no_compress:
|
||||
command += ' --minify'
|
||||
subprocess.call(command.split(' '))
|
||||
|
|
@ -42,7 +42,7 @@ def watch(no_compress):
|
|||
"""watch and rebuild if necessary"""
|
||||
|
||||
# new nodejs file watcher
|
||||
command = 'node ../apps/frappe/frappe/build.js --watch'
|
||||
command = 'node --use_strict ../apps/frappe/frappe/build.js --watch'
|
||||
subprocess.call(command.split(' '))
|
||||
|
||||
# setup()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ from frappe.core.doctype.communication.comment import (notify_mentions,
|
|||
from frappe.core.doctype.communication.email import (validate_email,
|
||||
notify, _notify, update_parent_status)
|
||||
from frappe.utils.bot import BotReply
|
||||
from email.utils import parseaddr
|
||||
from frappe.utils import parse_addr
|
||||
|
||||
from collections import Counter
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
|
@ -140,14 +141,9 @@ class Communication(Document):
|
|||
else:
|
||||
if self.sent_or_received=='Sent':
|
||||
validate_email_add(self.sender, throw=True)
|
||||
|
||||
sender_name, sender_email = parseaddr(self.sender)
|
||||
|
||||
if not sender_name:
|
||||
sender_name = get_fullname(sender_email)
|
||||
if sender_name == sender_email:
|
||||
sender_name = None
|
||||
|
||||
sender_name, sender_email = parse_addr(self.sender)
|
||||
if sender_name == sender_email:
|
||||
sender_name = None
|
||||
self.sender = sender_email
|
||||
self.sender_full_name = sender_name or get_fullname(frappe.session.user) if frappe.session.user!='Administrator' else None
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ from __future__ import unicode_literals, absolute_import
|
|||
from six.moves import range
|
||||
import frappe
|
||||
import json
|
||||
from email.utils import formataddr, parseaddr
|
||||
from email.utils import formataddr
|
||||
from frappe.utils import (get_url, get_formatted_email, cint,
|
||||
validate_email_add, split_emails, time_diff_in_seconds)
|
||||
validate_email_add, split_emails, time_diff_in_seconds, parse_addr)
|
||||
from frappe.utils.file_manager import get_file
|
||||
from frappe.email.queue import check_email_limit
|
||||
from frappe.utils.scheduler import log
|
||||
|
|
@ -321,11 +321,11 @@ def get_cc(doc, recipients=None, fetched_from_email_account=False):
|
|||
# exclude unfollows, recipients and unsubscribes
|
||||
exclude = [] #added to remove account check
|
||||
exclude += [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)]
|
||||
exclude += [(parseaddr(email)[1] or "").lower() for email in recipients]
|
||||
exclude += [(parse_addr(email)[1] or "").lower() for email in recipients]
|
||||
|
||||
if fetched_from_email_account:
|
||||
# exclude sender when pulling email
|
||||
exclude += [parseaddr(doc.sender)[1]]
|
||||
exclude += [parse_addr(doc.sender)[1]]
|
||||
|
||||
if doc.reference_doctype and doc.reference_name:
|
||||
exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"],
|
||||
|
|
@ -356,7 +356,7 @@ def filter_email_list(doc, email_list, exclude, is_cc=False):
|
|||
email_address_list = []
|
||||
|
||||
for email in list(set(email_list)):
|
||||
email_address = (parseaddr(email)[1] or "").lower()
|
||||
email_address = (parse_addr(email)[1] or "").lower()
|
||||
if not email_address:
|
||||
continue
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,27 @@ from __future__ import unicode_literals
|
|||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Communication')
|
||||
|
||||
|
||||
class TestCommunication(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def test_parse_addr(self):
|
||||
valid_email_list = ["me@example.com", "a.nonymous@example.com", "name@tag@example.com",
|
||||
"foo@example.com", 'Full Name <full@example.com>',
|
||||
'"Full Name with quotes and <weird@chars.com>" <weird@example.com>',
|
||||
'foo@bar@google.com', 'Surname, Name <name.surname@domain.com>',
|
||||
'Purchase@ABC <purchase@abc.com>', 'xyz@abc2.com <xyz@abc.com>',
|
||||
'Name [something else] <name@domain.com>',
|
||||
'.com@test@yahoo.com']
|
||||
|
||||
invalid_email_list = ['[invalid!email]', 'invalid-email',
|
||||
'tes2', 'e', 'rrrrrrrr', 'manas','[[[sample]]]',
|
||||
'[invalid!email].com']
|
||||
|
||||
for x in valid_email_list:
|
||||
self.assertTrue(frappe.utils.parse_addr(x))
|
||||
|
||||
for x in invalid_email_list:
|
||||
self.assertFalse(frappe.utils.parse_addr(x)[0])
|
||||
|
||||
|
|
|
|||
|
|
@ -770,6 +770,37 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "User can login using Email id or Mobile number",
|
||||
"fieldname": "allow_login_using_mobile_number",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Allow Login using Mobile Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
|
|
@ -902,7 +933,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-05-11 15:27:11.079447",
|
||||
"modified": "2017-05-19 09:12:50.353887",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "System Settings",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -73,6 +75,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -102,6 +105,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -133,6 +137,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -163,6 +168,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -193,6 +199,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
|
|
@ -223,6 +230,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -252,6 +260,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
|
|
@ -283,6 +292,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -311,6 +321,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -341,6 +352,7 @@
|
|||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -370,6 +382,7 @@
|
|||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -400,6 +413,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -429,6 +443,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -458,6 +473,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -488,6 +504,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -516,6 +533,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -546,6 +564,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -575,6 +594,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -606,6 +626,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -635,6 +656,37 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mobile_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Mobile No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -665,6 +717,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -693,6 +746,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -720,6 +774,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -748,6 +803,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -777,6 +833,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -806,6 +863,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -834,6 +892,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -864,6 +923,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -892,6 +952,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -921,6 +982,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -951,6 +1013,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -981,6 +1044,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1009,6 +1073,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -1038,6 +1103,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1069,6 +1135,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -1099,6 +1166,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1128,6 +1196,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1158,6 +1227,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -1189,6 +1259,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1218,6 +1289,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1248,6 +1320,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1280,6 +1353,7 @@
|
|||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1310,6 +1384,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -1340,6 +1415,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1370,6 +1446,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1403,6 +1480,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1432,6 +1510,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1461,6 +1540,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1490,6 +1570,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1520,6 +1601,7 @@
|
|||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1550,6 +1632,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1580,6 +1663,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1609,6 +1693,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1639,6 +1724,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
|
|
@ -1668,6 +1754,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1696,6 +1783,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1724,6 +1812,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1752,6 +1841,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1780,6 +1870,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1808,6 +1899,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1836,6 +1928,7 @@
|
|||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -1878,7 +1971,7 @@
|
|||
"istable": 0,
|
||||
"max_attachments": 5,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-04-01 14:38:25.869060",
|
||||
"modified": "2017-05-19 09:12:35.697915",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "User",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ frappe.customize_form.set_primary_action = function(frm) {
|
|||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
frappe.customize_form.clear_locals_and_refresh(frm);
|
||||
frm.script_manager.trigger("doc_type");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import frappe
|
|||
from frappe import _
|
||||
from frappe.utils import validate_email_add
|
||||
from frappe.model.document import Document
|
||||
from email.utils import parseaddr
|
||||
from frappe.utils import parse_addr
|
||||
|
||||
class EmailGroup(Document):
|
||||
def onload(self):
|
||||
|
|
@ -26,7 +26,7 @@ class EmailGroup(Document):
|
|||
|
||||
for user in frappe.db.get_all(doctype, [email_field, unsubscribed_field or "name"]):
|
||||
try:
|
||||
email = parseaddr(user.get(email_field))[1]
|
||||
email = parse_addr(user.get(email_field))[1]
|
||||
if email:
|
||||
frappe.get_doc({
|
||||
"doctype": "Email Group Member",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from frappe.utils.scheduler import log
|
|||
from frappe.email.queue import send
|
||||
from frappe.email.doctype.email_group.email_group import add_subscribers
|
||||
from frappe.utils.file_manager import get_file
|
||||
from frappe.utils import parse_addr
|
||||
|
||||
|
||||
class Newsletter(Document):
|
||||
|
|
@ -135,17 +136,15 @@ def return_unsubscribed_page(email, name):
|
|||
|
||||
def create_lead(email_id):
|
||||
"""create a lead if it does not exist"""
|
||||
from email.utils import parseaddr
|
||||
from frappe.model.naming import get_default_naming_series
|
||||
real_name, email_id = parseaddr(email_id)
|
||||
|
||||
full_name, email_id = parse_addr(email_id)
|
||||
if frappe.db.get_value("Lead", {"email_id": email_id}):
|
||||
return
|
||||
|
||||
lead = frappe.get_doc({
|
||||
"doctype": "Lead",
|
||||
"email_id": email_id,
|
||||
"lead_name": real_name or email_id,
|
||||
"lead_name": full_name or email_id,
|
||||
"status": "Lead",
|
||||
"naming_series": get_default_naming_series("Lead"),
|
||||
"company": frappe.db.get_default("Company"),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from frappe.email.smtp import get_outgoing_email_account
|
|||
from frappe.utils import (get_url, scrub_urls, strip, expand_relative_urls, cint,
|
||||
split_emails, to_markdown, markdown, encode, random_string)
|
||||
import email.utils
|
||||
from frappe.utils import parse_addr
|
||||
|
||||
def get_email(recipients, sender='', msg='', subject='[No Subject]',
|
||||
text_content = None, footer=None, print_html=None, formatted=None, attachments=None,
|
||||
|
|
@ -179,8 +180,7 @@ class EMail:
|
|||
def replace_sender(self):
|
||||
if cint(self.email_account.always_use_account_email_id_as_sender):
|
||||
self.set_header('X-Original-From', self.sender)
|
||||
|
||||
sender_name, sender_email = email.utils.parseaddr(self.sender)
|
||||
sender_name, sender_email = parse_addr(self.sender)
|
||||
self.sender = email.utils.formataddr((sender_name or self.email_account.name, self.email_account.email_id))
|
||||
|
||||
def set_message_id(self, message_id, is_notification=False):
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from email.header import decode_header
|
|||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import (extract_email_id, convert_utc_to_user_timezone, now,
|
||||
cint, cstr, strip, markdown)
|
||||
cint, cstr, strip, markdown, parse_addr)
|
||||
from frappe.utils.scheduler import log
|
||||
from frappe.utils.file_manager import get_random_filename, save_file, MaxFileSizeReachedError
|
||||
import re
|
||||
|
|
@ -411,7 +411,7 @@ class Email:
|
|||
if self.from_email:
|
||||
self.from_email = self.from_email.lower()
|
||||
|
||||
self.from_real_name = email.utils.parseaddr(_from_email)[0] if "@" in _from_email else _from_email
|
||||
self.from_real_name = parse_addr(_from_email)[0] if "@" in _from_email else _from_email
|
||||
|
||||
def decode_email(self, email):
|
||||
if not email: return
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ import frappe
|
|||
|
||||
'''
|
||||
FrappeClient is a library that helps you connect with other frappe systems
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
class AuthError(Exception):
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="print-format">
|
||||
<div class="print-format {% if landscape %} landscape {% endif %}"
|
||||
{% if columns.length > 20 %}
|
||||
style="font-size: 4.0pt"
|
||||
{% endif %}
|
||||
>
|
||||
{% if print_settings.letter_head %}
|
||||
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
|
||||
<div class="letter-head">{{ print_settings.letter_head.header }}</div>
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ frappe.search.AwesomeBar = Class.extend({
|
|||
},
|
||||
item: function(item, term) {
|
||||
var d = this.get_item(item.value);
|
||||
var name = d.prefix ? __(d.prefix + ' ' + (d.label || d.value)) :
|
||||
__(d.label || d.value);
|
||||
var name = __(d.label || d.value);
|
||||
var html = '<span>' + name + '</span>';
|
||||
if(d.description && d.value!==d.description) {
|
||||
html += '<br><span class="text-muted ellipsis">' + __(d.description) + '</span>';
|
||||
|
|
@ -123,8 +122,7 @@ frappe.search.AwesomeBar = Class.extend({
|
|||
|
||||
add_help: function() {
|
||||
this.options.push({
|
||||
label: __("Help on Search"),
|
||||
value: "Help on Search",
|
||||
value: __("Help on Search"),
|
||||
index: -10,
|
||||
default: "Help",
|
||||
onclick: function() {
|
||||
|
|
@ -140,7 +138,7 @@ frappe.search.AwesomeBar = Class.extend({
|
|||
<tr><td>'+__("Calculate")+'</td><td>'+
|
||||
__("e.g. (55 + 434) / 4 or =Math.sin(Math.PI/2)...")+'</td></tr>\
|
||||
</table>'
|
||||
msgprint(txt, "Search Help");
|
||||
msgprint(txt, __("Search Help"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -208,8 +206,8 @@ frappe.search.AwesomeBar = Class.extend({
|
|||
make_global_search: function(txt) {
|
||||
var me = this;
|
||||
this.options.push({
|
||||
label: __("Search for '" + txt.bold() + "'"),
|
||||
value: __("Search for '" + txt + "'"),
|
||||
label: __("Search for '{0}'", [txt.bold()]),
|
||||
value: __("Search for '{0}'", [txt]),
|
||||
match: txt,
|
||||
index: 100,
|
||||
default: "Search",
|
||||
|
|
|
|||
|
|
@ -87,8 +87,7 @@ frappe.search.utils = {
|
|||
if(level) {
|
||||
out.push({
|
||||
type: "In List",
|
||||
prefix: __("Find {0} in ", [__(parts[0]).bold()]),
|
||||
label: me.bolden_match_part(__(item), parts[1]),
|
||||
label: __('Find {0} in {1}', [__(parts[0]), me.bolden_match_part(__(item), parts[1])]),
|
||||
value: __('Find {0} in {1}', [__(parts[0]), __(item)]),
|
||||
route_options: {"name": ["like", "%" + parts[0] + "%"]},
|
||||
index: 1 + level,
|
||||
|
|
@ -110,8 +109,7 @@ frappe.search.utils = {
|
|||
if(level) {
|
||||
out.push({
|
||||
type: "New",
|
||||
prefix: "New ",
|
||||
label: me.bolden_match_part(__(item), keywords.substr(4)),
|
||||
label: __("New {0}", [me.bolden_match_part(__(item), keywords.substr(4))]),
|
||||
value: __("New {0}", [__(item)]),
|
||||
index: 1 + level,
|
||||
match: item,
|
||||
|
|
@ -131,8 +129,8 @@ frappe.search.utils = {
|
|||
var option = function(type, route, order) {
|
||||
return {
|
||||
type: type,
|
||||
label: __("{0}" + " " + type, [me.bolden_match_part(__(target), keywords)]),
|
||||
value: __(__(target) + " " + type),
|
||||
label: me.bolden_match_part(__(target), keywords) + " " + __(type),
|
||||
value: __(target) + " " + __(type),
|
||||
index: level + order,
|
||||
match: target,
|
||||
route: route,
|
||||
|
|
@ -191,8 +189,7 @@ frappe.search.utils = {
|
|||
route = ["query-report", item];
|
||||
out.push({
|
||||
type: "Report",
|
||||
prefix: "Report ",
|
||||
label: me.bolden_match_part(__(item), keywords),
|
||||
label: __("Report {0}" , [me.bolden_match_part(__(item), keywords)]),
|
||||
value: __("Report {0}" , [__(item)]),
|
||||
index: level,
|
||||
route: route
|
||||
|
|
@ -216,8 +213,7 @@ frappe.search.utils = {
|
|||
var page = me.pages[item];
|
||||
out.push({
|
||||
type: "Page",
|
||||
prefix: "Open ",
|
||||
label: me.bolden_match_part(__(item), keywords),
|
||||
label: __("Open {0}", [me.bolden_match_part(__(item), keywords)]),
|
||||
value: __("Open {0}", [__(item)]),
|
||||
match: item,
|
||||
index: level,
|
||||
|
|
@ -229,8 +225,6 @@ frappe.search.utils = {
|
|||
if(__('calendar').indexOf(keywords.toLowerCase()) === 0) {
|
||||
out.push({
|
||||
type: "Calendar",
|
||||
prefix: "Open ",
|
||||
label: __('Calendar'),
|
||||
value: __("Open {0}", [__(target)]),
|
||||
index: me.fuzzy_search(keywords, 'Calendar'),
|
||||
match: target,
|
||||
|
|
@ -240,8 +234,6 @@ frappe.search.utils = {
|
|||
if(__('email inbox').indexOf(keywords.toLowerCase()) === 0) {
|
||||
out.push({
|
||||
type: "Inbox",
|
||||
prefix: "Open ",
|
||||
label: __('Email Inbox'),
|
||||
value: __("Open {0}", [__('Email Inbox')]),
|
||||
index: me.fuzzy_search(keywords, 'email inbox'),
|
||||
match: target,
|
||||
|
|
@ -261,8 +253,7 @@ frappe.search.utils = {
|
|||
if(module._doctype) return;
|
||||
ret = {
|
||||
type: "Module",
|
||||
prefix: "Open ",
|
||||
label: me.bolden_match_part(__(item), keywords),
|
||||
label: __("Open {0}", [me.bolden_match_part(__(item), keywords)]),
|
||||
value: __("Open {0}", [__(item)]),
|
||||
index: level,
|
||||
}
|
||||
|
|
@ -575,6 +566,5 @@ frappe.search.utils = {
|
|||
return rendered;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({
|
|||
this.add_totals_row = 0;
|
||||
this.page = this.parent.page;
|
||||
this._body = $('<div>').appendTo(this.page.main);
|
||||
this.page_title = __('Report')+ ': ' + __(this.docname ? (this.doctype + ' - ' + this.docname) : this.doctype);
|
||||
this.page_title = __('Report')+ ': ' + (this.docname ?
|
||||
__(this.doctype) + ' - ' + __(this.docname) : __(this.doctype));
|
||||
this.page.set_title(this.page_title);
|
||||
this.init_user_settings();
|
||||
this.make({
|
||||
|
|
@ -723,7 +724,7 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({
|
|||
}
|
||||
open_url_post(frappe.request.url, args);
|
||||
|
||||
}, __("Export Report: " + me.doctype), __("Download"));
|
||||
}, __("Export Report: {0}",[__(me.doctype)]), __("Download"));
|
||||
|
||||
}, true);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -95,6 +95,11 @@ frappe.render_grid = function(opts) {
|
|||
}
|
||||
}
|
||||
|
||||
// show landscape view if columns more than 10
|
||||
if(opts.columns.length > 10) {
|
||||
opts.landscape = true;
|
||||
}
|
||||
|
||||
// render content
|
||||
if(!opts.content) {
|
||||
opts.content = frappe.render_template("print_grid", opts);
|
||||
|
|
@ -106,6 +111,11 @@ frappe.render_grid = function(opts) {
|
|||
var html = frappe.render_template("print_template", opts);
|
||||
|
||||
var w = window.open();
|
||||
|
||||
if(!w) {
|
||||
frappe.msgprint(__("Please enable pop-ups in your browser"))
|
||||
}
|
||||
|
||||
w.document.write(html);
|
||||
w.document.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
margin: auto;
|
||||
}
|
||||
|
||||
.print-format.landscape {
|
||||
max-width: 11.69in;
|
||||
padding: 0.2in;
|
||||
}
|
||||
|
||||
.page-break {
|
||||
padding: 30px 0px;
|
||||
border-bottom: 1px dashed #888;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@ from werkzeug.test import Client
|
|||
import os, re, urllib, sys, json, hashlib, requests, traceback
|
||||
from markdown2 import markdown as _markdown
|
||||
from .html_utils import sanitize_html
|
||||
|
||||
import frappe
|
||||
from frappe.utils.identicon import Identicon
|
||||
|
||||
from email.utils import parseaddr, formataddr
|
||||
# utility functions like cint, int, flt, etc.
|
||||
from frappe.utils.data import *
|
||||
|
||||
|
|
@ -62,9 +61,8 @@ def get_formatted_email(user):
|
|||
|
||||
def extract_email_id(email):
|
||||
"""fetch only the email part of the Email Address"""
|
||||
from email.utils import parseaddr
|
||||
fullname, email_id = parseaddr(email)
|
||||
if isinstance(email_id, basestring) and not isinstance(email_id, unicode):
|
||||
full_name, email_id = parse_addr(email)
|
||||
if email_id and isinstance(email_id, basestring) and not isinstance(email_id, unicode):
|
||||
email_id = email_id.decode("utf-8", "ignore")
|
||||
return email_id
|
||||
|
||||
|
|
@ -88,13 +86,12 @@ def validate_email_add(email_str, throw=False):
|
|||
|
||||
else:
|
||||
e = extract_email_id(e)
|
||||
match = re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", e.lower())
|
||||
match = re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", e.lower()) if e else None
|
||||
|
||||
if not match:
|
||||
_valid = False
|
||||
else:
|
||||
matched = match.group(0)
|
||||
|
||||
if match:
|
||||
match = matched==e.lower()
|
||||
|
||||
|
|
@ -450,18 +447,47 @@ def markdown(text, sanitize=True, linkify=True):
|
|||
return html
|
||||
|
||||
def sanitize_email(emails):
|
||||
from email.utils import parseaddr, formataddr
|
||||
|
||||
sanitized = []
|
||||
for e in split_emails(emails):
|
||||
if not validate_email_add(e):
|
||||
continue
|
||||
|
||||
fullname, email_id = parseaddr(e)
|
||||
sanitized.append(formataddr((fullname, email_id)))
|
||||
full_name, email_id = parse_addr(e)
|
||||
sanitized.append(formataddr((full_name, email_id)))
|
||||
|
||||
return ", ".join(sanitized)
|
||||
|
||||
def parse_addr(email_string):
|
||||
"""
|
||||
Return email_id and user_name based on email string
|
||||
Raise error if email string is not valid
|
||||
"""
|
||||
name, email = parseaddr(email_string)
|
||||
if check_format(email):
|
||||
return (name, email)
|
||||
else:
|
||||
email_regex = re.compile(r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)")
|
||||
email_list = re.findall(email_regex, email_string)
|
||||
if len(email_list) > 0 and check_format(email_list[0]):
|
||||
#take only first email address
|
||||
return (name, email_list[0])
|
||||
return (None, email)
|
||||
|
||||
def check_format(email_id):
|
||||
"""
|
||||
Check if email_id is valid. valid email:text@example.com
|
||||
String check ensures that email_id contains both '.' and
|
||||
'@' and index of '@' is less than '.'
|
||||
"""
|
||||
is_valid = False
|
||||
try:
|
||||
pos = email_id.rindex("@")
|
||||
is_valid = pos > 0 and (email_id.rindex(".") > pos) and (len(email_id) - pos > 4)
|
||||
except Exception, e:
|
||||
#print(e)
|
||||
pass
|
||||
return is_valid
|
||||
|
||||
def get_installed_apps_info():
|
||||
out = []
|
||||
for app in frappe.get_installed_apps():
|
||||
|
|
|
|||
|
|
@ -102,10 +102,11 @@ def get_allowed_functions_for_jenv():
|
|||
"user": user,
|
||||
"get_fullname": frappe.utils.get_fullname,
|
||||
"get_gravatar": frappe.utils.get_gravatar_url,
|
||||
"full_name": getattr(frappe.local, "session", None) and frappe.local.session.data.full_name or "Guest",
|
||||
"full_name": frappe.local.session.data.full_name if getattr(frappe.local, "session", None) else "Guest",
|
||||
"render_template": frappe.render_template,
|
||||
'session': {
|
||||
'user': user
|
||||
'user': user,
|
||||
'csrf_token': frappe.local.session.data.csrf_token if getattr(frappe.local, "session", None) else ''
|
||||
},
|
||||
},
|
||||
"autodoc": {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,12 @@
|
|||
</div>
|
||||
|
||||
<input type="text" id="login_email"
|
||||
class="form-control" placeholder="{{ _('Email address') }}" required autofocus>
|
||||
class="form-control" placeholder="{{
|
||||
_('Email address or Mobile number')
|
||||
if frappe.utils.cint(frappe.db.get_value('System Settings', 'System Settings', 'allow_login_using_mobile_number'))
|
||||
else _('Email address') }}"
|
||||
required autofocus>
|
||||
|
||||
|
||||
<input type="password" id="login_password"
|
||||
class="form-control" placeholder="{{ _('Password') }}" required>
|
||||
|
|
|
|||
30
package.json
Normal file
30
package.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "frappe",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/frappe/frappe.git"
|
||||
},
|
||||
"author": "Frappé Technologies Pvt. Ltd.",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/frappe/frappe/issues"
|
||||
},
|
||||
"homepage": "https://frappe.io",
|
||||
"dependencies": {
|
||||
"babel-core": "^6.24.1",
|
||||
"babel-preset-babili": "0.0.12",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-es2016": "^6.24.1",
|
||||
"babel-preset-es2017": "^6.24.1",
|
||||
"chokidar": "^1.7.0",
|
||||
"cookie": "^0.3.1",
|
||||
"express": "^4.15.3",
|
||||
"less": "^2.7.2",
|
||||
"redis": "^2.7.1",
|
||||
"socket.io": "^2.0.1",
|
||||
"superagent": "^3.5.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ httplib2
|
|||
jinja2
|
||||
markdown2
|
||||
markupsafe
|
||||
mysql-python==1.2.5
|
||||
mysqlclient==1.3.8
|
||||
python-geoip
|
||||
python-geoip-geolite2
|
||||
python-dateutil
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue