@@ -7,13 +7,13 @@ globals attached to frappe module | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
from werkzeug.local import Local, release_local | from werkzeug.local import Local, release_local | ||||
import os, importlib, inspect, json | |||||
import os, sys, importlib, inspect, json | |||||
# public | # public | ||||
from .exceptions import * | from .exceptions import * | ||||
from .utils.jinja import get_jenv, get_template, render_template | from .utils.jinja import get_jenv, get_template, render_template | ||||
__version__ = "7.0.9" | |||||
__version__ = "7.0.10" | |||||
local = Local() | local = Local() | ||||
@@ -755,6 +755,9 @@ def get_hooks(hook=None, default=None, app_name=None): | |||||
# if app is not installed while restoring | # if app is not installed while restoring | ||||
# ignore it | # ignore it | ||||
pass | pass | ||||
print 'Could not find app "{0}"'.format(app_name) | |||||
if not request: | |||||
sys.exit(1) | |||||
raise | raise | ||||
for key in dir(app_hooks): | for key in dir(app_hooks): | ||||
if not key.startswith("_"): | if not key.startswith("_"): | ||||
@@ -128,7 +128,7 @@ def add_to_email_queue(context, email_path): | |||||
with frappe.init_site(site): | with frappe.init_site(site): | ||||
frappe.connect() | frappe.connect() | ||||
for email in os.listdir(email_path): | for email in os.listdir(email_path): | ||||
with open(os.path.join(email_path, email)) as email_data: | |||||
with open(os.path.join(email_path, email)) as email_data: | |||||
kwargs = json.load(email_data) | kwargs = json.load(email_data) | ||||
kwargs['delayed'] = True | kwargs['delayed'] = True | ||||
frappe.sendmail(**kwargs) | frappe.sendmail(**kwargs) | ||||
@@ -152,10 +152,10 @@ def export_doc(context, doctype, docname): | |||||
@click.command('export-json') | @click.command('export-json') | ||||
@click.argument('doctype') | @click.argument('doctype') | ||||
@click.argument('name') | |||||
@click.argument('path') | @click.argument('path') | ||||
@click.option('--name', help='Export only one document') | |||||
@pass_context | @pass_context | ||||
def export_json(context, doctype, name, path): | |||||
def export_json(context, doctype, path, name=None): | |||||
"Export doclist as json to the given path, use '-' as name for Singles." | "Export doclist as json to the given path, use '-' as name for Singles." | ||||
from frappe.core.page.data_import_tool import data_import_tool | from frappe.core.page.data_import_tool import data_import_tool | ||||
for site in context.sites: | for site in context.sites: | ||||
@@ -63,6 +63,11 @@ def export_json(doctype, path, filters=None, name=None): | |||||
for doc in frappe.get_all(doctype, fields=["name"], filters=filters, limit_page_length=0, order_by="creation asc"): | for doc in frappe.get_all(doctype, fields=["name"], filters=filters, limit_page_length=0, order_by="creation asc"): | ||||
out.append(frappe.get_doc(doctype, doc.name).as_dict()) | out.append(frappe.get_doc(doctype, doc.name).as_dict()) | ||||
post_process(out) | post_process(out) | ||||
dirname = os.path.dirname(path) | |||||
if not os.path.exists(dirname): | |||||
path = os.path.join('..', path) | |||||
with open(path, "w") as outfile: | with open(path, "w") as outfile: | ||||
outfile.write(frappe.as_json(out)) | outfile.write(frappe.as_json(out)) | ||||
@@ -180,7 +180,7 @@ def remove_app(app_name, dry_run=False): | |||||
for module_name in frappe.get_module_list(app_name): | for module_name in frappe.get_module_list(app_name): | ||||
for doctype in frappe.get_list("DocType", filters={"module": module_name}, | for doctype in frappe.get_list("DocType", filters={"module": module_name}, | ||||
fields=["name", "issingle"]): | fields=["name", "issingle"]): | ||||
print "removing {0}...".format(doctype.name) | |||||
print "removing DocType {0}...".format(doctype.name) | |||||
# drop table | # drop table | ||||
if not dry_run: | if not dry_run: | ||||
@@ -189,7 +189,15 @@ def remove_app(app_name, dry_run=False): | |||||
if not doctype.issingle: | if not doctype.issingle: | ||||
drop_doctypes.append(doctype.name) | drop_doctypes.append(doctype.name) | ||||
for page in frappe.get_list("Page", filters={"module": module_name}): | |||||
print "removing Page {0}...".format(page.name) | |||||
# drop table | |||||
if not dry_run: | |||||
frappe.delete_doc("Page", page.name) | |||||
print "removing Module {0}...".format(module_name) | print "removing Module {0}...".format(module_name) | ||||
if not dry_run: | if not dry_run: | ||||
frappe.delete_doc("Module Def", module_name) | frappe.delete_doc("Module Def", module_name) | ||||
@@ -89,7 +89,7 @@ def rename_parent_and_child(doctype, old, new, meta): | |||||
def validate_rename(doctype, new, meta, merge, force, ignore_permissions): | def validate_rename(doctype, new, meta, merge, force, ignore_permissions): | ||||
# using for update so that it gets locked and someone else cannot edit it while this rename is going on! | # using for update so that it gets locked and someone else cannot edit it while this rename is going on! | ||||
exists = frappe.db.sql("select name from `tab{doctype}` where name=%s for update".format(doctype=frappe.db.escape(doctype)), new) | |||||
exists = frappe.db.sql("select name from `tab{doctype}` where name=%s COLLATE utf8mb4_unicode_ci for update".format(doctype=frappe.db.escape(doctype)), new) | |||||
exists = exists[0][0] if exists else None | exists = exists[0][0] if exists else None | ||||
if merge and not exists: | if merge and not exists: | ||||
@@ -405,10 +405,10 @@ fieldset[disabled] .form-control { | |||||
.ui-menu .ui-menu-item { | .ui-menu .ui-menu-item { | ||||
font-size: 12px; | font-size: 12px; | ||||
} | } | ||||
.ui-menu .ui-menu-item a, | |||||
.ui-menu .ui-menu-item div { | |||||
.ui-menu .ui-menu-item .ui-menu-item-wrapper { | |||||
padding: 9px 11.8px !important; | padding: 9px 11.8px !important; | ||||
text-decoration: none; | text-decoration: none; | ||||
margin: 0; | |||||
} | } | ||||
@media (min-width: 768px) { | @media (min-width: 768px) { | ||||
.video-modal { | .video-modal { | ||||
@@ -57,16 +57,18 @@ | |||||
} | } | ||||
#search-modal .modal-header { | #search-modal .modal-header { | ||||
background: #fff; | background: #fff; | ||||
display: table; | |||||
width: 100%; | width: 100%; | ||||
} | } | ||||
#search-modal .modal-header form, | |||||
#search-modal .modal-header button { | |||||
display: table-cell; | |||||
#search-modal .modal-header form { | |||||
vertical-align: middle; | vertical-align: middle; | ||||
} | } | ||||
#search-modal .modal-header button { | #search-modal .modal-header button { | ||||
height: 30px; | |||||
line-height: 0; | |||||
position: absolute; | |||||
right: 0; | |||||
top: 0; | |||||
z-index: 9; | |||||
padding: 9px; | |||||
} | } | ||||
.dropdown-navbar-new-comments > a { | .dropdown-navbar-new-comments > a { | ||||
border: 0; | border: 0; | ||||
@@ -57,16 +57,18 @@ | |||||
} | } | ||||
#search-modal .modal-header { | #search-modal .modal-header { | ||||
background: #fff; | background: #fff; | ||||
display: table; | |||||
width: 100%; | width: 100%; | ||||
} | } | ||||
#search-modal .modal-header form, | |||||
#search-modal .modal-header button { | |||||
display: table-cell; | |||||
#search-modal .modal-header form { | |||||
vertical-align: middle; | vertical-align: middle; | ||||
} | } | ||||
#search-modal .modal-header button { | #search-modal .modal-header button { | ||||
height: 30px; | |||||
line-height: 0; | |||||
position: absolute; | |||||
right: 0; | |||||
top: 0; | |||||
z-index: 9; | |||||
padding: 9px; | |||||
} | } | ||||
.dropdown-navbar-new-comments > a { | .dropdown-navbar-new-comments > a { | ||||
border: 0; | border: 0; | ||||
@@ -219,7 +219,6 @@ body[data-route^="Module"] .main-menu .form-sidebar { | |||||
box-shadow: 5px 0 25px 0px rgba(0, 0, 0, 0.3); | box-shadow: 5px 0 25px 0px rgba(0, 0, 0, 0.3); | ||||
height: 100%; | height: 100%; | ||||
width: 40%; | width: 40%; | ||||
padding: 25px; | |||||
display: block !important; | display: block !important; | ||||
transition: transform 200ms ease-in-out; | transition: transform 200ms ease-in-out; | ||||
} | } | ||||
@@ -227,11 +226,31 @@ body[data-route^="Module"] .main-menu .form-sidebar { | |||||
transform: translateX(0); | transform: translateX(0); | ||||
overflow-y: auto; | overflow-y: auto; | ||||
} | } | ||||
.layout-side-section .overlay-sidebar .divider { | |||||
height: 1px; | |||||
background-color: #d8dfe5; | |||||
opacity: 0.7; | |||||
} | |||||
.layout-side-section .overlay-sidebar li:not(.divider):not(.tagit-new):not(.module-sidebar-item) { | |||||
padding: 10px 15px; | |||||
} | |||||
.layout-side-section .overlay-sidebar .modified-by, | |||||
.layout-side-section .overlay-sidebar .created-by { | |||||
margin: 0; | |||||
} | |||||
.layout-side-section .overlay-sidebar .badge { | |||||
top: 9px; | |||||
right: 15px; | |||||
} | |||||
.layout-side-section .overlay-sidebar .reports-dropdown { | .layout-side-section .overlay-sidebar .reports-dropdown { | ||||
margin: 10px 0; | |||||
margin-top: 10px; | |||||
margin-bottom: -10px; | |||||
} | } | ||||
.layout-side-section .overlay-sidebar .reports-dropdown li:not(.divider) { | .layout-side-section .overlay-sidebar .reports-dropdown li:not(.divider) { | ||||
padding: 10px 0; | |||||
padding: 12.5px 0 !important; | |||||
} | |||||
.layout-side-section .overlay-sidebar .reports-dropdown li.divider { | |||||
height: 0; | |||||
} | } | ||||
} | } | ||||
@media (max-width: 767px) { | @media (max-width: 767px) { | ||||
@@ -260,7 +279,7 @@ body[data-route^="Module"] .main-menu .form-sidebar { | |||||
padding-right: 0; | padding-right: 0; | ||||
} | } | ||||
.layout-side-section .module-sidebar-nav .module-link { | .layout-side-section .module-sidebar-nav .module-link { | ||||
padding-left: 25px; | |||||
padding: 15px 15px 15px 25px; | |||||
} | } | ||||
} | } | ||||
.sidebar-left .list-sidebar .stat-label, | .sidebar-left .list-sidebar .stat-label, | ||||
@@ -694,8 +694,8 @@ fieldset { | |||||
background-color: #fafbfc; | background-color: #fafbfc; | ||||
position: absolute; | position: absolute; | ||||
height: 100%; | height: 100%; | ||||
width: 4000px; | |||||
left: -2000px; | |||||
width: 100vw; | |||||
left: calc((100vw - 100%)/ -2); | |||||
z-index: -1; | z-index: -1; | ||||
} | } | ||||
.blog-comment-row { | .blog-comment-row { | ||||
@@ -36,7 +36,6 @@ | |||||
<ul class="list-unstyled sidebar-menu form-attachments"> | <ul class="list-unstyled sidebar-menu form-attachments"> | ||||
<li class="divider"></li> | <li class="divider"></li> | ||||
<li class="h6 attachments-label">{%= __("Attachments") %}</li> | <li class="h6 attachments-label">{%= __("Attachments") %}</li> | ||||
<li class="divider"></li> | |||||
<li><a class="strong add-attachment">{%= __("Attach File") %} | <li><a class="strong add-attachment">{%= __("Attach File") %} | ||||
<i class="octicon octicon-plus" style="margin-left: 2px;"></i></li></a> | <i class="octicon octicon-plus" style="margin-left: 2px;"></i></li></a> | ||||
</ul> | </ul> | ||||
@@ -13,6 +13,7 @@ | |||||
</ul> | </ul> | ||||
</div> | </div> | ||||
</li> | </li> | ||||
<li class="divider"></li> | |||||
<li class="hide tree-link"><a href="#Tree/{%= doctype %}">{%= __("Tree") %}</a></li> | <li class="hide tree-link"><a href="#Tree/{%= doctype %}">{%= __("Tree") %}</a></li> | ||||
<li class="hide calendar-link"><a href="#Calendar/{%= doctype %}">{%= __("Calendar") %}</a></li> | <li class="hide calendar-link"><a href="#Calendar/{%= doctype %}">{%= __("Calendar") %}</a></li> | ||||
<li class="hide gantt-link"><a href="#Gantt/{%= doctype %}">{%= __("Gantt") %}</a></li> | <li class="hide gantt-link"><a href="#Gantt/{%= doctype %}">{%= __("Gantt") %}</a></li> | ||||
@@ -61,9 +61,9 @@ | |||||
<div class="input-group" style="width: 100%"> | <div class="input-group" style="width: 100%"> | ||||
<input id="modal-search" type="text" class="form-control" | <input id="modal-search" type="text" class="form-control" | ||||
placeholder="{%= __("Search or type a command") %}" aria-haspopup="true"> | placeholder="{%= __("Search or type a command") %}" aria-haspopup="true"> | ||||
<button type="reset" class="close"><i class="octicon octicon-x"></i></button> | |||||
</div> | </div> | ||||
</form> | </form> | ||||
<button type="button" class="close" data-dismiss="modal"><i class="octicon octicon-x"></i></button> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -201,7 +201,7 @@ frappe.views.QueryReport = Class.extend({ | |||||
formData.append("blob", blob); | formData.append("blob", blob); | ||||
var xhr = new XMLHttpRequest(); | var xhr = new XMLHttpRequest(); | ||||
xhr.open("POST", '/api/method/frappe.www.print.report_to_pdf'); | |||||
xhr.open("POST", '/api/method/frappe.utils.print_format.report_to_pdf'); | |||||
xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token); | xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token); | ||||
xhr.responseType = "arraybuffer"; | xhr.responseType = "arraybuffer"; | ||||
@@ -7,6 +7,10 @@ | |||||
// font-family: "Open Sans", "Helvetica", Arial, "sans-serif"; | // font-family: "Open Sans", "Helvetica", Arial, "sans-serif"; | ||||
// } | // } | ||||
html { | |||||
// overflow-x: hidden; | |||||
} | |||||
body { | body { | ||||
font-family: -apple-system, BlinkMacSystemFont, | font-family: -apple-system, BlinkMacSystemFont, | ||||
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", | "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", | ||||
@@ -221,9 +221,10 @@ textarea.form-control { | |||||
.ui-menu .ui-menu-item { | .ui-menu .ui-menu-item { | ||||
font-size: @text-medium; | font-size: @text-medium; | ||||
a, div { | |||||
.ui-menu-item-wrapper{ | |||||
padding: 9px 11.8px !important; | padding: 9px 11.8px !important; | ||||
text-decoration: none; | text-decoration: none; | ||||
margin: 0; | |||||
} | } | ||||
} | } | ||||
@@ -69,15 +69,19 @@ | |||||
} | } | ||||
.modal-header { | .modal-header { | ||||
background: #fff; | background: #fff; | ||||
display: table; | |||||
width: 100%; | width: 100%; | ||||
form, button { | |||||
display: table-cell; | |||||
form { | |||||
vertical-align: middle; | vertical-align: middle; | ||||
} | } | ||||
button { | button { | ||||
height: 30px; | |||||
line-height: 0; | |||||
position: absolute; | |||||
right: 0; | |||||
top: 0; | |||||
z-index: 9; | |||||
padding: 9px; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -288,7 +288,6 @@ body[data-route^="Module"] .main-menu { | |||||
box-shadow: 5px 0 25px 0px rgba(0,0,0,0.3); | box-shadow: 5px 0 25px 0px rgba(0,0,0,0.3); | ||||
height: 100%; | height: 100%; | ||||
width: 40%; | width: 40%; | ||||
padding: 25px; | |||||
display: block !important; | display: block !important; | ||||
transition: transform 200ms ease-in-out; | transition: transform 200ms ease-in-out; | ||||
@@ -297,11 +296,35 @@ body[data-route^="Module"] .main-menu { | |||||
overflow-y: auto; | overflow-y: auto; | ||||
} | } | ||||
.divider { | |||||
height: 1px; | |||||
background-color: #d8dfe5; | |||||
opacity: 0.7; | |||||
} | |||||
li:not(.divider):not(.tagit-new):not(.module-sidebar-item) { | |||||
padding: 10px 15px; | |||||
} | |||||
.modified-by, .created-by { | |||||
margin: 0; | |||||
} | |||||
.badge { | |||||
top: 9px; | |||||
right: 15px; | |||||
} | |||||
.reports-dropdown { | .reports-dropdown { | ||||
margin: 10px 0; | |||||
margin-top: 10px; | |||||
margin-bottom: -10px; | |||||
li:not(.divider) { | li:not(.divider) { | ||||
padding: 10px 0; | |||||
padding: 12.5px 0 !important; | |||||
} | |||||
li.divider { | |||||
height: 0; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -334,7 +357,7 @@ body[data-route^="Module"] .main-menu { | |||||
padding-right: 0; | padding-right: 0; | ||||
.module-link { | .module-link { | ||||
padding-left: 25px; | |||||
padding: 15px 15px 15px 25px; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -405,8 +405,8 @@ fieldset { | |||||
background-color: @light-bg; | background-color: @light-bg; | ||||
position: absolute; | position: absolute; | ||||
height: 100%; | height: 100%; | ||||
width: 4000px; | |||||
left: -2000px; | |||||
width: 100vw; | |||||
left: ~"calc((100vw - 100%)/ -2)"; | |||||
z-index: -1; | z-index: -1; | ||||
} | } | ||||
@@ -171,12 +171,14 @@ function get_task_room(socket, task_id) { | |||||
} | } | ||||
function get_site_name(socket) { | function get_site_name(socket) { | ||||
if (conf.default_site) { | |||||
return conf.default_site; | |||||
} | |||||
else if (socket.request.headers['x-frappe-site-name']) { | |||||
if (socket.request.headers['x-frappe-site-name']) { | |||||
return get_hostname(socket.request.headers['x-frappe-site-name']); | return get_hostname(socket.request.headers['x-frappe-site-name']); | ||||
} | } | ||||
else if (['localhost', '127.0.0.1'].indexOf(socket.request.headers.host) !== -1 | |||||
&& conf.default_site) { | |||||
// from currentsite.txt since host is localhost | |||||
return conf.default_site; | |||||
} | |||||
else if (socket.request.headers.origin) { | else if (socket.request.headers.origin) { | ||||
return get_hostname(socket.request.headers.origin); | return get_hostname(socket.request.headers.origin); | ||||
} | } | ||||