Merge branch 'staging' into develop
This commit is contained in:
commit
b727233948
30 changed files with 262 additions and 128 deletions
|
|
@ -17,6 +17,10 @@ def clear_user_cache(user=None):
|
|||
"defaults", "user_permissions", "home_page", "linked_with",
|
||||
"desktop_icons", 'portal_menu_items')
|
||||
|
||||
# this will automatically reload the global cache
|
||||
# so it is important to clear this first
|
||||
clear_notifications(user)
|
||||
|
||||
if user:
|
||||
for name in groups:
|
||||
cache.hdel(name, user)
|
||||
|
|
@ -28,8 +32,6 @@ def clear_user_cache(user=None):
|
|||
clear_defaults_cache()
|
||||
clear_global_cache()
|
||||
|
||||
clear_notifications(user)
|
||||
|
||||
def clear_global_cache():
|
||||
from frappe.website.render import clear_cache as clear_website_cache
|
||||
|
||||
|
|
|
|||
|
|
@ -184,15 +184,17 @@ def list_apps(context):
|
|||
@click.argument('email')
|
||||
@click.option('--first-name')
|
||||
@click.option('--last-name')
|
||||
@click.option('--password')
|
||||
@click.option('--send-welcome-email', default=False, is_flag=True)
|
||||
@pass_context
|
||||
def add_system_manager(context, email, first_name, last_name, send_welcome_email):
|
||||
def add_system_manager(context, email, first_name, last_name, send_welcome_email, password):
|
||||
"Add a new system manager to a site"
|
||||
import frappe.utils.user
|
||||
for site in context.sites:
|
||||
frappe.connect(site=site)
|
||||
try:
|
||||
frappe.utils.user.add_system_manager(email, first_name, last_name, send_welcome_email)
|
||||
frappe.utils.user.add_system_manager(email, first_name, last_name,
|
||||
send_welcome_email, password)
|
||||
frappe.db.commit()
|
||||
finally:
|
||||
frappe.destroy()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ from frappe.commands import pass_context, get_site
|
|||
from frappe.utils import update_progress_bar, get_bench_path
|
||||
from frappe.utils.response import json_handler
|
||||
from coverage import Coverage
|
||||
import cProfile, pstats
|
||||
from six import StringIO
|
||||
|
||||
@click.command('build')
|
||||
@click.option('--app', help='Build assets for app')
|
||||
|
|
@ -114,8 +116,9 @@ def reset_perms(context):
|
|||
@click.argument('method')
|
||||
@click.option('--args')
|
||||
@click.option('--kwargs')
|
||||
@click.option('--profile', is_flag=True, default=False)
|
||||
@pass_context
|
||||
def execute(context, method, args=None, kwargs=None):
|
||||
def execute(context, method, args=None, kwargs=None, profile=False):
|
||||
"Execute a function"
|
||||
for site in context.sites:
|
||||
try:
|
||||
|
|
@ -135,8 +138,18 @@ def execute(context, method, args=None, kwargs=None):
|
|||
else:
|
||||
kwargs = {}
|
||||
|
||||
if profile:
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
|
||||
ret = frappe.get_attr(method)(*args, **kwargs)
|
||||
|
||||
if profile:
|
||||
pr.disable()
|
||||
s = StringIO()
|
||||
pstats.Stats(pr, stream=s).sort_stats('cumulative').print_stats(.5)
|
||||
print(s.getvalue())
|
||||
|
||||
if frappe.db:
|
||||
frappe.db.commit()
|
||||
finally:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint
|
||||
from frappe.utils.jinja import validate_template
|
||||
from frappe import _
|
||||
|
||||
|
|
@ -17,7 +18,8 @@ class AddressTemplate(Document):
|
|||
if not self.is_default:
|
||||
if not self.defaults:
|
||||
self.is_default = 1
|
||||
frappe.msgprint(_("Setting this Address Template as default as there is no other default"))
|
||||
if cint(frappe.db.get_single_value('System Settings', 'setup_complete')):
|
||||
frappe.msgprint(_("Setting this Address Template as default as there is no other default"))
|
||||
|
||||
validate_template(self.template)
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,9 @@ def create_custom_field(doctype, df, ignore_validate=False):
|
|||
"dt": doctype,
|
||||
"permlevel": 0,
|
||||
"fieldtype": 'Data',
|
||||
"hidden": 0
|
||||
"hidden": 0,
|
||||
# Looks like we always use this programatically?
|
||||
# "is_standard": 1
|
||||
})
|
||||
custom_field.update(df)
|
||||
custom_field.flags.ignore_validate = ignore_validate
|
||||
|
|
@ -125,6 +127,7 @@ def create_custom_fields(custom_fields, ignore_validate = False, update=True):
|
|||
field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": df["fieldname"]})
|
||||
if not field:
|
||||
try:
|
||||
df["owner"] = "Administrator"
|
||||
create_custom_field(doctype, df, ignore_validate=ignore_validate)
|
||||
except frappe.exceptions.DuplicateEntryError:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ def quick_kanban_board(doctype, board_name, field_name, project=None):
|
|||
'label': 'Kanban Column',
|
||||
'fieldname': 'kanban_column',
|
||||
'fieldtype': 'Select',
|
||||
'hidden': 1
|
||||
'hidden': 1,
|
||||
'owner': 'Administrator'
|
||||
})
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def get_notifications():
|
|||
notification_count[name] = count
|
||||
|
||||
return {
|
||||
"open_count_doctype": get_notifications_for_doctypes(config, notification_count),
|
||||
"open_count_doctype": {},
|
||||
"open_count_module": get_notifications_for_modules(config, notification_count),
|
||||
"open_count_other": get_notifications_for_other(config, notification_count),
|
||||
"targets": get_notifications_for_targets(config, notification_percent),
|
||||
|
|
|
|||
|
|
@ -356,3 +356,55 @@ def enable_twofactor_all_roles():
|
|||
all_role.two_factor_auth = True
|
||||
all_role.save(ignore_permissions=True)
|
||||
|
||||
def make_records(records, debug=False):
|
||||
from frappe import _dict
|
||||
from frappe.modules import scrub
|
||||
|
||||
if debug:
|
||||
print("make_records: in DEBUG mode")
|
||||
|
||||
# LOG every success and failure
|
||||
for record in records:
|
||||
|
||||
doctype = record.get("doctype")
|
||||
condition = record.get('__condition')
|
||||
|
||||
if condition and not condition():
|
||||
continue
|
||||
|
||||
doc = frappe.new_doc(doctype)
|
||||
doc.update(record)
|
||||
|
||||
# ignore mandatory for root
|
||||
parent_link_field = ("parent_" + scrub(doc.doctype))
|
||||
if doc.meta.get_field(parent_link_field) and not doc.get(parent_link_field):
|
||||
doc.flags.ignore_mandatory = True
|
||||
|
||||
try:
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
except frappe.DuplicateEntryError as e:
|
||||
# print("Failed to insert duplicate {0} {1}".format(doctype, doc.name))
|
||||
|
||||
# pass DuplicateEntryError and continue
|
||||
if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name:
|
||||
# make sure DuplicateEntryError is for the exact same doc and not a related doc
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
exception = record.get('__exception')
|
||||
if exception:
|
||||
config = _dict(exception)
|
||||
if isinstance(e, config.exception):
|
||||
config.handler()
|
||||
else:
|
||||
show_document_insert_error()
|
||||
else:
|
||||
show_document_insert_error()
|
||||
|
||||
|
||||
def show_document_insert_error():
|
||||
print("Document Insert Error")
|
||||
print(frappe.get_traceback())
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe"
|
|||
app_license = "MIT"
|
||||
|
||||
develop_version = '12.x.x-develop'
|
||||
staging_version = '11.0.3-beta.36'
|
||||
staging_version = '11.0.3-beta.37'
|
||||
|
||||
app_email = "info@frappe.io"
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,11 @@ frappe.Application = Class.extend({
|
|||
|
||||
this.show_update_available();
|
||||
|
||||
if(frappe.ui.startup_setup_dialog && !frappe.boot.setup_complete) {
|
||||
frappe.ui.startup_setup_dialog.pre_show();
|
||||
frappe.ui.startup_setup_dialog.show();
|
||||
}
|
||||
|
||||
// listen to csrf_update
|
||||
frappe.realtime.on("csrf_generated", function(data) {
|
||||
// handles the case when a user logs in again from another tab
|
||||
|
|
|
|||
|
|
@ -124,4 +124,8 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({
|
|||
['clean']
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
clear() {
|
||||
this.quill.setText('');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -125,8 +125,11 @@ frappe.views.ListSidebar = class ListSidebar {
|
|||
add_reports(this.list_view.settings.reports);
|
||||
}
|
||||
|
||||
// Sort reports alphabetically
|
||||
var reports = Object.values(frappe.boot.user.all_reports).sort((a,b) => a.title.localeCompare(b.title)) || [];
|
||||
|
||||
// from specially tagged reports
|
||||
add_reports(frappe.boot.user.all_reports || []);
|
||||
add_reports(reports);
|
||||
}
|
||||
|
||||
setup_list_filter() {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,15 @@ Object.assign(frappe.utils, {
|
|||
return txt.toLowerCase().substr(0,7)=='http://'
|
||||
|| txt.toLowerCase().substr(0,8)=='https://'
|
||||
},
|
||||
to_title_case: function(string, with_space=false) {
|
||||
let titlecased_string = string.toLowerCase().replace(/(?:^|[\s-/])\w/g, function(match) {
|
||||
return match.toUpperCase();
|
||||
});
|
||||
|
||||
let replace_with = with_space ? ' ' : '';
|
||||
|
||||
return titlecased_string.replace(/-|_/g, replace_with);
|
||||
},
|
||||
toggle_blockquote: function(txt) {
|
||||
if (!txt) return txt;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,19 +44,24 @@ frappe.route = function() {
|
|||
|
||||
frappe.route_history.push(route);
|
||||
|
||||
if(route[0] && route[1] && frappe.views[route[0] + "Factory"]) {
|
||||
// has a view generator, generate!
|
||||
if(!frappe.view_factory[route[0]]) {
|
||||
frappe.view_factory[route[0]] = new frappe.views[route[0] + "Factory"]();
|
||||
}
|
||||
if(route[0]) {
|
||||
const title_cased_route = frappe.utils.to_title_case(route[0]);
|
||||
|
||||
frappe.view_factory[route[0]].show();
|
||||
} else {
|
||||
// show page
|
||||
const route_name = frappe.utils.xss_sanitise(route[0]);
|
||||
if (frappe.views.pageview) {
|
||||
if(route[1] && frappe.views[title_cased_route + "Factory"]) {
|
||||
// has a view generator, generate!
|
||||
if(!frappe.view_factory[title_cased_route]) {
|
||||
frappe.view_factory[title_cased_route] = new frappe.views[title_cased_route + "Factory"]();
|
||||
}
|
||||
|
||||
frappe.view_factory[title_cased_route].show();
|
||||
} else {
|
||||
// show page
|
||||
const route_name = frappe.utils.xss_sanitise(route[0]);
|
||||
frappe.views.pageview.show(route_name);
|
||||
}
|
||||
} else {
|
||||
// Show desk
|
||||
frappe.views.pageview.show('');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,14 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
make() {
|
||||
this.$wrapper = frappe.get_modal("", "");
|
||||
|
||||
if(this.static) {
|
||||
this.$wrapper.modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
});
|
||||
this.get_close_btn().hide();
|
||||
}
|
||||
|
||||
this.wrapper = this.$wrapper.find('.modal-dialog')
|
||||
.get(0);
|
||||
if ( this.size == "small" )
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<button class="btn btn-default btn-xs btn-order"
|
||||
data-value="{{ sort_order }}">
|
||||
<span class="octicon text-muted
|
||||
octicon-arrow-{{ sort_order===" desc " ? "down " : "up " }}">
|
||||
octicon-arrow-{{ sort_order==="desc" ? "down " : "up " }}">
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -11,13 +11,6 @@
|
|||
<div class="navbar-center ellipsis" style="display: none;"></div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="user-progress hide" title="Your Setup Progress">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" onclick="return false;" style="height: 40px;">
|
||||
<div class="progress-chart" style="width: 50px; margin-top: 8px;"><div class="progress">
|
||||
<div class="progress-bar"></div>
|
||||
</div></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="visible-xs">
|
||||
<a class="navbar-search-button" href="#" data-toggle="modal" data-target="#search-modal"><i class="octicon octicon-search"></i></a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ frappe.ui.toolbar.Toolbar = Class.extend({
|
|||
this.setup_sidebar();
|
||||
this.setup_help();
|
||||
|
||||
this.setup_modules_dialog();
|
||||
this.setup_progress_dialog();
|
||||
this.bind_events();
|
||||
|
||||
$(document).trigger('toolbar_setup');
|
||||
|
|
@ -199,41 +197,6 @@ frappe.ui.toolbar.Toolbar = Class.extend({
|
|||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setup_progress_dialog: function() {
|
||||
var me = this;
|
||||
frappe.call({
|
||||
method: "frappe.desk.user_progress.get_user_progress_slides",
|
||||
type: 'GET',
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
let slides = r.message;
|
||||
if(slides.length && slides.map(s => parseInt(s.done)).includes(0)) {
|
||||
frappe.require("assets/frappe/js/frappe/ui/toolbar/user_progress_dialog.js", function() {
|
||||
me.progress_dialog = new frappe.setup.UserProgressDialog({
|
||||
slides: slides
|
||||
});
|
||||
$('.user-progress').removeClass('hide');
|
||||
$('.user-progress .dropdown-toggle').on('click', () => {
|
||||
me.progress_dialog.show();
|
||||
});
|
||||
|
||||
if (cint(frappe.boot.sysdefaults.is_first_startup)) {
|
||||
me.progress_dialog.show();
|
||||
frappe.call({
|
||||
method: "frappe.desk.page.setup_wizard.setup_wizard.reset_is_first_startup",
|
||||
args: {},
|
||||
callback: () => {}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
freeze: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -260,6 +223,18 @@ $.extend(frappe.ui.toolbar, {
|
|||
frappe.ui.toolbar.get_menu(menu) : menu;
|
||||
|
||||
$('<li class="divider custom-menu"></li>').prependTo(menu);
|
||||
},
|
||||
add_icon_link(route, icon, index, class_name) {
|
||||
let parent_element = $(".navbar-right").get(0);
|
||||
let new_element = $(`<li class="${class_name}">
|
||||
<a class="btn" href="${route}" title="${frappe.utils.to_title_case(class_name, true)}" aria-haspopup="true" aria-expanded="true">
|
||||
<div>
|
||||
<i class="octicon ${icon}"></i>
|
||||
</div>
|
||||
</a>
|
||||
</li>`).get(0);
|
||||
|
||||
parent_element.insertBefore(new_element, parent_element.children[index]);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -952,12 +952,8 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
}
|
||||
|
||||
show_tip() {
|
||||
const part1 = __('For comparative filters, start with ">" or "<" or "=", e.g. >5 or =324');
|
||||
const part2 = __('For ranges use ":", e.g. "5:10" (to filter values between 5 & 10');
|
||||
this.page.footer.removeClass('hide').addClass('text-muted text-center').html(`
|
||||
<p>${part1}</p>
|
||||
<p>${part2}</p>
|
||||
`);
|
||||
const message = __('For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10).');
|
||||
this.page.footer.removeClass('hide').addClass('text-muted text-center').html(`<p>${message}</p>`);
|
||||
}
|
||||
|
||||
message_div(message) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
this.order_by = this.report_doc.json.order_by;
|
||||
this.add_totals_row = this.report_doc.json.add_totals_row;
|
||||
this.page_title = this.report_name;
|
||||
this.page_length = this.report_doc.json.page_length || 20;
|
||||
this.order_by = this.report_doc.json.order_by || 'modified desc';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +41,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
setup_view() {
|
||||
this.setup_columns();
|
||||
this.bind_charts_button();
|
||||
this.setup_dynamic_row_height_check();
|
||||
}
|
||||
|
||||
setup_result_area() {
|
||||
|
|
@ -50,8 +51,53 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
this.$result.append(this.$datatable_wrapper);
|
||||
}
|
||||
|
||||
setup_paging_area() {
|
||||
super.setup_paging_area();
|
||||
const message = __('For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10).');
|
||||
this.$paging_area.find('.level-left').append(
|
||||
`<p class="text-muted text-medium margin-left">${message}</p>`
|
||||
)
|
||||
}
|
||||
|
||||
setup_sort_selector() {
|
||||
this.sort_selector = new frappe.ui.SortSelector({
|
||||
parent: this.filter_area.$filter_list_wrapper,
|
||||
doctype: this.doctype,
|
||||
args: this.order_by,
|
||||
onchange: this.on_sort_change.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
before_render() {
|
||||
this.save_report_settings();
|
||||
if (this.report_doc) {
|
||||
this.set_dirty_state_for_custom_report();
|
||||
} else {
|
||||
this.save_report_settings();
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty_state_for_custom_report() {
|
||||
const json = JSON.stringify({
|
||||
filters: this.filter_area.get(),
|
||||
fields: this.fields,
|
||||
order_by: this.sort_selector.get_sql_string(),
|
||||
add_totals_row: this.add_totals_row,
|
||||
page_length: this.page_length
|
||||
});
|
||||
|
||||
const report_json = JSON.stringify({
|
||||
filters: this.report_doc.json.filters,
|
||||
fields: this.report_doc.json.fields,
|
||||
order_by: this.report_doc.json.order_by,
|
||||
add_totals_row: this.report_doc.json.add_totals_row,
|
||||
page_length: this.report_doc.json.page_length
|
||||
});
|
||||
|
||||
if (json != report_json) {
|
||||
this.page.set_indicator(__('Not Saved'), 'orange');
|
||||
} else {
|
||||
this.page.clear_indicator();
|
||||
}
|
||||
}
|
||||
|
||||
save_report_settings() {
|
||||
|
|
@ -121,16 +167,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
}
|
||||
}
|
||||
|
||||
on_filter_change() {
|
||||
if (this.report_doc) {
|
||||
if (JSON.stringify(this.filters) !== JSON.stringify(this.filter_area.get())) {
|
||||
this.page.set_indicator(__('Not Saved'), 'orange');
|
||||
} else {
|
||||
this.page.clear_indicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_row(doc, flash_row) {
|
||||
const to_refresh = [];
|
||||
|
||||
|
|
@ -178,8 +214,8 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
columns: this.columns,
|
||||
data: this.get_data(values),
|
||||
getEditor: this.get_editing_object.bind(this),
|
||||
dynamicRowHeight: !this.fixed_row_height.get_value(),
|
||||
checkboxColumn: true,
|
||||
inlineFilters: true,
|
||||
cellHeight: 37,
|
||||
events: {
|
||||
onRemoveColumn: (column) => {
|
||||
|
|
@ -534,7 +570,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
|
||||
set_fields() {
|
||||
if (this.report_name && this.report_doc.json.fields) {
|
||||
this.fields = this.report_doc.json.fields;
|
||||
this.fields = this.report_doc.json.fields.slice();
|
||||
return;
|
||||
} else if (this.view_user_settings.fields) {
|
||||
// get from user_settings
|
||||
|
|
@ -857,23 +893,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
});
|
||||
}
|
||||
|
||||
setup_dynamic_row_height_check() {
|
||||
this.fixed_row_height = frappe.ui.form.make_control({
|
||||
df: {
|
||||
fieldtype: 'Check',
|
||||
fieldname: 'fixed_row_height',
|
||||
label: __('Fixed height'),
|
||||
onchange: () => {
|
||||
this.render(true);
|
||||
}
|
||||
},
|
||||
parent: this.$paging_area.find('.level-left'),
|
||||
render_input: true
|
||||
});
|
||||
this.fixed_row_height.$wrapper.addClass('report-action-checkbox');
|
||||
this.fixed_row_height.set_value(1);
|
||||
}
|
||||
|
||||
get_checked_items(only_docnames) {
|
||||
const indexes = this.datatable.rowmanager.getCheckedRows();
|
||||
const items = indexes.filter(i => i != undefined)
|
||||
|
|
@ -889,17 +908,20 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
save_report(save_type) {
|
||||
const _save_report = (name) => {
|
||||
// callback
|
||||
const report_settings = {
|
||||
filters: this.filter_area.get(),
|
||||
fields: this.fields,
|
||||
order_by: this.sort_selector.get_sql_string(),
|
||||
add_totals_row: this.add_totals_row,
|
||||
page_length: this.page_length
|
||||
}
|
||||
|
||||
return frappe.call({
|
||||
method: 'frappe.desk.reportview.save_report',
|
||||
args: {
|
||||
name: name,
|
||||
doctype: this.doctype,
|
||||
json: JSON.stringify({
|
||||
filters: this.filter_area.get(),
|
||||
fields: this.fields,
|
||||
order_by: this.sort_selector.get_sql_string(),
|
||||
add_totals_row: this.add_totals_row
|
||||
})
|
||||
json: JSON.stringify(report_settings)
|
||||
},
|
||||
callback:(r) => {
|
||||
if(r.exc) {
|
||||
|
|
@ -907,12 +929,20 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
return;
|
||||
}
|
||||
if(r.message != this.report_name) {
|
||||
// Rerender the reports dropdown,
|
||||
// so that this report is included in the dropdown as well.
|
||||
frappe.boot.user.all_reports[r.message] = {
|
||||
ref_doctype: "Item",
|
||||
report_type: "Report Builder",
|
||||
title: r.message,
|
||||
};
|
||||
this.list_sidebar.setup_reports();
|
||||
frappe.set_route('List', this.doctype, 'Report', r.message);
|
||||
}
|
||||
|
||||
// reset dirty state
|
||||
this.filters = this.filter_area.get();
|
||||
this.on_filter_change();
|
||||
// update state
|
||||
this.report_doc.json = report_settings;
|
||||
this.set_dirty_state_for_custom_report();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ kbd {
|
|||
min-width: 200px;
|
||||
padding: 0px;
|
||||
font-size: @text-medium;
|
||||
max-height: 400px;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
// only rounded bottoms
|
||||
border-radius: 0px 0px 4px 4px;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@
|
|||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.flush-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.level {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,26 @@
|
|||
@import "avatar.less";
|
||||
@import "indicator.less";
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0; padding: 0; /* to avoid scrollbars */
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: @font-stack;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
.main-section {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
a& {
|
||||
color: @text-color;
|
||||
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@ def get():
|
|||
bootinfo["lang"] = frappe.translate.get_user_lang()
|
||||
bootinfo["disable_async"] = frappe.conf.disable_async
|
||||
|
||||
bootinfo["setup_complete"] = cint(frappe.db.get_single_value('System Settings', 'setup_complete'))
|
||||
|
||||
# limits
|
||||
bootinfo.limits = get_limits()
|
||||
bootinfo.expiry_message = get_expiry_message()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
{% block body %}
|
||||
<body data-path="{{ path }}">
|
||||
<div class="main-section">
|
||||
<div>
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
{%- block banner -%}
|
||||
{% include "templates/includes/banner_extension.html" ignore missing %}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ from __future__ import unicode_literals
|
|||
from unittest import TestCase
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from frappe.utils.scheduler import (enqueue_applicable_events, restrict_scheduler_events_if_dormant,
|
||||
get_enabled_scheduler_events, disable_scheduler_on_expiry)
|
||||
get_enabled_scheduler_events, disable_scheduler_on_expiry)
|
||||
from frappe import _dict
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from frappe.utils import now_datetime, today, add_days, add_to_date
|
||||
from frappe.limits import update_limits, clear_limit
|
||||
|
||||
import frappe
|
||||
import json, time
|
||||
import time
|
||||
|
||||
def test_timeout():
|
||||
'''This function needs to be pickleable'''
|
||||
|
|
@ -49,12 +49,12 @@ class TestScheduler(TestCase):
|
|||
frappe.flags.enabled_events = None
|
||||
|
||||
def test_enabled_events_day_change(self):
|
||||
val = json.dumps(["daily", "daily_long", "weekly", "weekly_long",
|
||||
"monthly", "monthly_long"])
|
||||
frappe.db.set_global('enabled_scheduler_events', val)
|
||||
|
||||
# TEMP for debug: this test fails randomly
|
||||
print('Setting enabled_scheduler_events {0}'.format(val))
|
||||
# use flags instead of globals as this test fails intermittently
|
||||
# the root cause has not been identified but the culprit seems cache
|
||||
# since cache is mutable, it maybe be changed by a parallel process
|
||||
frappe.flags.enabled_events = ["daily", "daily_long", "weekly", "weekly_long",
|
||||
"monthly", "monthly_long"]
|
||||
|
||||
# maintain last_event and next_event on different days
|
||||
next_event = now_datetime().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
|
@ -65,6 +65,8 @@ class TestScheduler(TestCase):
|
|||
self.assertTrue("all" in frappe.flags.ran_schedulers)
|
||||
self.assertFalse("hourly" in frappe.flags.ran_schedulers)
|
||||
|
||||
frappe.flags.enabled_events = None
|
||||
|
||||
|
||||
def test_restrict_scheduler_events(self):
|
||||
frappe.set_user("Administrator")
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ def after_install():
|
|||
# update admin password
|
||||
update_password("Administrator", get_admin_password())
|
||||
|
||||
# setup wizard now in frappe
|
||||
frappe.db.set_default('desktop:home_page', 'setup-wizard')
|
||||
if not frappe.conf.skip_setup_wizard:
|
||||
frappe.db.set_default('desktop:home_page', 'setup-wizard')
|
||||
|
||||
# clear test log
|
||||
with open(frappe.get_site_path('.test_log'), 'w') as f:
|
||||
|
|
@ -157,4 +157,4 @@ def add_country_and_currency(name, country):
|
|||
"smallest_currency_fraction_value": country.smallest_currency_fraction_value,
|
||||
"number_format": country.number_format,
|
||||
"docstatus": 0
|
||||
}).db_insert()
|
||||
}).db_insert()
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ def get_system_managers(only_name=False):
|
|||
def add_role(user, role):
|
||||
frappe.get_doc("User", user).add_roles(role)
|
||||
|
||||
def add_system_manager(email, first_name=None, last_name=None, send_welcome_email=False):
|
||||
def add_system_manager(email, first_name=None, last_name=None, send_welcome_email=False, password=None):
|
||||
# add user
|
||||
user = frappe.new_doc("User")
|
||||
user.update({
|
||||
|
|
@ -276,6 +276,11 @@ def add_system_manager(email, first_name=None, last_name=None, send_welcome_emai
|
|||
"send_welcome_email": 1 if send_welcome_email else 0
|
||||
})
|
||||
|
||||
if password:
|
||||
user.update({
|
||||
"new_password": password
|
||||
})
|
||||
|
||||
user.insert()
|
||||
|
||||
# add roles
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class Workflow(Document):
|
|||
"no_copy": 1,
|
||||
"fieldtype": "Link",
|
||||
"options": "Workflow State",
|
||||
"owner": "Administrator"
|
||||
}).save()
|
||||
|
||||
frappe.msgprint(_("Created Custom Field {0} in {1}").format(self.workflow_state_field,
|
||||
|
|
@ -86,4 +87,4 @@ class Workflow(Document):
|
|||
@frappe.whitelist()
|
||||
def get_fieldnames_for(doctype):
|
||||
return [f.fieldname for f in frappe.get_meta(doctype).fields \
|
||||
if f.fieldname not in no_value_fields]
|
||||
if f.fieldname not in no_value_fields]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="page-card">
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator blue'>{{ _("Reset Password") }}</span>
|
||||
<span class='indicator blue'>{{ _("Reset Password") if frappe.db.get_default('company') else _("Set Password")}}</span>
|
||||
</div>
|
||||
<form id="reset-password">
|
||||
<div class="form-group">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue