Merge branch 'develop' into staging
This commit is contained in:
commit
2c95983e4d
125 changed files with 1156 additions and 546 deletions
|
|
@ -52,6 +52,6 @@ before_script:
|
|||
|
||||
script:
|
||||
- set -e
|
||||
- bench --verbose run-tests
|
||||
- bench run-tests
|
||||
- sleep 5
|
||||
- bench --verbose run-ui-tests --app frappe
|
||||
- bench run-ui-tests --app frappe
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ globals attached to frappe module
|
|||
"""
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
from six import iteritems, text_type
|
||||
from six import iteritems, text_type, string_types
|
||||
from werkzeug.local import Local, release_local
|
||||
import os, sys, importlib, inspect, json
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ def as_unicode(text, encoding='utf-8'):
|
|||
return text
|
||||
elif text==None:
|
||||
return ''
|
||||
elif isinstance(text, basestring):
|
||||
elif isinstance(text, string_types):
|
||||
return text_type(text, encoding)
|
||||
else:
|
||||
return text_type(text)
|
||||
|
|
@ -164,7 +164,7 @@ def connect(site=None, db_name=None):
|
|||
|
||||
:param site: If site is given, calls `frappe.init`.
|
||||
:param db_name: Optional. Will use from `site_config.json`."""
|
||||
from database import Database
|
||||
from frappe.database import Database
|
||||
if site:
|
||||
init(site)
|
||||
local.db = Database(user=db_name or local.conf.db_name)
|
||||
|
|
@ -235,8 +235,8 @@ def cache():
|
|||
|
||||
def get_traceback():
|
||||
"""Returns error traceback."""
|
||||
import utils
|
||||
return utils.get_traceback()
|
||||
from frappe.utils import get_traceback
|
||||
return get_traceback()
|
||||
|
||||
def errprint(msg):
|
||||
"""Log error. This is sent back as `exc` in response.
|
||||
|
|
@ -268,7 +268,7 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None,
|
|||
:param raise_exception: [optional] Raise given exception and show message.
|
||||
:param as_table: [optional] If `msg` is a list of lists, render as HTML table.
|
||||
"""
|
||||
from utils import encode
|
||||
from frappe.utils import encode
|
||||
|
||||
out = _dict(message=msg)
|
||||
|
||||
|
|
@ -421,8 +421,8 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message
|
|||
if not delayed:
|
||||
now = True
|
||||
|
||||
import email.queue
|
||||
email.queue.send(recipients=recipients, sender=sender,
|
||||
from frappe.email import queue
|
||||
queue.send(recipients=recipients, sender=sender,
|
||||
subject=subject, message=message, text_content=text_content,
|
||||
reference_doctype = doctype or reference_doctype, reference_name = name or reference_name,
|
||||
unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message,
|
||||
|
|
@ -488,7 +488,7 @@ def clear_cache(user=None, doctype=None):
|
|||
elif user:
|
||||
frappe.sessions.clear_cache(user)
|
||||
else: # everything
|
||||
import translate
|
||||
from frappe import translate
|
||||
frappe.sessions.clear_cache()
|
||||
translate.clear_cache()
|
||||
reset_metadata_version()
|
||||
|
|
@ -533,7 +533,7 @@ def has_website_permission(doc=None, ptype='read', user=None, verbose=False, doc
|
|||
user = session.user
|
||||
|
||||
if doc:
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = get_doc(doctype, doc)
|
||||
|
||||
doctype = doc.doctype
|
||||
|
|
@ -576,7 +576,7 @@ def generate_hash(txt=None, length=None):
|
|||
"""Generates random hash for given text + current timestamp + random string."""
|
||||
import hashlib, time
|
||||
from .utils import random_string
|
||||
digest = hashlib.sha224((txt or "") + repr(time.time()) + repr(random_string(8))).hexdigest()
|
||||
digest = hashlib.sha224(((txt or "") + repr(time.time()) + repr(random_string(8))).encode()).hexdigest()
|
||||
if length:
|
||||
digest = digest[:length]
|
||||
return digest
|
||||
|
|
@ -903,7 +903,7 @@ def get_attr(method_string):
|
|||
|
||||
def call(fn, *args, **kwargs):
|
||||
"""Call a function and match arguments."""
|
||||
if isinstance(fn, basestring):
|
||||
if isinstance(fn, string_types):
|
||||
fn = get_attr(fn)
|
||||
|
||||
if hasattr(fn, 'fnargs'):
|
||||
|
|
@ -1111,7 +1111,7 @@ def get_list(doctype, *args, **kwargs):
|
|||
:param filters: List of filters (see example).
|
||||
:param order_by: Order By e.g. `modified desc`.
|
||||
:param limit_page_start: Start results at record #. Default 0.
|
||||
:param limit_poge_length: No of records in the page. Default 20.
|
||||
:param limit_page_length: No of records in the page. Default 20.
|
||||
|
||||
Example usage:
|
||||
|
||||
|
|
@ -1136,7 +1136,7 @@ def get_all(doctype, *args, **kwargs):
|
|||
:param filters: List of filters (see example).
|
||||
:param order_by: Order By e.g. `modified desc`.
|
||||
:param limit_page_start: Start results at record #. Default 0.
|
||||
:param limit_poge_length: No of records in the page. Default 20.
|
||||
:param limit_page_length: No of records in the page. Default 20.
|
||||
|
||||
Example usage:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ import frappe.handler
|
|||
import frappe.client
|
||||
from frappe.utils.response import build_response
|
||||
from frappe import _
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from urllib import urlencode
|
||||
from six.moves.urllib.parse import urlparse, urlencode
|
||||
|
||||
def handle():
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
|||
import os
|
||||
import MySQLdb
|
||||
from six import iteritems
|
||||
import logging
|
||||
|
||||
from werkzeug.wrappers import Request
|
||||
from werkzeug.local import LocalManager
|
||||
|
|
@ -177,7 +178,8 @@ def handle_exception(e):
|
|||
make_error_snapshot(e)
|
||||
|
||||
if return_as_message:
|
||||
response = frappe.website.render.render("message", http_status_code=http_status_code)
|
||||
response = frappe.website.render.render("message",
|
||||
http_status_code=http_status_code)
|
||||
|
||||
return response
|
||||
|
||||
|
|
@ -212,11 +214,11 @@ def serve(port=8000, profile=False, site=None, sites_path='.'):
|
|||
|
||||
if not os.environ.get('NO_STATICS'):
|
||||
application = SharedDataMiddleware(application, {
|
||||
b'/assets': os.path.join(sites_path, 'assets').encode("utf-8"),
|
||||
b'/assets': os.path.join(sites_path, 'assets'),
|
||||
})
|
||||
|
||||
application = StaticDataMiddleware(application, {
|
||||
b'/files': os.path.abspath(sites_path).encode("utf-8")
|
||||
b'/files': os.path.abspath(sites_path)
|
||||
})
|
||||
|
||||
application.debug = True
|
||||
|
|
@ -225,6 +227,10 @@ def serve(port=8000, profile=False, site=None, sites_path='.'):
|
|||
}
|
||||
|
||||
in_test_env = os.environ.get('CI')
|
||||
if in_test_env:
|
||||
log = logging.getLogger('werkzeug')
|
||||
log.setLevel(logging.ERROR)
|
||||
|
||||
run_simple('0.0.0.0', int(port), application,
|
||||
use_reloader=not in_test_env,
|
||||
use_debugger=not in_test_env,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from frappe.translate import get_lang_code
|
|||
from frappe.utils.password import check_password
|
||||
from frappe.core.doctype.authentication_log.authentication_log import add_authentication_log
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from twofactor import (should_run_2fa, authenticate_for_2factor,
|
||||
from frappe.twofactor import (should_run_2fa, authenticate_for_2factor,
|
||||
confirm_otp_token, get_cached_user_pass)
|
||||
|
||||
from six.moves.urllib.parse import quote
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import frappe.model
|
|||
import frappe.utils
|
||||
import json, os
|
||||
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
'''
|
||||
Handle RESTful requests that are mapped to the `/api/resource` route.
|
||||
|
|
@ -92,7 +92,7 @@ def set_value(doctype, name, fieldname, value=None):
|
|||
|
||||
if not value:
|
||||
values = fieldname
|
||||
if isinstance(fieldname, basestring):
|
||||
if isinstance(fieldname, string_types):
|
||||
try:
|
||||
values = json.loads(fieldname)
|
||||
except ValueError:
|
||||
|
|
@ -118,7 +118,7 @@ def insert(doc=None):
|
|||
'''Insert a document
|
||||
|
||||
:param doc: JSON or dict object to be inserted'''
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = json.loads(doc)
|
||||
|
||||
if doc.get("parent") and doc.get("parenttype"):
|
||||
|
|
@ -136,7 +136,7 @@ def insert_many(docs=None):
|
|||
'''Insert multiple documents
|
||||
|
||||
:param docs: JSON or list of dict objects to be inserted in one request'''
|
||||
if isinstance(docs, basestring):
|
||||
if isinstance(docs, string_types):
|
||||
docs = json.loads(docs)
|
||||
|
||||
out = []
|
||||
|
|
@ -162,7 +162,7 @@ def save(doc):
|
|||
'''Update (save) an existing document
|
||||
|
||||
:param doc: JSON or dict object with the properties of the document to be updated'''
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = json.loads(doc)
|
||||
|
||||
doc = frappe.get_doc(doc).save()
|
||||
|
|
@ -183,7 +183,7 @@ def submit(doc):
|
|||
'''Submit a document
|
||||
|
||||
:param doc: JSON or dict object to be submitted remotely'''
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = json.loads(doc)
|
||||
|
||||
doc = frappe.get_doc(doc)
|
||||
|
|
@ -221,7 +221,7 @@ def make_width_property_setter(doc):
|
|||
'''Set width Property Setter
|
||||
|
||||
:param doc: Property Setter document with `width` property'''
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = json.loads(doc)
|
||||
if doc["doctype"]=="Property Setter" and doc["property"]=="width":
|
||||
frappe.get_doc(doc).insert(ignore_permissions = True)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
|
|||
"""Install a new Frappe site"""
|
||||
|
||||
if not db_name:
|
||||
db_name = hashlib.sha1(site).hexdigest()[:16]
|
||||
db_name = hashlib.sha1(site.encode()).hexdigest()[:16]
|
||||
|
||||
from frappe.installer import install_db, make_site_dirs
|
||||
from frappe.installer import install_app as _install_app
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ def build(make_copy=False, verbose=False):
|
|||
@click.command('watch')
|
||||
def watch():
|
||||
"Watch and concatenate JS and CSS files as and when they change"
|
||||
# if os.environ.get('CI'):
|
||||
# return
|
||||
import frappe.build
|
||||
frappe.init('')
|
||||
frappe.build.watch(True)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ def get_data():
|
|||
{
|
||||
"type": "doctype",
|
||||
"name": "Deleted Document",
|
||||
"label": _("Deleted Documents"),
|
||||
"label": _("Deleted Documents"),
|
||||
"description": _("Restore or permanently delete a document.")
|
||||
},
|
||||
]
|
||||
|
|
@ -180,6 +180,11 @@ def get_data():
|
|||
"name": "Print Format",
|
||||
"description": _("Customized HTML Templates for printing transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Print Style",
|
||||
"description": _("Stylesheets for Print Formats")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from jinja2 import TemplateSyntaxError
|
|||
from frappe.utils.user import is_website_user
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
|
||||
class Address(Document):
|
||||
|
|
@ -115,7 +115,7 @@ def get_territory_from_address(address):
|
|||
if not address:
|
||||
return
|
||||
|
||||
if isinstance(address, basestring):
|
||||
if isinstance(address, string_types):
|
||||
address = frappe.get_doc("Address", address)
|
||||
|
||||
territory = None
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ frappe.ui.form.on("Contact", {
|
|||
|
||||
if(!frm.doc.user && !frm.is_new() && frm.perm[0].write) {
|
||||
frm.add_custom_button(__("Invite as User"), function() {
|
||||
frappe.call({
|
||||
return frappe.call({
|
||||
method: "frappe.contacts.doctype.contact.contact.invite_user",
|
||||
args: {
|
||||
contact: frm.doc.name
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
from six.moves import range
|
||||
from six import string_types
|
||||
import frappe
|
||||
import json
|
||||
from email.utils import formataddr
|
||||
|
|
@ -71,7 +72,7 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received =
|
|||
# if no reference given, then send it against the communication
|
||||
comm.db_set(dict(reference_doctype='Communication', reference_name=comm.name))
|
||||
|
||||
if isinstance(attachments, basestring):
|
||||
if isinstance(attachments, string_types):
|
||||
attachments = json.loads(attachments)
|
||||
|
||||
# if not committed, delayed task doesn't find the communication
|
||||
|
|
@ -250,11 +251,11 @@ def prepare_to_notify(doc, print_html=None, print_format=None, attachments=None)
|
|||
print_format=print_format, html=print_html))
|
||||
|
||||
if attachments:
|
||||
if isinstance(attachments, basestring):
|
||||
if isinstance(attachments, string_types):
|
||||
attachments = json.loads(attachments)
|
||||
|
||||
for a in attachments:
|
||||
if isinstance(a, basestring):
|
||||
if isinstance(a, string_types):
|
||||
# is it a filename?
|
||||
try:
|
||||
file = get_file(a)
|
||||
|
|
@ -342,7 +343,7 @@ def add_attachments(name, attachments):
|
|||
|
||||
# loop through attachments
|
||||
for a in attachments:
|
||||
if isinstance(a, basestring):
|
||||
if isinstance(a, string_types):
|
||||
attach = frappe.db.get_value("File", {"name":a},
|
||||
["file_name", "file_url", "is_private"], as_dict=1)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from frappe.utils import get_fullname
|
|||
from frappe import _
|
||||
from frappe.core.doctype.communication.comment import add_info_comment
|
||||
from frappe.core.doctype.authentication_log.authentication_log import add_authentication_log
|
||||
from six import string_types
|
||||
|
||||
def update_feed(doc, method=None):
|
||||
"adds a new communication with comment_type='Updated'"
|
||||
|
|
@ -25,7 +26,7 @@ def update_feed(doc, method=None):
|
|||
feed = doc.get_feed()
|
||||
|
||||
if feed:
|
||||
if isinstance(feed, basestring):
|
||||
if isinstance(feed, string_types):
|
||||
feed = {"subject": feed}
|
||||
|
||||
feed = frappe._dict(feed)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from frappe import _
|
|||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.utils import strip, get_files_path
|
||||
from PIL import Image, ImageOps
|
||||
from six import StringIO
|
||||
from six import StringIO, string_types
|
||||
from six.moves.urllib.parse import unquote
|
||||
import zipfile
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ class File(NestedSet):
|
|||
super(File, self).on_trash()
|
||||
self.delete_file()
|
||||
|
||||
def make_thumbnail(self):
|
||||
def make_thumbnail(self, set_as_thumbnail=True, width=300, height=300, suffix="small"):
|
||||
if self.file_url:
|
||||
if self.file_url.startswith("/files"):
|
||||
try:
|
||||
|
|
@ -184,15 +184,19 @@ class File(NestedSet):
|
|||
except (requests.exceptions.HTTPError, requests.exceptions.SSLError, IOError):
|
||||
return
|
||||
|
||||
size = 300, 300
|
||||
size = width, height
|
||||
image.thumbnail(size)
|
||||
|
||||
thumbnail_url = filename + "_small." + extn
|
||||
thumbnail_url = filename + "_" + suffix + "." + extn
|
||||
|
||||
path = os.path.abspath(frappe.get_site_path("public", thumbnail_url.lstrip("/")))
|
||||
|
||||
try:
|
||||
image.save(path)
|
||||
|
||||
if set_as_thumbnail:
|
||||
self.db_set("thumbnail_url", thumbnail_url)
|
||||
|
||||
self.db_set("thumbnail_url", thumbnail_url)
|
||||
except IOError:
|
||||
frappe.msgprint(_("Unable to write file format for {0}").format(path))
|
||||
|
|
@ -305,7 +309,7 @@ def create_new_folder(file_name, folder):
|
|||
|
||||
@frappe.whitelist()
|
||||
def move_file(file_list, new_parent, old_parent):
|
||||
if isinstance(file_list, basestring):
|
||||
if isinstance(file_list, string_types):
|
||||
file_list = json.loads(file_list)
|
||||
|
||||
for file_obj in file_list:
|
||||
|
|
@ -325,7 +329,12 @@ def setup_folder_path(filename, new_parent):
|
|||
|
||||
def get_extension(filename, extn, content):
|
||||
mimetype = None
|
||||
|
||||
if extn:
|
||||
# remove '?' char and parameters from extn if present
|
||||
if '?' in extn:
|
||||
extn = extn.split('?', 1)[0]
|
||||
|
||||
mimetype = mimetypes.guess_type(filename + "." + extn)[0]
|
||||
|
||||
if mimetype is None or not mimetype.startswith("image/") and content:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from frappe import _, throw, msgprint
|
|||
from frappe.utils import nowdate
|
||||
|
||||
from frappe.model.document import Document
|
||||
from six import string_types
|
||||
|
||||
class SMSSettings(Document):
|
||||
pass
|
||||
|
|
@ -55,7 +56,7 @@ def get_contact_number(contact_name, ref_doctype, ref_name):
|
|||
def send_sms(receiver_list, msg, sender_name = '', success_msg = True):
|
||||
|
||||
import json
|
||||
if isinstance(receiver_list, basestring):
|
||||
if isinstance(receiver_list, string_types):
|
||||
receiver_list = json.loads(receiver_list)
|
||||
if not isinstance(receiver_list, list):
|
||||
receiver_list = [receiver_list]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import re, csv, os
|
|||
from frappe.utils.csvutils import UnicodeWriter
|
||||
from frappe.utils import cstr, formatdate, format_datetime
|
||||
from frappe.core.page.data_import_tool.data_import_tool import get_data_keys
|
||||
from six import string_types
|
||||
|
||||
reflags = {
|
||||
"I":re.I,
|
||||
|
|
@ -29,7 +30,7 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data
|
|||
select_columns = json.loads(select_columns);
|
||||
docs_to_export = {}
|
||||
if doctype:
|
||||
if isinstance(doctype, basestring):
|
||||
if isinstance(doctype, string_types):
|
||||
doctype = [doctype];
|
||||
if len(doctype) > 1:
|
||||
docs_to_export = doctype[1]
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from frappe.utils.file_manager import save_url
|
|||
|
||||
from frappe.utils import cint, cstr, flt, getdate, get_datetime, get_url
|
||||
from frappe.core.page.data_import_tool.data_import_tool import get_data_keys
|
||||
from six import text_type
|
||||
from six import text_type, string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, no_email=True, overwrite=None,
|
||||
|
|
@ -119,7 +119,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False,
|
|||
elif fieldtype in ("Float", "Currency", "Percent"):
|
||||
d[fieldname] = flt(d[fieldname])
|
||||
elif fieldtype == "Date":
|
||||
if d[fieldname] and isinstance(d[fieldname], basestring):
|
||||
if d[fieldname] and isinstance(d[fieldname], string_types):
|
||||
d[fieldname] = getdate(parse_date(d[fieldname]))
|
||||
elif fieldtype == "Datetime":
|
||||
if d[fieldname]:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import redis
|
|||
import frappe.model.meta
|
||||
from frappe.utils import now, get_datetime, cstr
|
||||
from frappe import _
|
||||
from six import text_type, binary_type
|
||||
from six import text_type, binary_type, string_types, integer_types
|
||||
from frappe.utils.global_search import sync_global_search
|
||||
from frappe.model.utils.link_count import flush_local_link_count
|
||||
from six import iteritems, text_type
|
||||
|
|
@ -270,7 +270,7 @@ class Database:
|
|||
"""Returns true if the first row in the result has a Date, Datetime, Long Int."""
|
||||
if result and result[0]:
|
||||
for v in result[0]:
|
||||
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, long)):
|
||||
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, integer_types)):
|
||||
return True
|
||||
if formatted and isinstance(v, (int, float)):
|
||||
return True
|
||||
|
|
@ -287,7 +287,7 @@ class Database:
|
|||
|
||||
from frappe.utils import formatdate, fmt_money
|
||||
|
||||
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, long)):
|
||||
if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, integer_types)):
|
||||
if isinstance(v, datetime.date):
|
||||
v = text_type(v)
|
||||
if formatted:
|
||||
|
|
@ -298,7 +298,7 @@ class Database:
|
|||
v = text_type(v)
|
||||
|
||||
# long
|
||||
elif isinstance(v, long):
|
||||
elif isinstance(v, integer_types):
|
||||
v=int(v)
|
||||
|
||||
# convert to strings... (if formatted)
|
||||
|
|
@ -386,7 +386,7 @@ class Database:
|
|||
|
||||
conditions.append(condition)
|
||||
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = { "name": filters }
|
||||
|
||||
for f in filters:
|
||||
|
|
@ -451,7 +451,7 @@ class Database:
|
|||
user = frappe.db.get_values("User", "test@example.com", "*")[0]
|
||||
"""
|
||||
out = None
|
||||
if cache and isinstance(filters, basestring) and \
|
||||
if cache and isinstance(filters, string_types) and \
|
||||
(doctype, filters, fieldname) in self.value_cache:
|
||||
return self.value_cache[(doctype, filters, fieldname)]
|
||||
|
||||
|
|
@ -463,7 +463,7 @@ class Database:
|
|||
else:
|
||||
fields = fieldname
|
||||
if fieldname!="*":
|
||||
if isinstance(fieldname, basestring):
|
||||
if isinstance(fieldname, string_types):
|
||||
fields = [fieldname]
|
||||
else:
|
||||
fields = fieldname
|
||||
|
|
@ -483,7 +483,7 @@ class Database:
|
|||
else:
|
||||
out = self.get_values_from_single(fields, filters, doctype, as_dict, debug, update)
|
||||
|
||||
if cache and isinstance(filters, basestring):
|
||||
if cache and isinstance(filters, string_types):
|
||||
self.value_cache[(doctype, filters, fieldname)] = out
|
||||
|
||||
return out
|
||||
|
|
@ -670,7 +670,7 @@ class Database:
|
|||
delete from tabSingles
|
||||
where field in ({0}) and
|
||||
doctype=%s'''.format(', '.join(['%s']*len(keys))),
|
||||
keys + [dt], debug=debug)
|
||||
list(keys) + [dt], debug=debug)
|
||||
for key, value in iteritems(to_update):
|
||||
self.sql('''insert into tabSingles(doctype, field, value) values (%s, %s, %s)''',
|
||||
(dt, key, value), debug=debug)
|
||||
|
|
@ -789,7 +789,7 @@ class Database:
|
|||
|
||||
:param dt: DocType name.
|
||||
:param dn: Document name or filter dict."""
|
||||
if isinstance(dt, basestring):
|
||||
if isinstance(dt, string_types):
|
||||
if dt!="DocType" and dt==dn:
|
||||
return True # single always exists (!)
|
||||
try:
|
||||
|
|
@ -854,7 +854,7 @@ class Database:
|
|||
add index `%s`(%s)""" % (doctype, index_name, ", ".join(fields)))
|
||||
|
||||
def add_unique(self, doctype, fields, constraint_name=None):
|
||||
if isinstance(fields, basestring):
|
||||
if isinstance(fields, string_types):
|
||||
fields = [fields]
|
||||
if not constraint_name:
|
||||
constraint_name = "unique_" + "_".join(fields)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from frappe import _
|
|||
import json
|
||||
import random
|
||||
from frappe.model.document import Document
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
|
||||
class DesktopIcon(Document):
|
||||
|
|
@ -171,7 +171,7 @@ def add_user_icon(_doctype, _report=None, label=None, link=None, type='link', st
|
|||
@frappe.whitelist()
|
||||
def set_order(new_order, user=None):
|
||||
'''set new order by duplicating user icons (if user is set) or set global order'''
|
||||
if isinstance(new_order, basestring):
|
||||
if isinstance(new_order, string_types):
|
||||
new_order = json.loads(new_order)
|
||||
for i, module_name in enumerate(new_order):
|
||||
if module_name not in ('Explore',):
|
||||
|
|
@ -228,7 +228,7 @@ def set_hidden_list(hidden_list, user=None):
|
|||
'''Sets property `hidden`=1 in **Desktop Icon** for given user.
|
||||
If user is None then it will set global values.
|
||||
It will also set the rest of the icons as shown (`hidden` = 0)'''
|
||||
if isinstance(hidden_list, basestring):
|
||||
if isinstance(hidden_list, string_types):
|
||||
hidden_list = json.loads(hidden_list)
|
||||
|
||||
# set as hidden
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
from six.moves import range
|
||||
from six import string_types
|
||||
import frappe
|
||||
import json
|
||||
|
||||
|
|
@ -69,7 +70,7 @@ def send_event_digest():
|
|||
def get_events(start, end, user=None, for_reminder=False, filters=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
roles = frappe.get_roles(user)
|
||||
events = frappe.db.sql("""select name, subject, description, color,
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ from frappe.model.meta import is_single
|
|||
from frappe.modules import load_doctype_module
|
||||
import frappe.desk.form.meta
|
||||
import frappe.desk.form.load
|
||||
from six import string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None):
|
||||
if isinstance(linkinfo, basestring):
|
||||
if isinstance(linkinfo, string_types):
|
||||
# additional fields are added in linkinfo
|
||||
linkinfo = json.loads(linkinfo)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import json, inspect
|
|||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cint
|
||||
from six import text_type
|
||||
from six import text_type, string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def runserverobj(method, docs=None, dt=None, dn=None, arg=None, args=None):
|
||||
|
|
@ -62,7 +62,7 @@ def make_csv_output(res, dt):
|
|||
for r in res:
|
||||
row = []
|
||||
for v in r:
|
||||
if isinstance(v, basestring):
|
||||
if isinstance(v, string_types):
|
||||
v = v.encode("utf-8")
|
||||
row.append(v)
|
||||
writer.writerow(row)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import frappe.desk.form.meta
|
|||
import frappe.desk.form.load
|
||||
|
||||
from frappe import _
|
||||
from six import string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def remove_attach():
|
||||
|
|
@ -65,7 +66,7 @@ def get_next(doctype, value, prev, filters=None, order_by="modified desc"):
|
|||
sort_field, sort_order = order_by.split(" ")
|
||||
|
||||
if not filters: filters = []
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
|
||||
# condition based on sort order
|
||||
|
|
|
|||
|
|
@ -8,13 +8,9 @@
|
|||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.setup-wizard-slide.single-column {
|
||||
.setup-wizard-slide {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.setup-wizard-slide.two-column {
|
||||
max-width: 768px;
|
||||
}
|
||||
}
|
||||
|
||||
.setup-wizard-slide .lead {
|
||||
|
|
@ -45,7 +41,7 @@
|
|||
}
|
||||
|
||||
.setup-wizard-slide.with-form {
|
||||
margin: 30px auto;
|
||||
margin: 60px auto;
|
||||
padding: 10px 50px;
|
||||
border: 1px solid #d1d8dd;
|
||||
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.1);
|
||||
|
|
@ -145,7 +141,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.setup-wizard-message-image {
|
||||
margin: 15px auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from frappe.utils.file_manager import save_file
|
|||
from frappe.utils.password import update_password
|
||||
from werkzeug.useragents import UserAgent
|
||||
import install_fixtures
|
||||
from six import string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def setup_complete(args):
|
||||
|
|
@ -127,14 +128,14 @@ def update_user_name(args):
|
|||
def process_args(args):
|
||||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
if isinstance(args, basestring):
|
||||
if isinstance(args, string_types):
|
||||
args = json.loads(args)
|
||||
|
||||
args = frappe._dict(args)
|
||||
|
||||
# strip the whitespace
|
||||
for key, value in args.items():
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, string_types):
|
||||
args[key] = strip(value)
|
||||
|
||||
return args
|
||||
|
|
@ -204,7 +205,7 @@ def load_user_details():
|
|||
def prettify_args(args):
|
||||
# remove attachments
|
||||
for key, val in args.items():
|
||||
if isinstance(val, basestring) and "data:image" in val:
|
||||
if isinstance(val, string_types) and "data:image" in val:
|
||||
filename = val.split("data:image", 1)[0].strip(", ")
|
||||
size = round((len(val) * 3 / 4) / 1048576.0, 2)
|
||||
args[key] = "Image Attached: '{0}' of size {1} MB".format(filename, size)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from frappe.model.utils import render_include
|
|||
from frappe.translate import send_translations
|
||||
import frappe.desk.reportview
|
||||
from frappe.permissions import get_role_permissions
|
||||
from six import string_types
|
||||
|
||||
def get_report_doc(report_name):
|
||||
doc = frappe.get_doc("Report", report_name)
|
||||
|
|
@ -70,7 +71,7 @@ def run(report_name, filters=None, user=None):
|
|||
if not filters:
|
||||
filters = []
|
||||
|
||||
if filters and isinstance(filters, basestring):
|
||||
if filters and isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
|
||||
if not frappe.has_permission(report.ref_doctype, "report"):
|
||||
|
|
@ -127,13 +128,13 @@ def export_query():
|
|||
if "csrf_token" in data:
|
||||
del data["csrf_token"]
|
||||
|
||||
if isinstance(data.get("filters"), basestring):
|
||||
if isinstance(data.get("filters"), string_types):
|
||||
filters = json.loads(data["filters"])
|
||||
if isinstance(data.get("report_name"), basestring):
|
||||
if isinstance(data.get("report_name"), string_types):
|
||||
report_name = data["report_name"]
|
||||
if isinstance(data.get("file_format_type"), basestring):
|
||||
if isinstance(data.get("file_format_type"), string_types):
|
||||
file_format_type = data["file_format_type"]
|
||||
if isinstance(data.get("visible_idx"), basestring):
|
||||
if isinstance(data.get("visible_idx"), string_types):
|
||||
visible_idx = json.loads(data.get("visible_idx"))
|
||||
else:
|
||||
visible_idx = None
|
||||
|
|
@ -181,7 +182,7 @@ def add_total_row(result, columns, meta = None):
|
|||
has_percent = []
|
||||
for i, col in enumerate(columns):
|
||||
fieldtype, options = None, None
|
||||
if isinstance(col, basestring):
|
||||
if isinstance(col, string_types):
|
||||
if meta:
|
||||
# get fieldtype from the meta
|
||||
field = meta.get_field(col)
|
||||
|
|
@ -214,7 +215,7 @@ def add_total_row(result, columns, meta = None):
|
|||
total_row[i] = flt(total_row[i]) / len(result)
|
||||
|
||||
first_col_fieldtype = None
|
||||
if isinstance(columns[0], basestring):
|
||||
if isinstance(columns[0], string_types):
|
||||
first_col = columns[0].split(":")
|
||||
if len(first_col) > 1:
|
||||
first_col_fieldtype = first_col[1].split("/")[0]
|
||||
|
|
@ -319,7 +320,7 @@ def get_linked_doctypes(columns, data):
|
|||
for idx, col in enumerate(columns):
|
||||
df = columns_dict[idx]
|
||||
if df.get("fieldtype")=="Link":
|
||||
if isinstance(col, basestring):
|
||||
if isinstance(col, string_types):
|
||||
linked_doctypes[df["options"]] = idx
|
||||
else:
|
||||
# dict
|
||||
|
|
@ -355,7 +356,7 @@ def get_columns_dict(columns):
|
|||
col_dict = frappe._dict()
|
||||
|
||||
# string
|
||||
if isinstance(col, basestring):
|
||||
if isinstance(col, string_types):
|
||||
col = col.split(":")
|
||||
if len(col) > 1:
|
||||
if "/" in col[1]:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import frappe.permissions
|
|||
import MySQLdb
|
||||
from frappe.model.db_query import DatabaseQuery
|
||||
from frappe import _
|
||||
from six import text_type
|
||||
from six import text_type, string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def get():
|
||||
|
|
@ -31,13 +31,13 @@ def get_form_params():
|
|||
if "csrf_token" in data:
|
||||
del data["csrf_token"]
|
||||
|
||||
if isinstance(data.get("filters"), basestring):
|
||||
if isinstance(data.get("filters"), string_types):
|
||||
data["filters"] = json.loads(data["filters"])
|
||||
if isinstance(data.get("fields"), basestring):
|
||||
if isinstance(data.get("fields"), string_types):
|
||||
data["fields"] = json.loads(data["fields"])
|
||||
if isinstance(data.get("docstatus"), basestring):
|
||||
if isinstance(data.get("docstatus"), string_types):
|
||||
data["docstatus"] = json.loads(data["docstatus"])
|
||||
if isinstance(data.get("save_user_settings"), basestring):
|
||||
if isinstance(data.get("save_user_settings"), string_types):
|
||||
data["save_user_settings"] = json.loads(data["save_user_settings"])
|
||||
else:
|
||||
data["save_user_settings"] = True
|
||||
|
|
@ -341,7 +341,7 @@ def build_match_conditions(doctype, as_condition=True):
|
|||
return match_conditions
|
||||
|
||||
def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with_match_conditions=False):
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
|
||||
if filters:
|
||||
|
|
@ -350,7 +350,7 @@ def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with
|
|||
filters = filters.items()
|
||||
flt = []
|
||||
for f in filters:
|
||||
if isinstance(f[1], basestring) and f[1][0] == '!':
|
||||
if isinstance(f[1], string_types) and f[1][0] == '!':
|
||||
flt.append([doctype, f[0], '!=', f[1][1:]])
|
||||
elif isinstance(f[1], list) and \
|
||||
f[1][0] in (">", "<", ">=", "<=", "like", "not like", "in", "not in", "between"):
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
|||
import frappe, json
|
||||
from frappe.utils import cstr, unique
|
||||
from frappe import _
|
||||
from six import string_types
|
||||
|
||||
# this is called by the Link Field
|
||||
@frappe.whitelist()
|
||||
|
|
@ -18,7 +19,7 @@ def search_link(doctype, txt, query=None, filters=None, page_length=20, searchfi
|
|||
@frappe.whitelist()
|
||||
def search_widget(doctype, txt, query=None, searchfield=None, start=0,
|
||||
page_length=10, filters=None, filter_fields=None, as_dict=False):
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@
|
|||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Add your message here",
|
||||
"depends_on": "eval:!doc.is_standard",
|
||||
"depends_on": "",
|
||||
"fieldname": "message",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
|
|
@ -808,7 +808,7 @@
|
|||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-07-07 16:09:48.804218",
|
||||
"modified": "2017-08-13 22:43:49.079330",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Email Alert",
|
||||
|
|
|
|||
|
|
@ -7,13 +7,18 @@ import json, os
|
|||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.core.doctype.role.role import get_emails_from_role
|
||||
from frappe.utils import validate_email_add, nowdate
|
||||
from frappe.utils.data import parse_val
|
||||
from frappe.utils import validate_email_add, nowdate, parse_val, is_html
|
||||
from frappe.utils.jinja import validate_template
|
||||
from frappe.modules.utils import export_module_json, get_doc_module
|
||||
from markdown2 import markdown
|
||||
from six import string_types
|
||||
|
||||
class EmailAlert(Document):
|
||||
def onload(self):
|
||||
'''load message'''
|
||||
if self.is_standard:
|
||||
self.message = self.get_template()
|
||||
|
||||
def autoname(self):
|
||||
if not self.name:
|
||||
self.name = self.subject
|
||||
|
|
@ -30,6 +35,7 @@ class EmailAlert(Document):
|
|||
|
||||
self.validate_forbidden_types()
|
||||
self.validate_condition()
|
||||
self.validate_standard()
|
||||
|
||||
def on_update(self):
|
||||
frappe.cache().hdel('email_alerts', self.document_type)
|
||||
|
|
@ -52,6 +58,10 @@ def get_context(context):
|
|||
pass
|
||||
""")
|
||||
|
||||
def validate_standard(self):
|
||||
if self.is_standard and not frappe.conf.developer_mode:
|
||||
frappe.throw(_('Cannot edit Standard Email Alert. To edit, please disable this and duplicate it'))
|
||||
|
||||
def validate_condition(self):
|
||||
temp_doc = frappe.new_doc(self.document_type)
|
||||
if self.condition:
|
||||
|
|
@ -164,26 +174,31 @@ def get_context(context):
|
|||
self.property_value, update_modified = False)
|
||||
doc.set(self.set_property_after_alert, self.property_value)
|
||||
|
||||
def get_template(self):
|
||||
module = get_doc_module(self.module, self.doctype, self.name)
|
||||
def load_template(extn):
|
||||
template = ''
|
||||
template_path = os.path.join(os.path.dirname(module.__file__),
|
||||
frappe.scrub(self.name) + extn)
|
||||
if os.path.exists(template_path):
|
||||
with open(template_path, 'r') as f:
|
||||
template = f.read()
|
||||
return template
|
||||
|
||||
return load_template('.html') or load_template('.md')
|
||||
|
||||
def load_standard_properties(self, context):
|
||||
'''load templates and run get_context'''
|
||||
module = get_doc_module(self.module, self.doctype, self.name)
|
||||
if module:
|
||||
if hasattr(module, 'get_context'):
|
||||
out = module.get_context(context)
|
||||
if out: context.update(out)
|
||||
|
||||
def load_template(extn):
|
||||
template_path = os.path.join(os.path.dirname(module.__file__),
|
||||
frappe.scrub(self.name) + extn)
|
||||
if os.path.exists(template_path):
|
||||
with open(template_path, 'r') as f:
|
||||
self.message = f.read()
|
||||
return True
|
||||
|
||||
# get template
|
||||
if not load_template('.html'):
|
||||
if load_template('.md'):
|
||||
self.message = markdown(self.message)
|
||||
self.message = self.get_template()
|
||||
|
||||
if not is_html(self.message):
|
||||
self.message = markdown(self.message)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_documents_for_today(email_alert):
|
||||
|
|
@ -210,7 +225,7 @@ def trigger_email_alerts(doc, method=None):
|
|||
def evaluate_alert(doc, alert, event):
|
||||
from jinja2 import TemplateError
|
||||
try:
|
||||
if isinstance(alert, basestring):
|
||||
if isinstance(alert, string_types):
|
||||
alert = frappe.get_doc("Email Alert", alert)
|
||||
|
||||
context = get_context(doc)
|
||||
|
|
|
|||
23
frappe/email/doctype/email_alert/test_email_alert.js
Normal file
23
frappe/email/doctype/email_alert/test_email_alert.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Email Alert", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Email Alert
|
||||
() => frappe.tests.make('Email Alert', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
@ -72,13 +72,13 @@ class Newsletter(Document):
|
|||
files = frappe.get_all("File", fields = ["name"], filters = {"attached_to_doctype": "Newsletter",
|
||||
"attached_to_name":self.name}, order_by="creation desc")
|
||||
|
||||
for a in files:
|
||||
for file in files:
|
||||
try:
|
||||
# these attachments will be attached on-demand
|
||||
# and won't be stored in the message
|
||||
attachments.append({"fid": file.name})
|
||||
except IOError:
|
||||
frappe.throw(_("Unable to find attachment {0}").format(a))
|
||||
frappe.throw(_("Unable to find attachment {0}").format(file.name))
|
||||
|
||||
send(recipients = self.recipients, sender = sender,
|
||||
subject = self.subject, message = self.message,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
|||
import frappe, json
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.jinja import validate_template
|
||||
from six import string_types
|
||||
|
||||
class StandardReply(Document):
|
||||
def validate(self):
|
||||
|
|
@ -13,7 +14,7 @@ class StandardReply(Document):
|
|||
@frappe.whitelist()
|
||||
def get_standard_reply(template_name, doc):
|
||||
'''Returns the processed HTML of a standard reply with the given doc'''
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = json.loads(doc)
|
||||
|
||||
standard_reply = frappe.get_doc("Standard Reply", template_name)
|
||||
|
|
|
|||
|
|
@ -8,7 +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, parse_addr)
|
||||
import email.utils
|
||||
from six import iteritems, text_type
|
||||
from six import iteritems, text_type, string_types
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class EMail:
|
|||
from email import Charset
|
||||
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')
|
||||
|
||||
if isinstance(recipients, basestring):
|
||||
if isinstance(recipients, string_types):
|
||||
recipients = recipients.replace(';', ',').replace('\n', '')
|
||||
recipients = split_emails(recipients)
|
||||
|
||||
|
|
@ -432,7 +432,7 @@ def get_header(header=None):
|
|||
|
||||
if not header: return None
|
||||
|
||||
if isinstance(header, basestring):
|
||||
if isinstance(header, string_types):
|
||||
# header = 'My Title'
|
||||
header = [header, None]
|
||||
if len(header) == 1:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from frappe.utils import get_url, nowdate, encode, now_datetime, add_days, split
|
|||
from frappe.utils.file_manager import get_file
|
||||
from rq.timeouts import JobTimeoutException
|
||||
from frappe.utils.scheduler import log
|
||||
from six import text_type
|
||||
from six import text_type, string_types
|
||||
|
||||
class EmailLimitCrossedError(frappe.ValidationError): pass
|
||||
|
||||
|
|
@ -55,10 +55,10 @@ def send(recipients=None, sender=None, subject=None, message=None, text_content=
|
|||
if not recipients and not cc:
|
||||
return
|
||||
|
||||
if isinstance(recipients, basestring):
|
||||
if isinstance(recipients, string_types):
|
||||
recipients = split_emails(recipients)
|
||||
|
||||
if isinstance(cc, basestring):
|
||||
if isinstance(cc, string_types):
|
||||
cc = split_emails(cc)
|
||||
|
||||
if isinstance(send_after, int):
|
||||
|
|
@ -484,7 +484,7 @@ def prepare_message(email, recipient, recipients_list):
|
|||
pass
|
||||
else:
|
||||
if email.expose_recipients == "footer":
|
||||
if isinstance(email.show_as_cc, basestring):
|
||||
if isinstance(email.show_as_cc, string_types):
|
||||
email.show_as_cc = email.show_as_cc.split(",")
|
||||
email_sent_to = [r.recipient for r in recipients_list]
|
||||
email_sent_cc = ", ".join([e for e in email_sent_to if e in email.show_as_cc])
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
import requests
|
||||
import json
|
||||
import frappe
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
'''
|
||||
FrappeClient is a library that helps you connect with other frappe systems
|
||||
|
|
@ -49,7 +49,7 @@ class FrappeClient(object):
|
|||
|
||||
def get_list(self, doctype, fields='"*"', filters=None, limit_start=0, limit_page_length=0):
|
||||
"""Returns list of records of a particular type"""
|
||||
if not isinstance(fields, basestring):
|
||||
if not isinstance(fields, string_types):
|
||||
fields = json.dumps(fields)
|
||||
params = {
|
||||
"fields": fields,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import frappe.utils.file_manager
|
|||
import frappe.desk.form.run_method
|
||||
from frappe.utils.response import build_response
|
||||
from werkzeug.wrappers import Response
|
||||
from six import string_types
|
||||
|
||||
def handle():
|
||||
"""handle request"""
|
||||
|
|
@ -63,7 +64,7 @@ def is_whitelisted(method):
|
|||
# strictly sanitize form_dict
|
||||
# escapes html characters like <> except for predefined tags like a, b, ul etc.
|
||||
for key, value in frappe.form_dict.items():
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, string_types):
|
||||
frappe.form_dict[key] = frappe.utils.sanitize_html(value)
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -60,9 +60,8 @@ import frappe
|
|||
import json
|
||||
from frappe import _
|
||||
from frappe.utils import get_url, call_hook_method, cint
|
||||
from urllib import urlencode
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from frappe.model.document import Document
|
||||
import urllib
|
||||
from frappe.integrations.utils import create_request_log, make_post_request, create_payment_gateway
|
||||
|
||||
class PayPalSettings(Document):
|
||||
|
|
@ -237,9 +236,9 @@ def confirm_payment(token):
|
|||
redirect_url = "/integrations/payment-failed"
|
||||
|
||||
if redirect_to:
|
||||
redirect_url += '?' + urllib.urlencode({'redirect_to': redirect_to})
|
||||
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
|
||||
if redirect_message:
|
||||
redirect_url += '&' + urllib.urlencode({'redirect_message': redirect_message})
|
||||
redirect_url += '&' + urlencode({'redirect_message': redirect_message})
|
||||
|
||||
# this is done so that functions called via hooks can update flags.redirect_to
|
||||
if redirect:
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ For razorpay payment status is Authorized
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
import urllib, json
|
||||
import json
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import get_url, call_hook_method, cint
|
||||
from frappe.integrations.utils import make_get_request, make_post_request, create_request_log, create_payment_gateway
|
||||
|
|
@ -82,7 +83,7 @@ class RazorpaySettings(Document):
|
|||
frappe.throw(_("Please select another payment method. Razorpay does not support transactions in currency '{0}'").format(currency))
|
||||
|
||||
def get_payment_url(self, **kwargs):
|
||||
return get_url("./integrations/razorpay_checkout?{0}".format(urllib.urlencode(kwargs)))
|
||||
return get_url("./integrations/razorpay_checkout?{0}".format(urlencode(kwargs)))
|
||||
|
||||
def create_request(self, data):
|
||||
self.data = frappe._dict(data)
|
||||
|
|
@ -146,9 +147,9 @@ class RazorpaySettings(Document):
|
|||
redirect_url = 'payment-failed'
|
||||
|
||||
if redirect_to:
|
||||
redirect_url += '?' + urllib.urlencode({'redirect_to': redirect_to})
|
||||
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
|
||||
if redirect_message:
|
||||
redirect_url += '&' + urllib.urlencode({'redirect_message': redirect_message})
|
||||
redirect_url += '&' + urlencode({'redirect_message': redirect_message})
|
||||
|
||||
return {
|
||||
"redirect_to": redirect_url,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
|||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
import urllib
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from frappe.utils import get_url, call_hook_method, cint
|
||||
from frappe.integrations.utils import make_get_request, make_post_request, create_request_log, create_payment_gateway
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ class StripeSettings(Document):
|
|||
frappe.throw(_("Please select another payment method. Stripe does not support transactions in currency '{0}'").format(currency))
|
||||
|
||||
def get_payment_url(self, **kwargs):
|
||||
return get_url("./integrations/stripe_checkout?{0}".format(urllib.urlencode(kwargs)))
|
||||
return get_url("./integrations/stripe_checkout?{0}".format(urlencode(kwargs)))
|
||||
|
||||
def create_request(self, data):
|
||||
self.data = frappe._dict(data)
|
||||
|
|
@ -105,9 +105,9 @@ class StripeSettings(Document):
|
|||
redirect_url = 'payment-failed'
|
||||
|
||||
if redirect_to:
|
||||
redirect_url += '?' + urllib.urlencode({'redirect_to': redirect_to})
|
||||
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
|
||||
if redirect_message:
|
||||
redirect_url += '&' + urllib.urlencode({'redirect_message': redirect_message})
|
||||
redirect_url += '&' + urlencode({'redirect_message': redirect_message})
|
||||
|
||||
return {
|
||||
"redirect_to": redirect_url,
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@ from __future__ import unicode_literals
|
|||
import frappe, json
|
||||
from frappe.oauth import OAuthWebRequestValidator, WebApplicationServer
|
||||
from oauthlib.oauth2 import FatalClientError, OAuth2Error
|
||||
from urllib import urlencode
|
||||
from six.moves.urllib.parse import quote
|
||||
from werkzeug import url_fix
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from six.moves.urllib.parse import quote, urlencode, urlparse
|
||||
from frappe.integrations.doctype.oauth_provider_settings.oauth_provider_settings import get_oauth_settings
|
||||
from frappe import _
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
|||
import frappe
|
||||
import json
|
||||
from six.moves.urllib.parse import parse_qs
|
||||
from six import string_types
|
||||
from frappe.utils import get_request_session
|
||||
from frappe import _
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ def make_post_request(url, auth=None, headers=None, data=None):
|
|||
raise exc
|
||||
|
||||
def create_request_log(data, integration_type, service_name, name=None):
|
||||
if isinstance(data, basestring):
|
||||
if isinstance(data, string_types):
|
||||
data = json.loads(data)
|
||||
|
||||
integration_request = frappe.get_doc({
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ from frappe.utils import now_datetime, getdate, flt, cint, get_fullname
|
|||
from frappe.installer import update_site_config
|
||||
from frappe.utils.data import formatdate
|
||||
from frappe.utils.user import get_enabled_system_users, disable_users
|
||||
import os, subprocess, urllib
|
||||
from six.moves.urllib.parse import parse_qsl, urlsplit, urlunsplit
|
||||
import os, subprocess
|
||||
from six.moves.urllib.parse import parse_qsl, urlsplit, urlunsplit, urlencode
|
||||
from six import string_types
|
||||
|
||||
class SiteExpiredError(frappe.ValidationError):
|
||||
http_status_code = 417
|
||||
|
|
@ -131,7 +132,7 @@ def get_upgrade_url(upgrade_url):
|
|||
'country': frappe.db.get_value("System Settings", "System Settings", 'country')
|
||||
})
|
||||
|
||||
query = urllib.urlencode(params, doseq=True)
|
||||
query = urlencode(params, doseq=True)
|
||||
url = urlunsplit((parts.scheme, parts.netloc, parts.path, query, parts.fragment))
|
||||
return url
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ def update_limits(limits_dict):
|
|||
def clear_limit(key):
|
||||
'''Remove a limit option from site_config'''
|
||||
limits = get_limits()
|
||||
to_clear = [key] if isinstance(key, basestring) else key
|
||||
to_clear = [key] if isinstance(key, string_types) else key
|
||||
for key in to_clear:
|
||||
if key in limits:
|
||||
del limits[key]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from six import reraise as raise_, iteritems
|
||||
from six import iteritems, string_types
|
||||
import frappe, sys
|
||||
from frappe import _
|
||||
from frappe.utils import (cint, flt, now, cstr, strip_html, getdate, get_datetime, to_timedelta,
|
||||
|
|
@ -296,7 +296,7 @@ class BaseDocument(object):
|
|||
doctype = self.doctype,
|
||||
columns = ", ".join(["`"+c+"`" for c in columns]),
|
||||
values = ", ".join(["%s"] * len(columns))
|
||||
), d.values())
|
||||
), list(d.values()))
|
||||
except Exception as e:
|
||||
if e.args[0]==1062:
|
||||
if "PRIMARY" in cstr(e.args[1]):
|
||||
|
|
@ -307,8 +307,7 @@ class BaseDocument(object):
|
|||
return
|
||||
|
||||
frappe.msgprint(_("Duplicate name {0} {1}").format(self.doctype, self.name))
|
||||
traceback = sys.exc_info()[2]
|
||||
raise_(frappe.DuplicateEntryError, (self.doctype, self.name, e), traceback)
|
||||
raise frappe.DuplicateEntryError(self.doctype, self.name, e)
|
||||
|
||||
elif "Duplicate" in cstr(e.args[1]):
|
||||
# unique constraint
|
||||
|
|
@ -338,7 +337,7 @@ class BaseDocument(object):
|
|||
set {values} where name=%s""".format(
|
||||
doctype = self.doctype,
|
||||
values = ", ".join(["`"+c+"`=%s" for c in columns])
|
||||
), d.values() + [name])
|
||||
), list(d.values()) + [name])
|
||||
except Exception as e:
|
||||
if e.args[0]==1062 and "Duplicate" in cstr(e.args[1]):
|
||||
self.show_unique_validation_message(e)
|
||||
|
|
@ -361,7 +360,7 @@ class BaseDocument(object):
|
|||
frappe.msgprint(_("{0} must be unique".format(label or fieldname)))
|
||||
|
||||
# this is used to preserve traceback
|
||||
raise_(frappe.UniqueValidationError, (self.doctype, self.name, e), traceback)
|
||||
raise frappe.UniqueValidationError(self.doctype, self.name, e)
|
||||
|
||||
def db_set(self, fieldname, value=None, update_modified=True):
|
||||
'''Set a value in the document object, update the timestamp and update the database.
|
||||
|
|
@ -610,7 +609,7 @@ class BaseDocument(object):
|
|||
return
|
||||
|
||||
for fieldname, value in self.get_valid_dict().items():
|
||||
if not value or not isinstance(value, basestring):
|
||||
if not value or not isinstance(value, string_types):
|
||||
continue
|
||||
|
||||
value = frappe.as_unicode(value)
|
||||
|
|
@ -673,7 +672,7 @@ class BaseDocument(object):
|
|||
:param parentfield: If fieldname is in child table."""
|
||||
from frappe.model.meta import get_field_precision
|
||||
|
||||
if parentfield and not isinstance(parentfield, basestring):
|
||||
if parentfield and not isinstance(parentfield, string_types):
|
||||
parentfield = parentfield.parentfield
|
||||
|
||||
cache_key = parentfield or "main"
|
||||
|
|
@ -831,7 +830,7 @@ def _filter(data, filters, limit=None):
|
|||
fval = ("not None", fval)
|
||||
elif fval is False:
|
||||
fval = ("None", fval)
|
||||
elif isinstance(fval, basestring) and fval.startswith("^"):
|
||||
elif isinstance(fval, string_types) and fval.startswith("^"):
|
||||
fval = ("^", fval[1:])
|
||||
else:
|
||||
fval = ("=", fval)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
"""build query for doclistview and return results"""
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ class DatabaseQuery(object):
|
|||
update=None, add_total_row=None, user_settings=None):
|
||||
if not ignore_permissions and not frappe.has_permission(self.doctype, "read", user=user):
|
||||
frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(self.doctype))
|
||||
raise frappe.PermissionError, self.doctype
|
||||
raise frappe.PermissionError(self.doctype)
|
||||
|
||||
# fitlers and fields swappable
|
||||
# its hard to remember what comes first
|
||||
|
|
@ -47,7 +47,7 @@ class DatabaseQuery(object):
|
|||
filters, fields = fields, filters
|
||||
|
||||
elif fields and isinstance(filters, list) \
|
||||
and len(filters) > 1 and isinstance(filters[0], basestring):
|
||||
and len(filters) > 1 and isinstance(filters[0], string_types):
|
||||
# if `filters` is a list of strings, its probably fields
|
||||
filters, fields = fields, filters
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ class DatabaseQuery(object):
|
|||
|
||||
def parse_args(self):
|
||||
"""Convert fields and filters from strings to list, dicts"""
|
||||
if isinstance(self.fields, basestring):
|
||||
if isinstance(self.fields, string_types):
|
||||
if self.fields == "*":
|
||||
self.fields = ["*"]
|
||||
else:
|
||||
|
|
@ -168,7 +168,7 @@ class DatabaseQuery(object):
|
|||
|
||||
for filter_name in ["filters", "or_filters"]:
|
||||
filters = getattr(self, filter_name)
|
||||
if isinstance(filters, basestring):
|
||||
if isinstance(filters, string_types):
|
||||
filters = json.loads(filters)
|
||||
|
||||
if isinstance(filters, dict):
|
||||
|
|
@ -203,7 +203,7 @@ class DatabaseQuery(object):
|
|||
doctype = table_name[4:-1]
|
||||
if (not self.flags.ignore_permissions) and (not frappe.has_permission(doctype)):
|
||||
frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(doctype))
|
||||
raise frappe.PermissionError, doctype
|
||||
raise frappe.PermissionError(doctype)
|
||||
|
||||
def set_field_tables(self):
|
||||
'''If there are more than one table, the fieldname must not be ambigous.
|
||||
|
|
@ -230,7 +230,7 @@ class DatabaseQuery(object):
|
|||
# remove from filters
|
||||
to_remove = []
|
||||
for each in self.filters:
|
||||
if isinstance(each, basestring):
|
||||
if isinstance(each, string_types):
|
||||
each = [each]
|
||||
|
||||
for element in each:
|
||||
|
|
@ -264,7 +264,7 @@ class DatabaseQuery(object):
|
|||
filters = [filters]
|
||||
|
||||
for f in filters:
|
||||
if isinstance(f, basestring):
|
||||
if isinstance(f, string_types):
|
||||
conditions.append(f)
|
||||
else:
|
||||
conditions.append(self.prepare_filter_condition(f))
|
||||
|
|
@ -331,12 +331,12 @@ class DatabaseQuery(object):
|
|||
value = get_time(f.value).strftime("%H:%M:%S.%f")
|
||||
fallback = "'00:00:00'"
|
||||
|
||||
elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, basestring) and
|
||||
elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, string_types) and
|
||||
(not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])):
|
||||
value = "" if f.value==None else f.value
|
||||
fallback = '""'
|
||||
|
||||
if f.operator.lower() in ("like", "not like") and isinstance(value, basestring):
|
||||
if f.operator.lower() in ("like", "not like") and isinstance(value, string_types):
|
||||
# because "like" uses backslash (\) for escaping
|
||||
value = value.replace("\\", "\\\\").replace("%", "%%")
|
||||
|
||||
|
|
@ -345,7 +345,7 @@ class DatabaseQuery(object):
|
|||
fallback = 0
|
||||
|
||||
# put it inside double quotes
|
||||
if isinstance(value, basestring) and not f.operator.lower() == 'between':
|
||||
if isinstance(value, string_types) and not f.operator.lower() == 'between':
|
||||
value = '"{0}"'.format(frappe.db.escape(value, percent=False))
|
||||
|
||||
if (self.ignore_ifnull
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class DbTable:
|
|||
else:
|
||||
raise
|
||||
|
||||
if max_length and max_length[0][0] > new_length:
|
||||
if max_length and max_length[0][0] and max_length[0][0] > new_length:
|
||||
current_type = self.current_columns[col.fieldname]["type"]
|
||||
current_length = re.findall('varchar\(([\d]+)\)', current_type)
|
||||
if not current_length:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from frappe.utils.password import delete_all_passwords_for
|
|||
from frappe import _
|
||||
from frappe.model.naming import revert_series_if_last
|
||||
from frappe.utils.global_search import delete_for_document
|
||||
from six import string_types
|
||||
|
||||
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False,
|
||||
ignore_permissions=False, flags=None, ignore_on_trash=False):
|
||||
|
|
@ -26,7 +27,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa
|
|||
name = frappe.form_dict.get('dn')
|
||||
|
||||
names = name
|
||||
if isinstance(name, basestring):
|
||||
if isinstance(name, string_types):
|
||||
names = [name]
|
||||
|
||||
for name in names or []:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from frappe.utils import flt, cstr, now, get_datetime_str, file_lock
|
|||
from frappe.utils.background_jobs import enqueue
|
||||
from frappe.model.base_document import BaseDocument, get_controller
|
||||
from frappe.model.naming import set_new_name
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
from werkzeug.exceptions import NotFound, Forbidden
|
||||
import hashlib, json
|
||||
from frappe.model import optional_fields
|
||||
|
|
@ -41,7 +41,7 @@ def get_doc(arg1, arg2=None):
|
|||
"""
|
||||
if isinstance(arg1, BaseDocument):
|
||||
return arg1
|
||||
elif isinstance(arg1, basestring):
|
||||
elif isinstance(arg1, string_types):
|
||||
doctype = arg1
|
||||
else:
|
||||
doctype = arg1.get("doctype")
|
||||
|
|
@ -67,7 +67,7 @@ class Document(BaseDocument):
|
|||
self._default_new_docs = {}
|
||||
self.flags = frappe._dict()
|
||||
|
||||
if arg1 and isinstance(arg1, basestring):
|
||||
if arg1 and isinstance(arg1, string_types):
|
||||
if not arg2:
|
||||
# single
|
||||
self.doctype = self.name = arg1
|
||||
|
|
@ -662,7 +662,7 @@ class Document(BaseDocument):
|
|||
# hack! to run hooks even if method does not exist
|
||||
fn = lambda self, *args, **kwargs: None
|
||||
|
||||
fn.__name__ = method.encode("utf-8")
|
||||
fn.__name__ = str(method)
|
||||
out = Document.hook(fn)(self, *args, **kwargs)
|
||||
|
||||
self.run_email_alerts(method)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import frappe, json
|
|||
from frappe import _
|
||||
from frappe.utils import cstr
|
||||
from frappe.model import default_fields
|
||||
from six import string_types
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_mapped_doc(method, source_name, selected_children=None):
|
||||
|
|
@ -43,7 +44,7 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None,
|
|||
# main
|
||||
if not target_doc:
|
||||
target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"])
|
||||
elif isinstance(target_doc, basestring):
|
||||
elif isinstance(target_doc, string_types):
|
||||
target_doc = frappe.get_doc(json.loads(target_doc))
|
||||
|
||||
if not ignore_permissions and not target_doc.has_permission("create"):
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import frappe
|
|||
from frappe import _
|
||||
from frappe.utils import now_datetime, cint
|
||||
import re
|
||||
from six import string_types
|
||||
|
||||
def set_new_name(doc):
|
||||
"""
|
||||
|
|
@ -99,7 +100,7 @@ def make_autoname(key='', doctype='', doc=''):
|
|||
|
||||
def parse_naming_series(parts, doctype= '', doc = ''):
|
||||
n = ''
|
||||
if isinstance(parts, basestring):
|
||||
if isinstance(parts, string_types):
|
||||
parts = parts.split('.')
|
||||
|
||||
series_set = False
|
||||
|
|
@ -123,7 +124,7 @@ def parse_naming_series(parts, doctype= '', doc = ''):
|
|||
part = doc.get(e)
|
||||
else: part = e
|
||||
|
||||
if isinstance(part, basestring):
|
||||
if isinstance(part, string_types):
|
||||
n+=part
|
||||
|
||||
return n
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ def sync_for(app_name, force=0, sync_everything = False, verbose=False, reset_pe
|
|||
if l:
|
||||
for i, doc_path in enumerate(files):
|
||||
import_file_by_path(doc_path, force=force, ignore_version=True,
|
||||
reset_permissions=reset_permissions)
|
||||
reset_permissions=reset_permissions, for_sync=True)
|
||||
#print module_name + ' | ' + doctype + ' | ' + name
|
||||
|
||||
frappe.db.commit()
|
||||
|
|
@ -56,8 +56,9 @@ def sync_for(app_name, force=0, sync_everything = False, verbose=False, reset_pe
|
|||
def get_doc_files(files, start_path, force=0, sync_everything = False, verbose=False):
|
||||
"""walk and sync all doctypes and pages"""
|
||||
|
||||
document_type = ['doctype', 'page', 'report', 'print_format', 'website_theme', 'web_form', 'email_alert']
|
||||
for doctype in document_type:
|
||||
document_types = ['doctype', 'page', 'report', 'print_format',
|
||||
'website_theme', 'web_form', 'email_alert', 'print_style']
|
||||
for doctype in document_types:
|
||||
doctype_path = os.path.join(start_path, doctype)
|
||||
if os.path.exists(doctype_path):
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# such as page_limit, filters, last_view
|
||||
|
||||
import frappe, json
|
||||
from six import iteritems
|
||||
from six import iteritems, string_types
|
||||
|
||||
|
||||
def get_user_settings(doctype, for_update=False):
|
||||
|
|
@ -27,7 +27,7 @@ def update_user_settings(doctype, user_settings, for_update=False):
|
|||
else:
|
||||
current = json.loads(get_user_settings(doctype, for_update = True))
|
||||
|
||||
if isinstance(current, basestring):
|
||||
if isinstance(current, string_types):
|
||||
# corrupt due to old code, remove this in a future release
|
||||
current = {}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ def get_file_path(module, dt, dn):
|
|||
return path
|
||||
|
||||
def import_file_by_path(path, force=False, data_import=False, pre_process=None, ignore_version=None,
|
||||
reset_permissions=False):
|
||||
reset_permissions=False, for_sync=False):
|
||||
try:
|
||||
docs = read_doc_from_file(path)
|
||||
except IOError:
|
||||
|
|
@ -86,7 +86,9 @@ def read_doc_from_file(path):
|
|||
|
||||
ignore_values = {
|
||||
"Report": ["disabled"],
|
||||
"Print Format": ["disabled"]
|
||||
"Print Format": ["disabled"],
|
||||
"Email Alert": ["enabled"],
|
||||
"Print Style": ["disabled"]
|
||||
}
|
||||
|
||||
ignore_doctypes = [""]
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ import frappe.utils
|
|||
from frappe import _
|
||||
|
||||
lower_case_files_for = ['DocType', 'Page', 'Report',
|
||||
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State', 'Workflow Action', 'Print Format',
|
||||
"Website Theme", 'Web Form', 'Email Alert']
|
||||
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State',
|
||||
'Workflow Action', 'Print Format', "Website Theme", 'Web Form',
|
||||
'Email Alert', 'Print Style']
|
||||
|
||||
def export_module_json(doc, is_standard, module):
|
||||
"""Make a folder for the given doc and add its json file (make it a standard
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import json
|
|||
import frappe
|
||||
import frappe.defaults
|
||||
from frappe.desk.like import _toggle_like
|
||||
from six import string_types
|
||||
|
||||
def execute():
|
||||
for user in frappe.get_all("User"):
|
||||
|
|
@ -12,7 +13,7 @@ def execute():
|
|||
if not bookmarks:
|
||||
continue
|
||||
|
||||
if isinstance(bookmarks, basestring):
|
||||
if isinstance(bookmarks, string_types):
|
||||
bookmarks = json.loads(bookmarks)
|
||||
|
||||
for opts in bookmarks:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals, print_function
|
||||
from six.moves import range
|
||||
from six import string_types
|
||||
import frappe, copy, json
|
||||
from frappe import _, msgprint
|
||||
from frappe.utils import cint
|
||||
|
|
@ -51,7 +52,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
|
|||
["read" if ptype in ("email", "print") else ptype])
|
||||
|
||||
if doc:
|
||||
doc_name = doc if isinstance(doc, basestring) else doc.name
|
||||
doc_name = doc if isinstance(doc, string_types) else doc.name
|
||||
if doc_name in shared:
|
||||
if verbose: print("Shared")
|
||||
if ptype in ("read", "write", "share") or meta.permissions[0].get(ptype):
|
||||
|
|
@ -75,7 +76,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
|
|||
perm = True
|
||||
|
||||
if doc:
|
||||
if isinstance(doc, basestring):
|
||||
if isinstance(doc, string_types):
|
||||
doc = frappe.get_doc(meta.name, doc)
|
||||
|
||||
owner_perm = user_perm = controller_perm = None
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class TestPrintFormat(unittest.TestCase):
|
|||
|
||||
def test_print_user_modern(self):
|
||||
print_html = self.test_print_user("Modern")
|
||||
self.assertTrue("/* modern format: don't remove this line */" in print_html)
|
||||
self.assertTrue("/* modern format: for-test */" in print_html)
|
||||
|
||||
def test_print_user_classic(self):
|
||||
print_html = self.test_print_user("Classic")
|
||||
self.assertTrue("font-family: serif;" in print_html)
|
||||
self.assertTrue("/* classic format: for-test */" in print_html)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,15 @@
|
|||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Print Settings", "print_style", function (frm) {
|
||||
frm.get_field("print_style_preview").html('<img src="/assets/frappe/images/help/print-style-' +
|
||||
frm.doc.print_style.toLowerCase() + '.png" class="img-responsive">');
|
||||
frappe.db.get_value('Print Style', frm.doc.print_style, 'preview').then((r) => {
|
||||
if(r.message.preview) {
|
||||
frm.get_field("print_style_preview").$wrapper.html(
|
||||
`<img src="${r.message.preview}" class="img-responsive">`);
|
||||
} else {
|
||||
frm.get_field("print_style_preview").$wrapper.html(
|
||||
`<p style="margin: 60px 0px" class="text-center text-muted">${__("No Preview")}</p>`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Print Settings", "onload", function (frm) {
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@
|
|||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Page Settings",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
|
|
@ -191,188 +192,6 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"description": "",
|
||||
"fieldname": "attach_view_link",
|
||||
"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": "Send document web view link in email",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_style_section",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Print Style",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Modern",
|
||||
"fieldname": "print_style",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Print Style",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Modern\nClassic\nStandard\nMonochrome",
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Default",
|
||||
"fieldname": "font",
|
||||
"fieldtype": "Select",
|
||||
"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": "Font",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Default\nArial\nHelvetica\nVerdana\nMonospace",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "In points. Default is 9.",
|
||||
"fieldname": "font_size",
|
||||
"fieldtype": "Float",
|
||||
"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": "Font Size",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
|
|
@ -436,6 +255,67 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"description": "",
|
||||
"fieldname": "attach_view_link",
|
||||
"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": "Send document web view link in email",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"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,
|
||||
|
|
@ -467,6 +347,36 @@
|
|||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_page_break_inside_tables",
|
||||
"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 page break inside tables",
|
||||
"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,
|
||||
|
|
@ -504,8 +414,8 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_page_break_inside_tables",
|
||||
"fieldtype": "Check",
|
||||
"fieldname": "print_style_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
|
|
@ -513,11 +423,10 @@
|
|||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Allow page break inside tables",
|
||||
"label": "Print Style",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
|
|
@ -534,17 +443,20 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"default": "Modern",
|
||||
"fieldname": "print_style",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Print Style",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Print Style",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
|
|
@ -584,6 +496,97 @@
|
|||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Fonts",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Default",
|
||||
"fieldname": "font",
|
||||
"fieldtype": "Select",
|
||||
"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": "Font",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Default\nArial\nHelvetica\nVerdana\nMonospace",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "In points. Default is 9.",
|
||||
"fieldname": "font_size",
|
||||
"fieldtype": "Float",
|
||||
"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": "Font Size",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
|
|
@ -597,7 +600,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-05-03 05:58:55.562540",
|
||||
"modified": "2017-08-18 01:04:26.692081",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Printing",
|
||||
"name": "Print Settings",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Print Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Print Settings
|
||||
() => frappe.tests.make('Print Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
0
frappe/printing/doctype/print_style/__init__.py
Normal file
0
frappe/printing/doctype/print_style/__init__.py
Normal file
10
frappe/printing/doctype/print_style/print_style.js
Normal file
10
frappe/printing/doctype/print_style/print_style.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2017, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Print Style', {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Print Settings'), () => {
|
||||
frappe.set_route('Form', 'Print Settings');
|
||||
})
|
||||
}
|
||||
});
|
||||
214
frappe/printing/doctype/print_style/print_style.json
Normal file
214
frappe/printing/doctype/print_style/print_style.json
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:print_style_name",
|
||||
"beta": 0,
|
||||
"creation": "2017-08-17 01:25:56.910716",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_style_name",
|
||||
"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": "Print Style Name",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disabled",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "standard",
|
||||
"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": "Standard",
|
||||
"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,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "css",
|
||||
"fieldtype": "Code",
|
||||
"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": "CSS",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "preview",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Preview",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_field": "preview",
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-08-17 02:18:08.132853",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Printing",
|
||||
"name": "Print Style",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
23
frappe/printing/doctype/print_style/print_style.py
Normal file
23
frappe/printing/doctype/print_style/print_style.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PrintStyle(Document):
|
||||
def validate(self):
|
||||
if (self.standard==1
|
||||
and not frappe.local.conf.get("developer_mode")
|
||||
and not (frappe.flags.in_import or frappe.flags.in_test)):
|
||||
|
||||
frappe.throw(frappe._("Standard Print Style cannot be changed. Please duplicate to edit."))
|
||||
|
||||
def on_update(self):
|
||||
self.export_doc()
|
||||
|
||||
def export_doc(self):
|
||||
# export
|
||||
from frappe.modules.utils import export_module_json
|
||||
export_module_json(self, self.standard == 1, 'Printing')
|
||||
20
frappe/printing/doctype/print_style/test_print_style.js
Normal file
20
frappe/printing/doctype/print_style/test_print_style.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Print Style", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Print Style
|
||||
() => frappe.tests.make('Print Style', [
|
||||
// values to be set
|
||||
{print_style_name: 'Test Print Style'},
|
||||
{css: '/* some css value */'}
|
||||
]),
|
||||
]);
|
||||
|
||||
});
|
||||
10
frappe/printing/doctype/print_style/test_print_style.py
Normal file
10
frappe/printing/doctype/print_style/test_print_style.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestPrintStyle(unittest.TestCase):
|
||||
pass
|
||||
0
frappe/printing/print_style/__init__.py
Normal file
0
frappe/printing/print_style/__init__.py
Normal file
0
frappe/printing/print_style/classic/__init__.py
Normal file
0
frappe/printing/print_style/classic/__init__.py
Normal file
15
frappe/printing/print_style/classic/classic.json
Normal file
15
frappe/printing/print_style/classic/classic.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"creation": "2017-08-17 02:00:12.502887",
|
||||
"css": "/*\n\tcommon style for whole page\n\tThis should include:\n\t+ page size related settings\n\t+ font family settings\n\t+ line spacing settings\n*/\n.print-format div,\n.print-format span,\n.print-format td,\n.print-format h1,\n.print-format h2,\n.print-format h3,\n.print-format h4 {\n\tfont-family: Georgia, serif;\n}\n\n/* classic format: for-test */",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Style",
|
||||
"idx": 1,
|
||||
"modified": "2017-08-18 00:43:48.675833",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Classic",
|
||||
"owner": "Administrator",
|
||||
"preview": "/assets/frappe/images/help/print-style-classic.png",
|
||||
"print_style_name": "Classic",
|
||||
"standard": 1
|
||||
}
|
||||
0
frappe/printing/print_style/modern/__init__.py
Normal file
0
frappe/printing/print_style/modern/__init__.py
Normal file
15
frappe/printing/print_style/modern/modern.json
Normal file
15
frappe/printing/print_style/modern/modern.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"creation": "2017-08-17 02:16:58.060374",
|
||||
"css": ".print-heading {\n\ttext-align: right;\n\ttext-transform: uppercase;\n\tcolor: #666;\n\tpadding-bottom: 20px;\n\tmargin-bottom: 20px;\n\tborder-bottom: 1px solid #d1d8dd;\n}\n\n.print-heading h2 {\n\tfont-size: 24px;\n}\n\n.print-format th {\n\tbackground-color: #eee !important;\n\tborder-bottom: 0px !important;\n}\n\n/* modern format: for-test */",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Style",
|
||||
"idx": 0,
|
||||
"modified": "2017-08-18 00:44:07.438147",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Modern",
|
||||
"owner": "Administrator",
|
||||
"preview": "/assets/frappe/images/help/print-style-modern.png",
|
||||
"print_style_name": "Modern",
|
||||
"standard": 1
|
||||
}
|
||||
0
frappe/printing/print_style/monochrome/__init__.py
Normal file
0
frappe/printing/print_style/monochrome/__init__.py
Normal file
15
frappe/printing/print_style/monochrome/monochrome.json
Normal file
15
frappe/printing/print_style/monochrome/monochrome.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"creation": "2017-08-17 02:16:20.992989",
|
||||
"css": ".print-format * {\n\tcolor: #000 !important;\n}\n\n.print-format .alert {\n\tbackground-color: inherit;\n\tborder: 1px dashed #333;\n}\n\n.print-format .table-bordered,\n.print-format .table-bordered > thead > tr > th,\n.print-format .table-bordered > tbody > tr > th,\n.print-format .table-bordered > tfoot > tr > th,\n.print-format .table-bordered > thead > tr > td,\n.print-format .table-bordered > tbody > tr > td,\n.print-format .table-bordered > tfoot > tr > td {\n\tborder: 1px solid #333;\n}\n\n.print-format hr {\n\tborder-top: 1px solid #333;\n}\n\n.print-heading {\n\tborder-bottom: 2px solid #333;\n}\n",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Style",
|
||||
"idx": 0,
|
||||
"modified": "2017-08-18 00:44:25.023898",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Monochrome",
|
||||
"owner": "Administrator",
|
||||
"preview": "/assets/frappe/images/help/print-style-monochrome.png",
|
||||
"print_style_name": "Monochrome",
|
||||
"standard": 1
|
||||
}
|
||||
|
|
@ -11,6 +11,12 @@
|
|||
padding: 10px 0px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
}
|
||||
.print-toolbar > div {
|
||||
padding-right: 0px;
|
||||
}
|
||||
.print-toolbar > div:last-child {
|
||||
padding-right: 15px;
|
||||
}
|
||||
.form-inner-toolbar {
|
||||
padding: 10px 15px 0px;
|
||||
background-color: #fafbfc;
|
||||
|
|
@ -588,6 +594,16 @@ select.form-control {
|
|||
.password-strength-message {
|
||||
margin-top: -10px;
|
||||
}
|
||||
.control-code,
|
||||
.control-code.bold {
|
||||
height: 400px;
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
background-color: black;
|
||||
color: #fffce7;
|
||||
font-size: 12px;
|
||||
line-height: 1.7em;
|
||||
border: none;
|
||||
}
|
||||
.delivery-status-indicator {
|
||||
display: inline-block;
|
||||
margin-top: -3px;
|
||||
|
|
|
|||
|
|
@ -57,3 +57,6 @@
|
|||
.frappe-rtl .slick-wrapper {
|
||||
direction: ltr;
|
||||
}
|
||||
.slick-cell > span[data-field="_comments"] * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ frappe.Application = Class.extend({
|
|||
moment.tz.add(frappe.boot.timezone_info);
|
||||
}
|
||||
if(frappe.boot.print_css) {
|
||||
frappe.dom.set_style(frappe.boot.print_css)
|
||||
frappe.dom.set_style(frappe.boot.print_css, "print-style");
|
||||
}
|
||||
frappe.user.name = frappe.boot.user.name;
|
||||
} else {
|
||||
|
|
@ -482,14 +482,14 @@ frappe.Application = Class.extend({
|
|||
},
|
||||
|
||||
setup_beforeunload: function() {
|
||||
if (frappe.defaults.get_default('in_selenium')) {
|
||||
if (frappe.defaults.get_default('in_selenium') || frappe.boot.developer_mode) {
|
||||
return;
|
||||
}
|
||||
window.onbeforeunload = function () {
|
||||
if (frappe.flags.in_test) return null;
|
||||
var unsaved_docs = [];
|
||||
for (doctype in locals) {
|
||||
for (name in locals[doctype]) {
|
||||
for (const doctype in locals) {
|
||||
for (const name in locals[doctype]) {
|
||||
var doc = locals[doctype][name];
|
||||
if(doc.__unsaved) { unsaved_docs.push(doc.name); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ frappe.dom = {
|
|||
se.appendChild(document.createTextNode(txt));
|
||||
}
|
||||
document.getElementsByTagName('head')[0].appendChild(se);
|
||||
return se;
|
||||
},
|
||||
add: function(parent, newtag, className, cs, innerHTML, onclick) {
|
||||
if(parent && parent.substr)parent = frappe.dom.by_id(parent);
|
||||
|
|
|
|||
|
|
@ -744,9 +744,24 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
|
|||
},
|
||||
set_formatted_input: function(value) {
|
||||
this._super(value);
|
||||
if(value
|
||||
&& ((this.last_value && this.last_value !== value)
|
||||
|| (!this.datepicker.selectedDates.length))) {
|
||||
if(!value) return;
|
||||
|
||||
let should_refresh = this.last_value && this.last_value !== value;
|
||||
|
||||
if (!should_refresh) {
|
||||
if(this.datepicker.selectedDates.length > 0) {
|
||||
// if date is selected but different from value, refresh
|
||||
const selected_date =
|
||||
moment(this.datepicker.selectedDates[0])
|
||||
.format(moment.defaultDateFormat);
|
||||
should_refresh = selected_date !== value;
|
||||
} else {
|
||||
// if datepicker has no selected date, refresh
|
||||
should_refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(should_refresh) {
|
||||
this.datepicker.selectDate(frappe.datetime.str_to_obj(value));
|
||||
}
|
||||
},
|
||||
|
|
@ -938,8 +953,12 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({
|
|||
this.set_mandatory && this.set_mandatory(value);
|
||||
},
|
||||
parse: function(value) {
|
||||
if(value && (value.indexOf(',') !== -1 || value.indexOf('to') !== -1)) {
|
||||
var vals = value.split(/[( to )(,)]/);
|
||||
// replace the separator (which can be in user language) with comma
|
||||
const to = __('{0} to {1}').replace('{0}', '').replace('{1}', '');
|
||||
value = value.replace(to, ',');
|
||||
|
||||
if(value && value.includes(',')) {
|
||||
var vals = value.split(',');
|
||||
var from_date = moment(frappe.datetime.user_to_obj(vals[0])).format('YYYY-MM-DD');
|
||||
var to_date = moment(frappe.datetime.user_to_obj(vals[vals.length-1])).format('YYYY-MM-DD');
|
||||
return [from_date, to_date];
|
||||
|
|
@ -1787,7 +1806,7 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({
|
|||
this._super();
|
||||
$(this.input_area).find("textarea")
|
||||
.allowTabs()
|
||||
.css({"height":"400px", "font-family": "Monaco, \"Courier New\", monospace"});
|
||||
.addClass('control-code');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,18 @@ frappe.ui.form.Viewers = Class.extend({
|
|||
init: function(opts) {
|
||||
$.extend(this, opts);
|
||||
},
|
||||
get_viewers: function() {
|
||||
let docinfo = this.frm.get_docinfo();
|
||||
if (docinfo) {
|
||||
return docinfo.viewers || {};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
refresh: function(data_updated) {
|
||||
var me = this;
|
||||
this.parent.empty();
|
||||
|
||||
var viewers = this.frm.get_docinfo().viewers || {};
|
||||
var viewers = this.get_viewers();
|
||||
|
||||
var users = [];
|
||||
var new_users = [];
|
||||
|
|
@ -55,7 +62,8 @@ frappe.ui.form.Viewers = Class.extend({
|
|||
frappe.ui.form.set_viewers = function(data) {
|
||||
var doctype = data.doctype;
|
||||
var docname = data.docname;
|
||||
var past_viewers = (frappe.model.get_docinfo(doctype, docname).viewers || {}).past || [];
|
||||
var docinfo = frappe.model.get_docinfo(doctype, docname);
|
||||
var past_viewers = ((docinfo && docinfo.viewers) || {}).past || [];
|
||||
var viewers = data.viewers || [];
|
||||
|
||||
var new_viewers = viewers.filter(viewer => !past_viewers.includes(viewer));
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ frappe.ui.form.PrintPreview = Class.extend({
|
|||
this.print_sel = this.wrapper
|
||||
.find(".print-preview-select")
|
||||
.on("change", function () {
|
||||
me.multilingual_preview()
|
||||
me.multilingual_preview();
|
||||
});
|
||||
|
||||
//On selection of language get code and pass it to preview method
|
||||
|
|
@ -79,7 +79,7 @@ frappe.ui.form.PrintPreview = Class.extend({
|
|||
});
|
||||
|
||||
this.wrapper.find(".btn-print-edit").on("click", function () {
|
||||
var print_format = me.get_print_format();
|
||||
let print_format = me.get_print_format();
|
||||
if (print_format && print_format.name) {
|
||||
if (print_format.print_format_builder) {
|
||||
frappe.set_route("print-format-builder", print_format.name);
|
||||
|
|
@ -106,7 +106,8 @@ frappe.ui.form.PrintPreview = Class.extend({
|
|||
this.lang_code = this.frm.doc.language;
|
||||
// Load all languages in the field
|
||||
this.language_sel.empty()
|
||||
.add_options(frappe.get_languages())
|
||||
.add_options([{value:'', label:__("Select Language...")}]
|
||||
.concat(frappe.get_languages()))
|
||||
.val(this.lang_code);
|
||||
this.preview();
|
||||
},
|
||||
|
|
@ -193,6 +194,7 @@ frappe.ui.form.PrintPreview = Class.extend({
|
|||
this.print_formats = frappe.meta.get_print_formats(this.frm.doctype);
|
||||
return this.print_sel
|
||||
.empty().add_options(this.print_formats);
|
||||
|
||||
},
|
||||
with_old_style: function (opts) {
|
||||
frappe.require("/assets/js/print_format_v3.min.js", function () {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
frappe.provide('frappe.ui.form');
|
||||
|
||||
frappe.ui.form.make_quick_entry = (doctype, after_insert) => {
|
||||
frappe.ui.form.make_quick_entry = (doctype, after_insert, init_callback) => {
|
||||
var trimmed_doctype = doctype.replace(/ /g, '');
|
||||
var controller_name = "QuickEntryForm";
|
||||
|
||||
|
|
@ -8,14 +8,15 @@ frappe.ui.form.make_quick_entry = (doctype, after_insert) => {
|
|||
controller_name = trimmed_doctype + "QuickEntryForm";
|
||||
}
|
||||
|
||||
frappe.quick_entry = new frappe.ui.form[controller_name](doctype, after_insert);
|
||||
frappe.quick_entry = new frappe.ui.form[controller_name](doctype, after_insert, init_callback);
|
||||
return frappe.quick_entry.setup();
|
||||
};
|
||||
|
||||
frappe.ui.form.QuickEntryForm = Class.extend({
|
||||
init: function(doctype, after_insert){
|
||||
init: function(doctype, after_insert, init_callback){
|
||||
this.doctype = doctype;
|
||||
this.after_insert = after_insert;
|
||||
this.init_callback = init_callback;
|
||||
},
|
||||
|
||||
setup: function() {
|
||||
|
|
@ -106,6 +107,10 @@ frappe.ui.form.QuickEntryForm = Class.extend({
|
|||
this.dialog.onhide = () => frappe.quick_entry = null;
|
||||
this.dialog.show();
|
||||
this.set_defaults();
|
||||
|
||||
if (this.init_callback) {
|
||||
this.init_callback(this.dialog);
|
||||
}
|
||||
},
|
||||
|
||||
register_primary_action: function(){
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ frappe.ui.form.Sidebar = Class.extend({
|
|||
parent: this.sidebar.find(".tag-area"),
|
||||
frm: this.frm,
|
||||
on_change: function(user_tags) {
|
||||
me.frm.doc._user_tags = user_tags;
|
||||
me.frm.doc._user_tags += ("," + user_tags);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
<div class="col-xs-2">
|
||||
<select class="print-preview-select input-sm form-control"></select></div>
|
||||
<div class="col-xs-2">
|
||||
<select class="languages input-sm form-control"></select></div>
|
||||
<select class="languages input-sm form-control"
|
||||
placeholder="{{ __("Language") }}"></select></div>
|
||||
<div class="col-xs-2">
|
||||
<div class="checkbox small" style="margin-top: 7px; margin-bottom: 0px;">
|
||||
<label>
|
||||
|
|
@ -16,8 +17,10 @@
|
|||
<div class="btn-group">
|
||||
<a class="btn-print-print btn-sm btn btn-default">
|
||||
<strong>{%= __("Print") %}</strong></a>
|
||||
<a class="btn-sm btn btn-default" href="#Form/Print Settings">
|
||||
{%= __("Settings...") %}</a>
|
||||
<a class="btn-print-edit btn-sm btn btn-default">
|
||||
{%= __("Customize") %}</a>
|
||||
{%= __("Customize...") %}</a>
|
||||
<a class="btn-print-preview btn-sm btn btn-default">
|
||||
{%= __("Full Page") %}</a>
|
||||
<a class="btn-download-pdf btn-sm btn btn-default">
|
||||
|
|
|
|||
|
|
@ -108,6 +108,10 @@ frappe.views.ListRenderer = Class.extend({
|
|||
add_field(this.meta.title_field);
|
||||
}
|
||||
|
||||
if (this.meta.image_field) {
|
||||
add_field(this.meta.image_field);
|
||||
}
|
||||
|
||||
// enabled / disabled
|
||||
if (frappe.meta.has_field(this.doctype, 'enabled')) { add_field('enabled'); }
|
||||
if (frappe.meta.has_field(this.doctype, 'disabled')) { add_field('disabled'); }
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ $.extend(frappe.model, {
|
|||
});
|
||||
|
||||
frappe.create_routes = {};
|
||||
frappe.new_doc = function (doctype, opts) {
|
||||
frappe.new_doc = function (doctype, opts, init_callback) {
|
||||
return new Promise(resolve => {
|
||||
if(opts && $.isPlainObject(opts)) {
|
||||
frappe.route_options = opts;
|
||||
|
|
@ -324,7 +324,7 @@ frappe.new_doc = function (doctype, opts) {
|
|||
frappe.set_route(frappe.create_routes[doctype])
|
||||
.then(() => resolve());
|
||||
} else {
|
||||
frappe.ui.form.make_quick_entry(doctype)
|
||||
frappe.ui.form.make_quick_entry(doctype, null, init_callback)
|
||||
.then(() => resolve());
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ frappe.ui.keys.on('esc', function(e) {
|
|||
close_grid_and_dialog();
|
||||
});
|
||||
|
||||
frappe.ui.keys.on('Enter', function(e) {
|
||||
frappe.ui.keys.on('enter', function(e) {
|
||||
if(cur_dialog && cur_dialog.confirm_dialog) {
|
||||
cur_dialog.get_primary_btn().trigger('click');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ frappe.ui.TagEditor = Class.extend({
|
|||
method: 'frappe.desk.tags.add_tag',
|
||||
args: me.get_args(tag),
|
||||
callback: function(r) {
|
||||
var user_tags = me.user_tags.split(",");
|
||||
var user_tags = me.user_tags ? me.user_tags.split(",") : [];
|
||||
user_tags.push(tag)
|
||||
me.user_tags = user_tags.join(",");
|
||||
me.on_change && me.on_change(me.user_tags);
|
||||
|
|
|
|||
|
|
@ -560,6 +560,10 @@ frappe.views.CommunicationComposer = Class.extend({
|
|||
if(last_email) {
|
||||
var last_email_content = last_email.original_comment || last_email.content;
|
||||
|
||||
last_email_content = last_email_content
|
||||
.replace(/<meta[\s\S]*meta>/g, '') // remove <meta> tags
|
||||
.replace(/<style[\s\S]*<\/style>/g, ''); // // remove <style> tags
|
||||
|
||||
content = '<div><br></div>'
|
||||
+ reply
|
||||
+ "<br><!-- original-reply --><br>"
|
||||
|
|
|
|||
|
|
@ -534,7 +534,11 @@ frappe.views.QueryReport = Class.extend({
|
|||
col.field = df.fieldname || df.label;
|
||||
df.label = __(df.label);
|
||||
col.name = col.id = col.label = df.label;
|
||||
|
||||
|
||||
if(df.width < 0) {
|
||||
col.hidden = true;
|
||||
}
|
||||
|
||||
return col
|
||||
}));
|
||||
},
|
||||
|
|
@ -604,6 +608,7 @@ frappe.views.QueryReport = Class.extend({
|
|||
|
||||
var me = this;
|
||||
this.dataView.onRowCountChanged.subscribe(function (e, args) {
|
||||
me.update_totals_row();
|
||||
me.grid.updateRowCount();
|
||||
me.grid.render();
|
||||
});
|
||||
|
|
@ -613,8 +618,38 @@ frappe.views.QueryReport = Class.extend({
|
|||
me.grid.render();
|
||||
});
|
||||
},
|
||||
update_totals_row: function() {
|
||||
if(!this.report_doc.add_total_row) return;
|
||||
|
||||
const data_length = this.dataView.getLength();
|
||||
const last_index = data_length - 1;
|
||||
|
||||
const number_fields = ['Currency', 'Float', 'Int'];
|
||||
const fields = this.columns
|
||||
.filter(col => number_fields.includes(col.fieldtype))
|
||||
.map(col => col.field);
|
||||
|
||||
// reset numeric fields
|
||||
let updated_totals = Object.assign({}, this.dataView.getItem(last_index));
|
||||
fields.map(field => {
|
||||
updated_totals[field] = 0.0;
|
||||
});
|
||||
|
||||
// loop all the rows except the last Total row
|
||||
for (let i = 0; i < data_length - 1; i++) {
|
||||
const item = this.dataView.getItem(i);
|
||||
fields.map(field => {
|
||||
updated_totals[field] += item[field];
|
||||
});
|
||||
}
|
||||
this.dataView.updateItem(updated_totals.id, updated_totals);
|
||||
},
|
||||
inline_filter: function (item) {
|
||||
var me = frappe.container.page.query_report;
|
||||
if(me.report_doc.add_total_row) {
|
||||
// always show totals row
|
||||
if(Object.values(item).includes("'Total'")) return true;
|
||||
}
|
||||
for (var columnId in me.columnFilters) {
|
||||
if (columnId !== undefined && me.columnFilters[columnId] !== "") {
|
||||
var c = me.grid.getColumns()[me.grid.getColumnIndex(columnId)];
|
||||
|
|
@ -784,6 +819,16 @@ frappe.views.QueryReport = Class.extend({
|
|||
var cols = args.sortCols;
|
||||
|
||||
me.data.sort(function (dataRow1, dataRow2) {
|
||||
// Totals row should always be last
|
||||
if(me.report_doc.add_total_row) {
|
||||
if(Object.values(dataRow1).includes("'Total'")) {
|
||||
return 1;
|
||||
}
|
||||
if(Object.values(dataRow2).includes("'Total'")) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, l = cols.length; i < l; i++) {
|
||||
var field = cols[i].sortCol.field;
|
||||
var sign = cols[i].sortAsc ? 1 : -1;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@
|
|||
margin: 0px;
|
||||
padding: 10px 0px;
|
||||
border-bottom: 1px solid @border-color;
|
||||
|
||||
> div {
|
||||
padding-right: 0px;
|
||||
}
|
||||
> div:last-child {
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-inner-toolbar {
|
||||
|
|
@ -735,6 +742,16 @@ select.form-control {
|
|||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.control-code, .control-code.bold {
|
||||
height: 400px;
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
background-color: black;
|
||||
color: @light-yellow;
|
||||
font-size: 12px;
|
||||
line-height: 1.7em;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.delivery-status-indicator {
|
||||
display: inline-block;
|
||||
margin-top: -3px;
|
||||
|
|
|
|||
|
|
@ -63,4 +63,8 @@
|
|||
|
||||
.frappe-rtl .slick-wrapper {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.slick-cell > span[data-field="_comments"] * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import frappe
|
|||
from frappe import _
|
||||
from frappe.utils import flt, cint
|
||||
import json
|
||||
from six import string_types
|
||||
|
||||
no_cache = 1
|
||||
no_sitemap = 1
|
||||
|
|
@ -39,7 +40,7 @@ def get_api_key():
|
|||
def make_payment(razorpay_payment_id, options, reference_doctype, reference_docname):
|
||||
data = {}
|
||||
|
||||
if isinstance(options, basestring):
|
||||
if isinstance(options, string_types):
|
||||
data = json.loads(options)
|
||||
|
||||
data.update({
|
||||
|
|
|
|||
|
|
@ -61,8 +61,7 @@ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}"
|
|||
|
||||
{%- macro render_field_with_label(df, doc) -%}
|
||||
<div class="row {% if df.bold %}important{% endif %} data-field" {{ fieldmeta(df) }}>
|
||||
<div class="col-xs-{{ "9" if df.fieldtype=="Check" else "5" }}
|
||||
{%- if not doc._align_labels_left %} text-right{%- endif -%}">
|
||||
<div class="col-xs-{{ "9" if df.fieldtype=="Check" else "5" }}">
|
||||
{% if df.fieldtype not in ("Image","HTML","Check") and
|
||||
doc.get(df.fieldname) != None %}
|
||||
<label>{{ _(df.label) }}</label>
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
common style for whole page
|
||||
This should include:
|
||||
+ page size related settings
|
||||
+ font family settings
|
||||
+ line spacing settings
|
||||
*/
|
||||
.print-format div,
|
||||
.print-format span,
|
||||
.print-format td,
|
||||
.print-format h1,
|
||||
.print-format h2,
|
||||
.print-format h3,
|
||||
.print-format h4 {
|
||||
font-family: serif;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
.print-heading {
|
||||
text-align: right;
|
||||
text-transform: uppercase;
|
||||
color: #666;
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
}
|
||||
|
||||
.print-heading h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.print-format th {
|
||||
background-color: #eee !important;
|
||||
border-bottom: 0px !important;
|
||||
}
|
||||
|
||||
/* modern format: don't remove this line */
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
.print-format * {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.print-format .alert {
|
||||
background-color: inherit;
|
||||
border: 1px dashed #333;
|
||||
}
|
||||
|
||||
.print-format .table-bordered,
|
||||
.print-format .table-bordered > thead > tr > th,
|
||||
.print-format .table-bordered > tbody > tr > th,
|
||||
.print-format .table-bordered > tfoot > tr > th,
|
||||
.print-format .table-bordered > thead > tr > td,
|
||||
.print-format .table-bordered > tbody > tr > td,
|
||||
.print-format .table-bordered > tfoot > tr > td {
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.print-format hr {
|
||||
border-top: 1px solid #333;
|
||||
}
|
||||
|
||||
.print-heading {
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
|
|
@ -66,14 +66,22 @@ class TestFmtMoney(unittest.TestCase):
|
|||
def test_currency_precision(self):
|
||||
frappe.db.set_default("currency_precision", "4")
|
||||
frappe.db.set_default("number_format", "#,###.##")
|
||||
self.assertEquals(fmt_money(100), "100.0000")
|
||||
self.assertEquals(fmt_money(1000), "1,000.0000")
|
||||
self.assertEquals(fmt_money(10000), "10,000.0000")
|
||||
self.assertEquals(fmt_money(100000), "100,000.0000")
|
||||
self.assertEquals(fmt_money(1000000), "1,000,000.0000")
|
||||
self.assertEquals(fmt_money(10000000), "10,000,000.0000")
|
||||
self.assertEquals(fmt_money(100000000), "100,000,000.0000")
|
||||
self.assertEquals(fmt_money(1000000000), "1,000,000,000.0000")
|
||||
self.assertEquals(fmt_money(100), "100.00")
|
||||
self.assertEquals(fmt_money(1000), "1,000.00")
|
||||
self.assertEquals(fmt_money(10000), "10,000.00")
|
||||
self.assertEquals(fmt_money(100000), "100,000.00")
|
||||
self.assertEquals(fmt_money(1000000), "1,000,000.00")
|
||||
self.assertEquals(fmt_money(10000000), "10,000,000.00")
|
||||
self.assertEquals(fmt_money(100000000), "100,000,000.00")
|
||||
self.assertEquals(fmt_money(1000000000), "1,000,000,000.00")
|
||||
self.assertEquals(fmt_money(100.23), "100.23")
|
||||
self.assertEquals(fmt_money(1000.456), "1,000.456")
|
||||
self.assertEquals(fmt_money(10000.7890), "10,000.789")
|
||||
self.assertEquals(fmt_money(100000.1234), "100,000.1234")
|
||||
self.assertEquals(fmt_money(1000000.3456), "1,000,000.3456")
|
||||
self.assertEquals(fmt_money(10000000.3344567), "10,000,000.3345")
|
||||
self.assertEquals(fmt_money(100000000.37827268), "100,000,000.378")
|
||||
self.assertEquals(fmt_money(1000000000.2718272637), "1,000,000,000.27")
|
||||
frappe.db.set_default("currency_precision", "")
|
||||
|
||||
if __name__=="__main__":
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from frappe.permissions import (add_user_permission, remove_user_permission,
|
|||
get_valid_perms)
|
||||
from frappe.core.page.permission_manager.permission_manager import update, reset
|
||||
from frappe.test_runner import make_test_records_for_doctype
|
||||
from six import string_types
|
||||
|
||||
test_records = frappe.get_test_records('Blog Post')
|
||||
|
||||
|
|
@ -361,7 +362,7 @@ def set_user_permission_doctypes(doctypes, role, apply_user_permissions,
|
|||
user_permission_doctypes):
|
||||
user_permission_doctypes = None if not user_permission_doctypes else json.dumps(user_permission_doctypes)
|
||||
|
||||
if isinstance(doctypes, basestring):
|
||||
if isinstance(doctypes, string_types):
|
||||
doctypes = [doctypes]
|
||||
|
||||
for doctype in doctypes:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import unittest
|
||||
|
||||
from frappe.utils import evaluate_filters, money_in_words
|
||||
from frappe.utils import evaluate_filters, money_in_words, scrub_urls, get_url
|
||||
|
||||
class TestFilters(unittest.TestCase):
|
||||
def test_simple_dict(self):
|
||||
|
|
@ -57,4 +57,30 @@ class TestMoney(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
money_in_words(num[0], "NGN"), num[1], "{0} is not the same as {1}".
|
||||
format(money_in_words(num[0], "NGN"), num[1])
|
||||
)
|
||||
)
|
||||
|
||||
class TestDataManipulation(unittest.TestCase):
|
||||
def test_scrub_urls(self):
|
||||
html = '''
|
||||
<p>You have a new message from: <b>John</b></p>
|
||||
<p>Hey, wassup!</p>
|
||||
<div class="more-info">
|
||||
<a href="http://test.com">Test link 1</a>
|
||||
<a href="/about">Test link 2</a>
|
||||
<a href="login">Test link 3</a>
|
||||
<img src="/assets/frappe/test.jpg">
|
||||
</div>
|
||||
<div style="background-image: url('/assets/frappe/bg.jpg')">
|
||||
Please mail us at <a href="mailto:test@example.com">email</a>
|
||||
</div>
|
||||
'''
|
||||
|
||||
html = scrub_urls(html)
|
||||
url = get_url()
|
||||
|
||||
self.assertTrue('<a href="http://test.com">Test link 1</a>' in html)
|
||||
self.assertTrue('<a href="{0}/about">Test link 2</a>'.format(url) in html)
|
||||
self.assertTrue('<a href="{0}/login">Test link 3</a>'.format(url) in html)
|
||||
self.assertTrue('<img src="{0}/assets/frappe/test.jpg">'.format(url) in html)
|
||||
self.assertTrue('style="background-image: url(\'{0}/assets/frappe/bg.jpg\') !important"'.format(url) in html)
|
||||
self.assertTrue('<a href="mailto:test@example.com">email</a>' in html)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,12 @@ frappe.tests = {
|
|||
// Method to check the visibility of an element
|
||||
return $(`${tag}:contains("${text}")`).is(`:visible`);
|
||||
},
|
||||
/**
|
||||
* Clicks a button on a form.
|
||||
* @param {String} text - The button's text
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if a matching visible button is not found
|
||||
*/
|
||||
click_button: function(text) {
|
||||
let element = $(`.btn:contains("${text}"):visible`);
|
||||
if(!element.length) {
|
||||
|
|
@ -148,6 +154,12 @@ frappe.tests = {
|
|||
element.click();
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
/**
|
||||
* Clicks a link on a form.
|
||||
* @param {String} text - The text of the link to be clicked
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if a link with the given text is not found
|
||||
*/
|
||||
click_link: function(text) {
|
||||
let element = $(`a:contains("${text}"):visible`);
|
||||
if(!element.length) {
|
||||
|
|
@ -156,6 +168,13 @@ frappe.tests = {
|
|||
element.get(0).click();
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
/**
|
||||
* Sets the given control to the value given.
|
||||
* @param {String} fieldname - The Doctype's field name
|
||||
* @param {String} value - The value the control should be changed to
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if the field is not found or is not visible
|
||||
*/
|
||||
set_control: function(fieldname, value) {
|
||||
let control = $(`.form-control[data-fieldname="${fieldname}"]:visible`);
|
||||
if(!control.length) {
|
||||
|
|
@ -164,5 +183,18 @@ frappe.tests = {
|
|||
control.val(value).trigger('change');
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if given field is disabled.
|
||||
* @param {String} fieldname - The Doctype field name
|
||||
* @return {Boolean} true if condition is met
|
||||
* @throws will throw an exception if the field is not found or is not a form control
|
||||
*/
|
||||
is_disabled_field: function(fieldname){
|
||||
let control = $(`.form-control[data-fieldname="${fieldname}"]:disabled`);
|
||||
if(!control.length) {
|
||||
throw `did not find any control with fieldname ${fieldname}`;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue