Merge branch 'develop'
This commit is contained in:
commit
c837deff60
563 changed files with 67978 additions and 40430 deletions
|
|
@ -13,7 +13,8 @@ import os, sys, importlib, inspect, json
|
|||
from .exceptions import *
|
||||
from .utils.jinja import get_jenv, get_template, render_template
|
||||
|
||||
__version__ = "7.0.47"
|
||||
__version__ = '7.2.0'
|
||||
__title__ = "Frappe Framework"
|
||||
|
||||
local = Local()
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ def _(msg, lang=None):
|
|||
lang = local.lang
|
||||
|
||||
# msg should always be unicode
|
||||
msg = cstr(msg)
|
||||
msg = cstr(msg).strip()
|
||||
|
||||
return get_full_dict(local.lang).get(msg) or msg
|
||||
|
||||
|
|
@ -55,8 +56,6 @@ def get_lang_dict(fortype, name=None):
|
|||
|
||||
:param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot`
|
||||
:param name: name of the document for which assets are to be returned."""
|
||||
if local.lang=="en":
|
||||
return {}
|
||||
from frappe.translate import get_dict
|
||||
return get_dict(fortype, name)
|
||||
|
||||
|
|
@ -172,7 +171,9 @@ def get_site_config(sites_path=None, site_path=None):
|
|||
if os.path.exists(site_config):
|
||||
config.update(get_file_json(site_config))
|
||||
elif local.site and not local.flags.new_site:
|
||||
raise IncorrectSitePath, "{0} does not exist".format(site_config)
|
||||
print "{0} does not exist".format(local.site)
|
||||
sys.exit(1)
|
||||
#raise IncorrectSitePath, "{0} does not exist".format(site_config)
|
||||
|
||||
return _dict(config)
|
||||
|
||||
|
|
@ -273,7 +274,7 @@ def msgprint(msg, title=None, raise_exception=0, as_table=False, indicator=None,
|
|||
if as_table and type(msg) in (list, tuple):
|
||||
out.msg = '<table border="1px" style="border-collapse: collapse" cellpadding="2px">' + ''.join(['<tr>'+''.join(['<td>%s</td>' % c for c in r])+'</tr>' for r in msg]) + '</table>'
|
||||
|
||||
if flags.print_messages:
|
||||
if flags.print_messages and out.msg:
|
||||
print "Message: " + repr(out.msg).encode("utf-8")
|
||||
|
||||
if title:
|
||||
|
|
@ -488,7 +489,7 @@ def has_permission(doctype=None, ptype="read", doc=None, user=None, verbose=Fals
|
|||
|
||||
return out
|
||||
|
||||
def has_website_permission(doctype, ptype="read", doc=None, user=None, verbose=False):
|
||||
def has_website_permission(doc=None, ptype='read', user=None, verbose=False):
|
||||
"""Raises `frappe.PermissionError` if not permitted.
|
||||
|
||||
:param doctype: DocType for which permission is to be check.
|
||||
|
|
@ -499,11 +500,21 @@ def has_website_permission(doctype, ptype="read", doc=None, user=None, verbose=F
|
|||
if not user:
|
||||
user = session.user
|
||||
|
||||
hooks = (get_hooks("has_website_permission") or {}).get(doctype, [])
|
||||
if hooks:
|
||||
if doc:
|
||||
if isinstance(doc, basestring):
|
||||
doc = get_doc(doctype, doc)
|
||||
|
||||
doctype = doc.doctype
|
||||
|
||||
if doc.flags.ignore_permissions:
|
||||
return True
|
||||
|
||||
# check permission in controller
|
||||
if hasattr(doc, 'has_website_permission'):
|
||||
return doc.has_website_permission(ptype, verbose=verbose)
|
||||
|
||||
hooks = (get_hooks("has_website_permission") or {}).get(doctype, [])
|
||||
if hooks:
|
||||
for method in hooks:
|
||||
result = call(method, doc=doc, ptype=ptype, user=user, verbose=verbose)
|
||||
# if even a single permission check is Falsy
|
||||
|
|
@ -553,7 +564,7 @@ def new_doc(doctype, parent_doc=None, parentfield=None, as_dict=False):
|
|||
from frappe.model.create_new import get_new_doc
|
||||
return get_new_doc(doctype, parent_doc, parentfield, as_dict=as_dict)
|
||||
|
||||
def set_value(doctype, docname, fieldname, value):
|
||||
def set_value(doctype, docname, fieldname, value=None):
|
||||
"""Set document value. Calls `frappe.client.set_value`"""
|
||||
import frappe.client
|
||||
return frappe.client.set_value(doctype, docname, fieldname, value)
|
||||
|
|
@ -1113,7 +1124,7 @@ def as_json(obj, indent=1):
|
|||
return json.dumps(obj, indent=indent, sort_keys=True, default=json_handler)
|
||||
|
||||
def are_emails_muted():
|
||||
return flags.mute_emails or conf.get("mute_emails") or False
|
||||
return flags.mute_emails or int(conf.get("mute_emails") or 0) or False
|
||||
|
||||
def get_test_records(doctype):
|
||||
"""Returns list of objects from `test_records.json` in the given doctype's folder."""
|
||||
|
|
@ -1125,13 +1136,21 @@ def get_test_records(doctype):
|
|||
else:
|
||||
return []
|
||||
|
||||
def format_value(value, df, doc=None, currency=None):
|
||||
def format_value(*args, **kwargs):
|
||||
"""Format value with given field properties.
|
||||
|
||||
:param value: Value to be formatted.
|
||||
:param df: DocField object with properties `fieldtype`, `options` etc."""
|
||||
:param df: (Optional) DocField object with properties `fieldtype`, `options` etc."""
|
||||
import frappe.utils.formatters
|
||||
return frappe.utils.formatters.format_value(value, df, doc, currency=currency)
|
||||
return frappe.utils.formatters.format_value(*args, **kwargs)
|
||||
|
||||
def format(*args, **kwargs):
|
||||
"""Format value with given field properties.
|
||||
|
||||
:param value: Value to be formatted.
|
||||
:param df: (Optional) DocField object with properties `fieldtype`, `options` etc."""
|
||||
import frappe.utils.formatters
|
||||
return frappe.utils.formatters.format_value(*args, **kwargs)
|
||||
|
||||
def get_print(doctype=None, name=None, print_format=None, style=None, html=None, as_pdf=False, doc=None):
|
||||
"""Get Print Format for given document.
|
||||
|
|
@ -1241,7 +1260,12 @@ log_level = None
|
|||
def logger(module=None, with_more_info=True):
|
||||
'''Returns a python logger that uses StreamHandler'''
|
||||
from frappe.utils.logger import get_logger
|
||||
return get_logger(module or __name__, with_more_info=with_more_info)
|
||||
return get_logger(module or 'default', with_more_info=with_more_info)
|
||||
|
||||
def log_error(message=None, title=None):
|
||||
'''Log error to Error Log'''
|
||||
get_doc(dict(doctype='Error Log', error=str(message or get_traceback()),
|
||||
method=title)).insert(ignore_permissions=True)
|
||||
|
||||
def get_desk_link(doctype, name):
|
||||
return '<a href="#Form/{0}/{1}" style="font-weight: bold;">{2} {1}</a>'.format(doctype, name, _(doctype))
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import frappe.handler
|
|||
import frappe.client
|
||||
from frappe.utils.response import build_response
|
||||
from frappe import _
|
||||
from urlparse import urlparse
|
||||
from urllib import urlencode
|
||||
from frappe.integration_broker.oauth2 import oauth_server
|
||||
|
||||
def handle():
|
||||
"""
|
||||
|
|
@ -32,6 +35,27 @@ def handle():
|
|||
|
||||
`/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method
|
||||
"""
|
||||
|
||||
form_dict = frappe.local.form_dict
|
||||
authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
|
||||
if authorization_header and authorization_header[0].lower() == "bearer":
|
||||
token = authorization_header[1]
|
||||
r = frappe.request
|
||||
parsed_url = urlparse(r.url)
|
||||
access_token = { "access_token": token}
|
||||
uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
|
||||
http_method = r.method
|
||||
body = r.get_data()
|
||||
headers = r.headers
|
||||
|
||||
required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(";")
|
||||
|
||||
valid, oauthlib_request = oauth_server.verify_request(uri, http_method, body, headers, required_scopes)
|
||||
|
||||
if valid:
|
||||
frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user"))
|
||||
frappe.local.form_dict = form_dict
|
||||
|
||||
parts = frappe.request.path[1:].split("/",3)
|
||||
call = doctype = name = None
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ def application(request):
|
|||
raise NotFound
|
||||
|
||||
except HTTPException, e:
|
||||
frappe.logger().error('Request Error', exc_info=True)
|
||||
return e
|
||||
|
||||
except frappe.SessionStopped, e:
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class LoginManager:
|
|||
if not resume:
|
||||
frappe.response["full_name"] = self.full_name
|
||||
|
||||
# redirect information
|
||||
redirect_to = frappe.cache().hget('redirect_after_login', self.user)
|
||||
if redirect_to:
|
||||
frappe.local.response["redirect_to"] = redirect_to
|
||||
frappe.cache().hdel('redirect_after_login', self.user)
|
||||
|
||||
|
||||
frappe.local.cookie_manager.set_cookie("full_name", self.full_name)
|
||||
frappe.local.cookie_manager.set_cookie("user_id", self.user)
|
||||
frappe.local.cookie_manager.set_cookie("user_image", self.info.user_image or "")
|
||||
|
|
|
|||
|
|
@ -103,16 +103,18 @@ def get_allowed_pages():
|
|||
return page_info
|
||||
|
||||
def load_translations(bootinfo):
|
||||
if frappe.local.lang != 'en':
|
||||
messages = frappe.get_lang_dict("boot")
|
||||
messages = frappe.get_lang_dict("boot")
|
||||
|
||||
bootinfo["lang"] = frappe.lang
|
||||
bootinfo["lang"] = frappe.lang
|
||||
|
||||
# load translated report names
|
||||
for name in bootinfo.user.all_reports:
|
||||
messages[name] = frappe._(name)
|
||||
# load translated report names
|
||||
for name in bootinfo.user.all_reports:
|
||||
messages[name] = frappe._(name)
|
||||
|
||||
bootinfo["__messages"] = messages
|
||||
# only untranslated
|
||||
messages = {k:v for k, v in messages.iteritems() if k!=v}
|
||||
|
||||
bootinfo["__messages"] = messages
|
||||
|
||||
def get_fullnames():
|
||||
"""map of user fullnames"""
|
||||
|
|
@ -165,3 +167,9 @@ def load_print(bootinfo, doclist):
|
|||
|
||||
def load_print_css(bootinfo, print_settings):
|
||||
bootinfo.print_css = frappe.get_attr("frappe.www.print.get_print_style")(print_settings.print_style or "Modern", for_legacy=True)
|
||||
|
||||
def get_unseen_notes():
|
||||
return frappe.db.sql('''select name, title, content from tabNote where notify_on_login=1
|
||||
and expire_notification_on > %s and %s not in
|
||||
(select user from `tabNote Seen By` nsb
|
||||
where nsb.parent=tabNote.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True)
|
||||
|
|
@ -57,14 +57,19 @@ def make_asset_dirs(make_copy=False):
|
|||
# symlink app/public > assets/app
|
||||
for app_name in frappe.get_all_apps(True):
|
||||
pymodule = frappe.get_module(app_name)
|
||||
source = os.path.join(os.path.abspath(os.path.dirname(pymodule.__file__)), 'public')
|
||||
target = os.path.join(assets_path, app_name)
|
||||
app_base_path = os.path.abspath(os.path.dirname(pymodule.__file__))
|
||||
|
||||
if not os.path.exists(target) and os.path.exists(source):
|
||||
if make_copy:
|
||||
shutil.copytree(os.path.abspath(source), target)
|
||||
else:
|
||||
os.symlink(os.path.abspath(source), target)
|
||||
symlinks = []
|
||||
symlinks.append([os.path.join(app_base_path, 'public'), os.path.join(assets_path, app_name)])
|
||||
symlinks.append([os.path.join(app_base_path, 'docs'), os.path.join(assets_path, app_name + '_docs')])
|
||||
|
||||
for source, target in symlinks:
|
||||
source = os.path.abspath(source)
|
||||
if not os.path.exists(target) and os.path.exists(source):
|
||||
if make_copy:
|
||||
shutil.copytree(source, target)
|
||||
else:
|
||||
os.symlink(source, target)
|
||||
|
||||
def build(no_compress=False, verbose=False):
|
||||
assets_path = os.path.join(frappe.local.sites_path, "assets")
|
||||
|
|
@ -72,9 +77,6 @@ def build(no_compress=False, verbose=False):
|
|||
for target, sources in get_build_maps().iteritems():
|
||||
pack(os.path.join(assets_path, target), sources, no_compress, verbose)
|
||||
|
||||
shutil.copy(os.path.join(os.path.dirname(os.path.abspath(frappe.__file__)), 'data', 'languages.txt'), frappe.local.sites_path)
|
||||
# reset_app_html()
|
||||
|
||||
def get_build_maps():
|
||||
"""get all build.jsons with absolute paths"""
|
||||
# framework js and css files
|
||||
|
|
|
|||
24
frappe/change_log/v7/v7_1_0.md
Normal file
24
frappe/change_log/v7/v7_1_0.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#### Gantt View
|
||||
- New Gantt view for documents where date range is available
|
||||
|
||||
#### In-App Help
|
||||
- Search for help from within the app. Click on "Help"
|
||||
|
||||
#### Web Form
|
||||
- Add grids (child tables)
|
||||
- Add page breaks (for long forms)
|
||||
- Add payment gateway
|
||||
- Add attachments
|
||||
|
||||
#### Auto Email Report
|
||||
- Email reports automatically on daily / weekly / monthly basis
|
||||
|
||||
#### Other Fixes
|
||||
- Send a popup to all users on login for a new Note by checking on "Notify users with a popup when they log in"
|
||||
- Portal Users (Customers, Supplier, Students) can now have roles
|
||||
- Sidebar in portal view will be rendered as per roles and can be configured from Portal Settings
|
||||
- Restrict the number of backups to be saved in System Settings
|
||||
- Scheduler log is now error log and as MyISAM
|
||||
- A better way to export customzations and Email Alert directly from Customize Form
|
||||
- Option to send email from Data Import Tool where applicable
|
||||
- Integration Broker
|
||||
|
|
@ -47,22 +47,32 @@ def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False):
|
|||
return frappe.db.get_value(doctype, filters, fieldname, as_dict=as_dict, debug=debug)
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_value(doctype, name, fieldname, value):
|
||||
def set_value(doctype, name, fieldname, value=None):
|
||||
'''Set a value using get_doc, group of values
|
||||
|
||||
:param doctype: DocType of the document
|
||||
:param name: name of the document
|
||||
:param fieldname: fieldname string or JSON / dict with key value pair
|
||||
:param value: value if fieldname is JSON / dict'''
|
||||
|
||||
if fieldname!="idx" and fieldname in frappe.model.default_fields:
|
||||
frappe.throw(_("Cannot edit standard fields"))
|
||||
|
||||
if not value:
|
||||
values = fieldname
|
||||
if isinstance(fieldname, basestring):
|
||||
values = json.loads(fieldname)
|
||||
else:
|
||||
values = {fieldname: value}
|
||||
|
||||
doc = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True)
|
||||
if doc and doc.parent and doc.parenttype:
|
||||
doc = frappe.get_doc(doc.parenttype, doc.parent)
|
||||
child = doc.getone({"doctype": doctype, "name": name})
|
||||
child.set(fieldname, value)
|
||||
child.update(values)
|
||||
else:
|
||||
doc = frappe.get_doc(doctype, name)
|
||||
df = doc.meta.get_field(fieldname)
|
||||
if df.fieldtype == "Read Only" or df.read_only:
|
||||
frappe.throw(_("Can not edit Read Only fields"))
|
||||
else:
|
||||
doc.set(fieldname, value)
|
||||
doc.update(values)
|
||||
|
||||
doc.save()
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ def build_docs(context, app, docs_version="current", target=None, local=False, w
|
|||
or "docs.py" in source_path):
|
||||
_build_docs_once(site, app, docs_version, target, local, only_content_updated=True)
|
||||
|
||||
apps_path = frappe.get_app_path("frappe", "..", "..")
|
||||
apps_path = frappe.get_app_path(app, "..", "..")
|
||||
start_watch(apps_path, handler=trigger_make)
|
||||
|
||||
def _build_docs_once(site, app, docs_version, target, local, only_content_updated=False):
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
|
|||
print "*** Scheduler is", scheduler_status, "***"
|
||||
|
||||
finally:
|
||||
os.remove(installing)
|
||||
if os.path.exists(installing):
|
||||
os.remove(installing)
|
||||
|
||||
frappe.destroy()
|
||||
|
||||
@click.command('restore')
|
||||
|
|
@ -238,6 +240,20 @@ def reload_doc(context, module, doctype, docname):
|
|||
finally:
|
||||
frappe.destroy()
|
||||
|
||||
@click.command('reload-doctype')
|
||||
@click.argument('doctype')
|
||||
@pass_context
|
||||
def reload_doctype(context, doctype):
|
||||
"Reload schema for a DocType"
|
||||
for site in context.sites:
|
||||
try:
|
||||
frappe.init(site=site)
|
||||
frappe.connect()
|
||||
frappe.reload_doctype(doctype, force=context.force)
|
||||
frappe.db.commit()
|
||||
finally:
|
||||
frappe.destroy()
|
||||
|
||||
|
||||
@click.command('use')
|
||||
@click.argument('site')
|
||||
|
|
@ -455,6 +471,7 @@ commands = [
|
|||
new_site,
|
||||
reinstall,
|
||||
reload_doc,
|
||||
reload_doctype,
|
||||
remove_from_installed_apps,
|
||||
restore,
|
||||
run_patch,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ def new_language(context, lang_code, app):
|
|||
frappe.translate.write_translations_file(app, lang_code)
|
||||
|
||||
print "File created at ./apps/{app}/{app}/translations/{lang_code}.csv".format(app=app, lang_code=lang_code)
|
||||
print "You will need to add the language in frappe/data/languages.txt, if you haven't done it already."
|
||||
print "You will need to add the language in frappe/geo/languages.json, if you haven't done it already."
|
||||
|
||||
@click.command('get-untranslated')
|
||||
@click.argument('lang')
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ def export_json(context, doctype, path, name=None):
|
|||
@click.argument('path')
|
||||
@pass_context
|
||||
def export_csv(context, doctype, path):
|
||||
"Export data import template for DocType"
|
||||
"Export data import template with data for DocType"
|
||||
from frappe.core.page.data_import_tool import data_import_tool
|
||||
for site in context.sites:
|
||||
try:
|
||||
|
|
@ -200,6 +200,13 @@ def export_fixtures(context):
|
|||
def import_doc(context, path, force=False):
|
||||
"Import (insert/update) doclist. If the argument is a directory, all files ending with .json are imported"
|
||||
from frappe.core.page.data_import_tool import data_import_tool
|
||||
|
||||
if not os.path.exists(path):
|
||||
path = os.path.join('..', path)
|
||||
if not os.path.exists(path):
|
||||
print 'Invalid path {0}'.format(path)
|
||||
sys.exit(1)
|
||||
|
||||
for site in context.sites:
|
||||
try:
|
||||
frappe.init(site=site)
|
||||
|
|
@ -213,13 +220,21 @@ def import_doc(context, path, force=False):
|
|||
@click.option('--only-insert', default=False, is_flag=True, help='Do not overwrite existing records')
|
||||
@click.option('--submit-after-import', default=False, is_flag=True, help='Submit document after importing it')
|
||||
@click.option('--ignore-encoding-errors', default=False, is_flag=True, help='Ignore encoding errors while coverting to unicode')
|
||||
@click.option('--no-email', default=True, is_flag=True, help='Send email if applicable')
|
||||
|
||||
@pass_context
|
||||
def import_csv(context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False):
|
||||
def import_csv(context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False, no_email=True):
|
||||
"Import CSV using data import tool"
|
||||
from frappe.core.page.data_import_tool import importer
|
||||
from frappe.utils.csvutils import read_csv_content
|
||||
site = get_site(context)
|
||||
|
||||
if not os.path.exists(path):
|
||||
path = os.path.join('..', path)
|
||||
if not os.path.exists(path):
|
||||
print 'Invalid path {0}'.format(path)
|
||||
sys.exit(1)
|
||||
|
||||
with open(path, 'r') as csvfile:
|
||||
content = read_csv_content(csvfile.read())
|
||||
|
||||
|
|
@ -227,7 +242,7 @@ def import_csv(context, path, only_insert=False, submit_after_import=False, igno
|
|||
frappe.connect()
|
||||
|
||||
try:
|
||||
importer.upload(content, submit_after_import=submit_after_import,
|
||||
importer.upload(content, submit_after_import=submit_after_import, no_email=no_email,
|
||||
ignore_encoding_errors=ignore_encoding_errors, overwrite=not only_insert,
|
||||
via_console=True)
|
||||
frappe.db.commit()
|
||||
|
|
@ -284,8 +299,9 @@ def console(context):
|
|||
@click.option('--driver', help="For Travis")
|
||||
@click.option('--module', help="Run tests in a module")
|
||||
@click.option('--profile', is_flag=True, default=False)
|
||||
@click.option('--junit-xml-output', help="Destination file path for junit xml report")
|
||||
@pass_context
|
||||
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False):
|
||||
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False, junit_xml_output=False):
|
||||
"Run tests"
|
||||
import frappe.test_runner
|
||||
from frappe.utils import sel
|
||||
|
|
@ -299,7 +315,7 @@ def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None
|
|||
|
||||
try:
|
||||
ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests,
|
||||
force=context.force, profile=profile)
|
||||
force=context.force, profile=profile, junit_xml_output=junit_xml_output)
|
||||
if len(ret.failures) == 0 and len(ret.errors) == 0:
|
||||
ret = 0
|
||||
finally:
|
||||
|
|
@ -382,6 +398,47 @@ def get_version():
|
|||
if hasattr(module, "__version__"):
|
||||
print "{0} {1}".format(m, module.__version__)
|
||||
|
||||
|
||||
|
||||
@click.command('setup-global-help')
|
||||
@click.option('--mariadb_root_password')
|
||||
def setup_global_help(mariadb_root_password=None):
|
||||
'''setup help table in a separate database that will be
|
||||
shared by the whole bench and set `global_help_setup` as 1 in
|
||||
common_site_config.json'''
|
||||
|
||||
from frappe.installer import update_site_config
|
||||
|
||||
frappe.local.flags = frappe._dict()
|
||||
frappe.local.flags.in_setup_help = True
|
||||
frappe.local.flags.in_install = True
|
||||
frappe.local.lang = 'en'
|
||||
frappe.local.conf = frappe.get_site_config(sites_path='.')
|
||||
|
||||
update_site_config('global_help_setup', 1,
|
||||
site_config_path=os.path.join('.', 'common_site_config.json'))
|
||||
|
||||
if mariadb_root_password:
|
||||
frappe.local.conf.root_password = mariadb_root_password
|
||||
|
||||
from frappe.utils.help import sync
|
||||
sync()
|
||||
|
||||
@click.command('setup-help')
|
||||
@pass_context
|
||||
def setup_help(context):
|
||||
'''Setup help table in the current site (called after migrate)'''
|
||||
from frappe.utils.help import sync
|
||||
|
||||
for site in context.sites:
|
||||
try:
|
||||
frappe.init(site)
|
||||
frappe.connect()
|
||||
sync()
|
||||
finally:
|
||||
frappe.destroy()
|
||||
|
||||
|
||||
commands = [
|
||||
build,
|
||||
clear_cache,
|
||||
|
|
@ -406,4 +463,6 @@ commands = [
|
|||
watch,
|
||||
_bulk_rename,
|
||||
add_to_email_queue,
|
||||
setup_global_help,
|
||||
setup_help
|
||||
]
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ def get_data():
|
|||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Scheduler Log",
|
||||
"name": "Error Log",
|
||||
"description": _("Errors in Background Events"),
|
||||
},
|
||||
{
|
||||
|
|
@ -51,6 +51,11 @@ def get_data():
|
|||
"name": "Email Queue",
|
||||
"description": _("Background Email Queue"),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"label": _("Background Jobs"),
|
||||
"name": "background_jobs",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Error Snapshot",
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ def get_data():
|
|||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Scheduler Log",
|
||||
"name": "Error Log",
|
||||
"description": _("Log of error on automated events (scheduler).")
|
||||
},
|
||||
{
|
||||
|
|
@ -156,8 +156,8 @@ def get_data():
|
|||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Email Group Member",
|
||||
"description": _("Email Group Member List"),
|
||||
"name": "Auto Email Report",
|
||||
"description": _("Setup Reports to be emailed at regular intervals"),
|
||||
},
|
||||
]
|
||||
},
|
||||
|
|
@ -222,10 +222,19 @@ def get_data():
|
|||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Dropbox Backup",
|
||||
"description": _("Manage cloud backups on Dropbox"),
|
||||
"hide_count": True
|
||||
}
|
||||
"name": "Integration Service",
|
||||
"description": _("Centralize access to Integrations"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "OAuth Client",
|
||||
"description": _("Register OAuth Client App"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "OAuth Provider Settings",
|
||||
"description": _("Settings for OAuth Provider"),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "label_and_type",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -67,6 +69,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
|
|
@ -95,6 +98,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -121,6 +125,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -149,6 +154,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
|
|
@ -176,6 +182,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -202,6 +209,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "search_index",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -230,6 +238,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -256,6 +265,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bold",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -281,6 +291,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.fieldtype===\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -307,6 +318,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
|
|
@ -333,6 +345,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -356,6 +369,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.",
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Text",
|
||||
|
|
@ -383,6 +397,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -409,6 +424,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -433,6 +449,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
|
|
@ -459,6 +476,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -487,6 +505,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -513,6 +532,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -538,6 +558,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Do not allow user to change after set the first time",
|
||||
"fieldname": "set_only_once",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -563,6 +584,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_13",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -586,6 +608,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -615,6 +638,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "User permissions should not apply for this Link",
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -640,6 +664,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -668,6 +693,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -696,6 +722,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field",
|
||||
"fieldname": "ignore_xss_filter",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -722,6 +749,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "display",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -746,6 +774,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_filter",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -774,6 +803,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "no_copy",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -802,6 +832,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -830,6 +861,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -856,6 +888,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -880,6 +913,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -908,6 +942,35 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Columns",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_22",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -931,6 +994,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -959,6 +1023,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "oldfieldname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
|
|
@ -984,6 +1049,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "oldfieldtype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
|
|
@ -1016,7 +1082,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:25:57.882851",
|
||||
"modified": "2016-08-23 11:59:07.036627",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocField",
|
||||
|
|
@ -1026,5 +1092,5 @@
|
|||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "role_and_level",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -38,6 +39,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "role",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -67,6 +69,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Filter records based on User Permissions defined for a user",
|
||||
"fieldname": "apply_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -92,6 +95,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Apply this rule if the User is the Owner",
|
||||
"fieldname": "if_owner",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -118,6 +122,34 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "is_custom",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Custom",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -141,6 +173,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -170,6 +203,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "JSON list of DocTypes used to apply User Permissions. If empty, all linked DocTypes will be used to apply User Permissions.",
|
||||
"fieldname": "user_permission_doctypes",
|
||||
|
|
@ -196,6 +230,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -220,6 +255,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "read",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -249,6 +285,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "write",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -278,6 +315,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "create",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -307,6 +345,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "delete",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -332,6 +371,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -355,6 +395,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "submit",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -383,6 +424,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cancel",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -411,6 +453,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amend",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -439,6 +482,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "additional_permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -463,6 +507,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "report",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -490,6 +535,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "export",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -515,6 +561,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "import",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -539,6 +586,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "This role update User Permissions for a user",
|
||||
"fieldname": "set_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -564,6 +612,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -587,6 +636,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "share",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -613,6 +663,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "print",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -638,6 +689,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "email",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -670,7 +722,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:27:59.695670",
|
||||
"modified": "2016-09-29 08:07:20.450064",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocPerm",
|
||||
|
|
@ -679,5 +731,6 @@
|
|||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -19,9 +19,7 @@ class DocShare(Document):
|
|||
self.get_doc().run_method("validate_share", self)
|
||||
|
||||
def cascade_permissions_downwards(self):
|
||||
if self.share:
|
||||
self.write = 1
|
||||
if self.write:
|
||||
if self.share or self.write:
|
||||
self.read = 1
|
||||
|
||||
def get_doc(self):
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class TestDocShare(unittest.TestCase):
|
|||
self.assertTrue(self.event.has_permission())
|
||||
|
||||
def test_share_permission(self):
|
||||
frappe.share.add("Event", self.event.name, self.user, share=1)
|
||||
frappe.share.add("Event", self.event.name, self.user, write=1, share=1)
|
||||
|
||||
frappe.set_user(self.user)
|
||||
self.assertTrue(self.event.has_permission("share"))
|
||||
|
|
@ -60,14 +60,14 @@ class TestDocShare(unittest.TestCase):
|
|||
self.assertRaises(frappe.PermissionError, frappe.share.add, "Event", self.event.name, self.user)
|
||||
|
||||
frappe.set_user("Administrator")
|
||||
frappe.share.add("Event", self.event.name, self.user, share=1)
|
||||
frappe.share.add("Event", self.event.name, self.user, write=1, share=1)
|
||||
|
||||
# test not raises
|
||||
frappe.set_user(self.user)
|
||||
frappe.share.add("Event", self.event.name, "test1@example.com", share=1)
|
||||
frappe.share.add("Event", self.event.name, "test1@example.com", write=1, share=1)
|
||||
|
||||
def test_remove_share(self):
|
||||
frappe.share.add("Event", self.event.name, self.user, share=1)
|
||||
frappe.share.add("Event", self.event.name, self.user, write=1, share=1)
|
||||
|
||||
frappe.set_user(self.user)
|
||||
self.assertTrue(self.event.has_permission("share"))
|
||||
|
|
|
|||
|
|
@ -11,18 +11,25 @@
|
|||
// }
|
||||
// })
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
if(doc.__islocal && (user !== "Administrator" || !frappe.boot.developer_mode)) {
|
||||
cur_frm.set_value("custom", 1);
|
||||
cur_frm.toggle_enable("custom", 0);
|
||||
}
|
||||
frappe.ui.form.on('DocType', {
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.__islocal && (user !== "Administrator" || !frappe.boot.developer_mode)) {
|
||||
frm.set_value("custom", 1);
|
||||
frm.toggle_enable("custom", 0);
|
||||
}
|
||||
|
||||
if(!frappe.boot.developer_mode && !doc.custom) {
|
||||
// make the document read-only
|
||||
cur_frm.set_read_only();
|
||||
}
|
||||
}
|
||||
if(!frappe.boot.developer_mode && !frm.doc.custom) {
|
||||
// make the document read-only
|
||||
frm.set_read_only();
|
||||
}
|
||||
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.toggle_enable("engine", 0);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// for legacy... :)
|
||||
cur_frm.cscript.validate = function(doc, cdt, cdn) {
|
||||
doc.server_code_compiled = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@
|
|||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sb0",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -41,6 +43,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "module",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -68,6 +71,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Child Tables are shown as a Grid in other DocTypes.",
|
||||
"fieldname": "istable",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -95,6 +99,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"depends_on": "istable",
|
||||
"fieldname": "editable_grid",
|
||||
|
|
@ -122,6 +127,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Single Types have only one record no tables associated. Values are stored in tabSingles",
|
||||
"fieldname": "issingle",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -149,6 +155,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb01",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -172,6 +179,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "document_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -199,6 +207,36 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "InnoDB",
|
||||
"depends_on": "eval:!doc.issingle",
|
||||
"fieldname": "engine",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Database Engine",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "InnoDB\nMyISAM",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "icon",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -223,6 +261,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "custom",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -247,6 +286,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "beta",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -272,6 +312,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval: doc.image_field",
|
||||
"fieldname": "image_view",
|
||||
|
|
@ -299,6 +340,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "app",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
|
|
@ -323,6 +365,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fields_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -348,6 +391,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fields",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
|
|
@ -375,6 +419,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sb1",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -399,6 +444,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Naming Options:\n<ol><li><b>field:[fieldname]</b> - By Field</li><li><b>naming_series:</b> - By Naming Series (field called naming_series must be present</li><li><b>Prompt</b> - Prompt user for a name</li><li><b>[series]</b> - Series by prefix (separated by a dot); for example PRE.#####</li></ol>",
|
||||
"fieldname": "autoname",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -426,6 +472,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "name_case",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -453,6 +500,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -479,6 +527,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break",
|
||||
|
|
@ -503,6 +552,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"description": "Show this field as title",
|
||||
"fieldname": "title_field",
|
||||
|
|
@ -529,6 +579,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "search_fields",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -556,6 +607,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Must be of type \"Attach Image\"",
|
||||
"fieldname": "image_field",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -582,6 +634,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "modified",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"description": "",
|
||||
|
|
@ -609,6 +662,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "DESC",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "sort_order",
|
||||
|
|
@ -636,6 +690,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"description": "Comments and Communications will be associated with this linked document",
|
||||
"fieldname": "timeline_field",
|
||||
|
|
@ -663,6 +718,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "sb2",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -688,6 +744,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "permissions",
|
||||
"fieldtype": "Table",
|
||||
|
|
@ -716,6 +773,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "sb3",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -740,6 +798,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb30",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -764,6 +823,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_create",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -790,6 +850,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -816,6 +877,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_submittable",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -840,6 +902,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Allow Import via Data Import Tool",
|
||||
"fieldname": "allow_import",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -865,6 +928,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_rename",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -891,6 +955,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_dialog",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -917,6 +982,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "read_only_onload",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -943,6 +1009,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "max_attachments",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
|
|
@ -969,6 +1036,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb31",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -993,6 +1061,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hide_heading",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -1019,6 +1088,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hide_toolbar",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -1045,6 +1115,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_copy",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -1071,6 +1142,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "track_seen",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -1096,6 +1168,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "quick_entry",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -1122,6 +1195,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "default_print_format",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -1154,7 +1228,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-25 12:18:27.724194",
|
||||
"modified": "2016-10-13 01:13:58.133080",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocType",
|
||||
|
|
@ -1170,6 +1244,7 @@
|
|||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
|
|
@ -1190,6 +1265,7 @@
|
|||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ class DocType(Document):
|
|||
elif self.istable:
|
||||
self.allow_import = 0
|
||||
|
||||
self.validate_series()
|
||||
self.scrub_field_names()
|
||||
self.validate_series()
|
||||
self.validate_document_type()
|
||||
validate_fields(self)
|
||||
|
||||
|
|
@ -120,6 +120,12 @@ class DocType(Document):
|
|||
if not autoname and self.get("fields", {"fieldname":"naming_series"}):
|
||||
self.autoname = "naming_series:"
|
||||
|
||||
# validate field name if autoname field:fieldname is used
|
||||
if autoname and autoname.startswith('field:'):
|
||||
field = autoname.split(":")[1]
|
||||
if not field or field not in [ df.fieldname for df in self.fields ]:
|
||||
frappe.throw(_("Invalid fieldname '{0}' in autoname".format(field)))
|
||||
|
||||
if autoname and (not autoname.startswith('field:')) \
|
||||
and (not autoname.startswith('eval:')) \
|
||||
and (not autoname.lower() in ('prompt', 'hash')) \
|
||||
|
|
@ -593,8 +599,7 @@ def make_module_and_roles(doc, perm_fieldname="permissions"):
|
|||
|
||||
for role in list(set(roles)):
|
||||
if not frappe.db.exists("Role", role):
|
||||
r = frappe.get_doc({"doctype": "Role", "role_name": role})
|
||||
r.role_name = role
|
||||
r = frappe.get_doc(dict(doctype= "Role", role_name=role, desk_access=1))
|
||||
r.flags.ignore_mandatory = r.flags.ignore_permissions = True
|
||||
r.insert()
|
||||
except frappe.DoesNotExistError, e:
|
||||
|
|
|
|||
8
frappe/core/doctype/error_log/error_log.js
Normal file
8
frappe/core/doctype/error_log/error_log.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2016, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Error Log', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "SCHLOG.#####",
|
||||
"autoname": "Error-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-16 13:09:40",
|
||||
"custom": 0,
|
||||
|
|
@ -10,11 +10,14 @@
|
|||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
"editable_grid": 0,
|
||||
"engine": "MyISAM",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "seen",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -41,6 +44,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "method",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -48,7 +52,7 @@
|
|||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Method",
|
||||
"label": "Title",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
|
|
@ -65,6 +69,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "error",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
|
|
@ -97,10 +102,10 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-03 14:24:13.581374",
|
||||
"modified": "2016-10-06 03:29:47.810715",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Scheduler Log",
|
||||
"name": "Error Log",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
|
@ -113,6 +118,7 @@
|
|||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
21
frappe/core/doctype/error_log/error_log.py
Normal file
21
frappe/core/doctype/error_log/error_log.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, 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 ErrorLog(Document):
|
||||
def onload(self):
|
||||
if not self.seen:
|
||||
self.db_set('seen', 1)
|
||||
frappe.db.commit()
|
||||
|
||||
def set_old_logs_as_seen():
|
||||
# set logs as seen
|
||||
frappe.db.sql("""update `tabError Log` set seen=1
|
||||
where seen=0 and datediff(curdate(), creation) > 7""")
|
||||
|
||||
# clear old logs
|
||||
frappe.db.sql("""delete from `tabError Log` where datediff(curdate(), creation) > 30""")
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
frappe.listview_settings['Scheduler Log'] = {
|
||||
frappe.listview_settings['Error Log'] = {
|
||||
add_fields: ["seen"],
|
||||
get_indicator: function(doc) {
|
||||
if(cint(doc.seen)) {
|
||||
12
frappe/core/doctype/error_log/test_error_log.py
Normal file
12
frappe/core/doctype/error_log/test_error_log.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Error Log')
|
||||
|
||||
class TestErrorLog(unittest.TestCase):
|
||||
pass
|
||||
|
|
@ -3,15 +3,18 @@
|
|||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "",
|
||||
"beta": 0,
|
||||
"creation": "2012-12-12 11:19:22",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "file_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -38,6 +41,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.is_folder",
|
||||
"fieldname": "is_private",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -53,17 +57,18 @@
|
|||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "preview",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -89,6 +94,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "preview_html",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
|
|
@ -114,6 +120,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -138,6 +145,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "is_home_folder",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -164,6 +172,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_attachments_folder",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
|
|
@ -189,6 +198,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "file_size",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
|
|
@ -213,6 +223,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -237,6 +248,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.is_folder",
|
||||
"fieldname": "file_url",
|
||||
"fieldtype": "Code",
|
||||
|
|
@ -262,6 +274,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "thumbnail_url",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -287,6 +300,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "folder",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
|
|
@ -313,6 +327,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_folder",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -338,6 +353,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.is_folder",
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -363,6 +379,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "attached_to_doctype",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -388,6 +405,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -412,6 +430,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "attached_to_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -436,6 +455,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "content_hash",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
|
|
@ -460,6 +480,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
|
|
@ -485,6 +506,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
|
|
@ -510,6 +532,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
|
|
@ -536,6 +559,7 @@
|
|||
"hide_toolbar": 0,
|
||||
"icon": "icon-file",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
|
|
@ -543,7 +567,7 @@
|
|||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-02-22 09:23:59.892258",
|
||||
"modified": "2016-09-21 12:23:34.017457",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "File",
|
||||
|
|
@ -590,7 +614,10 @@
|
|||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"title_field": "file_name"
|
||||
"sort_order": "ASC",
|
||||
"title_field": "file_name",
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import frappe
|
|||
import json
|
||||
import urllib
|
||||
import os
|
||||
import shutil
|
||||
import requests
|
||||
import requests.exceptions
|
||||
import StringIO
|
||||
|
|
@ -72,6 +73,23 @@ class File(NestedSet):
|
|||
|
||||
self.set_folder_size()
|
||||
|
||||
if frappe.db.exists('File', {'name': self.name, 'is_folder': 0}):
|
||||
if not self.is_folder and (self.is_private != self.db_get('is_private')):
|
||||
private_files = frappe.get_site_path('private', 'files')
|
||||
public_files = frappe.get_site_path('public', 'files')
|
||||
|
||||
if not self.is_private:
|
||||
shutil.move(os.path.join(private_files, self.file_name),
|
||||
os.path.join(public_files, self.file_name))
|
||||
|
||||
self.file_url = "/files/{0}".format(self.file_name)
|
||||
|
||||
else:
|
||||
shutil.move(os.path.join(public_files, self.file_name),
|
||||
os.path.join(private_files, self.file_name))
|
||||
|
||||
self.file_url = "/private/files/{0}".format(self.file_name)
|
||||
|
||||
def set_folder_size(self):
|
||||
"""Set folder size if folder"""
|
||||
if self.is_folder and not self.is_new():
|
||||
|
|
@ -350,4 +368,3 @@ def check_file_permission(file_url):
|
|||
return True
|
||||
|
||||
raise frappe.PermissionError
|
||||
|
||||
|
|
|
|||
8
frappe/core/doctype/language/language.js
Normal file
8
frappe/core/doctype/language/language.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2016, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Language', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
160
frappe/core/doctype/language/language.json
Normal file
160
frappe/core/doctype/language/language.json
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:language_code",
|
||||
"beta": 0,
|
||||
"creation": "2014-08-22 16:12:17.249590",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "language_code",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Language Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "language_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Language Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "flag",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Flag",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "based_on",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Based On",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Language",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-globe",
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-08-23 15:06:32.827148",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Language",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "language_name",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "language_name",
|
||||
"track_seen": 0
|
||||
}
|
||||
41
frappe/core/doctype/language/language.py
Normal file
41
frappe/core/doctype/language/language.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Language(Document):
|
||||
pass
|
||||
|
||||
def export_languages_json():
|
||||
'''Export list of all languages'''
|
||||
languages = frappe.db.get_all('Language', fields=['name', 'language_name'])
|
||||
languages = [{'name': d.language_name, 'code': d.name} for d in languages]
|
||||
|
||||
languages.sort(lambda a,b: 1 if a['code'] > b['code'] else -1)
|
||||
|
||||
with open(frappe.get_app_path('frappe', 'geo', 'languages.json'), 'w') as f:
|
||||
f.write(frappe.as_json(languages))
|
||||
|
||||
def sync_languages():
|
||||
'''Sync frappe/geo/languages.json with Language'''
|
||||
with open(frappe.get_app_path('frappe', 'geo', 'languages.json'), 'r') as f:
|
||||
data = json.loads(f.read())
|
||||
|
||||
for l in data:
|
||||
if not frappe.db.exists('Language', l['code']):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Language',
|
||||
'language_code': l['code'],
|
||||
'language_name': l['name']
|
||||
}).insert()
|
||||
|
||||
def update_language_names():
|
||||
'''Update frappe/geo/languages.json names (for use via patch)'''
|
||||
with open(frappe.get_app_path('frappe', 'geo', 'languages.json'), 'r') as f:
|
||||
data = json.loads(f.read())
|
||||
|
||||
for l in data:
|
||||
frappe.db.set_value('Language', l['code'], 'language_name', l['name'])
|
||||
12
frappe/core/doctype/language/test_language.py
Normal file
12
frappe/core/doctype/language/test_language.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Language')
|
||||
|
||||
class TestLanguage(unittest.TestCase):
|
||||
pass
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import os
|
||||
from frappe.model.document import Document
|
||||
from frappe.build import html_to_js_template
|
||||
from frappe.model.utils import render_include
|
||||
|
|
@ -49,15 +50,10 @@ class Page(Document):
|
|||
from frappe.core.doctype.doctype.doctype import make_module_and_roles
|
||||
make_module_and_roles(self, "roles")
|
||||
|
||||
if not frappe.flags.in_import and getattr(conf,'developer_mode', 0) and self.standard=='Yes':
|
||||
from frappe.modules.export_file import export_to_files
|
||||
from frappe.modules import get_module_path, scrub
|
||||
import os
|
||||
export_to_files(record_list=[['Page', self.name]])
|
||||
|
||||
# write files
|
||||
path = os.path.join(get_module_path(self.module), 'page', scrub(self.name), scrub(self.name))
|
||||
from frappe.modules.utils import export_module_json
|
||||
path = export_module_json(self, self.standard=='Yes', self.module)
|
||||
|
||||
if path:
|
||||
# js
|
||||
if not os.path.exists(path + '.js'):
|
||||
with open(path + '.js', 'w') as f:
|
||||
|
|
@ -132,6 +128,9 @@ class Page(Document):
|
|||
template = frappe.render_template(template, context)
|
||||
self.script = html_to_js_template(fname, template) + self.script
|
||||
|
||||
# flag for not caching this page
|
||||
self._dynamic_page = True
|
||||
|
||||
if frappe.lang != 'en':
|
||||
from frappe.translate import get_lang_js
|
||||
self.script += get_lang_js("page", self.name)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
from frappe import _
|
||||
import frappe.desk.query_report
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.modules.export_file import export_to_files
|
||||
|
|
@ -48,6 +50,40 @@ class Report(Document):
|
|||
make_boilerplate("controller.py", self, {"name": self.name})
|
||||
make_boilerplate("controller.js", self, {"name": self.name})
|
||||
|
||||
def get_data(self, filters=None, limit=None, user=None):
|
||||
'''Run the report'''
|
||||
out = []
|
||||
|
||||
if self.report_type in ('Query Report', 'Script Report'):
|
||||
# query and script reports
|
||||
data = frappe.desk.query_report.run(self.name, filters=filters, user=user)
|
||||
out.append([d.split(':')[0] for d in data.get('columns')])
|
||||
out += data.get('result')
|
||||
else:
|
||||
# standard report
|
||||
params = json.loads(self.json)
|
||||
columns = params.get('columns')
|
||||
filters = params.get('filters')
|
||||
|
||||
def _format(parts):
|
||||
# sort by is saved as DocType.fieldname, covert it to sql
|
||||
return '`tab{0}`.`{1}`'.format(*parts)
|
||||
|
||||
order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
|
||||
if params.get('sort_by_next'):
|
||||
order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next')
|
||||
|
||||
result = frappe.get_list(self.ref_doctype, fields = [_format([c[1], c[0]]) for c in columns],
|
||||
filters=filters, order_by = order_by, as_list=True, limit=limit, user=user)
|
||||
|
||||
meta = frappe.get_meta(self.ref_doctype)
|
||||
|
||||
out.append([meta.get_label(c[0]) for c in columns])
|
||||
out = out + [list(d) for d in result]
|
||||
|
||||
return out
|
||||
|
||||
|
||||
@Document.whitelist
|
||||
def toggle_disable(self, disable):
|
||||
self.db_set("disabled", cint(disable))
|
||||
|
|
|
|||
|
|
@ -1,10 +1,30 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json, os
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Report')
|
||||
|
||||
class TestReport(unittest.TestCase):
|
||||
pass
|
||||
def test_report_builder(self):
|
||||
if frappe.db.exists('Report', 'User Activity Report'):
|
||||
frappe.delete_doc('Report', 'User Activity Report')
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), 'user_activity_report.json'), 'r') as f:
|
||||
frappe.get_doc(json.loads(f.read())).insert()
|
||||
|
||||
report = frappe.get_doc('Report', 'User Activity Report')
|
||||
data = report.get_data()
|
||||
self.assertEquals(data[0][0], 'ID')
|
||||
self.assertEquals(data[0][1], 'User Type')
|
||||
self.assertTrue('Administrator' in [d[0] for d in data])
|
||||
|
||||
def test_query_report(self):
|
||||
report = frappe.get_doc('Report', 'Permitted Documents For User')
|
||||
data = report.get_data(filters={'user': 'Administrator', 'doctype': 'DocType'})
|
||||
self.assertEquals(data[0][0], 'Name')
|
||||
self.assertEquals(data[0][1], 'Module')
|
||||
self.assertTrue('User' in [d[0] for d in data])
|
||||
|
||||
|
|
|
|||
17
frappe/core/doctype/report/user_activity_report.json
Normal file
17
frappe/core/doctype/report/user_activity_report.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"is_standard": "No",
|
||||
"javascript": null,
|
||||
"json": "{\"filters\":[],\"columns\":[[\"name\",\"User\"],[\"user_type\",\"User\"],[\"first_name\",\"User\"],[\"last_name\",\"User\"],[\"last_active\",\"User\"],[\"role\",\"UserRole\"]],\"sort_by\":\"User.modified\",\"sort_order\":\"desc\",\"sort_by_next\":null,\"sort_order_next\":\"desc\"}",
|
||||
"modified": "2016-09-01 02:59:07.728890",
|
||||
"module": "Core",
|
||||
"name": "User Activity Report",
|
||||
"query": null,
|
||||
"ref_doctype": "User",
|
||||
"report_name": "User Activity Report",
|
||||
"report_type": "Report Builder"
|
||||
}
|
||||
|
|
@ -14,13 +14,14 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "role_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Role Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "If disabled, this role will be removed from all users.",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -61,6 +63,33 @@
|
|||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "desk_access",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Desk Access",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
|
|
@ -74,7 +103,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-25 05:24:24.406260",
|
||||
"modified": "2016-09-23 05:38:14.727541",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Role",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,22 @@
|
|||
[
|
||||
{
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role"
|
||||
},
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role",
|
||||
"desk_access": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role 2"
|
||||
},
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role 2",
|
||||
"desk_access": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role 3"
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role 3",
|
||||
"desk_access": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Role",
|
||||
"role_name": "_Test Role 4",
|
||||
"desk_access": 0
|
||||
}
|
||||
]
|
||||
|
|
@ -1 +0,0 @@
|
|||
Log exceptions (errors) raised when executing the scheduler.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Scheduler Log', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class SchedulerLog(Document):
|
||||
def onload(self):
|
||||
if not self.seen:
|
||||
self.seen = 1
|
||||
self.save()
|
||||
|
||||
def set_old_logs_as_seen():
|
||||
frappe.db.sql("""update `tabScheduler Log` set seen=1
|
||||
where seen=0 and datediff(curdate(), creation) > 7""")
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Scheduler Log')
|
||||
|
||||
class TestSchedulerLog(unittest.TestCase):
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
frappe.ui.form.on("System Settings", "refresh", function(frm) {
|
||||
frappe.setup_language_field(frm);
|
||||
frappe.call({
|
||||
method: "frappe.core.doctype.system_settings.system_settings.load",
|
||||
callback: function(data) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,6 +9,9 @@ import unittest
|
|||
from frappe import _
|
||||
|
||||
class TestTranslation(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.sql('delete from tabTranslation')
|
||||
|
||||
def tearDown(self):
|
||||
frappe.local.lang = 'en'
|
||||
frappe.local.lang_full_dict=None
|
||||
|
|
@ -19,21 +22,51 @@ class TestTranslation(unittest.TestCase):
|
|||
frappe.local.lang = key
|
||||
frappe.local.lang_full_dict=None
|
||||
translation = create_translation(key, val)
|
||||
self.assertEquals(_(translation.source_name), val[1])
|
||||
self.assertEquals(_(val[0]), val[1])
|
||||
|
||||
frappe.delete_doc('Translation', translation.name)
|
||||
frappe.local.lang_full_dict=None
|
||||
self.assertEquals(_(translation.source_name), val[0])
|
||||
|
||||
self.assertEquals(_(val[0]), val[0])
|
||||
|
||||
def test_parent_language(self):
|
||||
data = [
|
||||
['es', ['Test Data', 'datos de prueba']],
|
||||
['es', ['Test Spanish', 'prueba de español']],
|
||||
['es-MX', ['Test Data', 'pruebas de datos']]
|
||||
]
|
||||
|
||||
for key, val in data:
|
||||
create_translation(key, val)
|
||||
|
||||
frappe.local.lang = 'es'
|
||||
|
||||
frappe.local.lang_full_dict=None
|
||||
self.assertTrue(_(data[0][0]), data[0][1])
|
||||
|
||||
frappe.local.lang_full_dict=None
|
||||
self.assertTrue(_(data[1][0]), data[1][1])
|
||||
|
||||
frappe.local.lang = 'es-MX'
|
||||
|
||||
# different translation for es-MX
|
||||
frappe.local.lang_full_dict=None
|
||||
self.assertTrue(_(data[2][0]), data[2][1])
|
||||
|
||||
# from spanish (general)
|
||||
frappe.local.lang_full_dict=None
|
||||
self.assertTrue(_(data[1][0]), data[1][1])
|
||||
|
||||
def get_translation_data():
|
||||
html_source_data = """ <font color="#848484" face="arial, tahoma, verdana, sans-serif">
|
||||
<span style="font-size: 11px; line-height: 16.9px;">Test Data</span></font> """
|
||||
html_translated_data = """ <font color="#848484" face="arial, tahoma, verdana, sans-serif">
|
||||
html_source_data = """<font color="#848484" face="arial, tahoma, verdana, sans-serif">
|
||||
<span style="font-size: 11px; line-height: 16.9px;">Test Data</span></font>"""
|
||||
html_translated_data = """<font color="#848484" face="arial, tahoma, verdana, sans-serif">
|
||||
<span style="font-size: 11px; line-height: 16.9px;"> testituloksia </span></font>"""
|
||||
|
||||
return {'hr': ['Test data', 'Testdaten'],
|
||||
'ms': ['Test Data','ujian Data'],
|
||||
'et': ['Test Data', 'testandmed'],
|
||||
'es': ['Test Data', 'datos de prueba'],
|
||||
'en': ['Quotation', 'Tax Invoice'],
|
||||
'fi': [html_source_data, html_translated_data]}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@
|
|||
|
||||
|
||||
frappe.ui.form.on('Translation', {
|
||||
before_load: function(frm) {
|
||||
frappe.setup_language_field(frm);
|
||||
},
|
||||
language: function(frm) {
|
||||
frm.events.update_language_code(frm);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,70 +3,22 @@
|
|||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "",
|
||||
"beta": 0,
|
||||
"creation": "2016-02-17 12:21:16.175465",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "",
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Language",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "en",
|
||||
"fieldname": "language_code",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
|
|
@ -75,6 +27,7 @@
|
|||
"label": "Language Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Language",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
|
|
@ -90,6 +43,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -114,6 +68,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "If your data is in HTML, please copy paste the exact HTML code with the tags.",
|
||||
"fieldname": "source_name",
|
||||
"fieldtype": "Code",
|
||||
|
|
@ -140,6 +95,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -164,13 +120,14 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "target_name",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Translated",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
|
|
@ -189,13 +146,14 @@
|
|||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-04 15:42:07.020950",
|
||||
"modified": "2016-08-24 03:48:55.525143",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Translation",
|
||||
|
|
@ -223,9 +181,11 @@
|
|||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "language_code"
|
||||
"title_field": "source_name",
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -5,10 +5,11 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.translate import clear_cache
|
||||
|
||||
class Translation(Document):
|
||||
def on_update(self):
|
||||
frappe.cache().hdel('lang_user_translations', self.language_code)
|
||||
clear_cache()
|
||||
|
||||
def on_trash(self):
|
||||
frappe.cache().hdel('lang_user_translations', self.language_code)
|
||||
clear_cache()
|
||||
|
|
|
|||
|
|
@ -8,14 +8,36 @@ import requests
|
|||
from frappe.model.delete_doc import delete_doc
|
||||
from frappe.utils.data import today, add_to_date
|
||||
from frappe import _dict
|
||||
from frappe.limits import SiteExpiredError, update_limits, clear_limit
|
||||
from frappe.limits import update_limits, clear_limit
|
||||
from frappe.utils import get_url
|
||||
from frappe.installer import update_site_config
|
||||
from frappe.core.doctype.user.user import MaxUsersReachedError
|
||||
|
||||
test_records = frappe.get_test_records('User')
|
||||
|
||||
class TestUser(unittest.TestCase):
|
||||
def test_user_type(self):
|
||||
new_user = frappe.get_doc(dict(doctype='User', email='test-for-type@example.com',
|
||||
first_name='Tester')).insert()
|
||||
self.assertEquals(new_user.user_type, 'Website User')
|
||||
|
||||
# role with desk access
|
||||
new_user.add_roles('_Test Role 2')
|
||||
new_user.save()
|
||||
self.assertEquals(new_user.user_type, 'System User')
|
||||
|
||||
# clear role
|
||||
new_user.user_roles = []
|
||||
new_user.save()
|
||||
self.assertEquals(new_user.user_type, 'Website User')
|
||||
|
||||
# role without desk access
|
||||
new_user.add_roles('_Test Role 4')
|
||||
new_user.save()
|
||||
self.assertEquals(new_user.user_type, 'Website User')
|
||||
|
||||
frappe.delete_doc('User', new_user.name)
|
||||
|
||||
|
||||
def test_delete(self):
|
||||
frappe.get_doc("User", "test@example.com").add_roles("_Test Role 2")
|
||||
self.assertRaises(frappe.LinkExistsError, delete_doc, "Role", "_Test Role 2")
|
||||
|
|
@ -122,6 +144,7 @@ class TestUser(unittest.TestCase):
|
|||
clear_limit('users')
|
||||
|
||||
# def test_deny_multiple_sessions(self):
|
||||
# from frappe.installer import update_site_config
|
||||
# clear_limit('users')
|
||||
#
|
||||
# # allow one session
|
||||
|
|
@ -156,13 +179,18 @@ class TestUser(unittest.TestCase):
|
|||
# test_request(conn1)
|
||||
|
||||
def test_site_expiry(self):
|
||||
user = frappe.get_doc('User', 'test@example.com')
|
||||
user.enabled = 1
|
||||
user.new_password = 'testpassword'
|
||||
user.save()
|
||||
|
||||
update_limits({'expiry': add_to_date(today(), days=-1)})
|
||||
frappe.local.conf = _dict(frappe.get_site_config())
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
res = requests.post(get_url(), params={'cmd': 'login', 'usr': 'test@example.com', 'pwd': 'testpassword',
|
||||
'device': 'desktop'})
|
||||
res = requests.post(get_url(), params={'cmd': 'login', 'usr':
|
||||
'test@example.com', 'pwd': 'testpassword', 'device': 'desktop'})
|
||||
|
||||
# While site is expired status code returned is 417 Failed Expectation
|
||||
self.assertEqual(res.status_code, 417)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
frappe.ui.form.on('User', {
|
||||
before_load: function(frm) {
|
||||
frappe.setup_language_field(frm);
|
||||
|
||||
var update_tz_select = function(user_language) {
|
||||
frm.set_df_property("time_zone", "options", [""].concat(frappe.all_timezones));
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -38,17 +38,22 @@ class User(Document):
|
|||
[m.module_name for m in frappe.db.get_all('Desktop Icon',
|
||||
fields=['module_name'], filters={'standard': 1}, order_by="module_name")])
|
||||
|
||||
def before_insert(self):
|
||||
self.flags.in_insert = True
|
||||
|
||||
def after_insert(self):
|
||||
self.set_default_roles()
|
||||
|
||||
def validate(self):
|
||||
self.check_demo()
|
||||
|
||||
self.in_insert = self.get("__islocal")
|
||||
|
||||
# clear new password
|
||||
self.__new_password = self.new_password
|
||||
self.new_password = ""
|
||||
|
||||
if self.name not in STANDARD_USERS:
|
||||
self.validate_email_type(self.email)
|
||||
self.validate_email_type(self.name)
|
||||
self.add_system_manager_role()
|
||||
self.set_system_user()
|
||||
self.set_full_name()
|
||||
|
|
@ -70,6 +75,10 @@ class User(Document):
|
|||
frappe.clear_cache(user=self.name)
|
||||
self.send_password_notification(self.__new_password)
|
||||
|
||||
def has_website_permission(self, ptype, verbose=False):
|
||||
"""Returns true if current user is the session user"""
|
||||
return self.name == frappe.session.user
|
||||
|
||||
def check_demo(self):
|
||||
if frappe.session.user == 'demo@erpnext.com':
|
||||
frappe.throw('Cannot change user details in demo. Please signup for a new account at https://erpnext.com', title='Not Allowed')
|
||||
|
|
@ -89,6 +98,33 @@ class User(Document):
|
|||
if not cint(self.enabled) and getattr(frappe.local, "login_manager", None):
|
||||
frappe.local.login_manager.logout(user=self.name)
|
||||
|
||||
def set_default_roles(self):
|
||||
"""Set a default role if specified by rules (`default_role`) in hooks or Portal Settings
|
||||
|
||||
Hooks for default roles can be set as:
|
||||
|
||||
default_roles = [
|
||||
{'role': 'Customer', 'doctype':'Contact', 'email_field': 'email_id',
|
||||
'filters': {'ifnull(customer, "")': ('!=', '')}}
|
||||
]
|
||||
|
||||
"""
|
||||
role_found = False
|
||||
for rule in frappe.get_hooks('default_roles'):
|
||||
filters = {rule.get('email_field'): self.email}
|
||||
if rule.get('filters'):
|
||||
filters.update(rule.get('filters'))
|
||||
|
||||
match = frappe.get_all(rule.get('doctype'), filters=filters, limit=1)
|
||||
if match:
|
||||
role_found = True
|
||||
self.add_roles(rule.get('role'))
|
||||
|
||||
if not role_found:
|
||||
default_role = frappe.db.get_single_value('Portal Settings', 'default_role')
|
||||
if default_role:
|
||||
self.add_roles(default_role)
|
||||
|
||||
def add_system_manager_role(self):
|
||||
# if adding system manager, do nothing
|
||||
if not cint(self.enabled) or ("System Manager" in [user_role.role for user_role in
|
||||
|
|
@ -116,7 +152,7 @@ class User(Document):
|
|||
])
|
||||
|
||||
def email_new_password(self, new_password=None):
|
||||
if new_password and not self.in_insert:
|
||||
if new_password and not self.flags.in_insert:
|
||||
_update_password(self.name, new_password)
|
||||
|
||||
if self.send_password_update_notification:
|
||||
|
|
@ -124,14 +160,26 @@ class User(Document):
|
|||
frappe.msgprint(_("New password emailed"))
|
||||
|
||||
def set_system_user(self):
|
||||
if self.user_roles or self.name == 'Administrator':
|
||||
'''Set as System User if any of the given roles has desk_access'''
|
||||
if self.has_desk_access() or self.name == 'Administrator':
|
||||
self.user_type = 'System User'
|
||||
else:
|
||||
self.user_type = 'Website User'
|
||||
|
||||
def has_desk_access(self):
|
||||
'''Return true if any of the set roles has desk access'''
|
||||
if not self.user_roles:
|
||||
return False
|
||||
|
||||
return len(frappe.db.sql("""select name
|
||||
from `tabRole` where desk_access=1
|
||||
and name in ({0}) limit 1""".format(', '.join(['%s'] * len(self.user_roles))),
|
||||
[d.role for d in self.user_roles]))
|
||||
|
||||
|
||||
def share_with_self(self):
|
||||
if self.user_type=="System User":
|
||||
frappe.share.add(self.doctype, self.name, self.name, share=1,
|
||||
frappe.share.add(self.doctype, self.name, self.name, write=1, share=1,
|
||||
flags={"ignore_share_permission": True})
|
||||
else:
|
||||
frappe.share.remove(self.doctype, self.name, self.name,
|
||||
|
|
@ -147,7 +195,7 @@ class User(Document):
|
|||
|
||||
def send_password_notification(self, new_password):
|
||||
try:
|
||||
if self.in_insert:
|
||||
if self.flags.in_insert:
|
||||
if self.name not in STANDARD_USERS:
|
||||
if new_password:
|
||||
# new password given, no email required
|
||||
|
|
@ -155,12 +203,15 @@ class User(Document):
|
|||
|
||||
if not self.flags.no_welcome_mail and self.send_welcome_email:
|
||||
self.send_welcome_mail_to_user()
|
||||
msgprint(_("Welcome email sent"))
|
||||
self.flags.email_sent = 1
|
||||
if frappe.session.user != 'Guest':
|
||||
msgprint(_("Welcome email sent"))
|
||||
return
|
||||
else:
|
||||
self.email_new_password(new_password)
|
||||
|
||||
except frappe.OutgoingEmailError:
|
||||
print frappe.get_traceback()
|
||||
pass # email server not set, don't send email
|
||||
|
||||
|
||||
|
|
@ -458,6 +509,13 @@ def update_password(new_password, key=None, old_password=None):
|
|||
|
||||
user_doc, redirect_url = reset_user_data(user)
|
||||
|
||||
# get redirect url from cache
|
||||
redirect_to = frappe.cache().hget('redirect_after_login', user)
|
||||
if redirect_to:
|
||||
redirect_url = redirect_to
|
||||
frappe.cache().hdel('redirect_after_login', user)
|
||||
|
||||
|
||||
frappe.local.login_manager.login_as(user)
|
||||
|
||||
if user_doc.user_type == "System User":
|
||||
|
|
@ -517,7 +575,7 @@ def verify_password(password):
|
|||
frappe.local.login_manager.check_password(frappe.session.user, password)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def sign_up(email, full_name):
|
||||
def sign_up(email, full_name, redirect_to):
|
||||
user = frappe.db.get("User", {"email": email})
|
||||
if user:
|
||||
if user.disabled:
|
||||
|
|
@ -526,9 +584,12 @@ def sign_up(email, full_name):
|
|||
return _("Already Registered")
|
||||
else:
|
||||
if frappe.db.sql("""select count(*) from tabUser where
|
||||
HOUR(TIMEDIFF(CURRENT_TIMESTAMP, TIMESTAMP(modified)))=1""")[0][0] > 200:
|
||||
frappe.msgprint("Login is closed for sometime, please check back again in an hour.")
|
||||
raise Exception, "Too Many New Users"
|
||||
HOUR(TIMEDIFF(CURRENT_TIMESTAMP, TIMESTAMP(modified)))=1""")[0][0] > 300:
|
||||
|
||||
frappe.respond_as_web_page(_('Temperorily Disabled'),
|
||||
_('Too many users signed up recently, so the registration is disabled. Please try back in an hour'),
|
||||
http_status_code=429)
|
||||
|
||||
from frappe.utils import random_string
|
||||
user = frappe.get_doc({
|
||||
"doctype":"User",
|
||||
|
|
@ -540,7 +601,14 @@ def sign_up(email, full_name):
|
|||
})
|
||||
user.flags.ignore_permissions = True
|
||||
user.insert()
|
||||
return _("Registration Details Emailed.")
|
||||
|
||||
if redirect_to:
|
||||
frappe.cache().hset('redirect_after_login', user.name, redirect_to)
|
||||
|
||||
if user.flags.email_sent:
|
||||
return _("Please check your email for verification")
|
||||
else:
|
||||
return _("Please ask your administrator to verify your sign-up")
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def reset_password(user):
|
||||
|
|
@ -630,10 +698,10 @@ def has_permission(doc, user):
|
|||
# dont allow non Administrator user to view / edit Administrator user
|
||||
return False
|
||||
|
||||
def notifify_admin_access_to_system_manager(login_manager=None):
|
||||
def notify_admin_access_to_system_manager(login_manager=None):
|
||||
if (login_manager
|
||||
and login_manager.user == "Administrator"
|
||||
and frappe.local.conf.notifify_admin_access_to_system_manager):
|
||||
and frappe.local.conf.notify_admin_access_to_system_manager):
|
||||
|
||||
message = """<p>
|
||||
{dear_system_manager} <br><br>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import frappe
|
|||
def get_notification_config():
|
||||
return {
|
||||
"for_doctype": {
|
||||
"Scheduler Log": {"seen": 0},
|
||||
"Error Log": {"seen": 0},
|
||||
"Communication": {"status": "Open", "communication_type": "Communication"},
|
||||
"ToDo": "frappe.core.notifications.get_things_todo",
|
||||
"Event": "frappe.core.notifications.get_todays_events",
|
||||
|
|
|
|||
39
frappe/core/page/background_jobs/background_jobs.html
Normal file
39
frappe/core/page/background_jobs/background_jobs.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<div class="list-jobs">
|
||||
{% if jobs.length %}
|
||||
<table class="table table-bordered" style="table-layout: fixed;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%">Queue / Worker</th>
|
||||
<th>Job</th>
|
||||
<th style="width: 15%">Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for j in jobs %}
|
||||
<tr>
|
||||
<td><span class="indicator {{ j.color }}" title="{{ j.status }}">{{ j.queue.split(".").slice(-1)[0] }}</span></td>
|
||||
<td style="overflow: auto;">
|
||||
<div>
|
||||
{{ frappe.utils.encode_tags(j.job_name) }}
|
||||
</div>
|
||||
{% if j.exc_info %}
|
||||
<div>
|
||||
<pre>{{ frappe.utils.encode_tags(j.exc_info) }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="small">{{ j.creation }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
<span class="indicator green" style="margin-right: 20px;">Started</span>
|
||||
<span class="indicator orange" style="margin-right: 20px;">Queued</span>
|
||||
<span class="indicator red">Failed</span>
|
||||
</p>
|
||||
{% else %}
|
||||
<p class="text-muted">No pending or current jobs for this site</p>
|
||||
{% endif %}
|
||||
<p class="text-muted" style="margin-top: 30px;">Last refreshed {{ frappe.datetime.now_datetime() }}</p>
|
||||
</div>
|
||||
39
frappe/core/page/background_jobs/background_jobs.js
Normal file
39
frappe/core/page/background_jobs/background_jobs.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
frappe.pages['background_jobs'].on_page_load = function(wrapper) {
|
||||
var page = frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Background Jobs',
|
||||
single_column: true
|
||||
});
|
||||
|
||||
$(frappe.render_template('background_jobs_outer')).appendTo(page.body);
|
||||
page.content = $(page.body).find('.table-area');
|
||||
|
||||
frappe.pages.background_jobs.page = page;
|
||||
}
|
||||
|
||||
frappe.pages['background_jobs'].on_page_show = function(wrapper) {
|
||||
frappe.pages.background_jobs.refresh_jobs();
|
||||
}
|
||||
|
||||
frappe.pages.background_jobs.refresh_jobs = function() {
|
||||
var page = frappe.pages.background_jobs.page;
|
||||
|
||||
// don't call if already waiting for a response
|
||||
if(page.called) return;
|
||||
page.called = true;
|
||||
frappe.call({
|
||||
method: 'frappe.core.page.background_jobs.background_jobs.get_info',
|
||||
args: {
|
||||
show_failed: page.body.find('.show-failed').prop('checked') ? 1 : 0
|
||||
},
|
||||
callback: function(r) {
|
||||
page.called = false;
|
||||
page.body.find('.list-jobs').remove();
|
||||
$(frappe.render_template('background_jobs', {jobs:r.message || []})).appendTo(page.content);
|
||||
|
||||
if(frappe.get_route()[0]==='background_jobs') {
|
||||
frappe.background_jobs_timeout = setTimeout(frappe.pages.background_jobs.refresh_jobs, 2000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
22
frappe/core/page/background_jobs/background_jobs.json
Normal file
22
frappe/core/page/background_jobs/background_jobs.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"content": null,
|
||||
"creation": "2016-08-18 16:44:14.322642",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"idx": 0,
|
||||
"modified": "2016-08-18 16:48:11.577611",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "background_jobs",
|
||||
"owner": "Administrator",
|
||||
"page_name": "background_jobs",
|
||||
"roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
}
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"title": "Background Jobs"
|
||||
}
|
||||
51
frappe/core/page/background_jobs/background_jobs.py
Normal file
51
frappe/core/page/background_jobs/background_jobs.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from rq import Queue, Worker
|
||||
from frappe.utils.background_jobs import get_redis_conn
|
||||
from frappe.utils import format_datetime, cint
|
||||
|
||||
colors = {
|
||||
'queued': 'orange',
|
||||
'failed': 'red',
|
||||
'started': 'green'
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_info(show_failed=False):
|
||||
conn = get_redis_conn()
|
||||
queues = Queue.all(conn)
|
||||
workers = Worker.all(conn)
|
||||
jobs = []
|
||||
|
||||
def add_job(j, name):
|
||||
if j.kwargs.get('site')==frappe.local.site or True:
|
||||
jobs.append({
|
||||
'job_name': j.kwargs.get('kwargs', {}).get('playbook_method') \
|
||||
or str(j.kwargs.get('job_name')),
|
||||
'status': j.status, 'queue': name,
|
||||
'creation': format_datetime(j.created_at),
|
||||
'color': colors[j.status]
|
||||
})
|
||||
if j.exc_info:
|
||||
jobs[-1]['exc_info'] = j.exc_info
|
||||
|
||||
for w in workers:
|
||||
j = w.get_current_job()
|
||||
if j:
|
||||
add_job(j, w.name)
|
||||
|
||||
for q in queues:
|
||||
if q.name != 'failed':
|
||||
for j in q.get_jobs(): add_job(j, q.name)
|
||||
|
||||
if cint(show_failed):
|
||||
for q in queues:
|
||||
if q.name == 'failed':
|
||||
for j in q.get_jobs()[:10]: add_job(j, q.name)
|
||||
|
||||
|
||||
return jobs
|
||||
12
frappe/core/page/background_jobs/background_jobs_outer.html
Normal file
12
frappe/core/page/background_jobs/background_jobs_outer.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div style="padding: 20px;">
|
||||
<p>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" class="show-failed"> {{ __("Show failed jobs") }}
|
||||
</label>
|
||||
</div>
|
||||
</p>
|
||||
<div class="table-area">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -77,6 +77,12 @@
|
|||
{%= __("Ignore encoding errors.") %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="no_email" checked>
|
||||
{%= __("Do not send Emails.") %}
|
||||
</label>
|
||||
</div>
|
||||
<p>
|
||||
<button class="btn btn-sm btn-primary btn-import">Import</button>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -42,11 +42,15 @@ frappe.DataImportTool = Class.extend({
|
|||
if(me.doctype) {
|
||||
|
||||
// render select columns
|
||||
var doctype_list = [frappe.get_doc('DocType', me.doctype)];
|
||||
var parent_doctype = frappe.get_doc('DocType', me.doctype);
|
||||
parent_doctype["reqd"] = true;
|
||||
var doctype_list = [parent_doctype];
|
||||
|
||||
frappe.meta.get_table_fields(me.doctype).forEach(function(df) {
|
||||
doctype_list.push(frappe.get_doc('DocType', df.options));
|
||||
var d = frappe.get_doc('DocType', df.options);
|
||||
d["reqd"]=df.reqd;
|
||||
doctype_list.push(d);
|
||||
});
|
||||
|
||||
$(frappe.render_template("data_import_tool_columns", {doctype_list: doctype_list}))
|
||||
.appendTo(me.select_columns.empty());
|
||||
}
|
||||
|
|
@ -103,7 +107,8 @@ frappe.DataImportTool = Class.extend({
|
|||
return {
|
||||
submit_after_import: me.page.main.find('[name="submit_after_import"]').prop("checked"),
|
||||
ignore_encoding_errors: me.page.main.find('[name="ignore_encoding_errors"]').prop("checked"),
|
||||
overwrite: !me.page.main.find('[name="always_insert"]').prop("checked")
|
||||
overwrite: !me.page.main.find('[name="always_insert"]').prop("checked"),
|
||||
no_email: me.page.main.find('[name="no_email"]').prop("checked")
|
||||
}
|
||||
},
|
||||
args: {
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ def get_doctype_options():
|
|||
doctype = frappe.form_dict['doctype']
|
||||
return [doctype] + [d.options for d in frappe.get_meta(doctype).get_table_fields()]
|
||||
|
||||
def import_file_by_path(path, ignore_links=False, overwrite=False, submit=False, pre_process=None):
|
||||
def import_file_by_path(path, ignore_links=False, overwrite=False, submit=False, pre_process=None, no_email=True):
|
||||
from frappe.utils.csvutils import read_csv_content
|
||||
from frappe.core.page.data_import_tool.importer import upload
|
||||
print "Importing " + path
|
||||
with open(path, "r") as infile:
|
||||
upload(rows = read_csv_content(infile.read()), ignore_links=ignore_links, overwrite=overwrite,
|
||||
upload(rows = read_csv_content(infile.read()), ignore_links=ignore_links, no_email=no_email, overwrite=overwrite,
|
||||
submit_after_import=submit, pre_process=pre_process)
|
||||
|
||||
def export_csv(doctype, path):
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<div class="row">
|
||||
{% for f in doctype.fields %}
|
||||
{% if (frappe.model.no_value_type.indexOf(f.fieldtype)===-1) %}
|
||||
{% doctype.reqd||(f.reqd=0);%}
|
||||
<div class="col-sm-4">
|
||||
<div class="checkbox" style="margin: 5px 0px;">
|
||||
<label>
|
||||
|
|
|
|||
|
|
@ -16,19 +16,24 @@ from frappe.utils import cint, cstr, flt, getdate, get_datetime
|
|||
from frappe.core.page.data_import_tool.data_import_tool import get_data_keys
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, overwrite=None,
|
||||
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, no_email=True, overwrite=None,
|
||||
ignore_links=False, pre_process=None, via_console=False):
|
||||
"""upload data"""
|
||||
frappe.flags.mute_emails = True
|
||||
|
||||
frappe.flags.in_import = True
|
||||
|
||||
# extra input params
|
||||
params = json.loads(frappe.form_dict.get("params") or '{}')
|
||||
|
||||
|
||||
|
||||
if params.get("submit_after_import"):
|
||||
submit_after_import = True
|
||||
if params.get("ignore_encoding_errors"):
|
||||
ignore_encoding_errors = True
|
||||
if not params.get("no_email"):
|
||||
no_email = False
|
||||
|
||||
frappe.flags.mute_emails = no_email
|
||||
|
||||
from frappe.utils.csvutils import read_csv_content_from_uploaded_file
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ def get_roles_and_doctypes():
|
|||
istable=0 and
|
||||
name not in ('DocType') and
|
||||
exists(select * from `tabDocField` where parent=dt.name)""")],
|
||||
"roles": [d[0] for d in frappe.db.sql("""select name from tabRole where name not in
|
||||
('Administrator')""")]
|
||||
"roles": [d[0] for d in frappe.db.sql("""select name from tabRole where
|
||||
name != 'Administrator' and disabled=0""")]
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ frappe.query_reports["Permitted Documents For User"] = {
|
|||
return {
|
||||
"query": "frappe.core.report.permitted_documents_for_user.permitted_documents_for_user.query_doctypes",
|
||||
"filters": {
|
||||
"user": frappe.query_report.filters_by_name.user.get_value()
|
||||
"user": frappe.query_report_filters_by_name.user.get_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
frappe/core/web_form/edit_profile/edit_profile.js
Normal file
3
frappe/core/web_form/edit_profile/edit_profile.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
frappe.ready(function() {
|
||||
// bind events here
|
||||
})
|
||||
86
frappe/core/web_form/edit_profile/edit_profile.json
Normal file
86
frappe/core/web_form/edit_profile/edit_profile.json
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
"allow_comments": 0,
|
||||
"allow_delete": 0,
|
||||
"allow_edit": 1,
|
||||
"allow_multiple": 0,
|
||||
"breadcrumbs": "[{\"title\": _(\"My Account\"), \"route\": \"me\"}]",
|
||||
"creation": "2016-09-19 05:16:59.242754",
|
||||
"doc_type": "User",
|
||||
"docstatus": 0,
|
||||
"doctype": "Web Form",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"login_required": 1,
|
||||
"modified": "2016-09-24 04:31:41.920694",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "edit-profile",
|
||||
"owner": "Administrator",
|
||||
"published": 1,
|
||||
"route": "update-profile",
|
||||
"show_sidebar": 1,
|
||||
"sidebar_items": [],
|
||||
"success_message": "Profile updated successfully.",
|
||||
"success_url": "/me",
|
||||
"title": "Update Profile",
|
||||
"web_form_fields": [
|
||||
{
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "First Name",
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Middle Name (Optional)",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Last Name",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"fieldname": "user_image",
|
||||
"fieldtype": "Attach",
|
||||
"hidden": 0,
|
||||
"label": "User Image",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"label": "More Information",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Phone",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Language",
|
||||
"options": "Language",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
7
frappe/core/web_form/edit_profile/edit_profile.py
Normal file
7
frappe/core/web_form/edit_profile/edit_profile.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
# do your magic here
|
||||
pass
|
||||
|
|
@ -9,12 +9,14 @@
|
|||
"description": "Adds a custom script (client or server) to a DocType",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "dt",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -42,6 +44,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Client",
|
||||
"fieldname": "script_type",
|
||||
"fieldtype": "Select",
|
||||
|
|
@ -70,6 +73,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "script",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
|
|
@ -97,6 +101,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sample",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
|
|
@ -130,7 +135,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-25 05:24:24.245725",
|
||||
"modified": "2016-09-24 05:47:53.900418",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Custom Script",
|
||||
|
|
@ -177,7 +182,7 @@
|
|||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@
|
|||
frappe.provide("frappe.customize_form");
|
||||
|
||||
frappe.ui.form.on("Customize Form", {
|
||||
setup: function(frm) {
|
||||
frm.get_docfield("fields").allow_bulk_edit = 1;
|
||||
},
|
||||
onload: function(frm) {
|
||||
frappe.customize_form.add_fields_help(frm);
|
||||
|
||||
frm.set_query("doc_type", function() {
|
||||
return {
|
||||
translate_values: false,
|
||||
filters: [
|
||||
['DocType', 'issingle', '=', 0],
|
||||
['DocType', 'custom', '=', 0],
|
||||
|
|
@ -71,6 +75,28 @@ frappe.ui.form.on("Customize Form", {
|
|||
frm.add_custom_button(__('Reset to defaults'), function() {
|
||||
frappe.customize_form.confirm(__('Remove all customizations?'), frm);
|
||||
}, "icon-eraser", "btn-default");
|
||||
|
||||
if(frappe.boot.developer_mode) {
|
||||
frm.add_custom_button(__('Export Customizations'), function() {
|
||||
frappe.prompt(
|
||||
[
|
||||
{fieldtype:'Link', fieldname:'module', options:'Module Def',
|
||||
label: __('Module to Export')},
|
||||
{fieldtype:'Check', fieldname:'sync_on_migrate',
|
||||
label: __('Sync on Migrate'), 'default': 1},
|
||||
],
|
||||
function(data) {
|
||||
frappe.call({
|
||||
method: 'frappe.modules.utils.export_customizations',
|
||||
args: {
|
||||
doctype: frm.doc.doc_type,
|
||||
module: data.module,
|
||||
sync_on_migrate: data.sync_on_migrate
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// sort order select
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "doc_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "doc_type",
|
||||
"fieldname": "properties",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -65,6 +67,33 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Change Label (via Custom Translation)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "default_print_format",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -90,6 +119,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "max_attachments",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -115,6 +145,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_copy",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -139,6 +170,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "istable",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -164,6 +196,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "istable",
|
||||
"fieldname": "editable_grid",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -190,6 +223,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "quick_entry",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -216,6 +250,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: doc.image_field",
|
||||
"fieldname": "image_view",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -242,6 +277,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -266,6 +302,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Use this fieldname to generate title",
|
||||
"fieldname": "title_field",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -292,6 +329,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Must be of type \"Attach Image\"",
|
||||
"fieldname": "image_field",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -318,6 +356,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Fields separated by comma (,) will be included in the \"Search By\" list of Search dialog box",
|
||||
"fieldname": "search_fields",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -343,6 +382,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "doc_type",
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -368,6 +408,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sort_field",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -392,6 +433,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -416,6 +458,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sort_order",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -441,6 +484,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "doc_type",
|
||||
"description": "Customize Label, Print Hide, Default etc.",
|
||||
"fieldname": "fields_section_break",
|
||||
|
|
@ -467,6 +511,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fields",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
|
|
@ -500,7 +545,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-08 04:40:57.045612",
|
||||
"modified": "2016-09-16 02:36:09.171273",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Customize Form",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from __future__ import unicode_literals
|
|||
Thus providing a better UI from user perspective
|
||||
"""
|
||||
import frappe
|
||||
import frappe.translate
|
||||
from frappe import _
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
|
|
@ -54,7 +55,8 @@ docfield_properties = {
|
|||
'default': 'Text',
|
||||
'precision': 'Select',
|
||||
'read_only': 'Check',
|
||||
'length': 'Int'
|
||||
'length': 'Int',
|
||||
'columns': 'Int'
|
||||
}
|
||||
|
||||
allowed_fieldtype_change = (('Currency', 'Float', 'Percent'), ('Small Text', 'Data'),
|
||||
|
|
@ -83,8 +85,36 @@ class CustomizeForm(Document):
|
|||
new_d[property] = d.get(property)
|
||||
self.append("fields", new_d)
|
||||
|
||||
# load custom translation
|
||||
translation = self.get_name_translation()
|
||||
self.label = translation.target_name if translation else ''
|
||||
|
||||
# NOTE doc is sent to clientside by run_method
|
||||
|
||||
def get_name_translation(self):
|
||||
'''Get translation object if exists of current doctype name in the default language'''
|
||||
return frappe.get_value('Translation',
|
||||
{'source_name': self.doc_type, 'language_code': frappe.local.lang or 'en'},
|
||||
['name', 'target_name'], as_dict=True)
|
||||
|
||||
def set_name_translation(self):
|
||||
'''Create, update custom translation for this doctype'''
|
||||
current = self.get_name_translation()
|
||||
if current:
|
||||
if self.label and current!=self.label:
|
||||
frappe.db.set_value('Translation', current.name, 'target_name', self.label)
|
||||
frappe.translate.clear_cache()
|
||||
else:
|
||||
# clear translation
|
||||
frappe.delete_doc('Translation', current.name)
|
||||
|
||||
else:
|
||||
if self.label:
|
||||
frappe.get_doc(dict(doctype='Translation',
|
||||
source_name=self.doc_type,
|
||||
target_name=self.label,
|
||||
language_code=frappe.local.lang or 'en')).insert()
|
||||
|
||||
def clear_existing_doc(self):
|
||||
doc_type = self.doc_type
|
||||
|
||||
|
|
@ -101,10 +131,18 @@ class CustomizeForm(Document):
|
|||
if not self.doc_type:
|
||||
return
|
||||
|
||||
self.flags.update_db = False
|
||||
|
||||
self.set_property_setters()
|
||||
self.update_custom_fields()
|
||||
self.set_name_translation()
|
||||
validate_fields_for_doctype(self.doc_type)
|
||||
|
||||
if self.flags.update_db:
|
||||
from frappe.model.db_schema import updatedb
|
||||
updatedb(self.doc_type)
|
||||
|
||||
|
||||
frappe.msgprint(_("{0} updated").format(_(self.doc_type)))
|
||||
frappe.clear_cache(doctype=self.doc_type)
|
||||
self.fetch_to_customize()
|
||||
|
|
@ -117,7 +155,6 @@ class CustomizeForm(Document):
|
|||
self.make_property_setter(property=property, value=self.get(property),
|
||||
property_type=doctype_properties[property])
|
||||
|
||||
update_db = False
|
||||
for df in self.get("fields"):
|
||||
if df.get("__islocal"):
|
||||
continue
|
||||
|
|
@ -144,10 +181,10 @@ class CustomizeForm(Document):
|
|||
|
||||
elif property == "precision" and cint(df.get("precision")) > 6 \
|
||||
and cint(df.get("precision")) > cint(meta_df[0].get("precision")):
|
||||
update_db = True
|
||||
self.flags.update_db = True
|
||||
|
||||
elif property == "unique":
|
||||
update_db = True
|
||||
self.flags.update_db = True
|
||||
|
||||
elif (property == "read_only" and cint(df.get("read_only"))==0
|
||||
and frappe.db.get_value("DocField", {"parent": self.doc_type, "fieldname": df.fieldname}, "read_only")==1):
|
||||
|
|
@ -158,16 +195,14 @@ class CustomizeForm(Document):
|
|||
self.make_property_setter(property=property, value=df.get(property),
|
||||
property_type=docfield_properties[property], fieldname=df.fieldname)
|
||||
|
||||
if update_db:
|
||||
from frappe.model.db_schema import updatedb
|
||||
updatedb(self.doc_type)
|
||||
|
||||
def update_custom_fields(self):
|
||||
for i, df in enumerate(self.get("fields")):
|
||||
if df.get("__islocal"):
|
||||
self.add_custom_field(df, i)
|
||||
else:
|
||||
self.update_in_custom_field(df, i)
|
||||
if df.get("is_custom_field"):
|
||||
if not frappe.db.exists('Custom Field', {'dt': self.doc_type, 'fieldname': df.fieldname}):
|
||||
self.add_custom_field(df, i)
|
||||
self.flags.update_db = True
|
||||
else:
|
||||
self.update_in_custom_field(df, i)
|
||||
|
||||
self.delete_custom_fields()
|
||||
|
||||
|
|
@ -179,7 +214,8 @@ class CustomizeForm(Document):
|
|||
for property in docfield_properties:
|
||||
d.set(property, df.get(property))
|
||||
|
||||
d.insert_after = self.fields[i-1].fieldname
|
||||
if i!=0:
|
||||
d.insert_after = self.fields[i-1].fieldname
|
||||
d.idx = i
|
||||
|
||||
d.insert()
|
||||
|
|
@ -189,6 +225,7 @@ class CustomizeForm(Document):
|
|||
meta = frappe.get_meta(self.doc_type)
|
||||
meta_df = meta.get("fields", {"fieldname": df.fieldname})
|
||||
if not (meta_df and meta_df[0].get("is_custom_field")):
|
||||
# not a custom field
|
||||
return
|
||||
|
||||
custom_field = frappe.get_doc("Custom Field", meta_df[0].name)
|
||||
|
|
@ -202,15 +239,17 @@ class CustomizeForm(Document):
|
|||
changed = True
|
||||
|
||||
# check and update `insert_after` property
|
||||
insert_after = self.fields[i-1].fieldname
|
||||
if custom_field.insert_after != insert_after:
|
||||
custom_field.insert_after = insert_after
|
||||
custom_field.idx = i
|
||||
changed = True
|
||||
if i!=0:
|
||||
insert_after = self.fields[i-1].fieldname
|
||||
if custom_field.insert_after != insert_after:
|
||||
custom_field.insert_after = insert_after
|
||||
custom_field.idx = i
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
custom_field.flags.ignore_validate = True
|
||||
custom_field.save()
|
||||
custom_field.db_update()
|
||||
self.flags.update_db = True
|
||||
#custom_field.save()
|
||||
|
||||
def delete_custom_fields(self):
|
||||
meta = frappe.get_meta(self.doc_type)
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class TestCustomizeForm(unittest.TestCase):
|
|||
d.append("fields", {
|
||||
"label": "Test Add Custom Field Via Customize Form",
|
||||
"fieldtype": "Data",
|
||||
"__islocal": 1
|
||||
"is_custom_field": 1
|
||||
})
|
||||
d.run_method("save_customization")
|
||||
self.assertEquals(frappe.db.get_value("Custom Field",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "label_and_type",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -66,6 +68,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
|
|
@ -94,6 +97,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -120,6 +124,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -148,6 +153,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -173,6 +179,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -197,6 +204,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -221,6 +229,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
|
|
@ -249,6 +258,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -275,6 +285,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.",
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Text",
|
||||
|
|
@ -302,6 +313,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -327,6 +339,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18",
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
|
|
@ -354,6 +367,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
|
|
@ -381,6 +395,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -409,6 +424,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -434,6 +450,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -460,6 +477,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
|
|
@ -486,6 +504,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -510,6 +529,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -534,6 +554,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -560,6 +581,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -586,6 +608,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "display",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -611,6 +634,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -637,6 +661,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "in_filter",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -665,6 +690,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_21",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -689,6 +715,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -717,6 +744,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -743,6 +771,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -769,6 +798,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Print Width of the field, if the field is a column in a table",
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -796,6 +826,35 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:cur_frm.doc.istable",
|
||||
"description": "Number of columns for a field in a Grid (Total Columns in a grid should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Columns",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -824,6 +883,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_custom_field",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
|
|
@ -856,7 +916,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:27:58.928043",
|
||||
"modified": "2016-08-23 12:03:07.126339",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Customize Form Field",
|
||||
|
|
@ -865,5 +925,6 @@
|
|||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ CREATE TABLE `tabDocField` (
|
|||
`ignore_user_permissions` int(1) NOT NULL DEFAULT 0,
|
||||
`width` varchar(255) DEFAULT NULL,
|
||||
`print_width` varchar(255) DEFAULT NULL,
|
||||
`columns` int(11) NOT NULL DEFAULT 0,
|
||||
`default` text,
|
||||
`description` text,
|
||||
`in_filter` int(1) NOT NULL DEFAULT 0,
|
||||
|
|
@ -76,6 +77,7 @@ CREATE TABLE `tabDocPerm` (
|
|||
`permlevel` int(11) DEFAULT '0',
|
||||
`role` varchar(255) DEFAULT NULL,
|
||||
`match` varchar(255) DEFAULT NULL,
|
||||
`is_custom` int(1) NOT NULL DEFAULT 0,
|
||||
`read` int(1) NOT NULL DEFAULT 1,
|
||||
`write` int(1) NOT NULL DEFAULT 1,
|
||||
`create` int(1) NOT NULL DEFAULT 1,
|
||||
|
|
@ -144,6 +146,7 @@ CREATE TABLE `tabDocType` (
|
|||
`tag_fields` varchar(255) DEFAULT NULL,
|
||||
`subject` varchar(255) DEFAULT NULL,
|
||||
`_last_update` varchar(32) DEFAULT NULL,
|
||||
`engine` varchar(20) DEFAULT 'InnoDB',
|
||||
`default_print_format` varchar(255) DEFAULT NULL,
|
||||
`is_submittable` int(1) NOT NULL DEFAULT 0,
|
||||
`_user_tags` varchar(255) DEFAULT NULL,
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
ar العربية
|
||||
bg bǎlgarski
|
||||
bn বাংলা
|
||||
bo ལྷ་སའི་སྐད་
|
||||
bs bosanski
|
||||
ca català
|
||||
cs česky
|
||||
da dansk
|
||||
da-DK dansk (Danmark)
|
||||
de deutsch
|
||||
el ελληνικά
|
||||
en english
|
||||
es español
|
||||
es-PE Español (Perú)
|
||||
et eesti
|
||||
fa پارسی
|
||||
fi suomalainen
|
||||
fr français
|
||||
gu ગુજરાતી
|
||||
he עברית
|
||||
hi हिंदी
|
||||
hr hrvatski
|
||||
hu magyar
|
||||
id Indonesia
|
||||
is íslenska
|
||||
it italiano
|
||||
ja 日本語
|
||||
km ភាសាខ្មែរ
|
||||
kn ಕನ್ನಡ
|
||||
ko 한국의
|
||||
lv latviešu valoda
|
||||
mk македонски
|
||||
ml മലയാളം
|
||||
mr मराठी
|
||||
ms Melayu
|
||||
my မြန်မာ
|
||||
nl nederlands
|
||||
no norsk
|
||||
pl polski
|
||||
pt português
|
||||
pt-BR português brasileiro
|
||||
ro român
|
||||
ru русский
|
||||
sk slovenčina (Slovak)
|
||||
sl slovenščina (Slovene)
|
||||
sv svenska
|
||||
sq shqiptar
|
||||
sr српски
|
||||
ta தமிழ்
|
||||
te తెలుగు
|
||||
th ไทย
|
||||
tr Türk
|
||||
uk українська
|
||||
ur اردو
|
||||
vi việt
|
||||
zh-cn 簡體中文
|
||||
zh-tw 正體中文
|
||||
|
|
@ -108,7 +108,8 @@ def set_default(key, value, parent, parenttype="__default"):
|
|||
:param parent: Usually, **User** to whom the default belongs.
|
||||
:param parenttype: [optional] default is `__default`."""
|
||||
frappe.db.sql("""delete from `tabDefaultValue` where defkey=%s and parent=%s""", (key, parent))
|
||||
add_default(key, value, parent)
|
||||
if value != None:
|
||||
add_default(key, value, parent)
|
||||
|
||||
def add_default(key, value, parent, parenttype=None):
|
||||
d = frappe.get_doc({
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ def get(name):
|
|||
page = frappe.get_doc('Page', name)
|
||||
if page.is_permitted():
|
||||
page.load_assets()
|
||||
return page
|
||||
docs = frappe._dict(page.as_dict())
|
||||
if getattr(page, '_dynamic_page', None):
|
||||
docs['_dynamic_page'] = 1
|
||||
|
||||
return docs
|
||||
else:
|
||||
frappe.response['403'] = 1
|
||||
raise frappe.PermissionError, 'No read permission for Page %s' % \
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "document_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
|
|
@ -31,7 +32,7 @@
|
|||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "field",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -56,7 +58,7 @@
|
|||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
|
|
@ -65,6 +67,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "update_value",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
|
|
@ -81,15 +84,16 @@
|
|||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "SQL Conditions. Example: status=\"Open\"",
|
||||
"fieldname": "condition",
|
||||
"fieldtype": "Small Text",
|
||||
|
|
@ -114,8 +118,9 @@
|
|||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "500",
|
||||
"description": "Max 500 records at a time",
|
||||
"fieldname": "limit",
|
||||
|
|
@ -150,7 +155,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-15 06:24:42.575613",
|
||||
"modified": "2016-09-23 05:10:19.377701",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Bulk Update",
|
||||
|
|
@ -178,7 +183,7 @@
|
|||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
|
|
|
|||
|
|
@ -29,7 +29,12 @@ def update(doctype, field, value, condition='', limit=500):
|
|||
for i, d in enumerate(items):
|
||||
doc = frappe.get_doc(doctype, d)
|
||||
doc.set(field, value)
|
||||
doc.save()
|
||||
|
||||
try:
|
||||
doc.save()
|
||||
except Exception, e:
|
||||
frappe.msgprint(_("Validation failed for {0}").format(frappe.bold(doc.name)))
|
||||
raise e
|
||||
|
||||
frappe.publish_progress(float(i)*100/n,
|
||||
title = _('Updating Records'), doctype='Bulk Update', docname='Bulk Update')
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
import json
|
||||
import random
|
||||
from frappe.model.document import Document
|
||||
|
|
@ -81,6 +82,10 @@ def get_desktop_icons(user=None):
|
|||
# sort by idx
|
||||
user_icons.sort(lambda a, b: 1 if a.idx > b.idx else -1)
|
||||
|
||||
# translate
|
||||
for d in user_icons:
|
||||
if d.label: d.label = _(d.label)
|
||||
|
||||
frappe.cache().hset('desktop_icons', user, user_icons)
|
||||
|
||||
return user_icons
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import getdate, cint, add_months, date_diff, add_days, nowdate, get_datetime_str, cstr
|
||||
from frappe.utils import (getdate, cint, add_months, date_diff, add_days,
|
||||
nowdate, get_datetime_str, cstr, get_datetime)
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.user import get_enabled_system_users
|
||||
|
||||
|
|
@ -12,15 +13,14 @@ weekdays = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
|
|||
|
||||
class Event(Document):
|
||||
def validate(self):
|
||||
if self.starts_on and self.ends_on and self.starts_on > self.ends_on:
|
||||
if self.starts_on and self.ends_on and get_datetime(self.starts_on) > get_datetime(self.ends_on):
|
||||
frappe.msgprint(frappe._("Event end must be after start"), raise_exception=True)
|
||||
|
||||
if self.starts_on == self.ends_on:
|
||||
# this scenario doesn't make sense i.e. it starts and ends at the same second!
|
||||
self.ends_on = None
|
||||
|
||||
if self.starts_on and self.ends_on and int(date_diff(self.ends_on.split(" ")[0], self.starts_on.split(" ")[0])) > 0 \
|
||||
and self.repeat_on == "Every Day":
|
||||
if getdate(self.starts_on) == getdate(self.ends_on) and self.repeat_on == "Every Day":
|
||||
frappe.msgprint(frappe._("Every day events should finish on the same day."), raise_exception=True)
|
||||
|
||||
def get_permission_query_conditions(user):
|
||||
|
|
|
|||
3
frappe/desk/doctype/event/event_list.js
Normal file
3
frappe/desk/doctype/event/event_list.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
frappe.listview_settings['Event'] = {
|
||||
add_fields: ["starts_on", "ends_on"]
|
||||
}
|
||||
|
|
@ -26,11 +26,9 @@ frappe.ui.form.on("Note", {
|
|||
// hide all other fields
|
||||
$.each(frm.fields_dict, function(fieldname, field) {
|
||||
|
||||
if(fieldname !== "content"
|
||||
&& !in_list(["Section Break", "Column Break"], field.df.fieldtype)) {
|
||||
frm.set_df_property(fieldname, "hidden", editable ? 0: 1);
|
||||
}
|
||||
|
||||
if(fieldname !== "content") {
|
||||
frm.set_df_property(fieldname, "hidden", editable ? 0: 1);
|
||||
}
|
||||
})
|
||||
|
||||
// no label, description for content either
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"beta": 0,
|
||||
"creation": "2013-05-24 13:41:00",
|
||||
"custom": 0,
|
||||
"description": "Note is a free page where users can share documents / notes",
|
||||
"description": "",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -39,7 +40,8 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"description": "Everyone can read",
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "public",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
|
|
@ -64,6 +66,61 @@
|
|||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "public",
|
||||
"fieldname": "notify_on_login",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Notify users with a popup when they log in",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.notify_on_login && doc.public",
|
||||
"fieldname": "expire_notification_on",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Expire Notification On",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Help: To link to another record in the system, use \"#Form/Note/[Note Name]\" as the Link URL. (don't use \"http://\")",
|
||||
"fieldname": "content",
|
||||
"fieldtype": "Text Editor",
|
||||
|
|
@ -84,6 +141,59 @@
|
|||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "seen_by_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Seen By",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "seen_by",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Seen By Table",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Note Seen By",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
|
|
@ -97,7 +207,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-25 05:24:24.137761",
|
||||
"modified": "2016-08-30 00:28:57.094889",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Note",
|
||||
|
|
|
|||
|
|
@ -11,10 +11,23 @@ class Note(Document):
|
|||
import re
|
||||
self.name = re.sub("[%'\"#*?`]", "", self.title.strip())
|
||||
|
||||
def validate(self):
|
||||
if self.notify_on_login and not self.expire_notification_on:
|
||||
|
||||
# expire this notification in a week (default)
|
||||
self.expire_notification_on = frappe.utils.add_days(self.creation, 7)
|
||||
|
||||
def before_print(self):
|
||||
self.print_heading = self.name
|
||||
self.sub_heading = ""
|
||||
|
||||
@frappe.whitelist()
|
||||
def mark_as_seen(note):
|
||||
note = frappe.get_doc('Note', note)
|
||||
if frappe.session.user not in [d.user for d in note.seen_by]:
|
||||
note.append('seen_by', {'user': frappe.session.user})
|
||||
note.save()
|
||||
|
||||
def get_permission_query_conditions(user):
|
||||
if not user: user = frappe.session.user
|
||||
|
||||
|
|
|
|||
64
frappe/desk/doctype/note_seen_by/note_seen_by.json
Normal file
64
frappe/desk/doctype/note_seen_by/note_seen_by.json
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-08-29 05:29:16.726172",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-08-29 06:02:41.531341",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Note Seen By",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
||||
10
frappe/desk/doctype/note_seen_by/note_seen_by.py
Normal file
10
frappe/desk/doctype/note_seen_by/note_seen_by.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, 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 NoteSeenBy(Document):
|
||||
pass
|
||||
|
|
@ -79,7 +79,8 @@ class FormMeta(Meta):
|
|||
def _add_code(self, path, fieldname):
|
||||
js = get_js(path)
|
||||
if js:
|
||||
self.set(fieldname, (self.get(fieldname) or "") + "\n\n" + js)
|
||||
self.set(fieldname, (self.get(fieldname) or "")
|
||||
+ "\n\n/* Adding {0} */\n\n".format(path) + js)
|
||||
|
||||
def add_html_templates(self, path):
|
||||
if self.custom:
|
||||
|
|
@ -103,7 +104,7 @@ class FormMeta(Meta):
|
|||
custom = frappe.db.get_value("Custom Script", {"dt": self.name,
|
||||
"script_type": "Client"}, "script") or ""
|
||||
|
||||
self.set("__js", (self.get('__js') or '') + "\n\n" + custom)
|
||||
self.set("__js", (self.get('__js') or '') + "\n\n/* Appending Custom Script */\n\n" + custom)
|
||||
|
||||
def add_search_fields(self):
|
||||
"""add search fields found in the doctypes indicated by link fields' options"""
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ frappe.pages['backups'].on_page_load = function(wrapper) {
|
|||
single_column: true
|
||||
});
|
||||
|
||||
page.add_inner_button(__("Set Number of Backups"), function() {
|
||||
frappe.set_route('Form', 'System Settings');
|
||||
});
|
||||
|
||||
frappe.breadcrumbs.add("Setup");
|
||||
|
||||
$(frappe.render_template("backups")).appendTo(page.body.addClass("no-border"));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
from frappe.utils import get_site_path
|
||||
import frappe
|
||||
from frappe.utils import get_site_path, cint
|
||||
from frappe.utils.data import convert_utc_to_user_timezone
|
||||
import datetime
|
||||
|
||||
|
|
@ -17,9 +18,41 @@ def get_context(context):
|
|||
|
||||
path = get_site_path('private', 'backups')
|
||||
files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))]
|
||||
backup_limit = get_scheduled_backup_limit()
|
||||
|
||||
if len(files) > backup_limit:
|
||||
cleanup_old_backups(path, files, backup_limit)
|
||||
|
||||
files = [('/backups/' + _file,
|
||||
get_time(os.path.join(path, _file)),
|
||||
get_size(os.path.join(path, _file))) for _file in files]
|
||||
files.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
return {"files": files}
|
||||
|
||||
def get_scheduled_backup_limit():
|
||||
backup_limit = frappe.db.get_singles_value('System Settings', 'backup_limit')
|
||||
return cint(backup_limit)
|
||||
|
||||
def cleanup_old_backups(site_path, files, limit):
|
||||
backup_paths = []
|
||||
for f in files:
|
||||
_path = os.path.abspath(os.path.join(site_path, f))
|
||||
backup_paths.append(_path)
|
||||
|
||||
backup_paths = sorted(backup_paths, key=os.path.getctime)
|
||||
files_to_delete = len(backup_paths) - limit
|
||||
|
||||
for idx in range(0, files_to_delete):
|
||||
f = os.path.basename(backup_paths[idx])
|
||||
files.remove(f)
|
||||
|
||||
os.remove(backup_paths[idx])
|
||||
|
||||
def delete_downloadable_backups():
|
||||
path = get_site_path('private', 'backups')
|
||||
files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))]
|
||||
backup_limit = get_scheduled_backup_limit()
|
||||
|
||||
if len(files) > backup_limit:
|
||||
cleanup_old_backups(path, files, backup_limit)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue