@@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json | |||||
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__ = '8.0.2' | |||||
__version__ = '8.0.3' | |||||
__title__ = "Frappe Framework" | __title__ = "Frappe Framework" | ||||
local = Local() | local = Local() | ||||
@@ -4,7 +4,8 @@ from frappe import _ | |||||
def get_data(): | def get_data(): | ||||
return [ | return [ | ||||
{ | { | ||||
"module_name": 'Communication', | |||||
"module_name": 'Core', | |||||
"type": 'list', | |||||
"label": _('Email Inbox'), | "label": _('Email Inbox'), | ||||
"_label": _('Email Inbox'), | "_label": _('Email Inbox'), | ||||
"_id": 'Email Inbox', | "_id": 'Email Inbox', | ||||
@@ -22,7 +22,7 @@ def get_info(show_failed=False): | |||||
jobs = [] | jobs = [] | ||||
def add_job(j, name): | def add_job(j, name): | ||||
if j.kwargs.get('site')==frappe.local.site or True: | |||||
if j.kwargs.get('site')==frappe.local.site: | |||||
jobs.append({ | jobs.append({ | ||||
'job_name': j.kwargs.get('kwargs', {}).get('playbook_method') \ | 'job_name': j.kwargs.get('kwargs', {}).get('playbook_method') \ | ||||
or str(j.kwargs.get('job_name')), | or str(j.kwargs.get('job_name')), | ||||
@@ -47,5 +47,4 @@ def get_info(show_failed=False): | |||||
if q.name == 'failed': | if q.name == 'failed': | ||||
for j in q.get_jobs()[:10]: add_job(j, q.name) | for j in q.get_jobs()[:10]: add_job(j, q.name) | ||||
return jobs | |||||
return jobs |
@@ -94,7 +94,7 @@ def get_desktop_icons(user=None): | |||||
def add_user_icon(_doctype, label=None, link=None, type='link', standard=0): | def add_user_icon(_doctype, label=None, link=None, type='link', standard=0): | ||||
'''Add a new user desktop icon to the desktop''' | '''Add a new user desktop icon to the desktop''' | ||||
if not label: label = frappe._(_doctype) | |||||
if not label: label = _doctype | |||||
if not link: link = 'List/{0}'.format(_doctype) | if not link: link = 'List/{0}'.format(_doctype) | ||||
# find if a standard icon exists | # find if a standard icon exists | ||||
@@ -36,7 +36,8 @@ def get_form_params(): | |||||
data["save_user_settings"] = json.loads(data["save_user_settings"]) | data["save_user_settings"] = json.loads(data["save_user_settings"]) | ||||
else: | else: | ||||
data["save_user_settings"] = True | data["save_user_settings"] = True | ||||
doctype = data["doctype"] | |||||
fields = data["fields"] | fields = data["fields"] | ||||
for field in fields: | for field in fields: | ||||
@@ -804,7 +804,9 @@ class Document(BaseDocument): | |||||
self.notify_update() | self.notify_update() | ||||
try: | try: | ||||
frappe.enqueue('frappe.utils.global_search.update_global_search', now=frappe.flags.in_test, doc=self) | |||||
frappe.enqueue('frappe.utils.global_search.update_global_search', | |||||
now=frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_migrate, | |||||
doc=self) | |||||
except redis.exceptions.ConnectionError: | except redis.exceptions.ConnectionError: | ||||
update_global_search(self) | update_global_search(self) | ||||
@@ -187,29 +187,19 @@ def _set_amended_name(doc): | |||||
doc.name = am_prefix + '-' + str(am_id) | doc.name = am_prefix + '-' + str(am_id) | ||||
return doc.name | return doc.name | ||||
def append_number_if_name_exists(doctype, name): | |||||
def append_number_if_name_exists(doctype, name, fieldname='name', separator='-'): | |||||
if frappe.db.exists(doctype, name): | if frappe.db.exists(doctype, name): | ||||
last = frappe.db.sql("""select name from `tab{}` | |||||
where name regexp '^{}-[[:digit:]]+' | |||||
order by length(name) desc, name desc limit 1""".format(doctype, name)) | |||||
last = frappe.db.sql("""select name from `tab{doctype}` | |||||
where {fieldname} regexp '^{name}{separator}[[:digit:]]+' | |||||
order by length({fieldname}) desc, | |||||
{fieldname} desc limit 1""".format(doctype=doctype, | |||||
name=name, fieldname=fieldname, separator=separator)) | |||||
if last: | if last: | ||||
count = str(cint(last[0][0].rsplit("-", 1)[1]) + 1) | count = str(cint(last[0][0].rsplit("-", 1)[1]) + 1) | ||||
else: | else: | ||||
count = "1" | count = "1" | ||||
name = "{0}-{1}".format(name, count) | |||||
return name | |||||
def de_duplicate(doctype, name): | |||||
original_name = name | |||||
count = 0 | |||||
while True: | |||||
if frappe.db.exists(doctype, name): | |||||
count += 1 | |||||
name = "{0}-{1}".format(original_name, count) | |||||
else: | |||||
break | |||||
name = "{0}{1}{2}".format(name, separator, count) | |||||
return name | return name |
@@ -173,3 +173,4 @@ frappe.patches.v7_2.update_communications | |||||
frappe.patches.v8_0.deprecate_integration_broker | frappe.patches.v8_0.deprecate_integration_broker | ||||
frappe.patches.v8_0.setup_email_inbox #2017-03-29 | frappe.patches.v8_0.setup_email_inbox #2017-03-29 | ||||
frappe.patches.v8_0.newsletter_childtable_migrate | frappe.patches.v8_0.newsletter_childtable_migrate | ||||
execute:frappe.db.sql("delete from `tabDesktop Icon` where module_name='Communication'") |
@@ -386,6 +386,9 @@ fieldset[disabled] .form-control { | |||||
.datepicker--cell.-selected-.-focus- { | .datepicker--cell.-selected-.-focus- { | ||||
background: rgba(94, 100, 255, 0.9); | background: rgba(94, 100, 255, 0.9); | ||||
} | } | ||||
.datepicker--button { | |||||
color: #5E64FF; | |||||
} | |||||
.hidden-xs-inline, | .hidden-xs-inline, | ||||
.hidden-xs-inline-block { | .hidden-xs-inline-block { | ||||
display: none; | display: none; | ||||
@@ -153,15 +153,13 @@ | |||||
.filterable { | .filterable { | ||||
cursor: pointer; | cursor: pointer; | ||||
display: inline-block; | display: inline-block; | ||||
overflow: hidden; | |||||
text-overflow: ellipsis; | text-overflow: ellipsis; | ||||
width: 100%; | |||||
} | |||||
.col-sm-2 .filterable { | |||||
max-width: 90px; | |||||
} | } | ||||
.col-sm-3 .filterable { | |||||
.col-sm-2:not(.list-row-right) .filterable, | |||||
.col-sm-3:not(.list-row-right) .filterable { | |||||
max-width: 145px; | max-width: 145px; | ||||
overflow: hidden; | |||||
width: 100%; | |||||
} | } | ||||
.doclist-row .label { | .doclist-row .label { | ||||
margin-right: 8px; | margin-right: 8px; | ||||
@@ -452,7 +452,7 @@ frappe.get_desktop_icons = function(show_hidden, show_global) { | |||||
out.push(module); | out.push(module); | ||||
} | } | ||||
var show_module = function(module) { | |||||
var show_module = function(m) { | |||||
var out = true; | var out = true; | ||||
if(m.type==="page") { | if(m.type==="page") { | ||||
out = m.link in frappe.boot.page_info; | out = m.link in frappe.boot.page_info; | ||||
@@ -469,7 +469,7 @@ frappe.get_desktop_icons = function(show_hidden, show_global) { | |||||
out = frappe.boot.user.allow_modules.indexOf(m.module_name) !== -1 | out = frappe.boot.user.allow_modules.indexOf(m.module_name) !== -1 | ||||
} | } | ||||
} | } | ||||
if(m.hidden&& !show_hidden) { | |||||
if(m.hidden && !show_hidden) { | |||||
out = false; | out = false; | ||||
} | } | ||||
if(m.blocked && !show_global) { | if(m.blocked && !show_global) { | ||||
@@ -610,38 +610,40 @@ frappe.ui.form.ControlCurrency = frappe.ui.form.ControlFloat.extend({ | |||||
frappe.ui.form.ControlPercent = frappe.ui.form.ControlFloat; | frappe.ui.form.ControlPercent = frappe.ui.form.ControlFloat; | ||||
frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | ||||
set_input: function(value) { | |||||
this._super(value); | |||||
if(value && this.last_value && this.last_value !== this.value) { | |||||
this.datepicker.selectDate(new Date(value)); | |||||
} | |||||
}, | |||||
make_input: function() { | make_input: function() { | ||||
this._super(); | this._super(); | ||||
this.set_date_options(); | this.set_date_options(); | ||||
this.set_datepicker(); | this.set_datepicker(); | ||||
this.set_t_for_today(); | this.set_t_for_today(); | ||||
}, | }, | ||||
set_input: function(value) { | |||||
this._super(value); | |||||
if(value | |||||
&& ((this.last_value && this.last_value !== this.value) | |||||
|| (!this.datepicker.selectedDates.length))) { | |||||
this.datepicker.selectDate(new Date(value)); | |||||
} | |||||
}, | |||||
set_date_options: function() { | set_date_options: function() { | ||||
var me = this; | var me = this; | ||||
var lang = frappe.boot.user.language; | var lang = frappe.boot.user.language; | ||||
if(!$.fn.datepicker.language[lang]) { | if(!$.fn.datepicker.language[lang]) { | ||||
lang = 'en' | lang = 'en' | ||||
} | |||||
} | |||||
this.datepicker_options = { | this.datepicker_options = { | ||||
language: lang, | language: lang, | ||||
autoClose: true, | autoClose: true, | ||||
todayButton: new Date() | |||||
todayButton: new Date(), | |||||
dateFormat: (frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd'), | |||||
onSelect: function(dateStr) { | |||||
if(me.setting_date_flag) return; | |||||
me.set_value(me.get_value()); | |||||
me.$input.trigger('change'); | |||||
}, | |||||
onShow: function() { | |||||
$('.datepicker--button:visible').text(__('Today')); | |||||
}, | |||||
}; | }; | ||||
var date_format = | |||||
(frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd'); | |||||
this.datepicker_options.dateFormat = date_format; | |||||
this.datepicker_options.onSelect = function(dateStr) { | |||||
me.set_value(me.get_value()); | |||||
me.$input.trigger('change'); | |||||
} | |||||
}, | }, | ||||
set_datepicker: function() { | set_datepicker: function() { | ||||
this.$input.datepicker(this.datepicker_options); | this.$input.datepicker(this.datepicker_options); | ||||
@@ -689,11 +691,23 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({ | |||||
onSelect: function(dateObj) { | onSelect: function(dateObj) { | ||||
me.set_value(dateObj); | me.set_value(dateObj); | ||||
}, | }, | ||||
onShow: function() { | |||||
$('.datepicker--button:visible').text(__('Now')); | |||||
}, | |||||
todayButton: new Date() | todayButton: new Date() | ||||
}); | }); | ||||
this.datepicker = this.$input.data('datepicker'); | this.datepicker = this.$input.data('datepicker'); | ||||
this.refresh(); | this.refresh(); | ||||
} | |||||
}, | |||||
set_input: function(value) { | |||||
this._super(value); | |||||
if(value | |||||
&& ((this.last_value && this.last_value !== this.value) | |||||
|| (!this.datepicker.selectedDates.length))) { | |||||
this.datepicker.selectDate(moment(value, 'hh:mm:ss')._d); | |||||
} | |||||
}, | |||||
}); | }); | ||||
frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | ||||
@@ -701,6 +715,9 @@ frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | |||||
this._super(); | this._super(); | ||||
this.datepicker_options.timepicker = true; | this.datepicker_options.timepicker = true; | ||||
this.datepicker_options.timeFormat = "hh:ii:ss"; | this.datepicker_options.timeFormat = "hh:ii:ss"; | ||||
this.datepicker_options.onShow = function() { | |||||
$('.datepicker--button:visible').text(__('Now')); | |||||
}; | |||||
}, | }, | ||||
parse: function(value) { | parse: function(value) { | ||||
if(value) { | if(value) { | ||||
@@ -1683,6 +1700,7 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||||
this.set_input('<div><br></div>'); | this.set_input('<div><br></div>'); | ||||
}, | }, | ||||
setup_drag_drop: function() { | setup_drag_drop: function() { | ||||
var me = this; | |||||
this.note_editor.on('dragenter dragover', false) | this.note_editor.on('dragenter dragover', false) | ||||
.on('drop', function(e) { | .on('drop', function(e) { | ||||
var dataTransfer = e.originalEvent.dataTransfer; | var dataTransfer = e.originalEvent.dataTransfer; | ||||
@@ -50,7 +50,7 @@ frappe.views.ListRenderer = Class.extend({ | |||||
this.order_by = this.user_settings.order_by || this.settings.order_by; | this.order_by = this.user_settings.order_by || this.settings.order_by; | ||||
this.filters = this.user_settings.filters || this.settings.filters; | this.filters = this.user_settings.filters || this.settings.filters; | ||||
this.page_length = this.user_settings.page_length || this.settings.page_length; | |||||
this.page_length = this.settings.page_length; | |||||
// default filter for submittable doctype | // default filter for submittable doctype | ||||
if(frappe.model.is_submittable(this.doctype) && (!this.filters || !this.filters.length)) { | if(frappe.model.is_submittable(this.doctype) && (!this.filters || !this.filters.length)) { | ||||
@@ -441,10 +441,11 @@ frappe.views.ListView = frappe.ui.BaseList.extend({ | |||||
different = true; | different = true; | ||||
} | } | ||||
if (user_settings.page_length !== args.page_length) { | |||||
user_settings.page_length = args.page_length || 20 | |||||
different = true; | |||||
} | |||||
// never save page_length in user_settings | |||||
// if (user_settings.page_length !== args.page_length) { | |||||
// user_settings.page_length = args.page_length || 20 | |||||
// different = true; | |||||
// } | |||||
// save fields in list settings | // save fields in list settings | ||||
if (args.save_user_settings_fields) { | if (args.save_user_settings_fields) { | ||||
@@ -26,3 +26,4 @@ frappe.provide("frappe.utils"); | |||||
frappe.provide("frappe.ui"); | frappe.provide("frappe.ui"); | ||||
frappe.provide("frappe.modules"); | frappe.provide("frappe.modules"); | ||||
frappe.provide("frappe.templates"); | frappe.provide("frappe.templates"); | ||||
@@ -56,6 +56,13 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ | |||||
frappe.ui.open_dialogs.push(me); | frappe.ui.open_dialogs.push(me); | ||||
me.focus_on_first_input(); | me.focus_on_first_input(); | ||||
me.on_page_show && me.on_page_show(); | me.on_page_show && me.on_page_show(); | ||||
}) | |||||
.on('scroll', function() { | |||||
var $input = $('input:focus'); | |||||
if($input.length && ['Date', 'Datetime', | |||||
'Time'].includes($input.attr('data-fieldtype'))) { | |||||
$input.blur(); | |||||
} | |||||
}); | }); | ||||
}, | }, | ||||
@@ -235,6 +235,7 @@ frappe.provide("frappe.views"); | |||||
var self = {}; | var self = {}; | ||||
self.wrapper = opts.wrapper; | self.wrapper = opts.wrapper; | ||||
self.cur_list = opts.cur_list; | self.cur_list = opts.cur_list; | ||||
self.board_name = opts.board_name; | |||||
self.update_cards = function(cards) { | self.update_cards = function(cards) { | ||||
fluxify.doAction('update_cards', cards); | fluxify.doAction('update_cards', cards); | ||||
@@ -3,12 +3,12 @@ frappe.provide('frappe.views'); | |||||
frappe.views.KanbanView = frappe.views.ListRenderer.extend({ | frappe.views.KanbanView = frappe.views.ListRenderer.extend({ | ||||
name: 'Kanban', | name: 'Kanban', | ||||
render_view: function(values) { | render_view: function(values) { | ||||
if(this.kanban) { | |||||
var board_name = this.get_board_name(); | |||||
if(this.kanban && board_name === this.kanban.board_name) { | |||||
this.kanban.update_cards(values); | this.kanban.update_cards(values); | ||||
return; | return; | ||||
} | } | ||||
var board_name = this.get_board_name(); | |||||
this.kanban = new frappe.views.KanbanBoard({ | this.kanban = new frappe.views.KanbanBoard({ | ||||
doctype: this.doctype, | doctype: this.doctype, | ||||
board_name: board_name, | board_name: board_name, | ||||
@@ -300,7 +300,7 @@ frappe.views.QueryReport = Class.extend({ | |||||
// run report on change | // run report on change | ||||
f.$input.on("change", function() { | f.$input.on("change", function() { | ||||
if(!me.flags.filter_set) { | |||||
if(!me.flags.filters_set) { | |||||
// don't trigger change while setting filters | // don't trigger change while setting filters | ||||
return; | return; | ||||
} | } | ||||
@@ -107,7 +107,7 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({ | |||||
// add to desktop | // add to desktop | ||||
this.page.add_menu_item(__("Add to Desktop"), function() { | this.page.add_menu_item(__("Add to Desktop"), function() { | ||||
frappe.add_to_desktop(__('{0} Report', [me.doctype]), me.doctype); | |||||
frappe.add_to_desktop(me.docname || __('{0} Report', [me.doctype]), me.doctype); | |||||
}, true); | }, true); | ||||
}, | }, | ||||
@@ -183,6 +183,10 @@ textarea.form-control { | |||||
} | } | ||||
} | } | ||||
.datepicker--button { | |||||
color: @brand-primary; | |||||
} | |||||
.hidden-xs-inline, .hidden-xs-inline-block { | .hidden-xs-inline, .hidden-xs-inline-block { | ||||
display: none; | display: none; | ||||
} | } | ||||
@@ -190,17 +190,14 @@ | |||||
.filterable { | .filterable { | ||||
cursor: pointer; | cursor: pointer; | ||||
display: inline-block; | display: inline-block; | ||||
overflow: hidden; | |||||
text-overflow: ellipsis; | text-overflow: ellipsis; | ||||
width: 100%; | |||||
} | |||||
.col-sm-2 .filterable { | |||||
max-width: 90px; | |||||
} | } | ||||
.col-sm-3 .filterable { | |||||
.col-sm-2:not(.list-row-right) .filterable, | |||||
.col-sm-3:not(.list-row-right) .filterable { | |||||
max-width: 145px; | max-width: 145px; | ||||
overflow: hidden; | |||||
width: 100%; | |||||
} | } | ||||
@@ -42,7 +42,7 @@ def clear_cache(user=None): | |||||
frappe.defaults.clear_cache(user) | frappe.defaults.clear_cache(user) | ||||
else: | else: | ||||
for name in groups: | for name in groups: | ||||
cache.delete_key(name, user) | |||||
cache.delete_key(name) | |||||
clear_global_cache() | clear_global_cache() | ||||
frappe.defaults.clear_cache() | frappe.defaults.clear_cache() | ||||
@@ -33,16 +33,12 @@ | |||||
{%- block style %}{%- endblock -%} | {%- block style %}{%- endblock -%} | ||||
{%- endblock -%} | {%- endblock -%} | ||||
<script> | <script> | ||||
window.frappe = { | |||||
page_ready_events: {}, | |||||
ready: function(fn) { | |||||
if (!frappe.page_ready_events[location.pathname]) { | |||||
frappe.page_ready_events[location.pathname] = [] | |||||
} | |||||
frappe.page_ready_events[location.pathname].push(fn); | |||||
} | |||||
} | |||||
window.dev_server = {{ dev_server }}; | |||||
window.frappe = {}; | |||||
frappe.ready_events = []; | |||||
frappe.ready = function(fn) { | |||||
frappe.ready_events.push(fn); | |||||
} | |||||
window.dev_server = {{ dev_server }}; | |||||
</script> | </script> | ||||
</head> | </head> | ||||
<body data-path="{{ path }}"> | <body data-path="{{ path }}"> | ||||
@@ -250,17 +250,11 @@ $.extend(frappe, { | |||||
}, | }, | ||||
trigger_ready: function() { | trigger_ready: function() { | ||||
var ready_functions = frappe.page_ready_events[location.pathname]; | |||||
if (ready_functions && ready_functions.length) { | |||||
for (var i=0, l=ready_functions.length; i < l; i++) { | |||||
var ready = ready_functions[i]; | |||||
ready && ready(); | |||||
} | |||||
} | |||||
// remove them so that they aren't fired again and again! | |||||
delete frappe.page_ready_events[location.pathname]; | |||||
frappe.ready_events.forEach(function(fn) { | |||||
fn(); | |||||
}); | |||||
}, | }, | ||||
highlight_code_blocks: function() { | highlight_code_blocks: function() { | ||||
if(hljs) { | if(hljs) { | ||||
$('pre code').each(function(i, block) { | $('pre code').each(function(i, block) { | ||||