Merge branch 'develop'
Conflicts: frappe/__init__.py setup.py
This commit is contained in:
commit
d9dcf132a1
129 changed files with 3269 additions and 1366 deletions
|
|
@ -16,7 +16,7 @@ import json
|
|||
|
||||
from .exceptions import *
|
||||
|
||||
__version__ = "4.0.0"
|
||||
__version__ = "4.0.1"
|
||||
|
||||
local = Local()
|
||||
|
||||
|
|
@ -215,12 +215,20 @@ def set_user(username):
|
|||
def get_request_header(key, default=None):
|
||||
return request.headers.get(key, default)
|
||||
|
||||
def sendmail(recipients=(), sender="", subject="No Subject", message="No Message", as_markdown=False):
|
||||
import frappe.utils.email_lib
|
||||
if as_markdown:
|
||||
frappe.utils.email_lib.sendmail_md(recipients, sender=sender, subject=subject, msg=message)
|
||||
def sendmail(recipients=(), sender="", subject="No Subject", message="No Message",
|
||||
as_markdown=False, bulk=False):
|
||||
|
||||
if bulk:
|
||||
import frappe.utils.email_lib.bulk
|
||||
frappe.utils.email_lib.bulk.send(recipients=recipients, sender=sender,
|
||||
subject=subject, message=message, add_unsubscribe_link=False)
|
||||
|
||||
else:
|
||||
frappe.utils.email_lib.sendmail(recipients, sender=sender, subject=subject, msg=message)
|
||||
import frappe.utils.email_lib
|
||||
if as_markdown:
|
||||
frappe.utils.email_lib.sendmail_md(recipients, sender=sender, subject=subject, msg=message)
|
||||
else:
|
||||
frappe.utils.email_lib.sendmail(recipients, sender=sender, subject=subject, msg=message)
|
||||
|
||||
logger = None
|
||||
whitelisted = []
|
||||
|
|
@ -540,13 +548,15 @@ def build_match_conditions(doctype, as_condition=True):
|
|||
import frappe.widgets.reportview
|
||||
return frappe.widgets.reportview.build_match_conditions(doctype, as_condition)
|
||||
|
||||
def get_list(doctype, filters=None, fields=None, docstatus=None,
|
||||
def get_list(doctype, filters=None, fields=None, or_filters=None, docstatus=None,
|
||||
group_by=None, order_by=None, limit_start=0, limit_page_length=None,
|
||||
as_list=False, debug=False, ignore_permissions=False):
|
||||
import frappe.model.db_query
|
||||
return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters, fields=fields, docstatus=docstatus,
|
||||
group_by=group_by, order_by=order_by, limit_start=limit_start, limit_page_length=limit_page_length,
|
||||
as_list=as_list, debug=debug, ignore_permissions=ignore_permissions)
|
||||
return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters,
|
||||
fields=fields, docstatus=docstatus, or_filters=or_filters,
|
||||
group_by=group_by, order_by=order_by, limit_start=limit_start,
|
||||
limit_page_length=limit_page_length, as_list=as_list, debug=debug,
|
||||
ignore_permissions=ignore_permissions)
|
||||
|
||||
run_query = get_list
|
||||
|
||||
|
|
|
|||
|
|
@ -44,11 +44,12 @@ def handle():
|
|||
elif call=="resource":
|
||||
if "run_method" in frappe.local.form_dict:
|
||||
doc = frappe.get_doc(doctype, name)
|
||||
doc.is_whitelisted(frappe.local.form_dict.run_method)
|
||||
|
||||
if frappe.local.request.method=="GET":
|
||||
if not doc.has_permission("read"):
|
||||
frappe.throw(_("Not permitted"), frappe.PermissionError)
|
||||
doc.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
|
||||
doc.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
|
||||
|
||||
if frappe.local.request.method=="POST":
|
||||
if not doc.has_permission("write"):
|
||||
|
|
@ -69,7 +70,7 @@ def handle():
|
|||
doc = frappe.get_doc(doctype, name)
|
||||
# Not checking permissions here because it's checked in doc.save
|
||||
doc.update(data)
|
||||
frappe.local.response.update({
|
||||
frappe.local.response.update({
|
||||
"data": doc.save().as_dict()
|
||||
})
|
||||
frappe.db.commit()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ def get_bootinfo():
|
|||
bootinfo.modules = {}
|
||||
for app in frappe.get_installed_apps():
|
||||
try:
|
||||
bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.data") or {})
|
||||
bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.get_data")() or {})
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -49,11 +49,8 @@ def setup_celery(app, conf):
|
|||
|
||||
if conf.celery_error_emails:
|
||||
app.conf.CELERY_SEND_TASK_ERROR_EMAILS = True
|
||||
app.conf.ADMINS = conf.celery_error_email_recepients
|
||||
if conf.mail_port:
|
||||
app.conf.EMAIL_PORT = conf.mail_port
|
||||
if conf.mail_server:
|
||||
app.conf.EMAIL_HOST = conf.mail_server
|
||||
for k, v in conf.celery_error_emails.iteritems():
|
||||
setattr(app.conf, k, v)
|
||||
|
||||
class SiteRouter(object):
|
||||
def route_for_task(self, task, args=None, kwargs=None):
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ def setup_test(parser):
|
|||
parser.add_argument("--tests", metavar="TEST FUNCTION", nargs="*",
|
||||
help="Run one or more specific test functions")
|
||||
parser.add_argument("--serve_test", action="store_true", help="Run development server for testing")
|
||||
parser.add_argument("--driver", nargs="?", help="Run selenium using given driver")
|
||||
|
||||
|
||||
def setup_utilities(parser):
|
||||
|
|
@ -231,6 +232,8 @@ def setup_utilities(parser):
|
|||
help="Clear cache, doctype cache and defaults")
|
||||
parser.add_argument("--reset_perms", default=False, action="store_true",
|
||||
help="Reset permissions for all doctypes")
|
||||
parser.add_argument("--clear_all_sessions", default=False, action="store_true",
|
||||
help="Clear sessions of all users (logs them out)")
|
||||
|
||||
# scheduler
|
||||
parser.add_argument("--run_scheduler", default=False, action="store_true",
|
||||
|
|
@ -307,7 +310,7 @@ def add_to_installed_apps(*apps):
|
|||
all_apps = frappe.get_all_apps(with_frappe=True)
|
||||
for each in apps:
|
||||
if each in all_apps:
|
||||
add_to_installed_apps(each)
|
||||
add_to_installed_apps(each, rebuild_sitemap=False)
|
||||
frappe.destroy()
|
||||
|
||||
@cmd
|
||||
|
|
@ -364,11 +367,7 @@ def latest(rebuild_website_config=True, quiet=False):
|
|||
|
||||
try:
|
||||
# run patches
|
||||
frappe.local.patch_log_list = []
|
||||
frappe.modules.patch_handler.run_all()
|
||||
if verbose:
|
||||
print "\n".join(frappe.local.patch_log_list)
|
||||
|
||||
# sync
|
||||
frappe.model.sync.sync_all(verbose=verbose)
|
||||
sync_fixtures()
|
||||
|
|
@ -381,9 +380,6 @@ def latest(rebuild_website_config=True, quiet=False):
|
|||
|
||||
frappe.translate.clear_cache()
|
||||
|
||||
except frappe.modules.patch_handler.PatchError:
|
||||
print "\n".join(frappe.local.patch_log_list)
|
||||
raise
|
||||
finally:
|
||||
frappe.destroy()
|
||||
|
||||
|
|
@ -399,9 +395,7 @@ def sync_all(force=False, quiet=False):
|
|||
def patch(patch_module, force=False):
|
||||
import frappe.modules.patch_handler
|
||||
frappe.connect()
|
||||
frappe.local.patch_log_list = []
|
||||
frappe.modules.patch_handler.run_single(patch_module, force=force)
|
||||
print "\n".join(frappe.local.patch_log_list)
|
||||
frappe.destroy()
|
||||
|
||||
@cmd
|
||||
|
|
@ -447,7 +441,6 @@ def backup(with_files=False, backup_path_db=None, backup_path_files=None, quiet=
|
|||
if with_files:
|
||||
print "files backup taken -", odb.backup_path_files, "- on", now()
|
||||
frappe.destroy()
|
||||
return odb
|
||||
|
||||
@cmd
|
||||
def move(dest_dir=None, site=None):
|
||||
|
|
@ -509,6 +502,14 @@ def clear_web():
|
|||
frappe.website.render.clear_cache()
|
||||
frappe.destroy()
|
||||
|
||||
@cmd
|
||||
def clear_all_sessions():
|
||||
import frappe.sessions
|
||||
frappe.connect()
|
||||
frappe.sessions.clear_all_sessions()
|
||||
frappe.db.commit()
|
||||
frappe.destroy()
|
||||
|
||||
@cmd
|
||||
def build_sitemap():
|
||||
from frappe.website import rebuild_config
|
||||
|
|
@ -705,11 +706,11 @@ def smtp_debug_server():
|
|||
os.execv(python, [python, '-m', "smtpd", "-n", "-c", "DebuggingServer", "localhost:25"])
|
||||
|
||||
@cmd
|
||||
def run_tests(app=None, module=None, doctype=None, verbose=False, tests=()):
|
||||
def run_tests(app=None, module=None, doctype=None, verbose=False, tests=(), driver=None):
|
||||
import frappe.test_runner
|
||||
from frappe.utils import sel
|
||||
|
||||
sel.start(verbose)
|
||||
sel.start(verbose, driver)
|
||||
|
||||
ret = 1
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,43 +1,50 @@
|
|||
from frappe import _
|
||||
|
||||
data = {
|
||||
"Calendar": {
|
||||
"color": "#2980b9",
|
||||
"icon": "icon-calendar",
|
||||
"label": _("Calendar"),
|
||||
"link": "Calendar/Event",
|
||||
"type": "view"
|
||||
},
|
||||
"Messages": {
|
||||
"color": "#9b59b6",
|
||||
"icon": "icon-comments",
|
||||
"label": _("Messages"),
|
||||
"link": "messages",
|
||||
"type": "page"
|
||||
},
|
||||
"To Do": {
|
||||
"color": "#f1c40f",
|
||||
"icon": "icon-check",
|
||||
"label": _("To Do"),
|
||||
"link": "List/ToDo",
|
||||
"doctype": "ToDo",
|
||||
"type": "list"
|
||||
},
|
||||
"Website": {
|
||||
"color": "#16a085",
|
||||
"icon": "icon-globe",
|
||||
"type": "module"
|
||||
},
|
||||
"Installer": {
|
||||
"color": "#888",
|
||||
"icon": "icon-download",
|
||||
"link": "applications",
|
||||
"type": "page",
|
||||
"label": _("Installer")
|
||||
},
|
||||
"Setup": {
|
||||
"color": "#bdc3c7",
|
||||
"icon": "icon-wrench",
|
||||
"type": "module"
|
||||
},
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
"Calendar": {
|
||||
"color": "#2980b9",
|
||||
"icon": "icon-calendar",
|
||||
"label": _("Calendar"),
|
||||
"link": "Calendar/Event",
|
||||
"type": "view"
|
||||
},
|
||||
"Messages": {
|
||||
"color": "#9b59b6",
|
||||
"icon": "icon-comments",
|
||||
"label": _("Messages"),
|
||||
"link": "messages",
|
||||
"type": "page"
|
||||
},
|
||||
"To Do": {
|
||||
"color": "#f1c40f",
|
||||
"icon": "icon-check",
|
||||
"label": _("To Do"),
|
||||
"link": "List/ToDo",
|
||||
"doctype": "ToDo",
|
||||
"type": "list"
|
||||
},
|
||||
"Website": {
|
||||
"color": "#16a085",
|
||||
"icon": "icon-globe",
|
||||
"type": "module"
|
||||
},
|
||||
"Installer": {
|
||||
"color": "#888",
|
||||
"icon": "icon-download",
|
||||
"link": "applications",
|
||||
"type": "page",
|
||||
"label": _("Installer")
|
||||
},
|
||||
"Setup": {
|
||||
"color": "#bdc3c7",
|
||||
"icon": "icon-wrench",
|
||||
"type": "module"
|
||||
},
|
||||
"Core": {
|
||||
"color": "#589494",
|
||||
"icon": "icon-cog",
|
||||
"type": "module",
|
||||
"system_manager": 1
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,193 +1,191 @@
|
|||
from frappe import _
|
||||
from frappe.widgets.moduleview import add_setup_section
|
||||
|
||||
data = [
|
||||
{
|
||||
"label": _("Users and Permissions"),
|
||||
"icon": "icon-group",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "User",
|
||||
"description": _("System and Website Users")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Role",
|
||||
"description": _("User Roles")
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "permission-manager",
|
||||
"label": "Permission Manager",
|
||||
"icon": "icon-lock",
|
||||
"description": _("Set Permissions on Document Types and Roles")
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "user-properties",
|
||||
"label": _("User Permission Restrictions"),
|
||||
"icon": "icon-user",
|
||||
"description": _("Set Defaults and Restrictions for Users")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "icon-wrench",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "System Settings",
|
||||
"label": _("System Settings"),
|
||||
"description": _("Language, Date and Time settings"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "modules_setup",
|
||||
"label": _("Show / Hide Modules"),
|
||||
"icon": "icon-upload",
|
||||
"description": _("Show or hide modules globally.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Naming Series",
|
||||
"description": _("Set numbering series for transactions."),
|
||||
"hide_count": True
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Data"),
|
||||
"icon": "icon-th",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "data-import-tool",
|
||||
"label": _("Import / Export Data"),
|
||||
"icon": "icon-upload",
|
||||
"description": _("Import / Export Data from .csv files.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Rename Tool",
|
||||
"description": _("Rename many items by uploading a .csv file."),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "File Data",
|
||||
"description": _("Manage uploaded files.")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Workflow"),
|
||||
"icon": "icon-random",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow",
|
||||
"description": _("Define workflows for forms.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow State",
|
||||
"description": _("States for workflow (e.g. Draft, Approved, Cancelled).")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow Action",
|
||||
"description": _("Actions for workflow (e.g. Approve, Cancel).")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Email"),
|
||||
"icon": "icon-envelope",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Outgoing Email Settings",
|
||||
"description": _("Set outgoing mail server.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Printing and Branding"),
|
||||
"icon": "icon-print",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Print Format",
|
||||
"description": _("Customized HTML Templates for printing transctions.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Customize"),
|
||||
"icon": "icon-glass",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Customize Form",
|
||||
"description": _("Change field properties (hide, readonly, permission etc.)"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Custom Field",
|
||||
"description": _("Add fields to forms.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Custom Script",
|
||||
"description": _("Add custom javascript to forms.")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("System"),
|
||||
"icon": "icon-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "applications",
|
||||
"label": _("Application Installer"),
|
||||
"description": _("Install Applications."),
|
||||
"icon": "icon-download"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Backup Manager",
|
||||
"label": _("Download Backup"),
|
||||
"onclick": "frappe.ui.toolbar.download_backup",
|
||||
"icon": "icon-download-alt",
|
||||
"description": _("Send download link of a recent backup to System Managers"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Social Login Keys",
|
||||
"description": _("Enter keys to enable login via Facebook, Google, GitHub."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Backup Manager",
|
||||
"description": _("Manage cloud backups on Dropbox"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Scheduler Log",
|
||||
"description": _("Log of error on automated events (scheduler).")
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
def get_data():
|
||||
out = list(data)
|
||||
add_setup_section(out, "frappe", "website", _("Website"), "icon-globe")
|
||||
return out
|
||||
data = [
|
||||
{
|
||||
"label": _("Users and Permissions"),
|
||||
"icon": "icon-group",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "User",
|
||||
"description": _("System and Website Users")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Role",
|
||||
"description": _("User Roles")
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "permission-manager",
|
||||
"label": "Permission Manager",
|
||||
"icon": "icon-lock",
|
||||
"description": _("Set Permissions on Document Types and Roles")
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "user-properties",
|
||||
"label": _("User Permission Restrictions"),
|
||||
"icon": "icon-user",
|
||||
"description": _("Set Defaults and Restrictions for Users")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "icon-wrench",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "System Settings",
|
||||
"label": _("System Settings"),
|
||||
"description": _("Language, Date and Time settings"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "modules_setup",
|
||||
"label": _("Show / Hide Modules"),
|
||||
"icon": "icon-upload",
|
||||
"description": _("Show or hide modules globally.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Naming Series",
|
||||
"description": _("Set numbering series for transactions."),
|
||||
"hide_count": True
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Data"),
|
||||
"icon": "icon-th",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "data-import-tool",
|
||||
"label": _("Import / Export Data"),
|
||||
"icon": "icon-upload",
|
||||
"description": _("Import / Export Data from .csv files.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Rename Tool",
|
||||
"description": _("Rename many items by uploading a .csv file."),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "File Data",
|
||||
"description": _("Manage uploaded files.")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Workflow"),
|
||||
"icon": "icon-random",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow",
|
||||
"description": _("Define workflows for forms.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow State",
|
||||
"description": _("States for workflow (e.g. Draft, Approved, Cancelled).")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Workflow Action",
|
||||
"description": _("Actions for workflow (e.g. Approve, Cancel).")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Email"),
|
||||
"icon": "icon-envelope",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Outgoing Email Settings",
|
||||
"description": _("Set outgoing mail server.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Printing and Branding"),
|
||||
"icon": "icon-print",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Print Format",
|
||||
"description": _("Customized HTML Templates for printing transctions.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Customize"),
|
||||
"icon": "icon-glass",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Customize Form",
|
||||
"description": _("Change field properties (hide, readonly, permission etc.)"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Custom Field",
|
||||
"description": _("Add fields to forms.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Custom Script",
|
||||
"description": _("Add custom javascript to forms.")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("System"),
|
||||
"icon": "icon-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "applications",
|
||||
"label": _("Application Installer"),
|
||||
"description": _("Install Applications."),
|
||||
"icon": "icon-download"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Backup Manager",
|
||||
"label": _("Download Backup"),
|
||||
"onclick": "frappe.ui.toolbar.download_backup",
|
||||
"icon": "icon-download-alt",
|
||||
"description": _("Send download link of a recent backup to System Managers"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Social Login Keys",
|
||||
"description": _("Enter keys to enable login via Facebook, Google, GitHub."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Backup Manager",
|
||||
"description": _("Manage cloud backups on Dropbox"),
|
||||
"hide_count": True
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Scheduler Log",
|
||||
"description": _("Log of error on automated events (scheduler).")
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
add_setup_section(data, "frappe", "website", _("Website"), "icon-globe")
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -1,93 +1,94 @@
|
|||
from frappe import _
|
||||
|
||||
data = [
|
||||
{
|
||||
"label": _("Documents"),
|
||||
"icon": "icon-star",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Web Page",
|
||||
"description": _("Content web page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Post",
|
||||
"description": _("Single Post (article)."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blogger",
|
||||
"description": _("User ID of a blog writer."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Group",
|
||||
"description": _("Web Site Forum Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Post",
|
||||
"description": _("List of Web Site Forum's Posts."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Slideshow",
|
||||
"description": _("Embed image slideshows in website pages."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Setup"),
|
||||
"icon": "icon-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Settings",
|
||||
"description": _("Setup of top navigation bar, footer and logo."),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name":"sitemap-browser",
|
||||
"label": _("Sitemap Browser"),
|
||||
"description": _("View or manage Website Route tree."),
|
||||
"icon": "icon-sitemap"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Style Settings",
|
||||
"description": _("Setup of fonts and background."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Script",
|
||||
"description": _("Javascript to append to the head section of the page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Settings",
|
||||
"description": _("Write titles and introductions to your blog."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Category",
|
||||
"description": _("Categorize blog posts."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "About Us Settings",
|
||||
"description": _("Settings for About Us Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Contact Us Settings",
|
||||
"description": _("Settings for Contact Us Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Page Permission",
|
||||
"description": _("Define read, write, admin permissions for a Website Page."),
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
def get_data():
|
||||
return [
|
||||
{
|
||||
"label": _("Documents"),
|
||||
"icon": "icon-star",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Web Page",
|
||||
"description": _("Content web page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Post",
|
||||
"description": _("Single Post (article)."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blogger",
|
||||
"description": _("User ID of a blog writer."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Group",
|
||||
"description": _("Web Site Forum Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Post",
|
||||
"description": _("List of Web Site Forum's Posts."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Slideshow",
|
||||
"description": _("Embed image slideshows in website pages."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Setup"),
|
||||
"icon": "icon-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Settings",
|
||||
"description": _("Setup of top navigation bar, footer and logo."),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name":"sitemap-browser",
|
||||
"label": _("Sitemap Browser"),
|
||||
"description": _("View or manage Website Route tree."),
|
||||
"icon": "icon-sitemap"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Style Settings",
|
||||
"description": _("Setup of fonts and background."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Script",
|
||||
"description": _("Javascript to append to the head section of the page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Settings",
|
||||
"description": _("Write titles and introductions to your blog."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Blog Category",
|
||||
"description": _("Categorize blog posts."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "About Us Settings",
|
||||
"description": _("Settings for About Us Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Contact Us Settings",
|
||||
"description": _("Settings for Contact Us Page."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Website Page Permission",
|
||||
"description": _("Define read, write, admin permissions for a Website Page."),
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from frappe.website.utils import is_signup_enabled
|
|||
from frappe.utils import get_url, cstr
|
||||
from frappe.utils.email_lib.email_body import get_email
|
||||
from frappe.utils.email_lib.smtp import send
|
||||
from frappe.utils import scrub_urls
|
||||
from frappe.utils import scrub_urls, cint
|
||||
from frappe import _
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
|
@ -78,6 +78,9 @@ def _make(doctype=None, name=None, content=None, subject=None, sent_or_received
|
|||
|
||||
d.communication_medium = communication_medium
|
||||
|
||||
d.idx = cint(frappe.db.sql("""select max(idx) from `tabCommunication`
|
||||
where parenttype=%s and parent=%s""", (doctype, name))[0][0]) + 1
|
||||
|
||||
comm.ignore_permissions = True
|
||||
comm.insert()
|
||||
|
||||
|
|
@ -118,7 +121,7 @@ def send_comm_email(d, name, sent_via=None, print_html=None, attachments='[]', s
|
|||
footer = set_portal_link(sent_via, d)
|
||||
|
||||
send_print_in_body = frappe.db.get_value("Outgoing Email Settings", None, "send_print_in_body_and_attachment")
|
||||
if not send_print_in_body:
|
||||
if print_html and not send_print_in_body:
|
||||
d.content += "<p>Please see attachment for document details.</p>"
|
||||
|
||||
mail = get_email(d.recipients, sender=d.sender, subject=d.subject,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ cur_frm.fields_dict['dt'].get_query = function(doc, dt, dn) {
|
|||
|
||||
cur_frm.cscript.fieldtype = function(doc, dt, dn) {
|
||||
if(doc.fieldtype == 'Link') cur_frm.fields_dict['options_help'].disp_area.innerHTML = 'Please enter name of the document you want this field to be linked to in <b>Options</b>.<br> Eg.: Customer';
|
||||
else if(doc.fieldtype == 'Select') cur_frm.fields_dict['options_help'].disp_area.innerHTML = 'Please enter values in <b>Options</b> separated by enter. <br>Eg.: <b>Field:</b> Country <br><b>Options:</b><br>China<br>India<br>United States<br><br><b> OR </b><br>You can also link it to existing Documents.<br>Eg.: <b>link:</b>Customer';
|
||||
else if(doc.fieldtype == 'Select') cur_frm.fields_dict['options_help'].disp_area.innerHTML = 'Please enter values in <b>Options</b>, with each option on a new line. <br>Eg.: <b>Field:</b> Country <br><b>Options:</b><br>China<br>India<br>United States<br><br><b>';
|
||||
else cur_frm.fields_dict['options_help'].disp_area.innerHTML = '';
|
||||
}
|
||||
|
||||
|
|
@ -64,9 +64,10 @@ cur_frm.cscript.dt = function(doc, dt, dn) {
|
|||
args: { doctype: doc.dt, fieldname: doc.fieldname },
|
||||
callback: function(r, rt) {
|
||||
set_field_options('insert_after', r.message);
|
||||
var fieldnames = $.map(r.message, function(v) { return v.value; });
|
||||
|
||||
if(insert_after==null || !in_list(r.message.split("\n"), insert_after)) {
|
||||
insert_after = r.message.split("\n")[0];
|
||||
if(insert_after==null || !in_list(fieldnames, insert_after)) {
|
||||
insert_after = fieldnames[-1];
|
||||
}
|
||||
|
||||
cur_frm.set_value('insert_after', insert_after);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
|
@ -9,7 +9,7 @@ from frappe import _
|
|||
from frappe.model.document import Document
|
||||
|
||||
class CustomField(Document):
|
||||
|
||||
|
||||
def autoname(self):
|
||||
self.set_fieldname()
|
||||
self.name = self.dt + "-" + self.fieldname
|
||||
|
|
@ -19,16 +19,16 @@ class CustomField(Document):
|
|||
if not self.label:
|
||||
frappe.throw(_("Label is mandatory"))
|
||||
# remove special characters from fieldname
|
||||
self.fieldname = filter(lambda x: x.isdigit() or x.isalpha() or '_',
|
||||
self.fieldname = filter(lambda x: x.isdigit() or x.isalpha() or '_',
|
||||
cstr(self.label).lower().replace(' ','_'))
|
||||
|
||||
def validate(self):
|
||||
if not self.idx:
|
||||
self.idx = len(frappe.get_meta(self.dt).get("fields")) + 1
|
||||
|
||||
|
||||
if not self.fieldname:
|
||||
frappe.throw(_("Fieldname not set for Custom Field"))
|
||||
|
||||
|
||||
def on_update(self):
|
||||
# validate field
|
||||
from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype
|
||||
|
|
@ -36,7 +36,7 @@ class CustomField(Document):
|
|||
validate_fields_for_doctype(self.dt)
|
||||
|
||||
frappe.clear_cache(doctype=self.dt)
|
||||
|
||||
|
||||
# create property setter to emulate insert after
|
||||
self.create_property_setter()
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class CustomField(Document):
|
|||
if not frappe.flags.in_test:
|
||||
from frappe.model.db_schema import updatedb
|
||||
updatedb(self.dt)
|
||||
|
||||
|
||||
def on_trash(self):
|
||||
# delete property setter entries
|
||||
frappe.db.sql("""\
|
||||
|
|
@ -57,57 +57,33 @@ class CustomField(Document):
|
|||
|
||||
def create_property_setter(self):
|
||||
if not self.insert_after: return
|
||||
idx_label_list, field_list = get_fields_label(self.dt, 0)
|
||||
label_index = idx_label_list.index(self.insert_after)
|
||||
if label_index==-1: return
|
||||
|
||||
prev_field = field_list[label_index]
|
||||
dt_meta = frappe.get_meta(self.dt)
|
||||
if not dt_meta.get_field(self.insert_after):
|
||||
frappe.throw(_("Insert After field '{0}' mentioned in Custom Field '{1}', does not exist")
|
||||
.format(dt_meta.get_label(self.insert_after), self.label), frappe.DoesNotExistError)
|
||||
|
||||
frappe.db.sql("""\
|
||||
DELETE FROM `tabProperty Setter`
|
||||
WHERE doc_type = %s
|
||||
AND field_name = %s
|
||||
AND property = 'previous_field'""", (self.dt, self.fieldname))
|
||||
|
||||
|
||||
frappe.make_property_setter({
|
||||
"doctype":self.dt,
|
||||
"fieldname": self.fieldname,
|
||||
"doctype":self.dt,
|
||||
"fieldname": self.fieldname,
|
||||
"property": "previous_field",
|
||||
"value": prev_field
|
||||
"value": self.insert_after
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_fields_label(dt=None, form=1):
|
||||
"""
|
||||
if form=1: Returns a string of field labels separated by \n
|
||||
if form=0: Returns lists of field labels and field names
|
||||
"""
|
||||
import frappe
|
||||
from frappe.utils import cstr
|
||||
fieldname = None
|
||||
if not dt:
|
||||
dt = frappe.form_dict.get('doctype')
|
||||
fieldname = frappe.form_dict.get('fieldname')
|
||||
if not dt: return ""
|
||||
|
||||
docfields = frappe.get_meta(dt).get("fields")
|
||||
|
||||
if fieldname:
|
||||
idx_label_list = [cstr(d.label) or cstr(d.fieldname) or cstr(d.fieldtype)
|
||||
for d in docfields if d.fieldname != fieldname]
|
||||
else:
|
||||
idx_label_list = [cstr(d.label) or cstr(d.fieldname) or cstr(d.fieldtype)
|
||||
for d in docfields]
|
||||
if form:
|
||||
return "\n".join(idx_label_list)
|
||||
else:
|
||||
# return idx_label_list, field_list
|
||||
field_list = [cstr(d.fieldname) for d in docfields]
|
||||
return idx_label_list, field_list
|
||||
def get_fields_label(doctype=None):
|
||||
return [{"value": df.fieldname, "label": _(df.label)} for df in frappe.get_meta(doctype).get("fields")]
|
||||
|
||||
def create_custom_field_if_values_exist(doctype, df):
|
||||
df = frappe._dict(df)
|
||||
if df.fieldname in frappe.db.get_table_columns(doctype) and \
|
||||
frappe.db.sql("""select count(*) from `tab{doctype}`
|
||||
frappe.db.sql("""select count(*) from `tab{doctype}`
|
||||
where ifnull({fieldname},'')!=''""".format(doctype=doctype, fieldname=df.fieldname))[0][0] and \
|
||||
not frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": df.fieldname}):
|
||||
frappe.get_doc({
|
||||
|
|
@ -120,4 +96,4 @@ def create_custom_field_if_values_exist(doctype, df):
|
|||
"options": df.options,
|
||||
"insert_after": df.insert_after
|
||||
}).insert()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"autoname": "DL.####",
|
||||
"creation": "2013-01-29 17:55:08.000000",
|
||||
"creation": "2013-01-29 17:55:08",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
"fieldname": "doc_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Enter Form Type",
|
||||
"no_copy": 0,
|
||||
"options": "DocType",
|
||||
|
|
@ -25,23 +26,37 @@
|
|||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "default_print_format",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Default Print Format",
|
||||
"no_copy": 0,
|
||||
"options": "Print Format",
|
||||
"permlevel": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"description": "Fields separated by comma (,) will be included in the<br /><b>Search By</b> list of Search dialog box",
|
||||
"fieldname": "search_fields",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Search Fields",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "default_print_format",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Print Format",
|
||||
"no_copy": 0,
|
||||
"options": "Print Format",
|
||||
"permlevel": 0,
|
||||
"search_index": 0
|
||||
"fieldname": "sort_field",
|
||||
"fieldtype": "Data",
|
||||
"label": "Sort Field",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "sort_order",
|
||||
"fieldtype": "Data",
|
||||
"label": "Sort Order",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break1",
|
||||
|
|
@ -111,7 +126,7 @@
|
|||
"icon": "icon-glass",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"modified": "2014-01-15 16:16:22.000000",
|
||||
"modified": "2014-05-08 09:27:44.167026",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Customize Form",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype
|
|||
class CustomizeForm(Document):
|
||||
doctype_properties = {
|
||||
'search_fields': 'Data',
|
||||
'sort_field': 'Data',
|
||||
'sort_order': 'Data',
|
||||
'default_print_format': 'Data',
|
||||
'read_only_onload': 'Check',
|
||||
'allow_attach': 'Check',
|
||||
|
|
|
|||
|
|
@ -138,6 +138,17 @@
|
|||
"options": "\nTitle Case\nUPPER CASE",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break",
|
||||
|
|
@ -162,15 +173,20 @@
|
|||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
"default": "modified",
|
||||
"description": "",
|
||||
"fieldname": "sort_field",
|
||||
"fieldtype": "Data",
|
||||
"label": "Sort Field",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"default": "DESC",
|
||||
"fieldname": "sort_order",
|
||||
"fieldtype": "Select",
|
||||
"label": "Sort Order",
|
||||
"options": "ASC\nDESC",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.istable",
|
||||
|
|
@ -329,7 +345,7 @@
|
|||
"idx": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2014-05-01 05:27:22.582492",
|
||||
"modified": "2014-05-08 09:23:56.952829",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocType",
|
||||
|
|
@ -361,5 +377,7 @@
|
|||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"search_fields": "module"
|
||||
"search_fields": "module",
|
||||
"sort_field": "name",
|
||||
"sort_order": "ASC"
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import os
|
|||
from frappe.utils import now, cint
|
||||
from frappe.model import no_value_fields
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.db_schema import type_map
|
||||
|
||||
class DocType(Document):
|
||||
def validate(self):
|
||||
|
|
@ -30,7 +31,6 @@ class DocType(Document):
|
|||
validate_permissions(self)
|
||||
|
||||
self.make_amendable()
|
||||
self.check_link_replacement_error()
|
||||
|
||||
def change_modified_of_parent(self):
|
||||
if frappe.flags.in_import:
|
||||
|
|
@ -93,12 +93,6 @@ class DocType(Document):
|
|||
module.on_doctype_update()
|
||||
frappe.clear_cache(doctype=self.name)
|
||||
|
||||
def check_link_replacement_error(self):
|
||||
for d in self.get("fields", {"fieldtype":"Select"}):
|
||||
if (frappe.db.get_value("DocField", d.name, "options") or "").startswith("link:") \
|
||||
and not d.options.startswith("link:"):
|
||||
frappe.throw(_("'link:' type Select {0} getting replaced").format(d.label))
|
||||
|
||||
def on_trash(self):
|
||||
frappe.db.sql("delete from `tabCustom Field` where dt = %s", self.name)
|
||||
frappe.db.sql("delete from `tabCustom Script` where dt = %s", self.name)
|
||||
|
|
@ -176,7 +170,7 @@ def validate_fields(fields):
|
|||
def check_unique_fieldname(fieldname):
|
||||
duplicates = filter(None, map(lambda df: df.fieldname==fieldname and str(df.idx) or None, fields))
|
||||
if len(duplicates) > 1:
|
||||
frappe.throw(_("Fieldname {0} appears multiple times in rows {1}").format(", ".join(duplicates)))
|
||||
frappe.throw(_("Fieldname {0} appears multiple times in rows {1}").format(fieldname, ", ".join(duplicates)))
|
||||
|
||||
def check_illegal_mandatory(d):
|
||||
if d.fieldtype in ('HTML', 'Button', 'Section Break', 'Column Break') and d.reqd:
|
||||
|
|
@ -198,7 +192,8 @@ def validate_fields(fields):
|
|||
def check_min_items_in_list(fields):
|
||||
if len(filter(lambda d: d.in_list_view, fields))==0:
|
||||
for d in fields[:5]:
|
||||
d.in_list_view = 1
|
||||
if d.fieldtype in type_map:
|
||||
d.in_list_view = 1
|
||||
|
||||
def check_width(d):
|
||||
if d.fieldtype == "Currency" and cint(d.width) < 100:
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"autoname": "EVP.#####",
|
||||
"creation": "2013-02-22 01:27:33.000000",
|
||||
"creation": "2013-02-22 01:27:33",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "person",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Person",
|
||||
"oldfieldname": "person",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "link:User",
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"print_width": "240px",
|
||||
"search_index": 1,
|
||||
|
|
@ -20,9 +20,12 @@
|
|||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2013-12-20 19:23:14.000000",
|
||||
"modified": "2014-05-09 02:12:32.374008",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Event User",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
|
|
@ -44,8 +44,8 @@ class FileData(Document):
|
|||
pass
|
||||
|
||||
# if file not attached to any other record, delete it
|
||||
if self.file_name and not frappe.db.count("File Data",
|
||||
{"content_hash": self.content_hash, "name": ["!=", self.name]}):
|
||||
if self.file_name and self.content_hash and (not frappe.db.count("File Data",
|
||||
{"content_hash": self.content_hash, "name": ["!=", self.name]})):
|
||||
delete_file_data_content(self)
|
||||
|
||||
def on_rollback(self):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"allow_attach": 1,
|
||||
"autoname": "field:letter_head_name",
|
||||
"creation": "2012-11-22 17:45:46.000000",
|
||||
"creation": "2012-11-22 17:45:46",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
"fieldname": "letter_head_name",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Letter Head Name",
|
||||
"oldfieldname": "letter_head_name",
|
||||
"oldfieldtype": "Data",
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
"depends_on": "letter_head_name",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Disabled",
|
||||
"oldfieldname": "disabled",
|
||||
"oldfieldtype": "Check",
|
||||
|
|
@ -29,6 +31,7 @@
|
|||
"description": "Check this to make this the default letter head in all prints",
|
||||
"fieldname": "is_default",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Default",
|
||||
"oldfieldname": "is_default",
|
||||
"oldfieldtype": "Check",
|
||||
|
|
@ -39,6 +42,7 @@
|
|||
"description": "Letter Head in HTML",
|
||||
"fieldname": "content",
|
||||
"fieldtype": "Text Editor",
|
||||
"in_list_view": 1,
|
||||
"label": "Content",
|
||||
"oldfieldname": "content",
|
||||
"oldfieldtype": "Text Editor",
|
||||
|
|
@ -48,7 +52,7 @@
|
|||
"icon": "icon-font",
|
||||
"idx": 1,
|
||||
"max_attachments": 3,
|
||||
"modified": "2014-01-20 17:48:56.000000",
|
||||
"modified": "2014-05-07 06:03:07.760995",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Letter Head",
|
||||
|
|
@ -69,11 +73,11 @@
|
|||
},
|
||||
{
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"email": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"report": 0,
|
||||
"role": "All"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"autoname": "hash",
|
||||
"creation": "2013-11-18 05:31:03.000000",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
|
|
@ -25,9 +26,9 @@
|
|||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"modified": "2013-12-20 19:24:14.000000",
|
||||
"modified": "2014-05-12 19:24:14.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Notification Count",
|
||||
"owner": "Administrator"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,19 +71,19 @@ class Page(Document):
|
|||
fpath = os.path.join(path, scrub(self.name) + '.js')
|
||||
if os.path.exists(fpath):
|
||||
with open(fpath, 'r') as f:
|
||||
self.script = f.read()
|
||||
self.script = unicode(f.read(), "utf-8")
|
||||
|
||||
# css
|
||||
fpath = os.path.join(path, scrub(self.name) + '.css')
|
||||
if os.path.exists(fpath):
|
||||
with open(fpath, 'r') as f:
|
||||
self.style = f.read()
|
||||
self.style = unicode(f.read(), "utf-8")
|
||||
|
||||
# html
|
||||
fpath = os.path.join(path, scrub(self.name) + '.html')
|
||||
if os.path.exists(fpath):
|
||||
with open(fpath, 'r') as f:
|
||||
self.content = f.read()
|
||||
self.content = unicode(f.read(), "utf-8")
|
||||
|
||||
if frappe.lang != 'en':
|
||||
from frappe.translate import get_lang_js
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
if(user!="Administrator") {
|
||||
if(doc.standard == 'Yes') {
|
||||
cur_frm.cscript.refresh = function (doc) {
|
||||
if (user!="Administrator") {
|
||||
if (doc.standard == 'Yes') {
|
||||
cur_frm.toggle_enable(["html", "doc_type", "module"], false);
|
||||
cur_frm.disable_save();
|
||||
} else {
|
||||
cur_frm.toggle_enable(["html", "doc_type", "module"], true);
|
||||
cur_frm.enable_save();
|
||||
}
|
||||
|
||||
cur_frm.toggle_enable("standard", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,21 +3,22 @@
|
|||
"allow_copy": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "Prompt",
|
||||
"creation": "2013-01-23 19:54:43.000000",
|
||||
"creation": "2013-01-23 19:54:43",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "module",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Module",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "module",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "link:Module Def",
|
||||
"options": "Module Def",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"report_hide": 0,
|
||||
|
|
@ -27,10 +28,11 @@
|
|||
{
|
||||
"description": "Belongs to",
|
||||
"fieldname": "doc_type",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "DocType",
|
||||
"options": "link:DocType",
|
||||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
|
|
@ -47,6 +49,7 @@
|
|||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Standard",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "standard",
|
||||
|
|
@ -62,6 +65,7 @@
|
|||
{
|
||||
"fieldname": "print_format_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Print Format Type",
|
||||
"options": "Client\nServer",
|
||||
"permlevel": 0
|
||||
|
|
@ -99,7 +103,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2014-01-20 17:49:00.000000",
|
||||
"modified": "2014-05-09 02:12:39.540952",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Print Format",
|
||||
|
|
@ -158,5 +162,7 @@
|
|||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ cur_frm.cscript.refresh = function(doc) {
|
|||
cur_frm.add_custom_button("Show Report", function() {
|
||||
switch(doc.report_type) {
|
||||
case "Report Builder":
|
||||
frappe.set_route("Report", doc.name);
|
||||
frappe.set_route("Report", doc.ref_doctype, doc.name);
|
||||
break;
|
||||
case "Query Report":
|
||||
frappe.set_route("query-report", doc.name);
|
||||
|
|
@ -12,7 +12,7 @@ cur_frm.cscript.refresh = function(doc) {
|
|||
break;
|
||||
}
|
||||
}, "icon-table")
|
||||
|
||||
|
||||
cur_frm.set_intro("");
|
||||
switch(doc.report_type) {
|
||||
case "Report Builder":
|
||||
|
|
@ -30,4 +30,4 @@ cur_frm.cscript.refresh = function(doc) {
|
|||
cur_frm.set_intro(__("Write a Python file in the same folder where this is saved and return column and result."))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"autoname": "field:report_name",
|
||||
"creation": "2013-03-09 15:45:57.000000",
|
||||
"creation": "2013-03-09 15:45:57",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
|
|
@ -101,7 +101,7 @@
|
|||
],
|
||||
"icon": "icon-table",
|
||||
"idx": 1,
|
||||
"modified": "2014-03-07 15:20:02.000000",
|
||||
"modified": "2014-05-12 17:08:04.185601",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Report",
|
||||
|
|
@ -157,5 +157,7 @@
|
|||
"role": "All",
|
||||
"submit": 0
|
||||
}
|
||||
]
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
frappe.pages['applications'].onload = function(wrapper) {
|
||||
frappe.pages['applications'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Application Installer'),
|
||||
|
|
@ -10,7 +10,7 @@ frappe.pages['applications'].onload = function(wrapper) {
|
|||
method:"frappe.core.page.applications.applications.get_app_list",
|
||||
callback: function(r) {
|
||||
var $main = $(wrapper).find(".layout-main");
|
||||
|
||||
|
||||
if(!keys(r.message).length) {
|
||||
$main.html('<div class="alert alert-info">No Apps Installed</div>');
|
||||
return;
|
||||
|
|
@ -54,7 +54,7 @@ frappe.pages['applications'].onload = function(wrapper) {
|
|||
</div>\
|
||||
</div>', app))
|
||||
$app.appendTo($main)
|
||||
|
||||
|
||||
if(app.installed) {
|
||||
$btn = $('<button class="btn btn-success" disabled=disabled>\
|
||||
<i class="icon-ok"></i> Installed</button>');
|
||||
|
|
@ -63,7 +63,7 @@ frappe.pages['applications'].onload = function(wrapper) {
|
|||
.attr("data-app", app.app_name)
|
||||
.on("click", function() {
|
||||
frappe.call({
|
||||
method:"frappe.installer.install_app",
|
||||
method:"frappe.core.page.applications.applications.install_app",
|
||||
args: {name: $(this).attr("data-app")},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe.installer
|
||||
from frappe import _
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_app_list():
|
||||
|
|
@ -19,8 +21,16 @@ def get_app_list():
|
|||
"app_publisher", "app_version", "app_url", "app_color"):
|
||||
val = app_hooks.get(key) or []
|
||||
out[app][key] = val[0] if len(val) else ""
|
||||
|
||||
|
||||
if app in installed:
|
||||
out[app]["installed"] = 1
|
||||
|
||||
|
||||
return out
|
||||
|
||||
@frappe.whitelist()
|
||||
def install_app(name):
|
||||
app_hooks = frappe.get_hooks(app_name=name)
|
||||
if app_hooks.get('hide_in_installer'):
|
||||
frappe.throw(_("You cannot install this app"))
|
||||
|
||||
frappe.installer.install_app(name)
|
||||
|
|
|
|||
|
|
@ -108,8 +108,6 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data
|
|||
if docfield.fieldtype == 'Select':
|
||||
if not docfield.options:
|
||||
return ''
|
||||
elif docfield.options.startswith('link:'):
|
||||
return 'Valid %s' % docfield.options[5:]
|
||||
else:
|
||||
return 'One of: %s' % ', '.join(filter(None, docfield.options.split('\n')))
|
||||
elif docfield.fieldtype == 'Link':
|
||||
|
|
|
|||
|
|
@ -186,9 +186,6 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False,
|
|||
doc = None
|
||||
|
||||
doc = get_doc(row_idx)
|
||||
if doc.get("name"):
|
||||
doc["_new_name_set"] = True
|
||||
|
||||
try:
|
||||
frappe.local.message_log = []
|
||||
if doc.get("parentfield"):
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ frappe.desktop.render = function() {
|
|||
$.each(modules_list, function(i, m) {
|
||||
var module = frappe.modules[m];
|
||||
if(module) {
|
||||
if(m!="Setup" && user_list.indexOf(m)!==-1)
|
||||
if(!in_list(["Setup", "Core"], m) && user_list.indexOf(m)!==-1)
|
||||
add_icon(m);
|
||||
}
|
||||
})
|
||||
|
|
@ -82,6 +82,9 @@ frappe.desktop.render = function() {
|
|||
if(user_roles.indexOf('System Manager')!=-1)
|
||||
add_icon('Setup')
|
||||
|
||||
if(user_roles.indexOf('Administrator')!=-1)
|
||||
add_icon('Core')
|
||||
|
||||
// all applications
|
||||
frappe.modules["All Applications"] = {
|
||||
icon: "icon-th",
|
||||
|
|
|
|||
|
|
@ -18,17 +18,17 @@ def get_users_and_links():
|
|||
def get_properties(parent=None, defkey=None, defvalue=None):
|
||||
if defkey and not frappe.permissions.can_restrict(defkey, defvalue):
|
||||
raise frappe.PermissionError
|
||||
|
||||
|
||||
conditions, values = _build_conditions(locals())
|
||||
|
||||
properties = frappe.db.sql("""select name, parent, defkey, defvalue
|
||||
|
||||
properties = frappe.db.sql("""select name, parent, defkey, defvalue
|
||||
from tabDefaultValue
|
||||
where parent not in ('__default', '__global')
|
||||
and substr(defkey,1,1)!='_'
|
||||
and parenttype='Restriction'
|
||||
{conditions}
|
||||
order by parent, defkey""".format(conditions=conditions), values, as_dict=True)
|
||||
|
||||
|
||||
if not defkey:
|
||||
out = []
|
||||
doctypes = get_restrictable_doctypes()
|
||||
|
|
@ -36,9 +36,9 @@ def get_properties(parent=None, defkey=None, defvalue=None):
|
|||
if p.defkey in doctypes:
|
||||
out.append(p)
|
||||
properties = out
|
||||
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
def _build_conditions(filters):
|
||||
conditions = []
|
||||
values = {}
|
||||
|
|
@ -46,7 +46,7 @@ def _build_conditions(filters):
|
|||
if filters.get(key):
|
||||
conditions.append("and `{key}`=%({key})s".format(key=key))
|
||||
values[key] = value
|
||||
|
||||
|
||||
return "\n".join(conditions), values
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -54,35 +54,35 @@ def remove(user, name, defkey, defvalue):
|
|||
if not frappe.permissions.can_restrict_user(user, defkey, defvalue):
|
||||
raise frappe.PermissionError("Cannot Remove Restriction for User: {user} on DocType: {doctype} and Name: {name}".format(
|
||||
user=user, doctype=defkey, name=defvalue))
|
||||
|
||||
frappe.defaults.clear_default(name=name)
|
||||
|
||||
|
||||
frappe.defaults.clear_default(key=defkey, value=defvalue, parent=user, name=name)
|
||||
|
||||
def clear_restrictions(doctype):
|
||||
frappe.defaults.clear_default(parenttype="Restriction", key=doctype)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add(user, defkey, defvalue):
|
||||
if not frappe.permissions.can_restrict_user(user, defkey, defvalue):
|
||||
raise frappe.PermissionError("Cannot Restrict User: {user} for DocType: {doctype} and Name: {name}".format(
|
||||
user=user, doctype=defkey, name=defvalue))
|
||||
|
||||
|
||||
# check if already exists
|
||||
d = frappe.db.sql("""select name from tabDefaultValue
|
||||
d = frappe.db.sql("""select name from tabDefaultValue
|
||||
where parent=%s and parenttype='Restriction' and defkey=%s and defvalue=%s""", (user, defkey, defvalue))
|
||||
|
||||
|
||||
if not d:
|
||||
frappe.defaults.add_default(defkey, defvalue, user, "Restriction")
|
||||
|
||||
|
||||
def get_restrictable_doctypes():
|
||||
user_roles = frappe.get_roles()
|
||||
condition = ""
|
||||
values = []
|
||||
if "System Manager" not in user_roles:
|
||||
condition = """and exists(select `tabDocPerm`.name from `tabDocPerm`
|
||||
condition = """and exists(select `tabDocPerm`.name from `tabDocPerm`
|
||||
where `tabDocPerm`.parent=`tabDocType`.name and `tabDocPerm`.`restrict`=1
|
||||
and `tabDocPerm`.role in ({roles}))""".format(roles=", ".join(["%s"]*len(user_roles)))
|
||||
values = user_roles
|
||||
|
||||
return frappe.db.sql_list("""select name from tabDocType
|
||||
|
||||
return frappe.db.sql_list("""select name from tabDocType
|
||||
where ifnull(issingle,0)=0 and ifnull(istable,0)=0 {condition}""".format(condition=condition),
|
||||
tuple(values))
|
||||
|
|
|
|||
|
|
@ -8,21 +8,21 @@
|
|||
|
||||
DROP TABLE IF EXISTS `tabDocField`;
|
||||
CREATE TABLE `tabDocField` (
|
||||
`name` varchar(120) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`creation` datetime(6) DEFAULT NULL,
|
||||
`modified` datetime(6) DEFAULT NULL,
|
||||
`modified_by` varchar(40) DEFAULT NULL,
|
||||
`owner` varchar(40) DEFAULT NULL,
|
||||
`modified_by` varchar(255) DEFAULT NULL,
|
||||
`owner` varchar(255) DEFAULT NULL,
|
||||
`docstatus` int(1) DEFAULT '0',
|
||||
`parent` varchar(120) DEFAULT NULL,
|
||||
`parentfield` varchar(120) DEFAULT NULL,
|
||||
`parenttype` varchar(120) DEFAULT NULL,
|
||||
`parent` varchar(255) DEFAULT NULL,
|
||||
`parentfield` varchar(255) DEFAULT NULL,
|
||||
`parenttype` varchar(255) DEFAULT NULL,
|
||||
`idx` int(8) DEFAULT NULL,
|
||||
`fieldname` varchar(180) DEFAULT NULL,
|
||||
`label` varchar(180) DEFAULT NULL,
|
||||
`oldfieldname` varchar(180) DEFAULT NULL,
|
||||
`fieldtype` varchar(180) DEFAULT NULL,
|
||||
`oldfieldtype` varchar(180) DEFAULT NULL,
|
||||
`fieldname` varchar(255) DEFAULT NULL,
|
||||
`label` varchar(255) DEFAULT NULL,
|
||||
`oldfieldname` varchar(255) DEFAULT NULL,
|
||||
`fieldtype` varchar(255) DEFAULT NULL,
|
||||
`oldfieldtype` varchar(255) DEFAULT NULL,
|
||||
`options` text,
|
||||
`search_index` int(1) DEFAULT NULL,
|
||||
`hidden` int(1) DEFAULT NULL,
|
||||
|
|
@ -32,12 +32,12 @@ CREATE TABLE `tabDocField` (
|
|||
`reqd` int(1) DEFAULT NULL,
|
||||
`no_copy` int(1) DEFAULT NULL,
|
||||
`allow_on_submit` int(1) DEFAULT NULL,
|
||||
`trigger` varchar(180) DEFAULT NULL,
|
||||
`depends_on` varchar(180) DEFAULT NULL,
|
||||
`trigger` varchar(255) DEFAULT NULL,
|
||||
`depends_on` varchar(255) DEFAULT NULL,
|
||||
`permlevel` int(11) DEFAULT '0',
|
||||
`ignore_restrictions` int(1) DEFAULT NULL,
|
||||
`width` varchar(180) DEFAULT NULL,
|
||||
`print_width` varchar(180) DEFAULT NULL,
|
||||
`width` varchar(255) DEFAULT NULL,
|
||||
`print_width` varchar(255) DEFAULT NULL,
|
||||
`default` text,
|
||||
`description` text,
|
||||
`in_filter` int(1) DEFAULT NULL,
|
||||
|
|
@ -57,22 +57,20 @@ CREATE TABLE `tabDocField` (
|
|||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tabDocPerm`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tabDocPerm` (
|
||||
`name` varchar(120) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`creation` datetime(6) DEFAULT NULL,
|
||||
`modified` datetime(6) DEFAULT NULL,
|
||||
`modified_by` varchar(40) DEFAULT NULL,
|
||||
`owner` varchar(40) DEFAULT NULL,
|
||||
`modified_by` varchar(255) DEFAULT NULL,
|
||||
`owner` varchar(255) DEFAULT NULL,
|
||||
`docstatus` int(1) DEFAULT '0',
|
||||
`parent` varchar(120) DEFAULT NULL,
|
||||
`parentfield` varchar(120) DEFAULT NULL,
|
||||
`parenttype` varchar(120) DEFAULT NULL,
|
||||
`parent` varchar(255) DEFAULT NULL,
|
||||
`parentfield` varchar(255) DEFAULT NULL,
|
||||
`parenttype` varchar(255) DEFAULT NULL,
|
||||
`idx` int(8) DEFAULT NULL,
|
||||
`permlevel` int(11) DEFAULT '0',
|
||||
`role` varchar(180) DEFAULT NULL,
|
||||
`match` varchar(180) DEFAULT NULL,
|
||||
`role` varchar(255) DEFAULT NULL,
|
||||
`match` varchar(255) DEFAULT NULL,
|
||||
`read` int(1) DEFAULT NULL,
|
||||
`write` int(1) DEFAULT NULL,
|
||||
`create` int(1) DEFAULT NULL,
|
||||
|
|
@ -89,43 +87,42 @@ CREATE TABLE `tabDocPerm` (
|
|||
PRIMARY KEY (`name`),
|
||||
KEY `parent` (`parent`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `tabDocType`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tabDocType`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tabDocType` (
|
||||
`name` varchar(180) NOT NULL DEFAULT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`creation` datetime(6) DEFAULT NULL,
|
||||
`modified` datetime(6) DEFAULT NULL,
|
||||
`modified_by` varchar(40) DEFAULT NULL,
|
||||
`owner` varchar(180) DEFAULT NULL,
|
||||
`modified_by` varchar(255) DEFAULT NULL,
|
||||
`owner` varchar(255) DEFAULT NULL,
|
||||
`docstatus` int(1) DEFAULT '0',
|
||||
`parent` varchar(120) DEFAULT NULL,
|
||||
`parentfield` varchar(120) DEFAULT NULL,
|
||||
`parenttype` varchar(120) DEFAULT NULL,
|
||||
`parent` varchar(255) DEFAULT NULL,
|
||||
`parentfield` varchar(255) DEFAULT NULL,
|
||||
`parenttype` varchar(255) DEFAULT NULL,
|
||||
`idx` int(8) DEFAULT NULL,
|
||||
`search_fields` varchar(180) DEFAULT NULL,
|
||||
`search_fields` varchar(255) DEFAULT NULL,
|
||||
`issingle` int(1) DEFAULT NULL,
|
||||
`istable` int(1) DEFAULT NULL,
|
||||
`version` int(11) DEFAULT NULL,
|
||||
`module` varchar(180) DEFAULT NULL,
|
||||
`plugin` varchar(180) DEFAULT NULL,
|
||||
`autoname` varchar(180) DEFAULT NULL,
|
||||
`name_case` varchar(180) DEFAULT NULL,
|
||||
`title_field` varchar(180) DEFAULT NULL,
|
||||
`module` varchar(255) DEFAULT NULL,
|
||||
`plugin` varchar(255) DEFAULT NULL,
|
||||
`autoname` varchar(255) DEFAULT NULL,
|
||||
`name_case` varchar(255) DEFAULT NULL,
|
||||
`title_field` varchar(255) DEFAULT NULL,
|
||||
`sort_field` varchar(255) DEFAULT NULL,
|
||||
`sort_order` varchar(255) DEFAULT NULL,
|
||||
`description` text,
|
||||
`colour` varchar(180) DEFAULT NULL,
|
||||
`colour` varchar(255) DEFAULT NULL,
|
||||
`read_only` int(1) DEFAULT NULL,
|
||||
`in_create` int(1) DEFAULT NULL,
|
||||
`show_in_menu` int(1) DEFAULT NULL,
|
||||
`menu_index` int(11) DEFAULT NULL,
|
||||
`parent_node` varchar(180) DEFAULT NULL,
|
||||
`smallicon` varchar(180) DEFAULT NULL,
|
||||
`parent_node` varchar(255) DEFAULT NULL,
|
||||
`smallicon` varchar(255) DEFAULT NULL,
|
||||
`allow_print` int(1) DEFAULT NULL,
|
||||
`allow_email` int(1) DEFAULT NULL,
|
||||
`allow_copy` int(1) DEFAULT NULL,
|
||||
|
|
@ -136,47 +133,33 @@ CREATE TABLE `tabDocType` (
|
|||
`allow_attach` int(1) DEFAULT NULL,
|
||||
`use_template` int(1) DEFAULT NULL,
|
||||
`max_attachments` int(11) DEFAULT NULL,
|
||||
`section_style` varchar(180) DEFAULT NULL,
|
||||
`client_script` mediumtext,
|
||||
`client_script_core` mediumtext,
|
||||
`server_code` mediumtext,
|
||||
`server_code_core` mediumtext,
|
||||
`server_code_compiled` mediumtext,
|
||||
`client_string` mediumtext,
|
||||
`server_code_error` varchar(180) DEFAULT NULL,
|
||||
`print_outline` varchar(180) DEFAULT NULL,
|
||||
`dt_template` mediumtext,
|
||||
`print_outline` varchar(255) DEFAULT NULL,
|
||||
`is_transaction_doc` int(1) DEFAULT NULL,
|
||||
`change_log` mediumtext,
|
||||
`read_only_onload` int(1) DEFAULT NULL,
|
||||
`allow_trash` int(1) DEFAULT NULL,
|
||||
`in_dialog` int(1) DEFAULT NULL,
|
||||
`document_type` varchar(180) DEFAULT NULL,
|
||||
`icon` varchar(180) DEFAULT NULL,
|
||||
`tag_fields` varchar(180) DEFAULT NULL,
|
||||
`subject` varchar(180) DEFAULT NULL,
|
||||
`document_type` varchar(255) DEFAULT NULL,
|
||||
`icon` varchar(255) DEFAULT NULL,
|
||||
`tag_fields` varchar(255) DEFAULT NULL,
|
||||
`subject` varchar(255) DEFAULT NULL,
|
||||
`_last_update` varchar(32) DEFAULT NULL,
|
||||
`default_print_format` varchar(180) DEFAULT NULL,
|
||||
`default_print_format` varchar(255) DEFAULT NULL,
|
||||
`is_submittable` int(1) DEFAULT NULL,
|
||||
`_user_tags` varchar(180) DEFAULT NULL,
|
||||
`_user_tags` varchar(255) DEFAULT NULL,
|
||||
`custom` int(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`name`),
|
||||
KEY `parent` (`parent`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `tabSeries`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tabSeries`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tabSeries` (
|
||||
`name` varchar(100) DEFAULT NULL,
|
||||
`current` int(10) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
|
||||
--
|
||||
|
|
@ -184,18 +167,15 @@ CREATE TABLE `tabSeries` (
|
|||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tabSessions`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tabSessions` (
|
||||
`user` varchar(255) DEFAULT NULL,
|
||||
`sid` varchar(120) DEFAULT NULL,
|
||||
`sid` varchar(255) DEFAULT NULL,
|
||||
`sessiondata` longtext,
|
||||
`ipaddress` varchar(16) DEFAULT NULL,
|
||||
`lastupdate` datetime(6) DEFAULT NULL,
|
||||
`status` varchar(20) DEFAULT NULL,
|
||||
KEY `sid` (`sid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
|
||||
--
|
||||
|
|
@ -203,11 +183,9 @@ CREATE TABLE `tabSessions` (
|
|||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tabSingles`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tabSingles` (
|
||||
`doctype` varchar(40) DEFAULT NULL,
|
||||
`field` varchar(40) DEFAULT NULL,
|
||||
`doctype` varchar(255) DEFAULT NULL,
|
||||
`field` varchar(255) DEFAULT NULL,
|
||||
`value` text,
|
||||
KEY `singles_doctype_field_index` (`doctype`, `field`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
|
@ -217,11 +195,9 @@ CREATE TABLE `tabSingles` (
|
|||
--
|
||||
|
||||
DROP TABLE IF EXISTS `__Auth`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `__Auth` (
|
||||
`user` VARCHAR(180) NOT NULL PRIMARY KEY,
|
||||
`password` VARCHAR(180) NOT NULL,
|
||||
`user` VARCHAR(255) NOT NULL PRIMARY KEY,
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
KEY `user` (`user`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
|
@ -231,22 +207,22 @@ CREATE TABLE `__Auth` (
|
|||
|
||||
DROP TABLE IF EXISTS `tabFile Data`;
|
||||
CREATE TABLE `tabFile Data` (
|
||||
`name` varchar(120) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`creation` datetime(6) DEFAULT NULL,
|
||||
`modified` datetime(6) DEFAULT NULL,
|
||||
`modified_by` varchar(40) DEFAULT NULL,
|
||||
`owner` varchar(40) DEFAULT NULL,
|
||||
`modified_by` varchar(255) DEFAULT NULL,
|
||||
`owner` varchar(255) DEFAULT NULL,
|
||||
`docstatus` int(1) DEFAULT '0',
|
||||
`parent` varchar(120) DEFAULT NULL,
|
||||
`parentfield` varchar(120) DEFAULT NULL,
|
||||
`parenttype` varchar(120) DEFAULT NULL,
|
||||
`parent` varchar(255) DEFAULT NULL,
|
||||
`parentfield` varchar(255) DEFAULT NULL,
|
||||
`parenttype` varchar(255) DEFAULT NULL,
|
||||
`idx` int(8) DEFAULT NULL,
|
||||
`file_name` varchar(180) DEFAULT NULL,
|
||||
`file_url` varchar(180) DEFAULT NULL,
|
||||
`module` varchar(180) DEFAULT NULL,
|
||||
`attached_to_name` varchar(180) DEFAULT NULL,
|
||||
`file_name` varchar(255) DEFAULT NULL,
|
||||
`file_url` varchar(255) DEFAULT NULL,
|
||||
`module` varchar(255) DEFAULT NULL,
|
||||
`attached_to_name` varchar(255) DEFAULT NULL,
|
||||
`file_size` int(11) DEFAULT NULL,
|
||||
`attached_to_doctype` varchar(180) DEFAULT NULL,
|
||||
`attached_to_doctype` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`name`),
|
||||
KEY `parent` (`parent`),
|
||||
KEY `attached_to_name` (`attached_to_name`),
|
||||
|
|
@ -259,18 +235,18 @@ CREATE TABLE `tabFile Data` (
|
|||
|
||||
DROP TABLE IF EXISTS `tabDefaultValue`;
|
||||
CREATE TABLE `tabDefaultValue` (
|
||||
`name` varchar(120) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`creation` datetime(6) DEFAULT NULL,
|
||||
`modified` datetime(6) DEFAULT NULL,
|
||||
`modified_by` varchar(40) DEFAULT NULL,
|
||||
`owner` varchar(40) DEFAULT NULL,
|
||||
`modified_by` varchar(255) DEFAULT NULL,
|
||||
`owner` varchar(255) DEFAULT NULL,
|
||||
`docstatus` int(1) DEFAULT '0',
|
||||
`parent` varchar(120) DEFAULT NULL,
|
||||
`parentfield` varchar(120) DEFAULT NULL,
|
||||
`parenttype` varchar(120) DEFAULT NULL,
|
||||
`parent` varchar(255) DEFAULT NULL,
|
||||
`parentfield` varchar(255) DEFAULT NULL,
|
||||
`parenttype` varchar(255) DEFAULT NULL,
|
||||
`idx` int(8) DEFAULT NULL,
|
||||
`defvalue` text,
|
||||
`defkey` varchar(180) DEFAULT NULL,
|
||||
`defkey` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`name`),
|
||||
KEY `parent` (`parent`),
|
||||
KEY `defaultvalue_parent_defkey_index` (`parent`,`defkey`)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ fr français
|
|||
hi हिंदी
|
||||
hr hrvatski
|
||||
it italiano
|
||||
kn ಕನ್ನಡ
|
||||
nl nederlands
|
||||
pt-BR português brasileiro
|
||||
pt português
|
||||
sr српски
|
||||
ta தமிழ்
|
||||
th ไทย
|
||||
zh-cn 中国(简体
|
||||
zh-tw 中國(繁體
|
||||
zh-cn 中国(简体)
|
||||
zh-tw 中國(繁體)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ scheduler_events = {
|
|||
"frappe.utils.email_lib.bulk.clear_outbox",
|
||||
"frappe.core.doctype.notification_count.notification_count.delete_event_notification_count",
|
||||
"frappe.core.doctype.event.event.send_event_digest",
|
||||
"frappe.sessions.clear_expired_sessions",
|
||||
],
|
||||
"hourly": [
|
||||
"frappe.templates.generators.website_group.clear_event_cache"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import getpass
|
|||
from frappe import _
|
||||
from frappe.model.db_schema import DbManager
|
||||
from frappe.model.sync import sync_for
|
||||
from frappe.utils.fixtures import sync_fixtures
|
||||
|
||||
def install_db(root_login="root", root_password=None, db_name=None, source_sql=None,
|
||||
admin_password = 'admin', verbose=True, force=0, site_config=None, reinstall=False):
|
||||
|
|
@ -81,7 +82,6 @@ def make_connection(root_login, root_password):
|
|||
root_password = getpass.getpass("MySQL root password: ")
|
||||
return frappe.database.Database(user=root_login, password=root_password)
|
||||
|
||||
@frappe.whitelist()
|
||||
def install_app(name, verbose=False, set_as_patched=True):
|
||||
frappe.flags.in_install_app = name
|
||||
frappe.clear_cache()
|
||||
|
|
@ -105,6 +105,7 @@ def install_app(name, verbose=False, set_as_patched=True):
|
|||
|
||||
if name != "frappe":
|
||||
add_module_defs(name)
|
||||
|
||||
sync_for(name, force=True, sync_everything=True, verbose=verbose)
|
||||
|
||||
add_to_installed_apps(name)
|
||||
|
|
@ -115,6 +116,8 @@ def install_app(name, verbose=False, set_as_patched=True):
|
|||
for after_install in app_hooks.after_install or []:
|
||||
frappe.get_attr(after_install)()
|
||||
|
||||
sync_fixtures()
|
||||
|
||||
frappe.flags.in_install_app = False
|
||||
|
||||
def add_to_installed_apps(app_name, rebuild_sitemap=True):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ class StaticDataMiddleware(SharedDataMiddleware):
|
|||
|
||||
def get_directory_loader(self, directory):
|
||||
def loader(path):
|
||||
site = get_site_name(self.environ.get('HTTP_HOST'))
|
||||
site = get_site_name(frappe.app._site or self.environ.get('HTTP_HOST'))
|
||||
path = os.path.join(directory, site, 'public', 'files', cstr(path))
|
||||
if os.path.isfile(path):
|
||||
return os.path.basename(path), self._opener(path)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
# model __init__.py
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
|
||||
|
||||
no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'Button', 'Image']
|
||||
default_fields = ['doctype','name','owner','creation','modified','modified_by','parent','parentfield','parenttype','idx','docstatus']
|
||||
|
|
@ -18,10 +20,10 @@ def insert(doclist):
|
|||
d["__islocal"] = 1
|
||||
else:
|
||||
d.set("__islocal", 1)
|
||||
|
||||
|
||||
wrapper = frappe.get_doc(doclist)
|
||||
wrapper.save()
|
||||
|
||||
|
||||
return wrapper
|
||||
|
||||
def rename(doctype, old, new, debug=False):
|
||||
|
|
@ -29,17 +31,17 @@ def rename(doctype, old, new, debug=False):
|
|||
frappe.model.rename_doc.rename_doc(doctype, old, new, debug)
|
||||
|
||||
def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfields=[]):
|
||||
if not tarfields:
|
||||
if not tarfields:
|
||||
tarfields = srcfields
|
||||
l = []
|
||||
data = src.get(srcfield)
|
||||
for d in data:
|
||||
newrow = tar.append(tarfield)
|
||||
newrow.idx = d.idx
|
||||
|
||||
|
||||
for i in range(len(srcfields)):
|
||||
newrow.set(tarfields[i], d.get(srcfields[i]))
|
||||
|
||||
|
||||
l.append(newrow)
|
||||
return l
|
||||
|
||||
|
|
@ -60,15 +62,15 @@ def delete_fields(args_dict, delete=0):
|
|||
for dt in args_dict.keys():
|
||||
fields = args_dict[dt]
|
||||
if not fields: continue
|
||||
|
||||
|
||||
frappe.db.sql("""\
|
||||
DELETE FROM `tabDocField`
|
||||
WHERE parent=%s AND fieldname IN (%s)
|
||||
""" % ('%s', ", ".join(['"' + f + '"' for f in fields])), dt)
|
||||
|
||||
|
||||
# Delete the data / column only if delete is specified
|
||||
if not delete: continue
|
||||
|
||||
|
||||
if frappe.db.get_value("DocType", dt, "issingle"):
|
||||
frappe.db.sql("""\
|
||||
DELETE FROM `tabSingles`
|
||||
|
|
@ -84,13 +86,13 @@ def delete_fields(args_dict, delete=0):
|
|||
|
||||
def rename_field(doctype, old_fieldname, new_fieldname):
|
||||
"""This functions assumes that doctype is already synced"""
|
||||
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
new_field = meta.get_field(new_fieldname)
|
||||
if not new_field:
|
||||
print "rename_field: " + (new_fieldname) + " not found in " + doctype
|
||||
return
|
||||
|
||||
|
||||
if new_field.fieldtype == "Table":
|
||||
# change parentfield of table mentioned in options
|
||||
frappe.db.sql("""update `tab%s` set parentfield=%s
|
||||
|
|
@ -99,22 +101,82 @@ def rename_field(doctype, old_fieldname, new_fieldname):
|
|||
elif new_field.fieldtype not in no_value_fields:
|
||||
if meta.issingle:
|
||||
frappe.db.sql("""update `tabSingles` set field=%s
|
||||
where doctype=%s and field=%s""",
|
||||
where doctype=%s and field=%s""",
|
||||
(new_fieldname, doctype, old_fieldname))
|
||||
else:
|
||||
# copy field value
|
||||
frappe.db.sql("""update `tab%s` set `%s`=`%s`""" % \
|
||||
(doctype, new_fieldname, old_fieldname))
|
||||
|
||||
|
||||
# update in property setter
|
||||
frappe.db.sql("""update `tabProperty Setter` set field_name = %s
|
||||
frappe.db.sql("""update `tabProperty Setter` set field_name = %s
|
||||
where doc_type=%s and field_name=%s""", (new_fieldname, doctype, old_fieldname))
|
||||
|
||||
|
||||
update_reports(doctype, old_fieldname, new_fieldname)
|
||||
update_users_report_view_settings(doctype, old_fieldname)
|
||||
|
||||
|
||||
def update_reports(doctype, old_fieldname, new_fieldname):
|
||||
def _get_new_sort_by(report_dict, report, key):
|
||||
sort_by = report_dict.get(key) or ""
|
||||
if sort_by:
|
||||
sort_by = sort_by.split(".")
|
||||
if len(sort_by) > 1:
|
||||
if sort_by[0]==doctype and sort_by[1]==old_fieldname:
|
||||
sort_by = doctype + "." + new_fieldname
|
||||
report_dict["updated"] = True
|
||||
elif report.ref_doctype == doctype and sort_by[0]==old_fieldname:
|
||||
sort_by = doctype + "." + new_fieldname
|
||||
report_dict["updated"] = True
|
||||
|
||||
if isinstance(sort_by, list):
|
||||
sort_by = '.'.join(sort_by)
|
||||
|
||||
return sort_by
|
||||
|
||||
reports = frappe.db.sql("""select name, ref_doctype, json from tabReport
|
||||
where report_type = 'Report Builder' and ifnull(is_standard, 'No') = 'No'
|
||||
and json like %s and json like %s""",
|
||||
('%%%s%%' % old_fieldname , '%%%s%%' % doctype), as_dict=True)
|
||||
|
||||
for r in reports:
|
||||
report_dict = json.loads(r.json)
|
||||
|
||||
# update filters
|
||||
new_filters = []
|
||||
for f in report_dict.get("filters"):
|
||||
if f[0] == doctype and f[1] == old_fieldname:
|
||||
new_filters.append([doctype, new_fieldname, f[2], f[3]])
|
||||
report_dict["updated"] = True
|
||||
else:
|
||||
new_filters.append(f)
|
||||
|
||||
# update columns
|
||||
new_columns = []
|
||||
for c in report_dict.get("columns"):
|
||||
if c[0] == old_fieldname and c[1] == doctype:
|
||||
new_columns.append([new_fieldname, doctype])
|
||||
report_dict["updated"] = True
|
||||
else:
|
||||
new_columns.append(c)
|
||||
|
||||
# update sort by
|
||||
new_sort_by = _get_new_sort_by(report_dict, r, "sort_by")
|
||||
new_sort_by_next = _get_new_sort_by(report_dict, r, "sort_by_next")
|
||||
|
||||
if report_dict.get("updated"):
|
||||
new_val = json.dumps({
|
||||
"filters": new_filters,
|
||||
"columns": new_columns,
|
||||
"sort_by": new_sort_by,
|
||||
"sort_order": report_dict.get("sort_order"),
|
||||
"sort_by_next": new_sort_by_next,
|
||||
"sort_order_next": report_dict.get("sort_order_next")
|
||||
})
|
||||
|
||||
frappe.db.sql("""update `tabReport` set `json`=%s where name=%s""", (new_val, r.name))
|
||||
|
||||
def update_users_report_view_settings(doctype, ref_fieldname):
|
||||
import json
|
||||
user_report_cols = frappe.db.sql("""select defkey, defvalue from `tabDefaultValue` where
|
||||
user_report_cols = frappe.db.sql("""select defkey, defvalue from `tabDefaultValue` where
|
||||
defkey like '_list_settings:%'""")
|
||||
for key, value in user_report_cols:
|
||||
new_columns = []
|
||||
|
|
@ -124,5 +186,5 @@ def update_users_report_view_settings(doctype, ref_fieldname):
|
|||
new_columns.append([field, field_doctype])
|
||||
columns_modified=True
|
||||
if columns_modified:
|
||||
frappe.db.sql("""update `tabDefaultValue` set defvalue=%s
|
||||
where defkey=%s""" % ('%s', '%s'), (json.dumps(new_columns), key))
|
||||
frappe.db.sql("""update `tabDefaultValue` set defvalue=%s
|
||||
where defkey=%s""" % ('%s', '%s'), (json.dumps(new_columns), key))
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@ class BaseDocument(object):
|
|||
if self.get("__islocal"):
|
||||
doc["__islocal"] = 1
|
||||
|
||||
elif self.get("__onload"):
|
||||
doc["__onload"] = self.get("__onload")
|
||||
|
||||
return doc
|
||||
|
||||
def as_json(self):
|
||||
|
|
@ -189,6 +192,7 @@ class BaseDocument(object):
|
|||
except Exception, e:
|
||||
if e.args[0]==1062:
|
||||
type, value, traceback = sys.exc_info()
|
||||
frappe.msgprint(_("Duplicate name {0} {1}".format(self.doctype, self.name)))
|
||||
raise frappe.NameError, (self.doctype, self.name, e), traceback
|
||||
else:
|
||||
raise
|
||||
|
|
@ -259,9 +263,6 @@ class BaseDocument(object):
|
|||
if not doctype:
|
||||
frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
|
||||
|
||||
elif doctype.lower().startswith("link:"):
|
||||
doctype = doctype[5:]
|
||||
|
||||
docname = self.get(df.fieldname)
|
||||
if docname and not frappe.db.get_value(doctype, docname):
|
||||
invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
|
||||
|
|
@ -285,7 +286,7 @@ class BaseDocument(object):
|
|||
current = frappe.db.get_value(self.doctype, self.name, "*", as_dict=True)
|
||||
for key, value in current.iteritems():
|
||||
df = self.meta.get_field(key)
|
||||
if df and not df.allow_on_submit and self.get(key) != value:
|
||||
if df and not df.allow_on_submit and (self.get(key) or value) and self.get(key) != value:
|
||||
frappe.throw(_("Not allowed to change {0} after submission").format(df.label),
|
||||
frappe.UpdateAfterSubmitError)
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ def get_new_doc(doctype, parent_doc = None, parentfield = None):
|
|||
elif d.fieldtype == "Time":
|
||||
doc.set(d.fieldname, nowtime())
|
||||
|
||||
elif (d.fieldtype == "Select" and d.options and not d.options.startswith("link:")
|
||||
and d.options != "[Select]"):
|
||||
elif (d.fieldtype == "Select" and d.options and d.options != "[Select]"):
|
||||
doc.set(d.fieldname, d.options.split("\n")[0])
|
||||
|
||||
return doc
|
||||
|
|
|
|||
|
|
@ -18,15 +18,17 @@ class DatabaseQuery(object):
|
|||
self.ignore_permissions = False
|
||||
self.fields = ["name"]
|
||||
|
||||
def execute(self, query=None, filters=None, fields=None, docstatus=None,
|
||||
group_by=None, order_by=None, limit_start=0, limit_page_length=20,
|
||||
as_list=False, with_childnames=False, debug=False, ignore_permissions=False):
|
||||
def execute(self, query=None, filters=None, fields=None, or_filters=None,
|
||||
docstatus=None, group_by=None, order_by=None, limit_start=0,
|
||||
limit_page_length=20, as_list=False, with_childnames=False, debug=False,
|
||||
ignore_permissions=False):
|
||||
if not frappe.has_permission(self.doctype, "read"):
|
||||
raise frappe.PermissionError
|
||||
|
||||
if fields:
|
||||
self.fields = fields
|
||||
self.filters = filters or []
|
||||
self.or_filters = or_filters or []
|
||||
self.docstatus = docstatus or []
|
||||
self.group_by = group_by
|
||||
self.order_by = order_by
|
||||
|
|
@ -67,17 +69,19 @@ class DatabaseQuery(object):
|
|||
|
||||
# query dict
|
||||
args.tables = ', '.join(self.tables)
|
||||
if self.or_conditions:
|
||||
self.conditions.append("({0})".format(" or ".join(self.or_conditions)))
|
||||
args.conditions = ' and '.join(self.conditions)
|
||||
args.fields = ', '.join(self.fields)
|
||||
|
||||
args.order_by = self.order_by or self.tables[0] + '.modified desc'
|
||||
self.set_order_by(args)
|
||||
|
||||
args.group_by = self.group_by and (" group by " + self.group_by) or ""
|
||||
|
||||
self.check_sort_by_table(args.order_by)
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def parse_args(self):
|
||||
if isinstance(self.filters, basestring):
|
||||
self.filters = json.loads(self.filters)
|
||||
|
|
@ -134,8 +138,10 @@ class DatabaseQuery(object):
|
|||
|
||||
def build_conditions(self):
|
||||
self.conditions = []
|
||||
self.or_conditions = []
|
||||
self.add_docstatus_conditions()
|
||||
self.build_filter_conditions()
|
||||
self.build_filter_conditions(self.filters, self.conditions)
|
||||
self.build_filter_conditions(self.or_filters, self.or_conditions)
|
||||
|
||||
# join parent, child tables
|
||||
for tname in self.tables[1:]:
|
||||
|
|
@ -153,11 +159,13 @@ class DatabaseQuery(object):
|
|||
else:
|
||||
self.conditions.append(self.tables[0] + '.docstatus < 2')
|
||||
|
||||
def build_filter_conditions(self):
|
||||
def build_filter_conditions(self, filters, conditions):
|
||||
"""build conditions from user filters"""
|
||||
for f in self.filters:
|
||||
if isinstance(filters, dict):
|
||||
filters = [filters]
|
||||
for f in filters:
|
||||
if isinstance(f, basestring):
|
||||
self.conditions.append(f)
|
||||
conditions.append(f)
|
||||
else:
|
||||
f = self.get_filter_tuple(f)
|
||||
|
||||
|
|
@ -172,7 +180,7 @@ class DatabaseQuery(object):
|
|||
opts = f[3].split(",")
|
||||
opts = ["'" + t.strip().replace("'", "\\'") + "'" for t in opts]
|
||||
f[3] = "(" + ', '.join(opts) + ")"
|
||||
self.conditions.append('ifnull(' + tname + '.' + f[1] + ", '') " + f[2] + " " + f[3])
|
||||
conditions.append('ifnull(' + tname + '.' + f[1] + ", '') " + f[2] + " " + f[3])
|
||||
else:
|
||||
df = frappe.get_meta(f[0]).get("fields", {"fieldname": f[1]})
|
||||
|
||||
|
|
@ -182,7 +190,7 @@ class DatabaseQuery(object):
|
|||
else:
|
||||
value, default_val = flt(f[3]), 0
|
||||
|
||||
self.conditions.append('ifnull({tname}.{fname}, {default_val}) {operator} {value}'.format(
|
||||
conditions.append('ifnull({tname}.{fname}, {default_val}) {operator} {value}'.format(
|
||||
tname=tname, fname=f[1], default_val=default_val, operator=f[2],
|
||||
value=value))
|
||||
|
||||
|
|
@ -203,7 +211,7 @@ class DatabaseQuery(object):
|
|||
"""add match conditions if applicable"""
|
||||
self.match_filters = {}
|
||||
self.match_conditions = []
|
||||
self.or_conditions = []
|
||||
self.match_or_conditions = []
|
||||
|
||||
if not self.tables: self.extract_tables()
|
||||
|
||||
|
|
@ -214,7 +222,7 @@ class DatabaseQuery(object):
|
|||
restrictions = frappe.defaults.get_restrictions()
|
||||
|
||||
if restricted_by_user:
|
||||
self.or_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=self.doctype,
|
||||
self.match_or_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=self.doctype,
|
||||
user=frappe.local.session.user))
|
||||
self.match_filters["owner"] = frappe.session.user
|
||||
|
||||
|
|
@ -247,12 +255,12 @@ class DatabaseQuery(object):
|
|||
if doctype_conditions:
|
||||
conditions += ' and ' + doctype_conditions if conditions else doctype_conditions
|
||||
|
||||
if self.or_conditions:
|
||||
if self.match_or_conditions:
|
||||
if conditions:
|
||||
conditions = '({conditions}) or {or_conditions}'.format(conditions=conditions,
|
||||
or_conditions = ' or '.join(self.or_conditions))
|
||||
or_conditions = ' or '.join(self.match_or_conditions))
|
||||
else:
|
||||
conditions = " or ".join(self.or_conditions)
|
||||
conditions = " or ".join(self.match_or_conditions)
|
||||
|
||||
return conditions
|
||||
|
||||
|
|
@ -272,6 +280,14 @@ class DatabaseQuery(object):
|
|||
query = query.replace('%(key)s', 'name')
|
||||
return frappe.db.sql(query, as_dict = (not self.as_list))
|
||||
|
||||
def set_order_by(self, args):
|
||||
meta = frappe.get_meta(self.doctype)
|
||||
if self.order_by:
|
||||
args.order_by = self.order_by
|
||||
else:
|
||||
args.order_by = "`tab{0}`.`{1}` {2}".format(self.doctype,
|
||||
meta.sort_field or "modified", meta.sort_order or "desc")
|
||||
|
||||
def check_sort_by_table(self, order_by):
|
||||
if "." in order_by:
|
||||
tbl = order_by.split('.')[0]
|
||||
|
|
|
|||
|
|
@ -175,27 +175,37 @@ class DbTable:
|
|||
for col in self.columns.values():
|
||||
col.check(self.current_columns.get(col.fieldname, None))
|
||||
|
||||
query = []
|
||||
|
||||
for col in self.add_column:
|
||||
frappe.db.sql("alter table `%s` add column `%s` %s" % (self.name, col.fieldname, col.get_definition()))
|
||||
query.append("add column `{}` {}".format(col.fieldname, col.get_definition()))
|
||||
|
||||
for col in self.change_type:
|
||||
frappe.db.sql("alter table `%s` change `%s` `%s` %s" % (self.name, col.fieldname, col.fieldname, col.get_definition()))
|
||||
query.append("change `{}` `{}` {}".format(col.fieldname, col.fieldname, col.get_definition()))
|
||||
|
||||
for col in self.add_index:
|
||||
# if index key not exists
|
||||
if not frappe.db.sql("show index from `%s` where key_name = %s" %
|
||||
(self.name, '%s'), col.fieldname):
|
||||
frappe.db.sql("alter table `%s` add index `%s`(`%s`)" % (self.name, col.fieldname, col.fieldname))
|
||||
query.append("add index `{}`(`{}`)".format(col.fieldname, col.fieldname))
|
||||
|
||||
for col in self.drop_index:
|
||||
if col.fieldname != 'name': # primary key
|
||||
# if index key exists
|
||||
if frappe.db.sql("show index from `%s` where key_name = %s" %
|
||||
(self.name, '%s'), col.fieldname):
|
||||
frappe.db.sql("alter table `%s` drop index `%s`" % (self.name, col.fieldname))
|
||||
query.append("drop index `{}`".format(col.fieldname))
|
||||
|
||||
for col in self.set_default:
|
||||
frappe.db.sql("alter table `%s` alter column `%s` set default %s" % (self.name, col.fieldname, '%s'), (col.default,))
|
||||
for col in list(set(self.set_default).difference(set(self.change_type))):
|
||||
if not col.default:
|
||||
col_default = "null"
|
||||
else:
|
||||
col_default = '"{}"'.format(col.default.replace('"', '\\"'))
|
||||
|
||||
query.append('alter column `{}` set default {}'.format(col.fieldname, col_default))
|
||||
|
||||
if query:
|
||||
frappe.db.sql("alter table `{}` {}".format(self.name, ", ".join(query)))
|
||||
|
||||
class DbColumn:
|
||||
def __init__(self, table, fieldname, fieldtype, length, default, set_index, options):
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from frappe.utils import flt, cint, cstr, now
|
|||
from frappe.modules import load_doctype_module
|
||||
from frappe.model.base_document import BaseDocument
|
||||
from frappe.model.naming import set_new_name
|
||||
from werkzeug.exceptions import NotFound, Forbidden
|
||||
|
||||
# once_only validation
|
||||
# methods
|
||||
|
|
@ -156,6 +157,8 @@ class Document(BaseDocument):
|
|||
self.set_parent_in_children()
|
||||
self.run_before_save_methods()
|
||||
self._validate()
|
||||
if self._action == "update_after_submit":
|
||||
self.validate_update_after_submit()
|
||||
|
||||
# parent
|
||||
if self.meta.issingle:
|
||||
|
|
@ -283,7 +286,6 @@ class Document(BaseDocument):
|
|||
elif docstatus==1:
|
||||
if self.docstatus==1:
|
||||
self._action = "update_after_submit"
|
||||
self.validate_update_after_submit()
|
||||
if not self.has_permission("submit"):
|
||||
self.raise_no_permission_to("submit")
|
||||
elif self.docstatus==2:
|
||||
|
|
@ -387,6 +389,7 @@ class Document(BaseDocument):
|
|||
elif self._action=="cancel":
|
||||
self.run_method("before_cancel")
|
||||
elif self._action=="update_after_submit":
|
||||
self.run_method("validate")
|
||||
self.run_method("before_update_after_submit")
|
||||
|
||||
def run_post_save_methods(self):
|
||||
|
|
@ -400,6 +403,11 @@ class Document(BaseDocument):
|
|||
elif self._action=="update_after_submit":
|
||||
self.run_method("on_update_after_submit")
|
||||
|
||||
@staticmethod
|
||||
def whitelist(f):
|
||||
f.whitelisted = True
|
||||
return f
|
||||
|
||||
@staticmethod
|
||||
def hook(f):
|
||||
def add_to_return_value(self, new_return_value):
|
||||
|
|
@ -433,6 +441,13 @@ class Document(BaseDocument):
|
|||
|
||||
return composer
|
||||
|
||||
def is_whitelisted(self, method):
|
||||
fn = getattr(self, method, None)
|
||||
if not fn:
|
||||
raise NotFound("Method {0} not found".format(method))
|
||||
elif not getattr(fn, "whitelisted", False):
|
||||
raise Forbidden("Method {0} not whitelisted".format(method))
|
||||
|
||||
def validate_value(self, fieldname, condition, val2, doc=None, raise_exception=None):
|
||||
"""check that value of fieldname should be 'condition' val2
|
||||
else throw exception"""
|
||||
|
|
|
|||
|
|
@ -59,11 +59,7 @@ class Meta(Document):
|
|||
raise
|
||||
|
||||
def get_link_fields(self):
|
||||
tmp = self.get("fields", {"fieldtype":"Link", "options":["!=", "[Select]"]})
|
||||
for df in self.get("fields", {"fieldtype":"Select", "options": "^link:"}):
|
||||
tmp.append(frappe._dict({"fieldname":df.fieldname, "label":df.label,
|
||||
"fieldtype":"Link", "options": df.options[5:]}))
|
||||
return tmp
|
||||
return self.get("fields", {"fieldtype": "Link", "options":["!=", "[Select]"]})
|
||||
|
||||
def get_table_fields(self):
|
||||
if not hasattr(self, "_table_fields"):
|
||||
|
|
@ -99,6 +95,21 @@ class Meta(Document):
|
|||
def get_options(self, fieldname):
|
||||
return self.get_field(fieldname).options
|
||||
|
||||
def get_search_fields(self):
|
||||
search_fields = self.search_fields or "name"
|
||||
search_fields = [d.strip() for d in search_fields.split(",")]
|
||||
if "name" not in search_fields:
|
||||
search_fields.append("name")
|
||||
|
||||
return search_fields
|
||||
|
||||
def get_list_fields(self):
|
||||
list_fields = ["name"] + [d.fieldname \
|
||||
for d in self.fields if (d.in_list_view and d.fieldtype in type_map)]
|
||||
if self.title_field and self.title_field not in list_fields:
|
||||
list_fields.append(self.title_field)
|
||||
return list_fields
|
||||
|
||||
def process(self):
|
||||
# don't process for special doctypes
|
||||
# prevent's circular dependency
|
||||
|
|
@ -203,7 +214,7 @@ doctype_table_fields = [
|
|||
def is_single(doctype):
|
||||
try:
|
||||
return frappe.db.get_value("DocType", doctype, "issingle")
|
||||
except IndexError, e:
|
||||
except IndexError:
|
||||
raise Exception, 'Cannot determine whether %s is single' % doctype
|
||||
|
||||
def get_parent_dt(dt):
|
||||
|
|
|
|||
|
|
@ -7,13 +7,9 @@ import frappe
|
|||
from frappe.utils import now_datetime, cint
|
||||
|
||||
def set_new_name(doc):
|
||||
if getattr(doc, "_new_name_set", False):
|
||||
# already set by doc
|
||||
if doc.name:
|
||||
return
|
||||
|
||||
doc._new_name_set = True
|
||||
autoname = frappe.get_meta(doc.doctype).autoname
|
||||
|
||||
# amendments
|
||||
if getattr(doc, "amended_from", None):
|
||||
return _get_amended_name(doc)
|
||||
|
|
@ -22,31 +18,35 @@ def set_new_name(doc):
|
|||
if tmp and not isinstance(tmp, basestring):
|
||||
# autoname in a function, not a property
|
||||
doc.autoname()
|
||||
if doc.name:
|
||||
return
|
||||
if doc.name:
|
||||
return
|
||||
|
||||
autoname = frappe.get_meta(doc.doctype).autoname
|
||||
|
||||
# based on a field
|
||||
if autoname and autoname.startswith('field:'):
|
||||
n = doc.get(autoname[6:])
|
||||
if not n:
|
||||
raise Exception, 'Name is required'
|
||||
doc.name = n.strip()
|
||||
if autoname:
|
||||
if autoname.startswith('field:'):
|
||||
n = doc.get(autoname[6:])
|
||||
if not n:
|
||||
raise Exception, 'Name is required'
|
||||
doc.name = n.strip()
|
||||
|
||||
elif autoname and autoname.startswith("naming_series:"):
|
||||
if not doc.naming_series:
|
||||
doc.naming_series = get_default_naming_series(doc.doctype)
|
||||
elif autoname.startswith("naming_series:"):
|
||||
if not doc.naming_series:
|
||||
doc.naming_series = get_default_naming_series(doc.doctype)
|
||||
|
||||
if not doc.naming_series:
|
||||
frappe.msgprint(frappe._("Naming Series mandatory"), raise_exception=True)
|
||||
doc.name = make_autoname(doc.naming_series+'.#####')
|
||||
if not doc.naming_series:
|
||||
frappe.msgprint(frappe._("Naming Series mandatory"), raise_exception=True)
|
||||
doc.name = make_autoname(doc.naming_series+'.#####')
|
||||
|
||||
# call the method!
|
||||
elif autoname and autoname!='Prompt':
|
||||
doc.name = make_autoname(autoname, doc.doctype)
|
||||
# call the method!
|
||||
elif autoname=='Prompt':
|
||||
# set from __newname in save.py
|
||||
if not doc.name:
|
||||
frappe.throw(frappe._("Name not set via Prompt"))
|
||||
|
||||
# given
|
||||
elif doc.get('__newname', None):
|
||||
doc.name = doc.get('__newname')
|
||||
else:
|
||||
doc.name = make_autoname(autoname, doc.doctype)
|
||||
|
||||
# default name for table
|
||||
elif doc.meta.istable:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from frappe.model.naming import validate_name
|
|||
def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=False):
|
||||
"""
|
||||
Renames a doc(dt, old) to doc(dt, new) and
|
||||
updates all linked fields of type "Link" or "Select" with "link:"
|
||||
updates all linked fields of type "Link"
|
||||
"""
|
||||
if not frappe.db.exists(doctype, old):
|
||||
return
|
||||
|
|
@ -138,10 +138,7 @@ def get_link_fields(doctype):
|
|||
where dt.name = df.parent) as issingle
|
||||
from tabDocField df
|
||||
where
|
||||
df.parent not like "old%%%%" and df.parent != '0' and
|
||||
((df.options=%s and df.fieldtype='Link') or
|
||||
(df.options='link:%s' and df.fieldtype='Select'))""" \
|
||||
% ('%s', doctype), (doctype,), as_dict=1)
|
||||
df.options=%s and df.fieldtype='Link'""", (doctype,), as_dict=1)
|
||||
|
||||
# get link fields from tabCustom Field
|
||||
custom_link_fields = frappe.db.sql("""\
|
||||
|
|
@ -150,10 +147,7 @@ def get_link_fields(doctype):
|
|||
where dt.name = df.dt) as issingle
|
||||
from `tabCustom Field` df
|
||||
where
|
||||
df.dt not like "old%%%%" and df.dt != '0' and
|
||||
((df.options=%s and df.fieldtype='Link') or
|
||||
(df.options='link:%s' and df.fieldtype='Select'))""" \
|
||||
% ('%s', doctype), (doctype,), as_dict=1)
|
||||
df.options=%s and df.fieldtype='Link'""", (doctype,), as_dict=1)
|
||||
|
||||
# add custom link fields list to link fields list
|
||||
link_fields += custom_link_fields
|
||||
|
|
@ -167,8 +161,7 @@ def get_link_fields(doctype):
|
|||
where
|
||||
ps.property_type='options' and
|
||||
ps.field_name is not null and
|
||||
(ps.value=%s or ps.value='link:%s')""" \
|
||||
% ('%s', doctype), (doctype,), as_dict=1)
|
||||
ps.value=%s""", (doctype,), as_dict=1)
|
||||
|
||||
link_fields += property_setter_link_fields
|
||||
|
||||
|
|
@ -199,10 +192,8 @@ def get_select_fields(old, new):
|
|||
where dt.name = df.parent) as issingle
|
||||
from tabDocField df
|
||||
where
|
||||
df.parent not like "old%%%%" and df.parent != '0' and
|
||||
df.parent != %s and df.fieldtype = 'Select' and
|
||||
df.options not like "link:%%%%" and
|
||||
(df.options like "%%%%%s%%%%")""" \
|
||||
df.options like "%%%%%s%%%%" """ \
|
||||
% ('%s', old), (new,), as_dict=1)
|
||||
|
||||
# get link fields from tabCustom Field
|
||||
|
|
@ -212,10 +203,8 @@ def get_select_fields(old, new):
|
|||
where dt.name = df.dt) as issingle
|
||||
from `tabCustom Field` df
|
||||
where
|
||||
df.dt not like "old%%%%" and df.dt != '0' and
|
||||
df.dt != %s and df.fieldtype = 'Select' and
|
||||
df.options not like "link:%%%%" and
|
||||
(df.options like "%%%%%s%%%%")""" \
|
||||
df.options like "%%%%%s%%%%" """ \
|
||||
% ('%s', old), (new,), as_dict=1)
|
||||
|
||||
# add custom link fields list to link fields list
|
||||
|
|
@ -231,8 +220,7 @@ def get_select_fields(old, new):
|
|||
ps.doc_type != %s and
|
||||
ps.property_type='options' and
|
||||
ps.field_name is not null and
|
||||
ps.value not like "link:%%%%" and
|
||||
(ps.value like "%%%%%s%%%%")""" \
|
||||
ps.value like "%%%%%s%%%%" """ \
|
||||
% ('%s', old), (new,), as_dict=1)
|
||||
|
||||
select_fields += property_setter_select_fields
|
||||
|
|
@ -243,16 +231,14 @@ def update_select_field_values(old, new):
|
|||
frappe.db.sql("""\
|
||||
update `tabDocField` set options=replace(options, %s, %s)
|
||||
where
|
||||
parent != %s and parent not like "old%%%%" and
|
||||
fieldtype = 'Select' and options not like "link:%%%%" and
|
||||
parent != %s and fieldtype = 'Select' and
|
||||
(options like "%%%%\\n%s%%%%" or options like "%%%%%s\\n%%%%")""" % \
|
||||
('%s', '%s', '%s', old, old), (old, new, new))
|
||||
|
||||
frappe.db.sql("""\
|
||||
update `tabCustom Field` set options=replace(options, %s, %s)
|
||||
where
|
||||
dt != %s and dt not like "old%%%%" and
|
||||
fieldtype = 'Select' and options not like "link:%%%%" and
|
||||
dt != %s and fieldtype = 'Select' and
|
||||
(options like "%%%%\\n%s%%%%" or options like "%%%%%s\\n%%%%")""" % \
|
||||
('%s', '%s', '%s', old, old), (old, new, new))
|
||||
|
||||
|
|
@ -260,7 +246,7 @@ def update_select_field_values(old, new):
|
|||
update `tabProperty Setter` set value=replace(value, %s, %s)
|
||||
where
|
||||
doc_type != %s and field_name is not null and
|
||||
property='options' and value not like "link%%%%" and
|
||||
property='options' and
|
||||
(value like "%%%%\\n%s%%%%" or value like "%%%%%s\\n%%%%")""" % \
|
||||
('%s', '%s', '%s', old, old), (old, new, new))
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ def walk_and_sync(start_path, force=0, sync_everything = False, verbose=False):
|
|||
"""walk and sync all doctypes and pages"""
|
||||
|
||||
modules = []
|
||||
|
||||
document_type = ['doctype', 'page', 'report']
|
||||
|
||||
document_type = ['doctype', 'page', 'report', 'print_format']
|
||||
|
||||
for path, folders, files in os.walk(start_path):
|
||||
# sort folders so that doctypes are synced before pages or reports
|
||||
|
||||
for dontwalk in (".git", "locale", "public"):
|
||||
if dontwalk in folders:
|
||||
if dontwalk in folders:
|
||||
folders.remove(dontwalk)
|
||||
|
||||
folders.sort()
|
||||
|
|
@ -47,10 +47,10 @@ def walk_and_sync(start_path, force=0, sync_everything = False, verbose=False):
|
|||
module_name = path.split(os.sep)[-3]
|
||||
doctype = path.split(os.sep)[-2]
|
||||
name = path.split(os.sep)[-1]
|
||||
|
||||
|
||||
if import_file_by_path(os.path.join(path, f), force=force) and verbose:
|
||||
print module_name + ' | ' + doctype + ' | ' + name
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
return modules
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
"""
|
||||
|
|
@ -8,12 +8,12 @@ from __future__ import unicode_literals
|
|||
import frappe, os
|
||||
import frappe.utils
|
||||
|
||||
lower_case_files_for = ['DocType', 'Page', 'Report',
|
||||
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State', 'Workflow Action']
|
||||
lower_case_files_for = ['DocType', 'Page', 'Report',
|
||||
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State', 'Workflow Action', 'Print Format']
|
||||
|
||||
def scrub(txt):
|
||||
return frappe.scrub(txt)
|
||||
|
||||
|
||||
def scrub_dt_dn(dt, dn):
|
||||
"""Returns in lowercase and code friendly names of doctype and name for certain types"""
|
||||
ndt, ndn = dt, dn
|
||||
|
|
@ -21,11 +21,11 @@ def scrub_dt_dn(dt, dn):
|
|||
ndt, ndn = scrub(dt), scrub(dn)
|
||||
|
||||
return ndt, ndn
|
||||
|
||||
|
||||
def get_module_path(module):
|
||||
"""Returns path of the given module"""
|
||||
return frappe.get_module_path(module)
|
||||
|
||||
|
||||
def get_doc_path(module, doctype, name):
|
||||
dt, dn = scrub_dt_dn(doctype, name)
|
||||
return os.path.join(get_module_path(module), dt, dn)
|
||||
|
|
@ -48,9 +48,9 @@ def load_doctype_module(doctype, module=None, prefix=""):
|
|||
if not module:
|
||||
module = get_doctype_module(doctype)
|
||||
return frappe.get_module(get_module_name(doctype, module, prefix))
|
||||
|
||||
|
||||
def get_module_name(doctype, module, prefix=""):
|
||||
from frappe.modules import scrub
|
||||
return '{app}.{module}.doctype.{doctype}.{prefix}{doctype}'.format(\
|
||||
app = scrub(frappe.local.module_app[scrub(module)]),
|
||||
app = scrub(frappe.local.module_app[scrub(module)]),
|
||||
module = scrub(module), doctype = scrub(doctype), prefix=prefix)
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ def import_file_by_path(path, force=False):
|
|||
|
||||
original_modified = doc.get("modified")
|
||||
|
||||
import_doc(doc)
|
||||
import_doc(doc, force=force)
|
||||
|
||||
if original_modified:
|
||||
# since there is a new timestamp on the file, update timestamp in
|
||||
if doc["doctype"] == doc["name"]:
|
||||
if doc["doctype"] == doc["name"] and doc["name"]!="DocType":
|
||||
frappe.db.sql("""update tabSingles set value=%s where field="modified" and doctype=%s""",
|
||||
(original_modified, doc["name"]))
|
||||
else:
|
||||
|
|
@ -78,7 +78,7 @@ ignore_values = {
|
|||
|
||||
ignore_doctypes = ["Page Role", "DocPerm"]
|
||||
|
||||
def import_doc(docdict):
|
||||
def import_doc(docdict, force=False):
|
||||
docdict["__islocal"] = 1
|
||||
doc = frappe.get_doc(docdict)
|
||||
|
||||
|
|
@ -87,14 +87,14 @@ def import_doc(docdict):
|
|||
if frappe.db.exists(doc.doctype, doc.name):
|
||||
old_doc = frappe.get_doc(doc.doctype, doc.name)
|
||||
|
||||
if doc.doctype in ignore_values:
|
||||
if doc.doctype in ignore_values and not force:
|
||||
# update ignore values
|
||||
for key in ignore_values.get(doc.doctype) or []:
|
||||
doc.set(key, old_doc.get(key))
|
||||
|
||||
# update ignored docs into new doc
|
||||
for df in doc.meta.get_table_fields():
|
||||
if df.options in ignore_doctypes:
|
||||
if df.options in ignore_doctypes and not force:
|
||||
doc.set(df.fieldname, [])
|
||||
ignore.append(df.options)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
"""
|
||||
Execute Patch Files
|
||||
|
||||
To run directly
|
||||
|
||||
|
||||
python lib/wnf.py patch patch1, patch2 etc
|
||||
python lib/wnf.py patch -f patch1, patch2 etc
|
||||
|
||||
|
||||
where patch1, patch2 is module name
|
||||
"""
|
||||
import frappe, os
|
||||
|
|
@ -19,21 +19,21 @@ class PatchError(Exception): pass
|
|||
def run_all():
|
||||
"""run all pending patches"""
|
||||
executed = [p[0] for p in frappe.db.sql("""select patch from `tabPatch Log`""")]
|
||||
|
||||
|
||||
for patch in get_all_patches():
|
||||
if patch and (patch not in executed):
|
||||
if not run_single(patchmodule = patch):
|
||||
log(patch + ': failed: STOPPED')
|
||||
raise PatchError(patch)
|
||||
|
||||
|
||||
def get_all_patches():
|
||||
patches = []
|
||||
for app in frappe.get_installed_apps():
|
||||
# 3-to-4 fix
|
||||
if app=="webnotes":
|
||||
if app=="webnotes":
|
||||
app="frappe"
|
||||
patches.extend(frappe.get_file_items(frappe.get_pymodule_path(app, "patches.txt")))
|
||||
|
||||
|
||||
return patches
|
||||
|
||||
def reload_doc(args):
|
||||
|
|
@ -42,22 +42,23 @@ def reload_doc(args):
|
|||
|
||||
def run_single(patchmodule=None, method=None, methodargs=None, force=False):
|
||||
from frappe import conf
|
||||
|
||||
|
||||
# don't write txt files
|
||||
conf.developer_mode = 0
|
||||
|
||||
|
||||
if force or method or not executed(patchmodule):
|
||||
return execute_patch(patchmodule, method, methodargs)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def execute_patch(patchmodule, method=None, methodargs=None):
|
||||
"""execute the patch"""
|
||||
success = False
|
||||
block_user(True)
|
||||
frappe.db.begin()
|
||||
try:
|
||||
log('Executing %s in %s' % (patchmodule or str(methodargs), frappe.db.cur_db_name))
|
||||
log('Executing {patch} in {site} ({db})'.format(patch=patchmodule or str(methodargs),
|
||||
site=frappe.local.site, db=frappe.db.cur_db_name))
|
||||
if patchmodule:
|
||||
if patchmodule.startswith("execute:"):
|
||||
exec patchmodule.split("execute:")[1] in globals()
|
||||
|
|
@ -66,66 +67,43 @@ def execute_patch(patchmodule, method=None, methodargs=None):
|
|||
update_patch_log(patchmodule)
|
||||
elif method:
|
||||
method(**methodargs)
|
||||
|
||||
|
||||
frappe.db.commit()
|
||||
success = True
|
||||
except Exception, e:
|
||||
frappe.db.rollback()
|
||||
tb = frappe.get_traceback()
|
||||
log(tb)
|
||||
import os
|
||||
if frappe.request:
|
||||
add_to_patch_log(tb)
|
||||
|
||||
block_user(False)
|
||||
if success:
|
||||
log('Success')
|
||||
return success
|
||||
|
||||
def add_to_patch_log(tb):
|
||||
"""add error log to patches/patch.log"""
|
||||
import conf, os
|
||||
# TODO use get_site_base_path
|
||||
with open(os.path.join(os.path.dirname(conf.__file__), 'app', 'patches','patch.log'),'a') as patchlog:
|
||||
patchlog.write('\n\n' + tb)
|
||||
|
||||
def update_patch_log(patchmodule):
|
||||
"""update patch_file in patch log"""
|
||||
if frappe.db.table_exists("__PatchLog"):
|
||||
frappe.db.sql("""INSERT INTO `__PatchLog` VALUES (%s, now())""", \
|
||||
patchmodule)
|
||||
else:
|
||||
frappe.get_doc({"doctype": "Patch Log", "patch": patchmodule}).insert()
|
||||
"""update patch_file in patch log"""
|
||||
frappe.get_doc({"doctype": "Patch Log", "patch": patchmodule}).insert()
|
||||
|
||||
def executed(patchmodule):
|
||||
"""return True if is executed"""
|
||||
if frappe.db.table_exists("__PatchLog"):
|
||||
done = frappe.db.sql("""select patch from __PatchLog where patch=%s""", patchmodule)
|
||||
else:
|
||||
done = frappe.db.get_value("Patch Log", {"patch": patchmodule})
|
||||
if done:
|
||||
print "Patch %s already executed in %s" % (patchmodule, frappe.db.cur_db_name)
|
||||
done = frappe.db.get_value("Patch Log", {"patch": patchmodule})
|
||||
# if done:
|
||||
# print "Patch %s already executed in %s" % (patchmodule, frappe.db.cur_db_name)
|
||||
return done
|
||||
|
||||
|
||||
def block_user(block):
|
||||
"""stop/start execution till patch is run"""
|
||||
frappe.local.flags.in_patch = block
|
||||
frappe.db.begin()
|
||||
msg = "Patches are being executed in the system. Please try again in a few moments."
|
||||
frappe.db.set_global('__session_status', block and 'stop' or None)
|
||||
frappe.db.set_global('__session_status_message', block and msg or None)
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
def check_session_stopped():
|
||||
if frappe.db.get_global("__session_status")=='stop':
|
||||
frappe.msgprint(frappe.db.get_global("__session_status_message"))
|
||||
raise frappe.SessionStopped('Session Stopped')
|
||||
|
||||
def setup():
|
||||
frappe.db.sql("""CREATE TABLE IF NOT EXISTS `__PatchLog` (
|
||||
patch TEXT, applied_on DATETIME) engine=InnoDB""")
|
||||
|
||||
def log(msg):
|
||||
if getattr(frappe.local, "patch_log_list", None) is None:
|
||||
frappe.local.patch_log_list = []
|
||||
|
||||
frappe.local.patch_log_list.append(msg)
|
||||
print msg
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
execute:import inlinestyler # new requirement
|
||||
|
||||
execute:frappe.db.sql("""update `tabPatch Log` set patch=replace(patch, '.4_0.', '.v4_0.')""") #2014-05-12
|
||||
execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2014-01-24
|
||||
execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2014-03-01
|
||||
execute:frappe.reload_doc('core', 'doctype', 'docperm') #2013-13-26
|
||||
|
|
@ -8,21 +9,24 @@ execute:frappe.reload_doc('core', 'doctype', 'report') #2013-13-26
|
|||
execute:frappe.reload_doc('core', 'doctype', 'version') #2014-02-21
|
||||
execute:frappe.db.sql("alter table `tabSessions` modify `user` varchar(255), engine=InnoDB")
|
||||
|
||||
frappe.patches.4_0.remove_index_sitemap
|
||||
frappe.patches.4_0.add_delete_permission
|
||||
frappe.patches.4_0.move_match_to_restricted
|
||||
frappe.patches.4_0.set_todo_checked_as_closed
|
||||
frappe.patches.4_0.website_sitemap_hierarchy
|
||||
frappe.patches.4_0.webnotes_to_frappe
|
||||
frappe.patches.v4_0.remove_old_parent
|
||||
frappe.patches.v4_0.remove_index_sitemap
|
||||
frappe.patches.v4_0.add_delete_permission
|
||||
frappe.patches.v4_0.move_match_to_restricted
|
||||
frappe.patches.v4_0.set_todo_checked_as_closed
|
||||
frappe.patches.v4_0.website_sitemap_hierarchy
|
||||
frappe.patches.v4_0.webnotes_to_frappe
|
||||
execute:frappe.reset_perms("Module Def")
|
||||
frappe.patches.4_0.rename_sitemap_to_route
|
||||
frappe.patches.4_0.rename_profile_to_user
|
||||
frappe.patches.4_0.set_website_route_idx
|
||||
frappe.patches.v4_0.rename_sitemap_to_route
|
||||
frappe.patches.v4_0.rename_profile_to_user
|
||||
frappe.patches.v4_0.set_website_route_idx
|
||||
execute:import frappe.installer;frappe.installer.make_site_dirs() #2014-02-19
|
||||
frappe.patches.4_0.private_backups
|
||||
frappe.patches.4_0.set_module_in_report
|
||||
frappe.patches.4_0.remove_old_parent
|
||||
frappe.patches.4_0.update_datetime
|
||||
frappe.patches.4_0.deprecate_control_panel
|
||||
frappe.patches.4_0.file_manager_hooks
|
||||
frappe.patches.v4_0.private_backups
|
||||
frappe.patches.v4_0.set_module_in_report
|
||||
frappe.patches.v4_0.update_datetime
|
||||
frappe.patches.v4_0.deprecate_control_panel
|
||||
frappe.patches.v4_0.file_manager_hooks
|
||||
execute:frappe.get_doc("User", "Guest").save()
|
||||
frappe.patches.v4_0.deprecate_link_selects
|
||||
frappe.patches.v4_0.set_user_gravatar
|
||||
frappe.patches.v4_0.update_custom_field_insert_after
|
||||
|
|
|
|||
13
frappe/patches/v4_0/deprecate_link_selects.py
Normal file
13
frappe/patches/v4_0/deprecate_link_selects.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for name in frappe.db.sql_list("""select name from `tabCustom Field`
|
||||
where fieldtype="Select" and options like "link:%" """):
|
||||
custom_field = frappe.get_doc("Custom Field", name)
|
||||
custom_field.fieldtype = "Link"
|
||||
custom_field.options = custom_field.options[5:]
|
||||
custom_field.save()
|
||||
|
|
@ -21,7 +21,16 @@ def execute():
|
|||
b.file_url = os.path.normpath('/' + old_file_name)
|
||||
else:
|
||||
b.file_url = os.path.normpath('/files/' + old_file_name)
|
||||
_file_name, content = get_file(name)
|
||||
b.content_hash = get_content_hash(content)
|
||||
b.save()
|
||||
try:
|
||||
_file_name, content = get_file(name)
|
||||
b.content_hash = get_content_hash(content)
|
||||
except IOError:
|
||||
print 'Warning: Error processing ', name
|
||||
_file_name = old_file_name
|
||||
b.content_hash = None
|
||||
|
||||
try:
|
||||
b.save()
|
||||
except frappe.DuplicateEntryError:
|
||||
frappe.delete_doc(b.doctype, b.name)
|
||||
|
||||
|
|
@ -7,3 +7,4 @@ import frappe
|
|||
def execute():
|
||||
for doctype in frappe.db.sql_list("""select name from `tabDocType` where istable=1"""):
|
||||
frappe.db.sql("""delete from `tab{0}` where parent like "old_par%:%" """.format(doctype))
|
||||
frappe.db.sql("""delete from `tabDocField` where parent="0" """)
|
||||
11
frappe/patches/v4_0/set_user_gravatar.py
Normal file
11
frappe/patches/v4_0/set_user_gravatar.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for name in frappe.db.sql_list("select name from `tabUser` where ifnull(user_image, '')=''"):
|
||||
user = frappe.get_doc("User", name)
|
||||
user.update_gravatar()
|
||||
user.db_set("user_image", user.user_image)
|
||||
18
frappe/patches/v4_0/update_custom_field_insert_after.py
Normal file
18
frappe/patches/v4_0/update_custom_field_insert_after.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for d in frappe.db.sql("""select name, dt, insert_after from `tabCustom Field`
|
||||
where docstatus < 2""", as_dict=1):
|
||||
dt_meta = frappe.get_meta(d.dt)
|
||||
if not dt_meta.get_field(d.insert_after):
|
||||
cf = frappe.get_doc("Custom Field", d.name)
|
||||
df = dt_meta.get("fields", {"label": d.insert_after})
|
||||
if df:
|
||||
cf.insert_after = df[0].fieldname
|
||||
else:
|
||||
cf.insert_after = None
|
||||
cf.save()
|
||||
|
|
@ -71,11 +71,12 @@ def has_unrestricted_access(doc, verbose=True):
|
|||
restrictions = get_restrictions()
|
||||
|
||||
meta = frappe.get_meta(doc.get("doctype"))
|
||||
user_perms = get_user_perms(meta)
|
||||
if get_user_perms(meta).restricted:
|
||||
if doc.owner == frappe.session.user:
|
||||
# owner is always allowed for restricted permissions
|
||||
return True
|
||||
elif not restrictions:
|
||||
elif not (restrictions and restrictions.get(doc.get("doctype"))):
|
||||
return False
|
||||
else:
|
||||
if not restrictions:
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ div#freeze {
|
|||
/*margin-top: -15px;*/
|
||||
}
|
||||
|
||||
.form-control {
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.form-headline {
|
||||
margin-bottom: 10px;
|
||||
font-size: 120%;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
// MIT License. See license.txt
|
||||
|
||||
// assign to is lined to todo
|
||||
// refresh - load todos
|
||||
|
|
@ -15,9 +15,9 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
this.wrapper = $('<div>\
|
||||
<div class="alert-list" style="margin-bottom: 7px;"></div>\
|
||||
</div>').appendTo(this.parent);
|
||||
|
||||
|
||||
this.$list = this.wrapper.find(".alert-list");
|
||||
|
||||
|
||||
this.parent.find(".btn").click(function() {
|
||||
me.add();
|
||||
});
|
||||
|
|
@ -36,11 +36,11 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
this.frm.get_docinfo().assignments = d;
|
||||
this.$list.empty();
|
||||
if(this.dialog) {
|
||||
this.dialog.hide();
|
||||
this.dialog.hide();
|
||||
}
|
||||
|
||||
if(d && d.length) {
|
||||
for(var i=0; i<d.length; i++) {
|
||||
for(var i=0; i<d.length; i++) {
|
||||
var info = frappe.user_info(d[i]);
|
||||
info.owner = d[i];
|
||||
info.avatar = frappe.avatar(d[i]);
|
||||
|
|
@ -58,12 +58,12 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
// set remove
|
||||
this.$list.find('a.close').click(function() {
|
||||
frappe.call({
|
||||
method:'frappe.widgets.form.assign_to.remove',
|
||||
method:'frappe.widgets.form.assign_to.remove',
|
||||
args: {
|
||||
doctype: me.frm.doctype,
|
||||
name: me.frm.docname,
|
||||
assign_to: $(this).attr('data-owner')
|
||||
},
|
||||
assign_to: $(this).attr('data-owner')
|
||||
},
|
||||
callback:function(r,rt) {
|
||||
me.render(r.message);
|
||||
me.frm.toolbar.show_infobar();
|
||||
|
|
@ -81,16 +81,15 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
if(!me.dialog) {
|
||||
me.dialog = new frappe.ui.Dialog({
|
||||
title: __('Add to To Do'),
|
||||
width: 350,
|
||||
fields: [
|
||||
{fieldtype:'Link', fieldname:'assign_to', options:'User',
|
||||
label:__("Assign To"),
|
||||
{fieldtype:'Link', fieldname:'assign_to', options:'User',
|
||||
label:__("Assign To"),
|
||||
description:__("Add to To Do List of"), reqd:true},
|
||||
{fieldtype:'Data', fieldname:'description', label:__("Comment")},
|
||||
{fieldtype:'Date', fieldname:'date', label: __("Complete By")},
|
||||
{fieldtype:'Data', fieldname:'description', label:__("Comment"), reqd:true},
|
||||
{fieldtype:'Date', fieldname:'date', label: __("Complete By")},
|
||||
{fieldtype:'Select', fieldname:'priority', label: __("Priority"),
|
||||
options:'Low\nMedium\nHigh', 'default':'Medium'},
|
||||
{fieldtype:'Check', fieldname:'notify',
|
||||
{fieldtype:'Check', fieldname:'notify',
|
||||
label:__("Notify By Email"), "default":1},
|
||||
{fieldtype:'Check', fieldname:'restrict',
|
||||
label:__("Add This To User's Restrictions")
|
||||
|
|
@ -98,7 +97,7 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
{fieldtype:'Button', label:__("Add"), fieldname:'add_btn'}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
me.dialog.fields_dict.restrict.$wrapper
|
||||
.find(".assign-user-properties")
|
||||
.on("click", function() {
|
||||
|
|
@ -108,14 +107,14 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
};
|
||||
frappe.set_route("user-properties");
|
||||
});
|
||||
|
||||
|
||||
me.dialog.fields_dict.add_btn.input.onclick = function() {
|
||||
|
||||
|
||||
var assign_to = me.dialog.fields_dict.assign_to.get_value();
|
||||
var args = me.dialog.get_values();
|
||||
if(assign_to) {
|
||||
return frappe.call({
|
||||
method:'frappe.widgets.form.assign_to.add',
|
||||
method:'frappe.widgets.form.assign_to.add',
|
||||
args: $.extend(args, {
|
||||
doctype: me.frm.doctype,
|
||||
name: me.frm.docname,
|
||||
|
|
@ -135,19 +134,19 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
me.dialog.fields_dict.assign_to.get_query = "frappe.core.doctype.user.user.user_query";
|
||||
}
|
||||
me.dialog.clear();
|
||||
|
||||
|
||||
(function toggle_restrict() {
|
||||
var can_restrict = frappe.model.can_restrict(me.frm.doctype, me.frm);
|
||||
me.dialog.fields_dict.restrict.$wrapper.toggle(can_restrict);
|
||||
me.dialog.get_input("restrict").prop("checked", can_restrict);
|
||||
})();
|
||||
|
||||
|
||||
if(me.frm.meta.title_field) {
|
||||
me.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field])
|
||||
}
|
||||
|
||||
|
||||
me.dialog.show();
|
||||
|
||||
|
||||
if(!frappe.perm.get_perm(me.frm.doctype)[0].restricted) {
|
||||
me.dialog.fields_dict.restrict.set_input(0);
|
||||
me.dialog.fields_dict.restrict.$wrapper.toggle(false);
|
||||
|
|
|
|||
|
|
@ -103,14 +103,15 @@ frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({
|
|||
make: function() {
|
||||
this._super();
|
||||
var me = this;
|
||||
this.$wrapper = $("<div></div>").appendTo(this.parent);
|
||||
this.$body = $("<div>").appendTo(this.$wrapper)
|
||||
.css({"margin-bottom": "10px", "margin-right": "15px", "float": "right",
|
||||
"text-align": "right", "max-width": "100%"})
|
||||
this.$wrapper = $("<div class='row'><div class='col-xs-4'></div></div>")
|
||||
.appendTo(this.parent)
|
||||
.css({"max-width": "600px", "margin": "0px"});
|
||||
this.$body = $("<div class='col-xs-8'>").appendTo(this.$wrapper)
|
||||
.css({"margin-bottom": "10px", "max-width": "100%"})
|
||||
this.$wrapper.on("refresh", function() {
|
||||
me.$body.empty();
|
||||
if(me.df.options && me.frm.doc[me.df.options]) {
|
||||
me.$img = $("<img src='"+me.frm.doc[me.df.options]+"' style='max-width: 70%;'>")
|
||||
me.$img = $("<img src='"+me.frm.doc[me.df.options]+"' style='max-width: 100%;'>")
|
||||
.appendTo(me.$body);
|
||||
} else {
|
||||
me.$buffer = $("<div class='missing-image'><i class='icon-camera'></i></div>")
|
||||
|
|
@ -694,7 +695,7 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({
|
|||
// set the default option (displayed)
|
||||
var input_value = this.$input.val();
|
||||
var model_value = frappe.model.get_value(this.doctype, this.docname, this.df.fieldname);
|
||||
if(model_value == null && input_value != (model_value || "")) {
|
||||
if(model_value == null && (input_value || "") != (model_value || "")) {
|
||||
this.set_model_value(input_value);
|
||||
} else {
|
||||
this.last_value = value;
|
||||
|
|
@ -784,16 +785,14 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
|
|||
this.$input.on("focus", function() {
|
||||
setTimeout(function() {
|
||||
if(!me.$input.val()) {
|
||||
me.$input.val("%").trigger("keydown");
|
||||
me.$input.autocomplete("search", "");
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
}, 500);
|
||||
});
|
||||
this.input = this.$input.get(0);
|
||||
this.has_input = true;
|
||||
//this.bind_change_event();
|
||||
var me = this;
|
||||
this.setup_buttons();
|
||||
//this.setup_typeahead();
|
||||
this.setup_autocomplete();
|
||||
},
|
||||
setup_buttons: function() {
|
||||
|
|
@ -841,10 +840,19 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
|
|||
if(value!==me.last_value) {
|
||||
me.parse_validate_and_set_in_model(value);
|
||||
}
|
||||
}});
|
||||
}
|
||||
});
|
||||
|
||||
var cache = {};
|
||||
this.$input.autocomplete({
|
||||
minLength: 0,
|
||||
source: function(request, response) {
|
||||
if (cache[request.term]!=null) {
|
||||
// from cache
|
||||
response(cache[request.term]);
|
||||
return;
|
||||
}
|
||||
|
||||
var args = {
|
||||
'txt': request.term,
|
||||
'doctype': me.df.options,
|
||||
|
|
@ -858,6 +866,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
|
|||
no_spinner: true,
|
||||
args: args,
|
||||
callback: function(r) {
|
||||
cache[request.term] = r.results;
|
||||
response(r.results);
|
||||
},
|
||||
});
|
||||
|
|
@ -879,17 +888,13 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
|
|||
}
|
||||
}
|
||||
}).data('ui-autocomplete')._renderItem = function(ul, d) {
|
||||
var html = "";
|
||||
if(keys(d).length > 1) {
|
||||
d.info = $.map(d, function(val, key) { return ["value", "label"].indexOf(key)!==-1 ? null : val }).join(", ") || "";
|
||||
html = repl("<a>%(value)s<br><span class='text-muted'>%(info)s</span></a>", d);
|
||||
} else {
|
||||
html = "<a>" + d.value + "</a>";
|
||||
var html = "<strong>" + d.value + "</strong>";
|
||||
if(d.value!==d.description) {
|
||||
html += '<br><span class="small">' + d.description + '</span>';
|
||||
}
|
||||
|
||||
return $('<li></li>')
|
||||
.data('item.autocomplete', d)
|
||||
.append(html)
|
||||
.html('<a><p>' + html + '</p></a>')
|
||||
.appendTo(ul);
|
||||
};
|
||||
// remove accessibility span (for now)
|
||||
|
|
|
|||
|
|
@ -109,13 +109,14 @@ frappe.ui.form.Grid = Class.extend({
|
|||
var me =this;
|
||||
$rows.sortable({
|
||||
handle: ".data-row, .panel-heading",
|
||||
helper: 'clone',
|
||||
update: function(event, ui) {
|
||||
me.frm.doc[me.df.parentfield] = [];
|
||||
me.frm.doc[me.df.fieldname] = [];
|
||||
$rows.find(".grid-row").each(function(i, item) {
|
||||
var doc = $(item).data("doc");
|
||||
doc.idx = i + 1;
|
||||
$(this).find(".row-index").html(i + 1);
|
||||
me.frm.doc[me.df.parentfield].push(doc);
|
||||
me.frm.doc[me.df.fieldname].push(doc);
|
||||
});
|
||||
me.frm.dirty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,12 +122,20 @@ frappe.ui.form.Layout = Class.extend({
|
|||
|
||||
if(df && df.idx===1)
|
||||
head.css({"margin-top": "0px"})
|
||||
if(this.sections.length > 1)
|
||||
this.section.css({
|
||||
"margin-top": "15px",
|
||||
"border-top": "1px solid #eee"
|
||||
});
|
||||
}
|
||||
|
||||
if(df.label || df.show_section_border) {
|
||||
if(this.sections.length > 1) {
|
||||
this.section.css("border-top", "1px solid #eee");
|
||||
|
||||
if (df.label) {
|
||||
this.section.css("margin-top", "15px");
|
||||
} else {
|
||||
this.section.css("padding-top", "15px");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(df.description) {
|
||||
$('<div class="col-md-12 small text-muted">' + df.description + '</div>')
|
||||
.css("padding-left", "40px")
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
name = name || this.frm.docname;
|
||||
handlers = this.get_handlers(event_name, doctype, name, callback);
|
||||
if(callback) handlers.push(callback);
|
||||
|
||||
|
||||
$.each(handlers, function(i, fn) {
|
||||
fn();
|
||||
})
|
||||
|
|
@ -38,7 +38,7 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
$.each(frappe.ui.form.handlers[doctype][event_name], function(i, fn) {
|
||||
handlers.push(function() { fn(me.frm, doctype, name) });
|
||||
});
|
||||
}
|
||||
}
|
||||
if(this.frm.cscript[event_name]) {
|
||||
handlers.push(function() { me.frm.cscript[event_name](me.frm.doc, doctype, name); });
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
},
|
||||
setup: function() {
|
||||
var doctype = this.frm.meta;
|
||||
var me = this;
|
||||
|
||||
// js
|
||||
var cs = doctype.__js;
|
||||
|
|
@ -56,6 +57,15 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
var tmp = eval(cs);
|
||||
}
|
||||
|
||||
// setup add fetch
|
||||
$.each(this.frm.fields, function(i, field) {
|
||||
var df = field.df;
|
||||
if(df.fieldtype==="Read Only" && df.options && df.options.indexOf(".")!=-1) {
|
||||
var parts = df.options.split(".");
|
||||
me.frm.add_fetch(parts[0], parts[1], df.fieldname);
|
||||
}
|
||||
});
|
||||
|
||||
// css
|
||||
doctype.__css && frappe.dom.set_style(doctype.__css);
|
||||
},
|
||||
|
|
@ -72,25 +82,25 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
},
|
||||
validate_link_and_fetch: function(df, docname, value, callback) {
|
||||
var me = this;
|
||||
|
||||
|
||||
if(value) {
|
||||
var fetch = '';
|
||||
|
||||
|
||||
if(this.frm && this.frm.fetch_dict[df.fieldname])
|
||||
fetch = this.frm.fetch_dict[df.fieldname].columns.join(', ');
|
||||
|
||||
|
||||
return frappe.call({
|
||||
method:'frappe.widgets.form.utils.validate_link',
|
||||
type: "GET",
|
||||
args: {
|
||||
'value': value,
|
||||
'options': df.options,
|
||||
'value': value,
|
||||
'options': df.options,
|
||||
'fetch': fetch
|
||||
},
|
||||
},
|
||||
no_spinner: true,
|
||||
callback: function(r) {
|
||||
if(r.message=='Ok') {
|
||||
if(r.fetch_values)
|
||||
if(r.fetch_values)
|
||||
me.set_fetch_values(df, docname, r.fetch_values);
|
||||
if(callback) callback(value);
|
||||
} else {
|
||||
|
|
@ -111,9 +121,9 @@ frappe.ui.form.ScriptManager = Class.extend({
|
|||
copy_from_first_row: function(parentfield, current_row, fieldnames) {
|
||||
var doclist = this.frm.doc[parentfield];
|
||||
if(doclist.length===1 || doclist[0]===current_row) return;
|
||||
|
||||
|
||||
$.each(fieldnames, function(i, fieldname) {
|
||||
current_row[fieldname] = doclist[0][fieldname];
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -207,7 +207,10 @@ frappe.ui.form.Toolbar = Class.extend({
|
|||
current = this.appframe.get_title_right_text(),
|
||||
status = null;
|
||||
|
||||
this.appframe.clear_primary_action();
|
||||
if (!this.frm.doc.__unsaved) {
|
||||
// don't clear actions menu if dirty
|
||||
this.appframe.clear_primary_action();
|
||||
}
|
||||
|
||||
if (this.can_submit()) {
|
||||
status = "Submit";
|
||||
|
|
|
|||
|
|
@ -8,17 +8,17 @@ frappe.tools.downloadify = function(data, roles, me) {
|
|||
msgprint(__("Export not allowed. You need {0} role to export.", [frappe.utils.comma_or(roles)]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var _get_data = function() { return frappe.tools.to_csv(data); };
|
||||
var flash_disabled = (navigator.mimeTypes["application/x-shockwave-flash"] == undefined);
|
||||
|
||||
|
||||
var download_from_server = function() {
|
||||
open_url_post("/", {
|
||||
args: { data: data, filename: me.title },
|
||||
cmd: "frappe.utils.datautils.send_csv_to_client"
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
// save file > abt 200 kb using server call
|
||||
if((_get_data().length > 200000) || flash_disabled) {
|
||||
download_from_server();
|
||||
|
|
@ -36,8 +36,8 @@ frappe.tools.downloadify = function(data, roles, me) {
|
|||
return me.title + '.csv';
|
||||
},
|
||||
data: _get_data,
|
||||
swf: 'lib/js/lib/downloadify/downloadify.swf',
|
||||
downloadImage: 'lib/js/lib/downloadify/download.png',
|
||||
swf: 'assets/frappe/js/lib/downloadify/downloadify.swf',
|
||||
downloadImage: 'assets/frappe/js/lib/downloadify/download.png',
|
||||
onComplete: function(){
|
||||
$(msgobj.msg_area).html("<p>Saved</p>")
|
||||
},
|
||||
|
|
@ -46,7 +46,7 @@ frappe.tools.downloadify = function(data, roles, me) {
|
|||
width: 100,
|
||||
height: 30,
|
||||
transparent: true,
|
||||
append: false
|
||||
append: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -56,11 +56,11 @@ frappe.markdown = function(txt) {
|
|||
frappe.require('assets/frappe/js/lib/markdown.js');
|
||||
frappe.md2html = new Showdown.converter();
|
||||
}
|
||||
|
||||
|
||||
while(txt.substr(0,1)==="\n") {
|
||||
txt = txt.substr(1);
|
||||
}
|
||||
|
||||
|
||||
// remove leading tab (if they exist in the first line)
|
||||
var whitespace_len = 0,
|
||||
first_line = txt.split("\n")[0];
|
||||
|
|
@ -69,7 +69,7 @@ frappe.markdown = function(txt) {
|
|||
whitespace_len++;
|
||||
first_line = first_line.substr(1);
|
||||
}
|
||||
|
||||
|
||||
if(whitespace_len && whitespace_len != first_line.length) {
|
||||
var txt1 = [];
|
||||
$.each(txt.split("\n"), function(i, t) {
|
||||
|
|
@ -77,7 +77,7 @@ frappe.markdown = function(txt) {
|
|||
})
|
||||
txt = txt1.join("\n");
|
||||
}
|
||||
|
||||
|
||||
return frappe.md2html.makeHtml(txt);
|
||||
}
|
||||
|
||||
|
|
@ -109,9 +109,9 @@ frappe.slickgrid_tools = {
|
|||
}
|
||||
row.push(val);
|
||||
});
|
||||
|
||||
|
||||
if(!filter || filter(row, d)) {
|
||||
res.push(row);
|
||||
res.push(row);
|
||||
}
|
||||
}
|
||||
return [col_row].concat(res);
|
||||
|
|
@ -119,7 +119,7 @@ frappe.slickgrid_tools = {
|
|||
add_property_setter_on_resize: function(grid) {
|
||||
grid.onColumnsResized.subscribe(function(e, args) {
|
||||
$.each(grid.getColumns(), function(i, col) {
|
||||
if(col.docfield && col.previousWidth != col.width &&
|
||||
if(col.docfield && col.previousWidth != col.width &&
|
||||
!in_list(frappe.model.std_fields_list, col.docfield.fieldname) ) {
|
||||
frappe.call({
|
||||
method:"frappe.client.make_width_property_setter",
|
||||
|
|
@ -131,7 +131,7 @@ frappe.slickgrid_tools = {
|
|||
field_name: col.docfield.fieldname,
|
||||
property: 'width',
|
||||
value: col.width,
|
||||
"__islocal": 1
|
||||
"__islocal": 1
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
|
@ -140,5 +140,5 @@ frappe.slickgrid_tools = {
|
|||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ $.extend(frappe.model, {
|
|||
doc[f.fieldname] = v;
|
||||
updated.push(f.fieldname);
|
||||
} else if(f.fieldtype == "Select" && f.options
|
||||
&& f.options.substr(0, 5)!="link:" && f.options!="[Select]") {
|
||||
&& f.options!="[Select]") {
|
||||
doc[f.fieldname] = f.options.split("\n")[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +166,14 @@ $.extend(frappe.model, {
|
|||
},
|
||||
|
||||
open_mapped_doc: function(opts) {
|
||||
if (opts.frm && opts.frm.doc.__unsaved) {
|
||||
frappe.throw(__("You have unsaved changes in this form. Please save before you continue."));
|
||||
|
||||
} else if (!opts.source_name && opts.frm) {
|
||||
opts.source_name = opts.frm.doc.name;
|
||||
|
||||
}
|
||||
|
||||
return frappe.call({
|
||||
type: "GET",
|
||||
method: opts.method,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({
|
|||
init: function(opts) {
|
||||
this.display = false;
|
||||
this.is_dialog = true;
|
||||
if(!opts.width) opts.width = 600;
|
||||
if(!opts.width) opts.width = "600px";
|
||||
|
||||
$.extend(this, opts);
|
||||
this._super();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
bsEditor = Class.extend({
|
||||
init: function(options) {
|
||||
this.options = $.extend(options || {}, this.default_options);
|
||||
this.options = $.extend({}, this.default_options, options || {});
|
||||
this.edit_mode = true;
|
||||
if(this.options.editor) {
|
||||
this.setup_editor(this.options.editor);
|
||||
|
|
@ -100,7 +100,7 @@ bsEditor = Class.extend({
|
|||
active_toolbar_class: 'btn-info',
|
||||
selection_marker: 'edit-focus-marker',
|
||||
selection_color: 'darkgrey',
|
||||
remove_typography: true,
|
||||
remove_typography: false,
|
||||
max_file_size: 1,
|
||||
},
|
||||
|
||||
|
|
@ -126,15 +126,18 @@ bsEditor = Class.extend({
|
|||
|
||||
var html = this.editor.html() || "";
|
||||
if(!$.trim(this.editor.text()) && !(this.editor.find("img"))) html = "";
|
||||
// html = html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
|
||||
|
||||
// remove custom typography (use CSS!)
|
||||
if(this.options.remove_typography) {
|
||||
html = html.replace(/(font-family|font-size|line-height):[^;]*;/g, '');
|
||||
html = html.replace(/<[^>]*(font=['"][^'"]*['"])>/g, function(a,b) { return a.replace(b, ''); });
|
||||
html = html.replace(/\s*style\s*=\s*["']\s*["']/g, '');
|
||||
return html;
|
||||
var tmp = $("<div></div>").html(html);
|
||||
// remove style attributes
|
||||
tmp.find("*")
|
||||
.removeAttr("style")
|
||||
.removeAttr("font");
|
||||
html = tmp.html();
|
||||
}
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
init_file_drops: function () {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
me.listobj.run();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
show_filters: function() {
|
||||
this.$w.find('.show_filters').toggle();
|
||||
if(!this.filters.length)
|
||||
|
|
@ -29,7 +29,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
this.filters = [];
|
||||
this.$w.find('.filter_area').empty();
|
||||
},
|
||||
|
||||
|
||||
add_filter: function(tablename, fieldname, condition, value) {
|
||||
this.push_new_filter(tablename, fieldname, condition, value);
|
||||
// list must be expanded
|
||||
|
|
@ -37,7 +37,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
this.$w.find('.show_filters').toggle(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
push_new_filter: function(tablename, fieldname, condition, value) {
|
||||
this.filters.push(new frappe.ui.Filter({
|
||||
flist: this,
|
||||
|
|
@ -47,7 +47,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
value: value
|
||||
}));
|
||||
},
|
||||
|
||||
|
||||
get_filters: function() {
|
||||
// get filter values as dict
|
||||
var values = [];
|
||||
|
|
@ -57,7 +57,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
})
|
||||
return values;
|
||||
},
|
||||
|
||||
|
||||
// remove hidden filters
|
||||
update_filters: function() {
|
||||
var fl = [];
|
||||
|
|
@ -66,7 +66,7 @@ frappe.ui.FilterList = Class.extend({
|
|||
})
|
||||
this.filters = fl;
|
||||
},
|
||||
|
||||
|
||||
get_filter: function(fieldname) {
|
||||
for(var i in this.filters) {
|
||||
if(this.filters[i].field && this.filters[i].field.df.fieldname==fieldname)
|
||||
|
|
@ -109,29 +109,30 @@ frappe.ui.Filter = Class.extend({
|
|||
make_select: function() {
|
||||
var me = this;
|
||||
this.fieldselect = new frappe.ui.FieldSelect({
|
||||
parent: this.$w.find('.fieldname_select_area'),
|
||||
doctype: this.doctype,
|
||||
filter_fields: this.filter_fields,
|
||||
parent: this.$w.find('.fieldname_select_area'),
|
||||
doctype: this.doctype,
|
||||
filter_fields: this.filter_fields,
|
||||
select: function(doctype, fieldname) {
|
||||
me.set_field(doctype, fieldname);
|
||||
}
|
||||
});
|
||||
this.fieldselect.set_value(this.doctype, this.fieldname);
|
||||
},
|
||||
set_events: function() {
|
||||
var me = this;
|
||||
|
||||
this.$w.find('a.close').bind('click', function() {
|
||||
|
||||
this.$w.find('a.close').bind('click', function() {
|
||||
me.$w.css('display','none');
|
||||
var value = me.field.get_parsed_value();
|
||||
var fieldname = me.field.df.fieldname;
|
||||
me.field = null;
|
||||
|
||||
|
||||
// hide filter section
|
||||
if(!me.flist.get_filters().length) {
|
||||
me.flist.$w.find('.set_filters').toggle(true);
|
||||
me.flist.$w.find('.show_filters').toggle(false);
|
||||
}
|
||||
|
||||
|
||||
me.flist.update_filters();
|
||||
me.flist.listobj.dirty = true;
|
||||
me.flist.listobj.run();
|
||||
|
|
@ -144,33 +145,33 @@ frappe.ui.Filter = Class.extend({
|
|||
me.set_field(me.field.df.parent, me.field.df.fieldname, 'Data');
|
||||
if(!me.field.desc_area)
|
||||
me.field.desc_area = $a(me.field.wrapper, 'span', 'help', null,
|
||||
'values separated by comma');
|
||||
'values separated by comma');
|
||||
} else {
|
||||
me.set_field(me.field.df.parent, me.field.df.fieldname, null,
|
||||
me.$w.find('.condition').val());
|
||||
me.set_field(me.field.df.parent, me.field.df.fieldname, null,
|
||||
me.$w.find('.condition').val());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// set the field
|
||||
if(me.fieldname) {
|
||||
// presents given (could be via tags!)
|
||||
this.set_values(me.tablename, me.fieldname, me.condition, me.value);
|
||||
} else {
|
||||
me.set_field(me.doctype, 'name');
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
set_values: function(tablename, fieldname, condition, value) {
|
||||
// presents given (could be via tags!)
|
||||
this.set_field(tablename, fieldname);
|
||||
if(condition) this.$w.find('.condition').val(condition).change();
|
||||
if(value!=null) this.field.set_input(value);
|
||||
},
|
||||
|
||||
|
||||
set_field: function(doctype, fieldname, fieldtype, condition) {
|
||||
var me = this;
|
||||
|
||||
|
||||
// set in fieldname (again)
|
||||
var cur = me.field ? {
|
||||
fieldname: me.field.df.fieldname,
|
||||
|
|
@ -185,13 +186,12 @@ frappe.ui.Filter = Class.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
var df = copy_dict(me.fieldselect.fields_by_name[doctype][fieldname]);
|
||||
this.set_fieldtype(df, fieldtype);
|
||||
|
||||
// called when condition is changed,
|
||||
|
||||
// called when condition is changed,
|
||||
// don't change if all is well
|
||||
if(me.field && cur.fieldname == fieldname && df.fieldtype == cur.fieldtype &&
|
||||
if(me.field && cur.fieldname == fieldname && df.fieldtype == cur.fieldtype &&
|
||||
df.parent == cur.parent) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -199,13 +199,13 @@ frappe.ui.Filter = Class.extend({
|
|||
// clear field area and make field
|
||||
me.fieldselect.selected_doctype = doctype;
|
||||
me.fieldselect.selected_fieldname = fieldname;
|
||||
|
||||
|
||||
// save old text
|
||||
var old_text = null;
|
||||
if(me.field) {
|
||||
old_text = me.field.get_parsed_value();
|
||||
}
|
||||
|
||||
|
||||
var field_area = me.$w.find('.filter_field').empty().get(0);
|
||||
var f = frappe.ui.form.make_control({
|
||||
df: df,
|
||||
|
|
@ -213,13 +213,13 @@ frappe.ui.Filter = Class.extend({
|
|||
only_input: true,
|
||||
})
|
||||
f.refresh();
|
||||
|
||||
|
||||
me.field = f;
|
||||
if(old_text)
|
||||
if(old_text && me.field.df.fieldtype===cur.fieldtype)
|
||||
me.field.set_input(old_text);
|
||||
|
||||
|
||||
if(!condition) this.set_default_condition(df, fieldtype);
|
||||
|
||||
|
||||
// run on enter
|
||||
$(me.field.wrapper).find(':input').keydown(function(ev) {
|
||||
if(ev.which==13) {
|
||||
|
|
@ -227,33 +227,33 @@ frappe.ui.Filter = Class.extend({
|
|||
}
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
set_fieldtype: function(df, fieldtype) {
|
||||
// reset
|
||||
if(df.original_type)
|
||||
df.fieldtype = df.original_type;
|
||||
else
|
||||
df.original_type = df.fieldtype;
|
||||
|
||||
|
||||
df.description = ''; df.reqd = 0;
|
||||
|
||||
|
||||
// given
|
||||
if(fieldtype) {
|
||||
df.fieldtype = fieldtype;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// scrub
|
||||
if(df.fieldtype=='Check') {
|
||||
df.fieldtype='Select';
|
||||
df.options='No\nYes';
|
||||
} else if(['Text','Small Text','Text Editor','Code','Tags','Comments'].indexOf(df.fieldtype)!=-1) {
|
||||
df.fieldtype = 'Data';
|
||||
df.fieldtype = 'Data';
|
||||
} else if(df.fieldtype=='Link' && this.$w.find('.condition').val()!="=") {
|
||||
df.fieldtype = 'Data';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
set_default_condition: function(df, fieldtype) {
|
||||
if(!fieldtype) {
|
||||
// set as "like" for data fields
|
||||
|
|
@ -261,27 +261,27 @@ frappe.ui.Filter = Class.extend({
|
|||
this.$w.find('.condition').val('like');
|
||||
} else {
|
||||
this.$w.find('.condition').val('=');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get_value: function() {
|
||||
var me = this;
|
||||
var val = me.field.get_parsed_value();
|
||||
var cond = me.$w.find('.condition').val();
|
||||
|
||||
|
||||
if(me.field.df.original_type == 'Check') {
|
||||
val = (val=='Yes' ? 1 :0);
|
||||
}
|
||||
|
||||
|
||||
if(cond=='like') {
|
||||
// add % only if not there at the end
|
||||
if ((val.length === 0) || (val.lastIndexOf("%") !== (val.length - 1))) {
|
||||
val = (val || "") + '%';
|
||||
}
|
||||
} else if(val === '%') val = null;
|
||||
|
||||
return [me.fieldselect.selected_doctype,
|
||||
|
||||
return [me.fieldselect.selected_doctype,
|
||||
me.field.df.fieldname, me.$w.find('.condition').val(), val];
|
||||
}
|
||||
|
||||
|
|
@ -311,10 +311,10 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(this.filter_fields) {
|
||||
for(var i in this.filter_fields)
|
||||
this.add_field_option(this.filter_fields[i])
|
||||
this.add_field_option(this.filter_fields[i])
|
||||
} else {
|
||||
this.build_options();
|
||||
}
|
||||
|
|
@ -340,14 +340,14 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
var me = this;
|
||||
this.clear();
|
||||
if(!doctype) return;
|
||||
|
||||
|
||||
// old style
|
||||
if(doctype.indexOf(".")!==-1) {
|
||||
parts = doctype.split(".");
|
||||
doctype = parts[0];
|
||||
fieldname = parts[1];
|
||||
}
|
||||
|
||||
|
||||
$.each(this.options, function(i, v) {
|
||||
if(v.doctype===doctype && v.fieldname===fieldname) {
|
||||
me.selected_doctype = doctype;
|
||||
|
|
@ -365,7 +365,7 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
if(d.fieldname=="name") opts.options = me.doctype;
|
||||
return $.extend(copy_dict(d), opts);
|
||||
});
|
||||
|
||||
|
||||
// add parenttype column
|
||||
var doctype_obj = locals['DocType'][me.doctype];
|
||||
if(doctype_obj && cint(doctype_obj.istable)) {
|
||||
|
|
@ -376,7 +376,7 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
parent: me.doctype,
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
// blank
|
||||
if(this.with_blank) {
|
||||
this.options.push({
|
||||
|
|
@ -414,7 +414,7 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
var label = df.label + ' (' + df.parent + ')';
|
||||
var table = df.parent;
|
||||
}
|
||||
if(frappe.model.no_value_type.indexOf(df.fieldtype)==-1 &&
|
||||
if(frappe.model.no_value_type.indexOf(df.fieldtype)==-1 &&
|
||||
!(me.fields_by_name[df.parent] && me.fields_by_name[df.parent][df.fieldname])) {
|
||||
this.options.push({
|
||||
label: __(label),
|
||||
|
|
@ -423,7 +423,7 @@ frappe.ui.FieldSelect = Class.extend({
|
|||
doctype: df.parent
|
||||
})
|
||||
if(!me.fields_by_name[df.parent]) me.fields_by_name[df.parent] = {};
|
||||
me.fields_by_name[df.parent][df.fieldname] = df;
|
||||
me.fields_by_name[df.parent][df.fieldname] = df;
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -257,5 +257,8 @@ frappe.ui.toolbar.show_about = function() {
|
|||
}
|
||||
|
||||
frappe.ui.toolbar.show_banner = function(msg) {
|
||||
return $('<div class="toolbar-banner"></div>').html(msg).appendTo($('header'));
|
||||
$banner = $('<div class="toolbar-banner">'+msg+'<a class="close">×</a></div>')
|
||||
.appendTo($('header'));
|
||||
$banner.find(".close").click(function() { $(".toolbar-banner").toggle(false); });
|
||||
return $banner;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ $.extend(frappe.report_dump, {
|
|||
$.each(r.message, function(doctype, doctype_data) {
|
||||
frappe.report_dump.set_data(doctype, doctype_data);
|
||||
});
|
||||
|
||||
|
||||
// reverse map names
|
||||
$.each(r.message, function(doctype, doctype_data) {
|
||||
// only if not pre-loaded
|
||||
|
|
@ -38,7 +38,7 @@ $.extend(frappe.report_dump, {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
callback();
|
||||
},
|
||||
progress_bar: progress_bar
|
||||
|
|
@ -62,7 +62,7 @@ $.extend(frappe.report_dump, {
|
|||
var row = make_row(d);
|
||||
replace_dict[row.name] = row;
|
||||
});
|
||||
|
||||
|
||||
// replace old data
|
||||
$.each(frappe.report_dump.data[doctype], function(i, d) {
|
||||
if(replace_dict[d.name]) {
|
||||
|
|
@ -75,13 +75,13 @@ $.extend(frappe.report_dump, {
|
|||
data.push(d);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// add new records
|
||||
$.each(replace_dict, function(name, d) {
|
||||
data.push(d);
|
||||
})
|
||||
} else {
|
||||
|
||||
|
||||
// first loading
|
||||
$.each(doctype_data.data, function(i, d) {
|
||||
data.push(make_row(d));
|
||||
|
|
@ -96,20 +96,20 @@ frappe.provide("frappe.views");
|
|||
frappe.views.GridReport = Class.extend({
|
||||
init: function(opts) {
|
||||
frappe.require("assets/js/slickgrid.min.js");
|
||||
|
||||
|
||||
this.filter_inputs = {};
|
||||
this.preset_checks = [];
|
||||
this.tree_grid = {show: false};
|
||||
var me = this;
|
||||
$.extend(this, opts);
|
||||
|
||||
|
||||
this.wrapper = $('<div>').appendTo(this.parent);
|
||||
|
||||
|
||||
if(this.filters) {
|
||||
this.make_filters();
|
||||
}
|
||||
this.make_waiting();
|
||||
|
||||
|
||||
this.get_data_and_refresh();
|
||||
},
|
||||
bind_show: function() {
|
||||
|
|
@ -118,14 +118,14 @@ frappe.views.GridReport = Class.extend({
|
|||
// this must be called after init
|
||||
// because "frappe.container.page" will only be set
|
||||
// once "load" event is over.
|
||||
|
||||
|
||||
var me = this;
|
||||
$(this.page).bind('show', function() {
|
||||
// reapply filters on show
|
||||
frappe.cur_grid_report = me;
|
||||
me.get_data_and_refresh();
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
get_data_and_refresh: function() {
|
||||
var me = this;
|
||||
|
|
@ -139,7 +139,7 @@ frappe.views.GridReport = Class.extend({
|
|||
var progress_bar = null;
|
||||
if(!this.setup_filters_done)
|
||||
progress_bar = this.wrapper.find(".progress .progress-bar");
|
||||
|
||||
|
||||
frappe.report_dump.with_data(this.doctypes, function() {
|
||||
if(!me.setup_filters_done) {
|
||||
me.setup_filters();
|
||||
|
|
@ -160,28 +160,28 @@ frappe.views.GridReport = Class.extend({
|
|||
function(d) { return d.name; });
|
||||
me.set_autocomplete(v, opts.list);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// refresh
|
||||
this.filter_inputs.refresh && this.filter_inputs.refresh.click(function() {
|
||||
this.filter_inputs.refresh && this.filter_inputs.refresh.click(function() {
|
||||
me.get_data(function() {
|
||||
me.refresh();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// reset filters
|
||||
this.filter_inputs.reset_filters && this.filter_inputs.reset_filters.click(function() {
|
||||
me.init_filter_values();
|
||||
this.filter_inputs.reset_filters && this.filter_inputs.reset_filters.click(function() {
|
||||
me.init_filter_values();
|
||||
me.refresh();
|
||||
});
|
||||
|
||||
|
||||
// range
|
||||
this.filter_inputs.range && this.filter_inputs.range.on("change", function() {
|
||||
me.refresh();
|
||||
});
|
||||
|
||||
|
||||
// plot check
|
||||
if(this.setup_plot_check)
|
||||
if(this.setup_plot_check)
|
||||
this.setup_plot_check();
|
||||
},
|
||||
set_filter: function(key, value) {
|
||||
|
|
@ -223,7 +223,7 @@ frappe.views.GridReport = Class.extend({
|
|||
filter.val("");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.set_default_values();
|
||||
},
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ frappe.views.GridReport = Class.extend({
|
|||
from_date: dateutil.str_to_user(sys_defaults.year_start_date),
|
||||
to_date: dateutil.str_to_user(sys_defaults.year_end_date)
|
||||
}
|
||||
|
||||
|
||||
var me = this;
|
||||
$.each(values, function(i, v) {
|
||||
if(me.filter_inputs[i] && !me.filter_inputs[i].val())
|
||||
|
|
@ -281,7 +281,7 @@ frappe.views.GridReport = Class.extend({
|
|||
});
|
||||
},
|
||||
make_waiting: function() {
|
||||
this.waiting = frappe.messages.waiting(this.wrapper, __("Loading Report")+"...", '10');
|
||||
this.waiting = frappe.messages.waiting(this.wrapper, __("Loading Report")+"...", '10');
|
||||
},
|
||||
load_filter_values: function() {
|
||||
var me = this;
|
||||
|
|
@ -298,12 +298,12 @@ frappe.views.GridReport = Class.extend({
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(this.filter_inputs.from_date && this.filter_inputs.to_date && (this.to_date < this.from_date)) {
|
||||
msgprint(__("From Date must be before To Date"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
make_name_map: function(data, key) {
|
||||
|
|
@ -314,7 +314,7 @@ frappe.views.GridReport = Class.extend({
|
|||
})
|
||||
return map;
|
||||
},
|
||||
|
||||
|
||||
reset_item_values: function(item) {
|
||||
var me = this;
|
||||
$.each(this.columns, function(i, col) {
|
||||
|
|
@ -323,7 +323,7 @@ frappe.views.GridReport = Class.extend({
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
round_item_values: function(item) {
|
||||
var me = this;
|
||||
$.each(this.columns, function(i, col) {
|
||||
|
|
@ -332,17 +332,17 @@ frappe.views.GridReport = Class.extend({
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
round_off_data: function() {
|
||||
var me = this;
|
||||
$.each(this.data, function(i, d) {
|
||||
me.round_item_values(d);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
refresh: function() {
|
||||
this.waiting.toggle(false);
|
||||
if(!this.grid_wrapper)
|
||||
if(!this.grid_wrapper)
|
||||
this.make();
|
||||
this.show_zero = $('.show-zero input:checked').length;
|
||||
this.load_filter_values();
|
||||
|
|
@ -361,15 +361,15 @@ frappe.views.GridReport = Class.extend({
|
|||
setup_dataview_columns: function() {
|
||||
this.dataview_columns = $.map(this.columns, function(col) {
|
||||
return !col.hidden ? col : null;
|
||||
});
|
||||
});
|
||||
},
|
||||
make: function() {
|
||||
var me = this;
|
||||
|
||||
|
||||
// plot wrapper
|
||||
this.plot_area = $('<div class="plot" style="margin-bottom: 15px; display: none; \
|
||||
height: 300px; width: 100%;"></div>').appendTo(this.wrapper);
|
||||
|
||||
|
||||
// print / export
|
||||
$('<div style="text-align: right;"> \
|
||||
<div class="processing" style="background-color: #fec; display: none; \
|
||||
|
|
@ -377,9 +377,9 @@ frappe.views.GridReport = Class.extend({
|
|||
<a href="#" class="grid-report-export"> \
|
||||
<i class="icon icon-download-alt"></i> Export</a> \
|
||||
</div>').appendTo(this.wrapper);
|
||||
|
||||
|
||||
this.wrapper.find(".grid-report-export").click(function() { return me.export(); });
|
||||
|
||||
|
||||
// grid wrapper
|
||||
this.grid_wrapper = $("<div style='height: 500px; border: 1px solid #aaa; \
|
||||
background-color: #eee; margin-top: 15px;'>")
|
||||
|
|
@ -392,10 +392,10 @@ frappe.views.GridReport = Class.extend({
|
|||
+'</div>').appendTo(this.wrapper);
|
||||
|
||||
this.bind_show();
|
||||
|
||||
|
||||
frappe.cur_grid_report = this;
|
||||
$(this.wrapper).trigger('make');
|
||||
|
||||
|
||||
},
|
||||
apply_filters_from_route: function() {
|
||||
var me = this;
|
||||
|
|
@ -432,12 +432,12 @@ frappe.views.GridReport = Class.extend({
|
|||
me.grid.invalidateRows(args.rows);
|
||||
me.grid.render();
|
||||
});
|
||||
|
||||
|
||||
this.dataView.onRowCountChanged.subscribe(function (e, args) {
|
||||
me.grid.updateRowCount();
|
||||
me.grid.render();
|
||||
});
|
||||
|
||||
|
||||
this.tree_grid.show && this.add_tree_grid_events();
|
||||
},
|
||||
prepare_data_view: function() {
|
||||
|
|
@ -459,13 +459,13 @@ frappe.views.GridReport = Class.extend({
|
|||
// from all filter_inputs
|
||||
var filters = this.filter_inputs;
|
||||
if(item._show) return true;
|
||||
|
||||
|
||||
for (i in filters) {
|
||||
if(!this.apply_filter(item, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
},
|
||||
apply_filter: function(item, fieldname) {
|
||||
|
|
@ -485,11 +485,11 @@ frappe.views.GridReport = Class.extend({
|
|||
if(col.formatter==me.currency_formatter && !col.hidden) {
|
||||
if(flt(item[col.field]) > 0.001 || flt(item[col.field]) < -0.001) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
show_zero_check: function() {
|
||||
|
|
@ -497,7 +497,7 @@ frappe.views.GridReport = Class.extend({
|
|||
this.wrapper.bind('make', function() {
|
||||
me.wrapper.find('.show-zero').toggle(true).find('input').click(function(){
|
||||
me.refresh();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
is_default: function(fieldname) {
|
||||
|
|
@ -535,16 +535,16 @@ frappe.views.GridReport = Class.extend({
|
|||
// link_formatter must have
|
||||
// filter_input, open_btn (true / false), doctype (will be eval'd)
|
||||
if(!value) return "";
|
||||
|
||||
|
||||
var me = frappe.cur_grid_report;
|
||||
|
||||
|
||||
if(dataContext._show) {
|
||||
return repl('<span style="%(_style)s">%(value)s</span>', {
|
||||
_style: dataContext._style || "",
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// make link to add a filter
|
||||
var link_formatter = me.dataview_columns[cell].link_formatter;
|
||||
if (link_formatter.filter_input) {
|
||||
|
|
@ -562,8 +562,8 @@ frappe.views.GridReport = Class.extend({
|
|||
|
||||
// make icon to open form
|
||||
if(link_formatter.open_btn) {
|
||||
var doctype = link_formatter.doctype
|
||||
? eval(link_formatter.doctype)
|
||||
var doctype = link_formatter.doctype
|
||||
? eval(link_formatter.doctype)
|
||||
: dataContext.doctype;
|
||||
html += me.get_link_open_icon(doctype, value);
|
||||
}
|
||||
|
|
@ -576,21 +576,21 @@ frappe.views.GridReport = Class.extend({
|
|||
return repl(' <a href="#Form/%(doctype)s/%(name)s">\
|
||||
<i class="icon icon-share" style="cursor: pointer;"></i></a>', {
|
||||
doctype: doctype,
|
||||
name: encodeURIComponent(name)
|
||||
name: encodeURIComponent(name)
|
||||
});
|
||||
},
|
||||
make_date_range_columns: function() {
|
||||
this.columns = [];
|
||||
|
||||
|
||||
var me = this;
|
||||
var range = this.filter_inputs.range.val();
|
||||
this.from_date = dateutil.user_to_str(this.filter_inputs.from_date.val());
|
||||
this.to_date = dateutil.user_to_str(this.filter_inputs.to_date.val());
|
||||
var date_diff = dateutil.get_diff(this.to_date, this.from_date);
|
||||
|
||||
|
||||
me.column_map = {};
|
||||
me.last_date = null;
|
||||
|
||||
|
||||
var add_column = function(date) {
|
||||
me.columns.push({
|
||||
id: date,
|
||||
|
|
@ -600,22 +600,22 @@ frappe.views.GridReport = Class.extend({
|
|||
width: 100
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var build_columns = function(condition) {
|
||||
// add column for each date range
|
||||
for(var i=0; i <= date_diff; i++) {
|
||||
var date = dateutil.add_days(me.from_date, i);
|
||||
if(!condition) condition = function() { return true; }
|
||||
|
||||
|
||||
if(condition(date)) add_column(date);
|
||||
me.last_date = date;
|
||||
|
||||
|
||||
if(me.columns.length) {
|
||||
me.column_map[date] = me.columns[me.columns.length-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// make columns for all date ranges
|
||||
if(range=='Daily') {
|
||||
build_columns();
|
||||
|
|
@ -623,7 +623,7 @@ frappe.views.GridReport = Class.extend({
|
|||
build_columns(function(date) {
|
||||
if(!me.last_date) return true;
|
||||
return !(dateutil.get_diff(date, me.from_date) % 7)
|
||||
});
|
||||
});
|
||||
} else if(range=='Monthly') {
|
||||
build_columns(function(date) {
|
||||
if(!me.last_date) return true;
|
||||
|
|
@ -633,7 +633,7 @@ frappe.views.GridReport = Class.extend({
|
|||
build_columns(function(date) {
|
||||
if(!me.last_date) return true;
|
||||
return dateutil.str_to_obj(date).getDate()==1 && in_list([0,3,6,9], dateutil.str_to_obj(date).getMonth())
|
||||
});
|
||||
});
|
||||
} else if(range=='Yearly') {
|
||||
build_columns(function(date) {
|
||||
if(!me.last_date) return true;
|
||||
|
|
@ -641,15 +641,15 @@ frappe.views.GridReport = Class.extend({
|
|||
return date==v.year_start_date ? true : null;
|
||||
}).length;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// set label as last date of period
|
||||
$.each(this.columns, function(i, col) {
|
||||
col.name = me.columns[i+1]
|
||||
? dateutil.str_to_user(dateutil.add_days(me.columns[i+1].id, -1))
|
||||
: dateutil.str_to_user(me.to_date);
|
||||
});
|
||||
: dateutil.str_to_user(me.to_date);
|
||||
});
|
||||
},
|
||||
trigger_refresh_on_change: function(filters) {
|
||||
var me = this;
|
||||
|
|
@ -670,10 +670,10 @@ frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
|
|||
}
|
||||
frappe.require('assets/frappe/js/lib/flot/jquery.flot.js');
|
||||
frappe.require('assets/frappe/js/lib/flot/jquery.flot.downsample.js');
|
||||
|
||||
|
||||
this.plot = $.plot(this.plot_area.toggle(true), plot_data,
|
||||
this.get_plot_options());
|
||||
|
||||
|
||||
this.setup_plot_hover();
|
||||
},
|
||||
setup_plot_check: function() {
|
||||
|
|
@ -692,7 +692,7 @@ frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
|
|||
});
|
||||
}
|
||||
me.render_plot();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
setup_plot_hover: function() {
|
||||
|
|
@ -718,16 +718,16 @@ frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
|
|||
me.previousPoint = item.dataIndex;
|
||||
|
||||
$("#" + me.tooltip_id).remove();
|
||||
showTooltip(item.pageX, item.pageY,
|
||||
showTooltip(item.pageX, item.pageY,
|
||||
me.get_tooltip_text(item.series.label, item.datapoint[0], item.datapoint[1]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$("#" + me.tooltip_id).remove();
|
||||
me.previousPoint = null;
|
||||
me.previousPoint = null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
get_tooltip_text: function(label, x, y) {
|
||||
var date = dateutil.obj_to_user(new Date(x));
|
||||
|
|
@ -749,19 +749,19 @@ frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
|
|||
points: {show: true},
|
||||
lines: {show: true, fill: true},
|
||||
});
|
||||
|
||||
// prepend opening
|
||||
data[data.length-1].data = [[dateutil.str_to_obj(me.from_date).getTime(),
|
||||
|
||||
// prepend opening
|
||||
data[data.length-1].data = [[dateutil.str_to_obj(me.from_date).getTime(),
|
||||
item.opening]].concat(data[data.length-1].data);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return data.length ? data : false;
|
||||
},
|
||||
get_plot_options: function() {
|
||||
return {
|
||||
grid: { hoverable: true, clickable: true },
|
||||
xaxis: { mode: "time",
|
||||
xaxis: { mode: "time",
|
||||
min: dateutil.str_to_obj(this.from_date).getTime(),
|
||||
max: dateutil.str_to_obj(this.to_date).getTime() },
|
||||
series: { downsample: { threshold: 1000 } }
|
||||
|
|
@ -780,7 +780,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
});
|
||||
if (!this.tl) this.tl = {};
|
||||
if (!this.tl[parent_doctype]) this.tl[parent_doctype] = [];
|
||||
|
||||
|
||||
$.each(frappe.report_dump.data[parent_doctype], function(i, parent) {
|
||||
if(tmap[parent.name]) {
|
||||
$.each(tmap[parent.name], function(i, d) {
|
||||
|
|
@ -811,15 +811,15 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
var me = frappe.cur_grid_report;
|
||||
value = value.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
var data = me.data;
|
||||
var spacer = "<span style='display:inline-block;height:1px;width:" +
|
||||
var spacer = "<span style='display:inline-block;height:1px;width:" +
|
||||
(15 * dataContext["indent"]) + "px'></span>";
|
||||
var idx = me.dataView.getIdxById(dataContext.id);
|
||||
var link = me.tree_grid.formatter(dataContext);
|
||||
|
||||
|
||||
if(dataContext.doctype) {
|
||||
link += me.get_link_open_icon(dataContext.doctype, dataContext.name);
|
||||
link += me.get_link_open_icon(dataContext.doctype, dataContext.name);
|
||||
}
|
||||
|
||||
|
||||
if (data[idx + 1] && data[idx + 1].indent > data[idx].indent) {
|
||||
if (dataContext._collapsed) {
|
||||
return spacer + " <span class='toggle expand'></span> " + link;
|
||||
|
|
@ -833,7 +833,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
tree_dataview_filter: function(item) {
|
||||
var me = frappe.cur_grid_report;
|
||||
if(!me.apply_filters(item)) return false;
|
||||
|
||||
|
||||
var parent = item[me.tree_grid.parent_field];
|
||||
while (parent) {
|
||||
if (me.item_by_name[parent]._collapsed) {
|
||||
|
|
@ -846,7 +846,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
prepare_tree: function(item_dt, group_dt) {
|
||||
var group_data = frappe.report_dump.data[group_dt];
|
||||
var item_data = frappe.report_dump.data[item_dt];
|
||||
|
||||
|
||||
// prepare map with child in respective group
|
||||
var me = this;
|
||||
var item_group_map = {};
|
||||
|
|
@ -855,12 +855,12 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
var parent = item[me.tree_grid.parent_field];
|
||||
if(!item_group_map[parent]) item_group_map[parent] = [];
|
||||
if(group_ids.indexOf(item.name)==-1) {
|
||||
item_group_map[parent].push(item);
|
||||
item_group_map[parent].push(item);
|
||||
} else {
|
||||
msgprint(__("Ignoring Item {0}, because a group exists with the same name!", [item.name.bold()]));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// arrange items besides their parent item groups
|
||||
var items = [];
|
||||
$.each(group_data, function(i, group){
|
||||
|
|
@ -884,7 +884,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
d.indent = indent;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
export: function() {
|
||||
var msgbox = msgprint($.format('<p>{0}</p>\
|
||||
<p><input type="checkbox" name="with_groups" checked="checked"> {1}</p>\
|
||||
|
|
@ -902,7 +902,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
var with_groups = $(msgbox.body).find("[name='with_groups']").prop("checked");
|
||||
var with_ledgers = $(msgbox.body).find("[name='with_ledgers']").prop("checked");
|
||||
|
||||
var data = frappe.slickgrid_tools.get_view_data(me.columns, me.dataView,
|
||||
var data = frappe.slickgrid_tools.get_view_data(me.columns, me.dataView,
|
||||
function(row, item) {
|
||||
if(with_groups) {
|
||||
// add row
|
||||
|
|
@ -914,15 +914,15 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
|
|||
if(with_ledgers && (item.group_or_ledger != "Group" && !item.is_group)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
frappe.tools.downloadify(data, ["Report Manager", "System Manager"], me);
|
||||
return false;
|
||||
})
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -216,15 +216,17 @@ frappe.views.moduleview.ModuleView = Class.extend({
|
|||
});
|
||||
} else {
|
||||
var route = item.route;
|
||||
if(item.type==="doctype") {
|
||||
route = "List/" + encodeURIComponent(item.name);
|
||||
} else if(item.type==="page") {
|
||||
route = item.route || item.link || item.name;
|
||||
} else if(item.type==="report") {
|
||||
if(item.is_query_report) {
|
||||
route = "query-report/" + encodeURIComponent(item.name);
|
||||
} else {
|
||||
route = "Report/" + encodeURIComponent(item.doctype) + "/" + encodeURIComponent(item.name);
|
||||
if(!route) {
|
||||
if(item.type==="doctype") {
|
||||
route = "List/" + encodeURIComponent(item.name);
|
||||
} else if(item.type==="page") {
|
||||
route = item.route || item.link || item.name;
|
||||
} else if(item.type==="report") {
|
||||
if(item.is_query_report) {
|
||||
route = "query-report/" + encodeURIComponent(item.name);
|
||||
} else {
|
||||
route = "Report/" + encodeURIComponent(item.doctype) + "/" + encodeURIComponent(item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ frappe.views.ReportView = frappe.ui.Listing.extend({
|
|||
if(!columns) {
|
||||
var columns = [['name', this.doctype],];
|
||||
$.each(frappe.meta.docfield_list[this.doctype], function(i, df) {
|
||||
if(df.in_filter && df.fieldname!='naming_series'
|
||||
if((df.in_filter || df.in_list_view) && df.fieldname!='naming_series'
|
||||
&& !in_list(frappe.model.no_value_type, df.fieldname)) {
|
||||
columns.push([df.fieldname, df.parent]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -719,6 +719,11 @@ _f.Frm.prototype.disable_save = function() {
|
|||
this.appframe.set_title_right("", null);
|
||||
}
|
||||
|
||||
_f.Frm.prototype.enable_save = function() {
|
||||
this.save_disabled = false;
|
||||
this.toolbar.set_title_right();
|
||||
}
|
||||
|
||||
_f.Frm.prototype.save_or_update = function() {
|
||||
if(this.save_disabled) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,56 +12,56 @@
|
|||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
.ui-helper-hidden { display: none; }
|
||||
.ui-helper-hidden-accessible {
|
||||
.ui-helper-hidden-accessible {
|
||||
border: 0; clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
.ui-helper-reset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
line-height: 1.3;
|
||||
text-decoration: none;
|
||||
font-size: 100%;
|
||||
list-style: none;
|
||||
.ui-helper-reset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
line-height: 1.3;
|
||||
text-decoration: none;
|
||||
font-size: 100%;
|
||||
list-style: none;
|
||||
}
|
||||
.ui-helper-clearfix:before,
|
||||
.ui-helper-clearfix:after {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
.ui-helper-clearfix:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
.ui-helper-clearfix:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
.ui-helper-clearfix {
|
||||
.ui-helper-clearfix {
|
||||
/*display: inline-block; */
|
||||
display:block;
|
||||
min-height: 0; /* support: IE7 */
|
||||
}
|
||||
/* required comment for clearfix to work in Opera \*/
|
||||
* html .ui-helper-clearfix {
|
||||
height:1%;
|
||||
* html .ui-helper-clearfix {
|
||||
height:1%;
|
||||
}
|
||||
|
||||
/* end clearfix */
|
||||
.ui-helper-zfix {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
filter:Alpha(Opacity=0);
|
||||
.ui-helper-zfix {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
filter:Alpha(Opacity=0);
|
||||
}
|
||||
.ui-front {
|
||||
z-index: 100;
|
||||
|
|
@ -77,11 +77,11 @@
|
|||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon {
|
||||
display: block;
|
||||
text-indent: -99999px;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
.ui-icon {
|
||||
display: block;
|
||||
text-indent: -99999px;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,12 +89,12 @@
|
|||
----------------------------------*/
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ui-widget-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -107,72 +107,72 @@
|
|||
* http://api.jqueryui.com/resizable/
|
||||
*/
|
||||
|
||||
.ui-resizable {
|
||||
.ui-resizable {
|
||||
position: relative;
|
||||
}
|
||||
.ui-resizable-handle {
|
||||
.ui-resizable-handle {
|
||||
position: absolute;
|
||||
font-size: 0.1px;
|
||||
z-index: 99999;
|
||||
display: block;
|
||||
z-index: 99999;
|
||||
display: block;
|
||||
}
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle {
|
||||
display: none;
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle {
|
||||
display: none;
|
||||
}
|
||||
.ui-resizable-n {
|
||||
cursor: n-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
top: -5px;
|
||||
left: 0;
|
||||
.ui-resizable-n {
|
||||
cursor: n-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
top: -5px;
|
||||
left: 0;
|
||||
}
|
||||
.ui-resizable-s {
|
||||
cursor: s-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
bottom: -5px;
|
||||
left: 0;
|
||||
.ui-resizable-s {
|
||||
cursor: s-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
bottom: -5px;
|
||||
left: 0;
|
||||
}
|
||||
.ui-resizable-e {
|
||||
cursor: e-resize;
|
||||
width: 7px;
|
||||
right: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
.ui-resizable-e {
|
||||
cursor: e-resize;
|
||||
width: 7px;
|
||||
right: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-resizable-w {
|
||||
cursor: w-resize;
|
||||
width: 7px;
|
||||
left: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
.ui-resizable-w {
|
||||
cursor: w-resize;
|
||||
width: 7px;
|
||||
left: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-resizable-se {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
.ui-resizable-se {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
}
|
||||
.ui-resizable-sw {
|
||||
cursor: sw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
bottom: -5px;
|
||||
.ui-resizable-sw {
|
||||
cursor: sw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
bottom: -5px;
|
||||
}
|
||||
.ui-resizable-nw {
|
||||
cursor: nw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
top: -5px;
|
||||
.ui-resizable-nw {
|
||||
cursor: nw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
top: -5px;
|
||||
}
|
||||
.ui-resizable-ne {
|
||||
cursor: ne-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
right: -5px;
|
||||
.ui-resizable-ne {
|
||||
cursor: ne-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
right: -5px;
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
|
|
@ -185,10 +185,10 @@
|
|||
*
|
||||
* http://jqueryui.com/selectable/
|
||||
*/
|
||||
.ui-selectable-helper {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
border:1px dotted black;
|
||||
.ui-selectable-helper {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
border:1px dotted black;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -198,17 +198,18 @@
|
|||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/
|
||||
*/
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; }
|
||||
/*.ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; }*/
|
||||
.ui-widget .ui-widget { font-size: 1em; }
|
||||
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }
|
||||
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }
|
||||
/*.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }*/
|
||||
/*.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }*/
|
||||
.ui-widget-content { border: 1px solid #aaaaaa; background-color: #ffffff; color: #404040;}
|
||||
.ui-widget-content a { color: #404040; }
|
||||
.ui-widget-header {
|
||||
font-weight:bold;
|
||||
|
|
@ -514,41 +515,41 @@
|
|||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-left,
|
||||
.ui-corner-tl {
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-khtml-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-left,
|
||||
.ui-corner-tl {
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-khtml-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-right,
|
||||
.ui-corner-tr {
|
||||
-moz-border-radius-topright: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
-khtml-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-right,
|
||||
.ui-corner-tr {
|
||||
-moz-border-radius-topright: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
-khtml-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-left,
|
||||
.ui-corner-bl {
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
-khtml-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-left,
|
||||
.ui-corner-bl {
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
-khtml-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-right,
|
||||
.ui-corner-br {
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
-khtml-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-right,
|
||||
.ui-corner-br {
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
-khtml-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -562,11 +563,11 @@
|
|||
* http://jqueryui.com/autocomplete/
|
||||
*/
|
||||
|
||||
.ui-autocomplete {
|
||||
position: absolute;
|
||||
.ui-autocomplete {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: default;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -685,9 +686,9 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
||||
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
||||
.ui-menu .ui-menu-item a.ui-state-focus,
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
background: #0064cd;
|
||||
background-color: #0064cd;
|
||||
|
|
@ -695,6 +696,11 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
border-color: #0064cd #0064cd #003f81;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.ui-menu .ui-menu-item a p { margin: 3px 0px; }
|
||||
.ui-menu .ui-menu-item a .small { color: #555555; }
|
||||
.ui-menu .ui-menu-item a.ui-state-focus .small,
|
||||
.ui-menu .ui-menu-item a.ui-state-active .small { color: #ffffff; }
|
||||
|
||||
/* Fix problem with border in ui-state-active */
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
padding: 1px .4em;
|
||||
|
|
@ -884,4 +890,4 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
-moz-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ def clear_cache(user=None):
|
|||
"time_zone"])
|
||||
|
||||
def delete_user_cache(user):
|
||||
for key in ("bootinfo", "lang", "roles", "restrictions"):
|
||||
for key in ("bootinfo", "lang", "roles", "restrictions", "home_page"):
|
||||
cache.delete_value(key + ":" + user)
|
||||
|
||||
def clear_notifications(user=None):
|
||||
|
|
@ -60,6 +60,7 @@ def clear_cache(user=None):
|
|||
delete_user_cache(sess.user)
|
||||
cache.delete_value("session:" + sess.sid)
|
||||
|
||||
delete_user_cache("Guest")
|
||||
clear_notifications()
|
||||
frappe.defaults.clear_cache()
|
||||
|
||||
|
|
@ -70,13 +71,24 @@ def clear_sessions(user=None, keep_current=False):
|
|||
if keep_current and frappe.session.sid==sid[0]:
|
||||
continue
|
||||
else:
|
||||
frappe.cache().delete_value("session:" + sid[0])
|
||||
frappe.db.sql("""delete from tabSessions where sid=%s""", (sid[0],))
|
||||
delete_session(sid[0])
|
||||
|
||||
def delete_session(sid=None):
|
||||
frappe.cache().delete_value("session:" + sid)
|
||||
frappe.db.sql("""delete from tabSessions where sid=%s""", sid)
|
||||
|
||||
def clear_all_sessions():
|
||||
"""This effectively logs out all users"""
|
||||
frappe.only_for("Administrator")
|
||||
for sid in frappe.db.sql_list("select sid from `tabSessions`"):
|
||||
delete_session(sid)
|
||||
|
||||
def clear_expired_sessions():
|
||||
"""This function is meant to be called from scheduler"""
|
||||
for sid in frappe.db.sql_list("""select sid
|
||||
from tabSessions where TIMEDIFF(NOW(), lastupdate) > TIME(%s)""", get_expiry_period()):
|
||||
delete_session(sid)
|
||||
|
||||
def get():
|
||||
"""get session boot info"""
|
||||
from frappe.core.doctype.notification_count.notification_count import \
|
||||
|
|
@ -139,7 +151,7 @@ class Session:
|
|||
self.data['data']['session_ip'] = frappe.get_request_header('REMOTE_ADDR')
|
||||
if self.user != "Guest":
|
||||
self.data['data']['last_updated'] = frappe.utils.now()
|
||||
self.data['data']['session_expiry'] = self.get_expiry_period()
|
||||
self.data['data']['session_expiry'] = get_expiry_period()
|
||||
self.data['data']['session_country'] = get_geo_ip_country(frappe.get_request_header('REMOTE_ADDR'))
|
||||
|
||||
# insert session
|
||||
|
|
@ -212,7 +224,7 @@ class Session:
|
|||
rec = frappe.db.sql("""select user, sessiondata
|
||||
from tabSessions where sid=%s and
|
||||
TIMEDIFF(NOW(), lastupdate) < TIME(%s)""", (self.sid,
|
||||
self.get_expiry_period()))
|
||||
get_expiry_period()))
|
||||
if rec:
|
||||
data = frappe._dict(eval(rec and rec[0][1] or '{}'))
|
||||
data.user = rec[0][0]
|
||||
|
|
@ -261,17 +273,14 @@ class Session:
|
|||
frappe.utils.now())
|
||||
frappe.cache().set_value("session:" + self.sid, self.data)
|
||||
|
||||
def get_expiry_period(self):
|
||||
exp_sec = frappe.defaults.get_global_default("session_expiry") or "06:00:00"
|
||||
def get_expiry_period():
|
||||
exp_sec = frappe.defaults.get_global_default("session_expiry") or "06:00:00"
|
||||
|
||||
# incase seconds is missing
|
||||
if exp_sec:
|
||||
if len(exp_sec.split(':')) == 2:
|
||||
exp_sec = exp_sec + ':00'
|
||||
else:
|
||||
exp_sec = "2:00:00"
|
||||
# incase seconds is missing
|
||||
if len(exp_sec.split(':')) == 2:
|
||||
exp_sec = exp_sec + ':00'
|
||||
|
||||
return exp_sec
|
||||
return exp_sec
|
||||
|
||||
def get_geo_ip_country(ip_addr):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ https://frappe.io/apps/frappe
|
|||
<meta name="{{ name }}" content="{{ metatags[name]|striptags }}">
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- for link in web_include_js %}
|
||||
<script type="text/javascript" src="{{ link }}"></script>
|
||||
{%- endfor -%}
|
||||
|
||||
{%- for link in web_include_css %}
|
||||
<link type="text/css" rel="stylesheet" href="{{ link }}">
|
||||
{%- endfor -%}
|
||||
|
|
@ -38,6 +34,7 @@ https://frappe.io/apps/frappe
|
|||
<body>
|
||||
<div id="wrap">
|
||||
{%- block banner -%}
|
||||
{% include "templates/includes/banner_extension.html" ignore missing %}
|
||||
{% if banner_html -%}
|
||||
<header class="container">{{ banner_html or "" }}</header>
|
||||
{%- endif %}
|
||||
|
|
@ -92,6 +89,10 @@ https://frappe.io/apps/frappe
|
|||
{%- block footer -%}{% include "templates/includes/footer.html" %}{%- endblock -%}
|
||||
</div>
|
||||
|
||||
{%- for link in web_include_js %}
|
||||
<script type="text/javascript" src="{{ link }}"></script>
|
||||
{%- endfor -%}
|
||||
|
||||
{%- block script %}
|
||||
<script data-html-block="script">
|
||||
{%- if script is defined -%}{{ script }}{%- endif -%}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>{{ subject }}</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL
|
||||
/* -------------------------------------
|
||||
GLOBAL
|
||||
------------------------------------- */
|
||||
img {
|
||||
max-width: 100%;
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100% !important;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
|
@ -21,18 +21,18 @@ body {
|
|||
background-color: #eee;
|
||||
}
|
||||
|
||||
.wrapper * {
|
||||
.wrapper * {
|
||||
margin:0;
|
||||
padding:0;
|
||||
font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
|
||||
font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
ELEMENTS
|
||||
/* -------------------------------------
|
||||
ELEMENTS
|
||||
------------------------------------- */
|
||||
.wrapper a {
|
||||
.wrapper a {
|
||||
color: #348eda;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ body {
|
|||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.last {
|
||||
.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
@ -92,10 +92,10 @@ body {
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BODY
|
||||
/* -------------------------------------
|
||||
BODY
|
||||
------------------------------------- */
|
||||
table.body-wrap {
|
||||
table.body-wrap {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
@ -105,18 +105,18 @@ table.body-wrap .container{
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------------------
|
||||
FOOTER
|
||||
/* -------------------------------------
|
||||
FOOTER
|
||||
------------------------------------- */
|
||||
table.footer-wrap {
|
||||
width: 100%;
|
||||
table.footer-wrap {
|
||||
width: 100%;
|
||||
clear:both!important;
|
||||
}
|
||||
|
||||
.footer-wrap .container p {
|
||||
font-size:12px;
|
||||
color:#666;
|
||||
|
||||
|
||||
}
|
||||
|
||||
table.footer-wrap a{
|
||||
|
|
@ -124,19 +124,19 @@ table.footer-wrap a{
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
------------------------------------- */
|
||||
.wrapper h1,
|
||||
.wrapper h2,
|
||||
.wrapper h3{
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
line-height: 1.1;
|
||||
margin-top:15px;
|
||||
margin-bottom:15px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
line-height: 1.1;
|
||||
margin-top:15px;
|
||||
margin-bottom:15px;
|
||||
color:#000;
|
||||
line-height: 1.2;
|
||||
font-weight:200;
|
||||
font-weight:200;
|
||||
}
|
||||
|
||||
.wrapper h1 {
|
||||
|
|
@ -152,23 +152,23 @@ table.footer-wrap a{
|
|||
margin: 20px 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.wrapper p,
|
||||
.wrapper ul,
|
||||
.wrapper ol {
|
||||
margin-bottom: 10px;
|
||||
font-weight: normal;
|
||||
.wrapper p,
|
||||
.wrapper ul,
|
||||
.wrapper ol {
|
||||
margin-bottom: 10px;
|
||||
font-weight: normal;
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
.wrapper ul li,
|
||||
.wrapper ul li,
|
||||
.wrapper ol li {
|
||||
margin-left:5px;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------
|
||||
/* ---------------------------------------------------
|
||||
RESPONSIVENESS
|
||||
Nuke it from orbit. It's the only way to be sure.
|
||||
Nuke it from orbit. It's the only way to be sure.
|
||||
------------------------------------------------------ */
|
||||
|
||||
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
|
||||
|
|
@ -188,12 +188,12 @@ table.footer-wrap a{
|
|||
.content {
|
||||
max-width:600px;
|
||||
margin:0 auto;
|
||||
display:block;
|
||||
display:block;
|
||||
}
|
||||
|
||||
/* Let's make sure tables in the content area are 100% wide */
|
||||
.content table {
|
||||
width: 100%;
|
||||
.content table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a.no-decoration {
|
||||
|
|
@ -209,9 +209,13 @@ small, .small {
|
|||
color: #999999;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: monospace !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
<div class="wrapper">
|
||||
|
|
@ -233,7 +237,7 @@ small, .small {
|
|||
</table>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
|
@ -245,7 +249,7 @@ small, .small {
|
|||
<tr>
|
||||
<td></td>
|
||||
<td class="container">
|
||||
|
||||
|
||||
<!-- content -->
|
||||
<div class="content">
|
||||
<table>
|
||||
|
|
@ -257,7 +261,7 @@ small, .small {
|
|||
</table>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
|
@ -269,4 +273,4 @@ small, .small {
|
|||
<div class="print-html">{{ print_html or "" }}</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ var blog = {
|
|||
b.avatar = "/" + b.avatar;
|
||||
}
|
||||
|
||||
b.month = b.month.toUpperCase().substr(0,3);
|
||||
|
||||
$(repl('<div class="row">\
|
||||
<div class="col-md-2 text-center" style="color: #ccc">\
|
||||
<h1 class="blog-day" style="margin: 0px;">%(day)s</h1>\
|
||||
|
|
@ -61,7 +63,7 @@ var blog = {
|
|||
<p>%(content)s</p>\
|
||||
<p style="color: #aaa; font-size: 90%">\
|
||||
<a href="/blog?by=%(blogger)s&by_name=%(full_name)s">\
|
||||
%(full_name)s</a> wrote this on %(published)s / %(comment_text)s</p>\
|
||||
%(full_name)s</a> / %(comment_text)s</p>\
|
||||
</div>\
|
||||
</div><hr>', b)).appendTo($wrap);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
<!-- post login tools -->
|
||||
{% if not disable_signup %}
|
||||
<li class="dropdown logged-in" id="website-post-login"
|
||||
data-label="website-post-login" style="display: none">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
|
|
@ -56,6 +55,7 @@
|
|||
{%- endfor -%}
|
||||
</ul>
|
||||
</li>
|
||||
{% if not disable_signup %}
|
||||
<li class="btn-login-area"><a href="/login">Sign Up / Login</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
|
@ -63,4 +63,4 @@
|
|||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<script>$('.dropdown-toggle').dropdown()</script>
|
||||
<script>$(function() { $('.dropdown-toggle').dropdown(); });</script>
|
||||
|
|
|
|||
|
|
@ -2,27 +2,27 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="about-content">
|
||||
{{ obj.doc.company_introduction or """<p>Some Introduction about your company that you would
|
||||
like your website visitor to know.
|
||||
More people than you think will read your About page.
|
||||
People always like to know who the are doing business with.
|
||||
Be authentic and avoid using jargon like 'value added services' etc.
|
||||
Be sure to update your company history and
|
||||
{{ doc.company_introduction or """<p>Some Introduction about your company that you would
|
||||
like your website visitor to know.
|
||||
More people than you think will read your About page.
|
||||
People always like to know who the are doing business with.
|
||||
Be authentic and avoid using jargon like 'value added services' etc.
|
||||
Be sure to update your company history and
|
||||
list of key team members in Website > About Us Settings</p>""" }}
|
||||
|
||||
{% if obj.get({"doctype":"Company History"}) %}
|
||||
<h3>{{ obj.doc.company_history_heading or "Company History" }}</h3>
|
||||
{% for d in obj.get({"doctype":"Company History"}) %}
|
||||
|
||||
{% if doc.get({"doctype":"Company History"}) %}
|
||||
<h3>{{ doc.company_history_heading or "Company History" }}</h3>
|
||||
{% for d in doc.get({"doctype":"Company History"}) %}
|
||||
<div class="row">
|
||||
<span class="col-md-2"><h4 style="margin:0px;">{{ d.year }}</h4></span>
|
||||
<span class="col-md-10"><p>{{ d.highlight }}</p></span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if obj.get({"doctype":"About Us Team Member"}) %}
|
||||
<h3>{{ obj.doc.team_members_heading or "Team Members" }}</h3>
|
||||
{% for d in obj.get({"doctype":"About Us Team Member"}) %}
|
||||
|
||||
{% if doc.get({"doctype":"About Us Team Member"}) %}
|
||||
<h3>{{ doc.team_members_heading or "Team Members" }}</h3>
|
||||
{% for d in doc.get({"doctype":"About Us Team Member"}) %}
|
||||
<div class="row" itemscope itemtype="http://schema.org/Person">
|
||||
<span class="col-md-2">
|
||||
<div class="avatar avatar-large">
|
||||
|
|
@ -35,6 +35,6 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ obj.doc.footer or "" }}
|
||||
{{ doc.footer or "" }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
return { "obj": frappe.get_doc("About Us Settings", "About Us Settings") }
|
||||
return { "doc": frappe.get_doc("About Us Settings", "About Us Settings") }
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
{% block title %}{{ heading or "Contact Us"}}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- no-sidebar -->
|
||||
<div class="contact-content">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<p id="contact-alert" class="alert alert-warning"
|
||||
{{ introduction or "" }}<br>
|
||||
<p id="contact-alert" class="alert alert-warning"
|
||||
style="display: none;"> </p>
|
||||
<div class="form-group">
|
||||
<select name="subject" class="form-control">
|
||||
{% if query_options -%}
|
||||
{% for option in query_options -%}
|
||||
{% for option in query_options.split("\n") -%}
|
||||
<option value="{{ option }}">{{ option }}</option>
|
||||
{%- endfor %}
|
||||
{% else %}
|
||||
|
|
@ -18,7 +20,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="email" type="text"
|
||||
<input class="form-control" name="email" type="text"
|
||||
placeholder="Your Email Address" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -53,9 +55,8 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ introduction or ""}}
|
||||
</div>
|
||||
<script>
|
||||
{% include "templates/includes/contact.js" %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
84
frappe/templates/pages/list.html
Normal file
84
frappe/templates/pages/list.html
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
{% block title %}{{ type }} {{ _("List") }}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<h2>{{ type }} {{ _("List") }}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- no-sidebar -->
|
||||
<div class="row">
|
||||
<div class=" col-sm-offset-8 col-sm-4">
|
||||
<form class="form-inline form-search" action="/list">
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="text" name="txt"
|
||||
placeholder="Search..." value="{{ txt or '' }}">
|
||||
<input type="hidden" name="type" value="{{ type }}">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="submit">
|
||||
<i class="icon-search"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
{% if txt %}
|
||||
<div class="alert alert-warning">Results filtered by <b>{{ txt }}</b>. <a href="/list?type={{ type }}" class="close">×</a></div>
|
||||
{% endif %}
|
||||
<div class="list-group" data-type="{{ type }}" data-txt="{{ txt or '[notxt]' }}">
|
||||
{% for item in items %}
|
||||
<div class="list-group-item">
|
||||
{{ item }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="more-block text-center hide">
|
||||
<button class="btn btn-default btn-more">More</button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
frappe.ready(function() {
|
||||
// show more button if len is 20
|
||||
$list_group = $(".list-group[data-type='{{ type }}'][data-txt='{{ txt or "[notxt]" }}']");
|
||||
|
||||
// more ajax
|
||||
frappe.start = 20;
|
||||
$(".btn-more").on("click", function() {
|
||||
$.ajax({
|
||||
url:"/api/method/frappe.templates.pages.list.get_items",
|
||||
data: {
|
||||
type: "{{ type }}",
|
||||
txt: "{{ txt or '' }}",
|
||||
limit_start: frappe.start
|
||||
},
|
||||
statusCode: {
|
||||
200: function(data) {
|
||||
frappe.start += 20;
|
||||
$.each(data.message.items, function(i, d) {
|
||||
$('<div class="list-group-item">')
|
||||
.html(d)
|
||||
.appendTo($list_group);
|
||||
});
|
||||
show_more();
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
var show_more = function() {
|
||||
var $items = $list_group.find(".list-group-item")
|
||||
if($items.length && ($items.length % 20 === 0)) {
|
||||
if($(".more-block").hasClass("hide"))
|
||||
$(".more-block").removeClass("hide");
|
||||
} else {
|
||||
if(!$(".more-block").hasClass("hide"))
|
||||
$(".more-block").addClass("hide");
|
||||
}
|
||||
};
|
||||
|
||||
show_more();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
50
frappe/templates/pages/list.py
Normal file
50
frappe/templates/pages/list.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, os
|
||||
from frappe.modules import get_doc_path
|
||||
from jinja2 import Environment, Template, FileSystemLoader
|
||||
|
||||
no_cache = 1
|
||||
no_sitemap = 1
|
||||
|
||||
def get_context(context):
|
||||
context.type = frappe.local.form_dict.type
|
||||
context.txt = frappe.local.form_dict.txt
|
||||
context.update(get_items(context.type, context.txt))
|
||||
return context
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_items(type, txt, limit_start=0):
|
||||
meta = frappe.get_meta(type)
|
||||
filters, or_filters = [], []
|
||||
out = frappe._dict()
|
||||
|
||||
if txt:
|
||||
if meta.search_fields:
|
||||
for f in meta.get_search_fields():
|
||||
or_filters.append([type, f.strip(), "like", "%" + txt + "%"])
|
||||
else:
|
||||
filters.append([type, "name", "like", "%" + txt + "%"])
|
||||
|
||||
|
||||
out.raw_items = frappe.get_list(type, fields = ["*"],
|
||||
filters=filters, or_filters = or_filters, limit_start=limit_start,
|
||||
limit_page_length = 20)
|
||||
template_path = os.path.join(get_doc_path(meta.module, "DocType", meta.name), "list_item.html")
|
||||
|
||||
if os.path.exists(template_path):
|
||||
env = Environment(loader = FileSystemLoader("/"))
|
||||
#template_path = os.path.relpath(template_path)
|
||||
template = env.get_template(template_path)
|
||||
else:
|
||||
template = Template("""<div><a href="/{{ doctype }}/{{ doc.name }}">
|
||||
{{ doc[title_field] }}</a></div>""")
|
||||
|
||||
out.items = [template.render(doc=i, doctype=type,
|
||||
title_field = meta.title_field or "name") for i in out.raw_items]
|
||||
|
||||
out.meta = meta
|
||||
|
||||
return out
|
||||
|
|
@ -7,4 +7,4 @@
|
|||
<div class="message-content">
|
||||
<p>{{ message }}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
|
@ -11,11 +11,11 @@ base_template_path = "templates/pages/rss.xml"
|
|||
|
||||
def get_context(context):
|
||||
"""generate rss feed"""
|
||||
|
||||
|
||||
host = get_request_site_address()
|
||||
|
||||
|
||||
blog_list = frappe.db.sql("""\
|
||||
select page_name as name, published_on, modified, title, content from `tabBlog Post`
|
||||
select page_name as name, published_on, modified, title, content from `tabBlog Post`
|
||||
where ifnull(published,0)=1
|
||||
order by published_on desc limit 20""", as_dict=1)
|
||||
|
||||
|
|
@ -23,22 +23,21 @@ def get_context(context):
|
|||
blog_page = cstr(urllib.quote(blog.name.encode("utf-8"))) + ".html"
|
||||
blog.link = urllib.basejoin(host, blog_page)
|
||||
blog.content = escape_html(blog.content or "")
|
||||
|
||||
|
||||
if blog_list:
|
||||
modified = max((blog['modified'] for blog in blog_list))
|
||||
else:
|
||||
modified = now()
|
||||
|
||||
ws = frappe.get_doc('Website Settings', 'Website Settings')
|
||||
blog_settings = frappe.get_doc('Blog Settings', 'Blog Settings')
|
||||
|
||||
context = {
|
||||
'title': ws.title_prefix,
|
||||
'description': ws.description or ((ws.title_prefix or "") + ' Blog'),
|
||||
'title': blog_settings.blog_title or "Blog",
|
||||
'description': blog_settings.blog_introduction or "",
|
||||
'modified': modified,
|
||||
'items': blog_list,
|
||||
'link': host + '/blog'
|
||||
}
|
||||
|
||||
|
||||
# print context
|
||||
return context
|
||||
|
||||
78
frappe/templates/pages/view.html
Normal file
78
frappe/templates/pages/view.html
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{% block title %}{{ doc.doctype }} / {{ doc[meta.title_field or "name"] }}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<h2>{{ doc[meta.title_field or "name"] }}</h2>
|
||||
<p><a href="/{{ doc.doctype }}">{{ doc.doctype }} {{ _("List") }}</a></p>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if custom_view %}
|
||||
{{ custom_view }}
|
||||
{% else %}
|
||||
|
||||
{% macro print_value(df, d, meta) -%}
|
||||
{% if df.fieldtype=="Check" %}
|
||||
<i class="{{ 'icon-check' if d[df.fieldname] else 'icon-check-empty' }}"></i>
|
||||
{% elif df.fieldtype=="Image" %}
|
||||
<img src="{{ doc[meta.get_field(df.fieldname).options] }}" class="img-responsive">
|
||||
{% else %}
|
||||
{{ d[df.fieldname] or "" }}
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro get_width(fieldtype) -%}
|
||||
{%- if fieldtype in ("Int", "Check") -%}{{ 60 }}
|
||||
{%- else -%}{{ 150 }}{% endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{% for df in meta.fields %}
|
||||
{% if not df.hidden and not df.permlevel and not df.print_hide %}
|
||||
{% if df.fieldtype=="Section Break" %}
|
||||
<h4>{{ df.label or "" }}</h4>
|
||||
{% elif df.fieldtype=="Column Break" %}
|
||||
{% elif df.fieldtype=="Table" %}
|
||||
{% set table_meta = frappe.get_meta(df.options) %}
|
||||
<div style="overflow-x: auto;">
|
||||
<table class="table table-bordered" style="table-layout: fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 40px">Sr</th>
|
||||
{% for tdf in table_meta.fields %}
|
||||
{% if tdf.fieldtype not in ("Column Break", "Section Break")
|
||||
and tdf.label %}
|
||||
<th style="width: {{ get_width(tdf.fieldtype) }}px">
|
||||
{{ tdf.label }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for d in doc[df.fieldname] %}
|
||||
<tr>
|
||||
<td>{{ d.idx }}</td>
|
||||
{% for tdf in table_meta.fields %}
|
||||
{% if tdf.fieldtype not in ("Column Break", "Section Break") %}
|
||||
<td>{{ print_value(tdf, d, table_meta) }}</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-right">
|
||||
{% if df.fieldtype not in ("Image","HTML") %}
|
||||
<label>{{ df.label }}</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
{{ print_value(df, doc, meta) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue