Merge branch 'develop' into fix-reviews-section
This commit is contained in:
commit
e5434d471c
32 changed files with 203 additions and 153 deletions
21
.travis.yml
21
.travis.yml
|
|
@ -1,5 +1,5 @@
|
|||
language: python
|
||||
dist: trusty
|
||||
dist: bionic
|
||||
|
||||
addons:
|
||||
hosts:
|
||||
|
|
@ -9,6 +9,10 @@ addons:
|
|||
postgresql: 9.5
|
||||
chrome: stable
|
||||
|
||||
services:
|
||||
- xvfb
|
||||
- mysql
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
|
|
@ -23,29 +27,24 @@ cache:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- name: "Python 3.6 MariaDB"
|
||||
python: 3.6
|
||||
- name: "Python 3.7 MariaDB"
|
||||
python: 3.7
|
||||
env: DB=mariadb TYPE=server
|
||||
script: bench --site test_site run-tests --coverage
|
||||
|
||||
- name: "Python 3.6 PostgreSQL"
|
||||
python: 3.6
|
||||
- name: "Python 3.7 PostgreSQL"
|
||||
python: 3.7
|
||||
env: DB=postgres TYPE=server
|
||||
script: bench --site test_site run-tests --coverage
|
||||
|
||||
- name: "Cypress"
|
||||
python: 3.6
|
||||
python: 3.7
|
||||
env: DB=mariadb TYPE=ui
|
||||
before_script:
|
||||
- bench --site test_site execute frappe.utils.install.complete_setup_wizard
|
||||
- bench --site test_site_producer execute frappe.utils.install.complete_setup_wizard
|
||||
script: bench --site test_site run-ui-tests frappe --headless
|
||||
|
||||
- name: "Python 2.7 MariaDB"
|
||||
python: 2.7
|
||||
env: DB=mariadb TYPE=server
|
||||
script: bench --site test_site run-tests --coverage
|
||||
|
||||
before_install:
|
||||
# install wkhtmltopdf
|
||||
- wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||
|
|
|
|||
25
CODEOWNERS
25
CODEOWNERS
|
|
@ -3,16 +3,17 @@
|
|||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
|
||||
* @frappe/frappe-review-team
|
||||
website/ @scmmishra
|
||||
web_form/ @scmmishra
|
||||
templates/ @scmmishra
|
||||
www/ @scmmishra
|
||||
integrations/ @Mangesh-Khairnar
|
||||
patches/ @sahil28297
|
||||
dashboard/ @prssanna
|
||||
email/ @Thunderbottom
|
||||
event_streaming/ @ruchamahabal
|
||||
data_import* @netchampfaris
|
||||
core/ @surajshetty3416
|
||||
* @frappe/frappe-review-team
|
||||
website/ @scmmishra
|
||||
web_form/ @scmmishra
|
||||
templates/ @scmmishra
|
||||
www/ @scmmishra
|
||||
integrations/ @Mangesh-Khairnar
|
||||
patches/ @sahil28297
|
||||
dashboard/ @prssanna
|
||||
email/ @Thunderbottom
|
||||
event_streaming/ @ruchamahabal
|
||||
data_import* @netchampfaris
|
||||
core/ @surajshetty3416
|
||||
requirements.txt @gavindsouza
|
||||
commands/ @gavindsouza
|
||||
|
|
|
|||
|
|
@ -49,7 +49,11 @@ class _dict(dict):
|
|||
return _dict(dict(self).copy())
|
||||
|
||||
def _(msg, lang=None, context=None):
|
||||
"""Returns translated string in current lang, if exists."""
|
||||
"""Returns translated string in current lang, if exists.
|
||||
Usage:
|
||||
_('Change')
|
||||
_('Change', context='Coins')
|
||||
"""
|
||||
from frappe.translate import get_full_dict
|
||||
from frappe.utils import strip_html_tags, is_html
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
|
|||
installing = touch_file(get_site_path('locks', 'installing.lock'))
|
||||
atexit.register(_new_site_cleanup, site, mariadb_root_username, mariadb_root_password)
|
||||
|
||||
install_db(root_login=mariadb_root_username, root_password=mariadb_root_password, db_name=db_name,
|
||||
install_db(root_login=mariadb_root_username, root_password=mariadb_root_password, db_name=db_name,
|
||||
admin_password=admin_password, verbose=verbose, source_sql=source_sql, force=force, reinstall=reinstall,
|
||||
db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port, no_mariadb_socket=no_mariadb_socket)
|
||||
apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or [])
|
||||
|
|
@ -101,7 +101,7 @@ def _new_site_cleanup(site, mariadb_root_username, mariadb_root_password):
|
|||
|
||||
if installing and os.path.exists(installing):
|
||||
if mariadb_root_password:
|
||||
_drop_site(site, mariadb_root_username, mariadb_root_password, force=True)
|
||||
_drop_site(site, mariadb_root_username, mariadb_root_password, force=True, no_backup=True)
|
||||
shutil.rmtree(site)
|
||||
|
||||
frappe.destroy()
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class User(Document):
|
|||
'frappe.core.doctype.user.user.create_contact',
|
||||
user=self,
|
||||
ignore_mandatory=True,
|
||||
now=frappe.flags.in_test
|
||||
now=frappe.flags.in_test or frappe.flags.in_install
|
||||
)
|
||||
if self.name not in ('Administrator', 'Guest') and not self.user_image:
|
||||
frappe.enqueue('frappe.core.doctype.user.user.update_gravatar', name=self.name)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import frappe
|
|||
from frappe import _
|
||||
import datetime
|
||||
import json
|
||||
from frappe.core.page.dashboard.dashboard import cache_source, get_from_date_from_timespan
|
||||
from frappe.utils.dashboard import cache_source, get_from_date_from_timespan
|
||||
from frappe.utils import nowdate, add_to_date, getdate, get_last_day, formatdate, get_datetime
|
||||
from frappe.model.naming import append_number_if_name_exists
|
||||
from frappe.boot import get_allowed_reports
|
||||
|
|
@ -27,7 +27,7 @@ def get_permission_query_conditions(user):
|
|||
return None
|
||||
|
||||
allowed_doctypes = tuple(frappe.permissions.get_doctypes_with_read())
|
||||
allowed_reports = tuple([key.encode('UTF8') for key in get_allowed_reports()])
|
||||
allowed_reports = tuple([key if type(key) == str else key.encode('UTF8') for key in get_allowed_reports()])
|
||||
|
||||
return '''
|
||||
`tabDashboard Chart`.`document_type` in {allowed_doctypes}
|
||||
|
|
|
|||
|
|
@ -193,30 +193,12 @@ class Leaderboard {
|
|||
|
||||
this.$search_box =
|
||||
$(`<div class="leaderboard-search form-group col-md-3">
|
||||
<input type="text" placeholder="Search" class="form-control leaderboard-search-input input-sm">
|
||||
<input type="text" placeholder="Search" data-element="search" class="form-control leaderboard-search-input input-sm">
|
||||
</div>`);
|
||||
|
||||
$(this.parent).find(".page-form").append(this.$search_box);
|
||||
}
|
||||
|
||||
setup_search(list_items) {
|
||||
let $search_input = this.$search_box.find(".leaderboard-search-input");
|
||||
|
||||
this.$search_box.on("keyup", ()=> {
|
||||
let text_filter = $search_input.val().toLowerCase();
|
||||
text_filter = text_filter.replace(/^\s+|\s+$/g, '');
|
||||
for (var i = 0; i < list_items.length; i++) {
|
||||
let text = list_items.eq(i).find(".list-id").text().trim().toLowerCase();
|
||||
|
||||
if (text.includes(text_filter)) {
|
||||
list_items.eq(i).css("display", "");
|
||||
} else {
|
||||
list_items.eq(i).css("display", "none");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
show_leaderboard(doctype) {
|
||||
if (this.doctypes.length) {
|
||||
if (this.doctypes.includes(doctype)) {
|
||||
|
|
@ -278,7 +260,7 @@ class Leaderboard {
|
|||
if (res && res.message.length) {
|
||||
me.message = null;
|
||||
me.$container.find(".leaderboard-list").html(me.render_list_view(res.message));
|
||||
me.setup_search($(me.parent).find('.list-item-container'));
|
||||
frappe.utils.setup_search($(me.parent), ".list-item-container", ".list-id");
|
||||
} else {
|
||||
me.$graph_area.hide();
|
||||
me.message = __("No items found.");
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ from __future__ import unicode_literals
|
|||
import frappe
|
||||
from frappe import _
|
||||
from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes
|
||||
from frappe.utils.dashboard import sync_dashboards
|
||||
|
||||
def install():
|
||||
update_genders()
|
||||
update_salutations()
|
||||
update_global_search_doctypes()
|
||||
setup_email_linking()
|
||||
sync_dashboards()
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_genders():
|
||||
|
|
@ -35,4 +37,3 @@ def setup_email_linking():
|
|||
"email_id": "email_linking@example.com",
|
||||
})
|
||||
doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
|
||||
|
||||
|
|
@ -75,22 +75,6 @@ This is the text version of this email
|
|||
else:
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rfc_5322_header_is_wrapped_at_998_chars(self):
|
||||
# unfortunately the db can only hold 140 chars so this can't be tested properly. test at max chars anyway.
|
||||
email = get_email_queue(
|
||||
recipients=['test@example.com'],
|
||||
sender='me@example.com',
|
||||
subject='Test Subject',
|
||||
content='<h1>Whatever</h1>',
|
||||
text_content='whatever',
|
||||
message_id="a.really.long.message.id.that.should.not.wrap.until.998.if.it.does.then.exchange.will.break" +
|
||||
".really.long.message.id.that.should.not.wrap.unti")
|
||||
result = safe_decode(prepare_message(email=email, recipient='test@test.com',
|
||||
recipients_list=[]))
|
||||
self.assertTrue(
|
||||
"a.really.long.message.id.that.should.not.wrap.until.998.if.it.does.then.exchange.will.break" +
|
||||
".really.long.message.id.that.should.not.wrap.unti" in result)
|
||||
|
||||
def test_image(self):
|
||||
img_signature = '''
|
||||
Content-Type: image/png
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import frappe.translate
|
|||
import frappe.modules.patch_handler
|
||||
import frappe.model.sync
|
||||
from frappe.utils.fixtures import sync_fixtures
|
||||
from frappe.utils.dashboard import sync_dashboards
|
||||
from frappe.cache_manager import clear_global_cache
|
||||
from frappe.desk.notifications import clear_notifications
|
||||
from frappe.website import render
|
||||
|
|
@ -23,6 +24,7 @@ def migrate(verbose=True, rebuild_website=False, skip_failing=False):
|
|||
- run before migrate hooks
|
||||
- run patches
|
||||
- sync doctypes (schema)
|
||||
- sync dashboards
|
||||
- sync fixtures
|
||||
- sync desktop icons
|
||||
- sync web pages (from /www)
|
||||
|
|
@ -53,6 +55,7 @@ def migrate(verbose=True, rebuild_website=False, skip_failing=False):
|
|||
frappe.translate.clear_cache()
|
||||
sync_jobs()
|
||||
sync_fixtures()
|
||||
sync_dashboards()
|
||||
sync_customizations()
|
||||
sync_languages()
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ def sync_for(app_name, force=0, sync_everything = False, verbose=False, reset_pe
|
|||
("data_migration", "data_migration_mapping"),
|
||||
("data_migration", "data_migration_plan_mapping"),
|
||||
("data_migration", "data_migration_plan"),
|
||||
("desk", "number_card"),
|
||||
("desk", "dashboard_chart"),
|
||||
("desk", "dashboard"),
|
||||
("desk", "onboarding_permission"),
|
||||
("desk", "onboarding_step"),
|
||||
("desk", "onboarding_step_map"),
|
||||
|
|
|
|||
|
|
@ -277,3 +277,4 @@ frappe.patches.v13_0.set_existing_dashboard_charts_as_public
|
|||
frappe.patches.v13_0.set_path_for_homepage_in_web_page_view
|
||||
frappe.patches.v13_0.migrate_translation_column_data
|
||||
frappe.patches.v13_0.set_read_times
|
||||
frappe.patches.v13_0.remove_web_view
|
||||
|
|
|
|||
|
|
@ -2,14 +2,4 @@ import frappe
|
|||
|
||||
def execute():
|
||||
frappe.reload_doctype('Translation')
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabTranslation`
|
||||
SET
|
||||
translated_text=target_name,
|
||||
source_text=source_name,
|
||||
contribution_status=(CASE status
|
||||
WHEN 'Deleted' THEN 'Rejected'
|
||||
ELSE ''
|
||||
END),
|
||||
contributed=0
|
||||
""")
|
||||
frappe.db.sql("UPDATE `tabTranslation` SET `translated_text`=`target_name`, `source_text`=`source_name`, `contributed`=0")
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ def get_read_time(blog):
|
|||
if blog.content_type == "Markdown":
|
||||
content = markdown(blog.content_md)
|
||||
|
||||
total_words = len(strip_html_tags(content).split())
|
||||
total_words = len(strip_html_tags(content or "").split())
|
||||
return ceil(total_words/250)
|
||||
|
|
@ -54,6 +54,22 @@ Quill.register(FontStyle, true);
|
|||
Quill.register(AlignStyle, true);
|
||||
Quill.register(DirectionStyle, true);
|
||||
|
||||
// replace font tag with span
|
||||
const Inline = Quill.import('blots/inline');
|
||||
|
||||
class CustomColor extends Inline {
|
||||
constructor(domNode, value) {
|
||||
super(domNode, value);
|
||||
this.domNode.style.color = this.domNode.color;
|
||||
domNode.outerHTML = this.domNode.outerHTML.replace(/<font/g, '<span').replace(/<\/font>/g, '</span>');
|
||||
}
|
||||
}
|
||||
|
||||
CustomColor.blotName = "customColor";
|
||||
CustomColor.tagName = "font";
|
||||
|
||||
Quill.register(CustomColor, true);
|
||||
|
||||
frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
|
||||
make_wrapper() {
|
||||
this._super();
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
</a>
|
||||
<ul class="dropdown-menu list-stats-dropdown" role="menu">
|
||||
<div class="dropdown-search">
|
||||
<input type="text" placeholder="Search" class="form-control dropdown-search-input input-xs">
|
||||
<input type="text" placeholder="Search" data-element="search" class="form-control input-xs">
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -242,40 +242,6 @@ frappe.views.ListSidebar = class ListSidebar {
|
|||
});
|
||||
}
|
||||
|
||||
setup_dropdown_search(dropdown, text_class) {
|
||||
let $dropdown_search = dropdown.find('.dropdown-search').show();
|
||||
let $search_input = $dropdown_search.find('.dropdown-search-input');
|
||||
$search_input.focus();
|
||||
$dropdown_search.on('click',(e)=>{
|
||||
e.stopPropagation();
|
||||
});
|
||||
let $elements = dropdown.find('li');
|
||||
$dropdown_search.on('keyup',()=> {
|
||||
let text_filter = $search_input.val().toLowerCase();
|
||||
// Replace trailing and leading spaces
|
||||
text_filter = text_filter.replace(/^\s+|\s+$/g, '');
|
||||
for (var i = 0; i < $elements.length; i++) {
|
||||
let text_element = $elements.eq(i).find(text_class);
|
||||
|
||||
let text = text_element.text().toLowerCase();
|
||||
// Search data-name since label for current user is 'Me'
|
||||
let name = '';
|
||||
if (text_element.data('name')) {
|
||||
name = text_element.data('name').toLowerCase();
|
||||
}
|
||||
if (text.includes(text_filter) || name.includes(text_filter)) {
|
||||
$elements.eq(i).css('display','');
|
||||
} else {
|
||||
$elements.eq(i).css('display','none');
|
||||
}
|
||||
}
|
||||
});
|
||||
dropdown.parent().on('hide.bs.dropdown',()=> {
|
||||
$dropdown_search.val('');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
get_cat_tags() {
|
||||
return this.cat_tags;
|
||||
}
|
||||
|
|
@ -294,7 +260,7 @@ frappe.views.ListSidebar = class ListSidebar {
|
|||
callback: function(r) {
|
||||
me.render_stat("_user_tags", (r.message.stats || {})["_user_tags"]);
|
||||
let stats_dropdown = me.sidebar.find('.list-stats-dropdown');
|
||||
me.setup_dropdown_search(stats_dropdown,'.stat-label');
|
||||
frappe.utils.setup_search(stats_dropdown, '.stat-link', '.stat-label');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ frappe.views.ListGroupBy = class ListGroupBy {
|
|||
title: __("Select Filters"),
|
||||
fields: this.get_group_by_dropdown_fields()
|
||||
});
|
||||
|
||||
d.set_primary_action("Save", ({ group_by_fields }) => {
|
||||
frappe.model.user_settings.save(this.doctype, 'group_by_fields', group_by_fields || null);
|
||||
this.group_by_fields = group_by_fields ? ['assigned_to', 'owner', ...group_by_fields] : ['assigned_to', 'owner'];
|
||||
|
|
@ -29,7 +30,12 @@ frappe.views.ListGroupBy = class ListGroupBy {
|
|||
d.hide();
|
||||
});
|
||||
|
||||
this.page.sidebar.find(".add-list-group-by a ").on("click", () => {
|
||||
d.$body.prepend(`<div class="filters-search">
|
||||
<input type="text" placeholder="${__('Search')}" data-element="search" class="form-control input-xs">
|
||||
</div>`);
|
||||
|
||||
this.page.sidebar.find(".add-list-group-by a").on("click", () => {
|
||||
frappe.utils.setup_search(d.$body, '.unit-checkbox', '.label-area');
|
||||
d.show();
|
||||
});
|
||||
}
|
||||
|
|
@ -95,7 +101,7 @@ frappe.views.ListGroupBy = class ListGroupBy {
|
|||
this.get_group_by_count(fieldname).then(field_count_list => {
|
||||
if (field_count_list.length) {
|
||||
this.render_dropdown_items(field_count_list, fieldtype, dropdown);
|
||||
this.sidebar.setup_dropdown_search(dropdown, '.group-by-value');
|
||||
frappe.utils.setup_search(dropdown, '.group-by-item', '.group-by-value', 'data-name');
|
||||
} else {
|
||||
dropdown.find('.group-by-loading').html(`${__("No filters found")}`);
|
||||
}
|
||||
|
|
@ -165,7 +171,7 @@ frappe.views.ListGroupBy = class ListGroupBy {
|
|||
};
|
||||
let standard_html = `
|
||||
<div class="dropdown-search">
|
||||
<input type="text" placeholder="${__('Search')}" class="form-control dropdown-search-input input-xs">
|
||||
<input type="text" placeholder="${__('Search')}" data-element="search" class="dropdown-search-input form-control input-xs">
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -695,7 +695,32 @@ Object.assign(frappe.utils, {
|
|||
return null;
|
||||
}
|
||||
},
|
||||
setup_search($wrapper, el_class, text_class, data_attr) {
|
||||
const $search_input = $wrapper.find('[data-element="search"]').show();
|
||||
$search_input.focus().val('');
|
||||
const $elements = $wrapper.find(el_class).show();
|
||||
|
||||
$search_input.off('keyup').on('keyup', () => {
|
||||
let text_filter = $search_input.val().toLowerCase();
|
||||
// Replace trailing and leading spaces
|
||||
text_filter = text_filter.replace(/^\s+|\s+$/g, '');
|
||||
for (let i = 0; i < $elements.length; i++) {
|
||||
const text_element = $elements.eq(i).find(text_class);
|
||||
const text = text_element.text().toLowerCase();
|
||||
|
||||
let name = '';
|
||||
if (data_attr && text_element.attr(data_attr)) {
|
||||
name = text_element.attr(data_attr).toLowerCase();
|
||||
}
|
||||
|
||||
if (text.includes(text_filter) || name.includes(text_filter)) {
|
||||
$elements.eq(i).css('display', '');
|
||||
} else {
|
||||
$elements.eq(i).css('display', 'none');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
deep_equal(a, b) {
|
||||
return deep_equal(a, b);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,11 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
}
|
||||
});
|
||||
|
||||
d.$body.prepend(`<div class="columns-search">
|
||||
<input type="text" placeholder="${__('Search')}" data-element="search" class="form-control input-xs">
|
||||
</div>`);
|
||||
|
||||
frappe.utils.setup_search(d.$body, '.unit-checkbox', '.label-area');
|
||||
d.show();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ export default class ChartWidget extends Widget {
|
|||
colors.push(field.color);
|
||||
});
|
||||
} else if (["Line", "Bar"].includes(this.chart_doc.type)) {
|
||||
colors = [this.chart_doc.color || "light-blue"];
|
||||
colors = [this.chart_doc.color || []];
|
||||
}
|
||||
|
||||
if (!this.data || !this.data.labels.length || !Object.keys(this.data).length) {
|
||||
|
|
|
|||
|
|
@ -173,21 +173,26 @@ export default class OnboardingWidget extends Widget {
|
|||
frappe.ui.form.make_quick_entry(
|
||||
step.reference_document,
|
||||
() => {
|
||||
if (frappe.get_route_str != current_route) {
|
||||
let args = {};
|
||||
args.message = __("Let's take you back to onboarding");
|
||||
args.title = __("Looks Great");
|
||||
args.primary_action = {
|
||||
action: () => {
|
||||
frappe.set_route(current_route).then(() => {
|
||||
this.mark_complete(step);
|
||||
});
|
||||
},
|
||||
label: __("Continue"),
|
||||
};
|
||||
if (frappe.get_route_str() != current_route) {
|
||||
let success_dialog = frappe.msgprint({
|
||||
message: __("Let's take you back to onboarding"),
|
||||
title: __("Looks Great"),
|
||||
primary_action: {
|
||||
action: () => {
|
||||
success_dialog.hide();
|
||||
frappe.set_route(current_route).then(() => {
|
||||
this.mark_complete(step);
|
||||
});
|
||||
},
|
||||
label: __("Continue"),
|
||||
}
|
||||
});
|
||||
|
||||
frappe.msgprint(args);
|
||||
frappe.msg_dialog.custom_onhide = () => args.primary_action.action();
|
||||
frappe.msg_dialog.custom_onhide = () => {
|
||||
frappe.set_route(current_route).then(() => {
|
||||
this.mark_complete(step);
|
||||
});
|
||||
};
|
||||
} else {
|
||||
this.mark_complete(step);
|
||||
}
|
||||
|
|
@ -277,25 +282,27 @@ export default class OnboardingWidget extends Widget {
|
|||
</div>
|
||||
`);
|
||||
|
||||
let success_dialog = new frappe.ui.Dialog({
|
||||
primary_action: () => {
|
||||
success_dialog.hide();
|
||||
// Wait for modal to close before removing widget
|
||||
setTimeout(() => {
|
||||
this.delete();
|
||||
}, 300);
|
||||
},
|
||||
primary_action_label: __("Continue"),
|
||||
});
|
||||
if (!this.success_dialog) {
|
||||
this.success_dialog = new frappe.ui.Dialog({
|
||||
primary_action: () => {
|
||||
this.success_dialog.hide();
|
||||
// Wait for modal to close before removing widget
|
||||
setTimeout(() => {
|
||||
this.delete();
|
||||
}, 300);
|
||||
},
|
||||
primary_action_label: __("Continue"),
|
||||
});
|
||||
|
||||
success_dialog.set_title(__("Onboarding Complete"));
|
||||
success_dialog.header
|
||||
.find(".indicator")
|
||||
.removeClass("hidden")
|
||||
.addClass("green");
|
||||
this.success_dialog.set_title(__("Onboarding Complete"));
|
||||
this.success_dialog.header
|
||||
.find(".indicator")
|
||||
.removeClass("hidden")
|
||||
.addClass("green");
|
||||
|
||||
success.appendTo(success_dialog.$body);
|
||||
success_dialog.show();
|
||||
success.appendTo(this.success_dialog.$body);
|
||||
this.success_dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
set_body() {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.columns-search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.report-wrapper {
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -413,6 +413,9 @@ body[data-route^="Module"] .main-menu {
|
|||
}
|
||||
}
|
||||
|
||||
.filters-search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
// module sidebar
|
||||
.layout-side-section .module-sidebar-nav {
|
||||
margin-top: 15px;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{% if frappe.form_dict.scope %}
|
||||
<input type="text" hidden name="scope" value="{{ frappe.form_dict.scope }}">
|
||||
<input type="text" hidden name="scope" value="{{ frappe.sanitize_html(frappe.form_dict.scope) }}">
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ class TestFormLoad(unittest.TestCase):
|
|||
user.remove_roles('Blogger', 'Website Manager')
|
||||
user.add_roles(*user_roles)
|
||||
|
||||
blog_doc.delete()
|
||||
|
||||
def test_fieldlevel_permissions_in_load_for_child_table(self):
|
||||
contact = frappe.new_doc('Contact')
|
||||
contact.first_name = '_Test Contact 1'
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import frappe, unittest, os
|
||||
import frappe.translate
|
||||
from frappe import _
|
||||
|
||||
dirname = os.path.dirname(__file__)
|
||||
translation_string_file = os.path.join(dirname, 'translation_test_file.txt')
|
||||
|
|
@ -13,6 +14,11 @@ class TestTranslate(unittest.TestCase):
|
|||
data = frappe.translate.get_messages_from_file(translation_string_file)
|
||||
self.assertListEqual(data, expected_output)
|
||||
|
||||
def test_translation_with_context(self):
|
||||
frappe.local.lang = 'fr'
|
||||
self.assertEqual(_('Change'), 'Changement')
|
||||
self.assertEqual(_('Change', context='Coins'), 'la monnaie')
|
||||
|
||||
expected_output = [
|
||||
('apps/frappe/frappe/tests/translation_test_file.txt', 'Warning: Unable to find {0} in any table related to {1}', 'This is some context', 2),
|
||||
('apps/frappe/frappe/tests/translation_test_file.txt', 'Warning: Unable to find {0} in any table related to {1}', None, 4),
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ def get_translation_dict_from_file(path, lang, app):
|
|||
|
||||
for item in csv_content:
|
||||
if len(item)==3 and item[2]:
|
||||
key = item[1] + ':' + item[2]
|
||||
key = item[0] + ':' + item[2]
|
||||
translation_map[key] = strip(item[1])
|
||||
elif len(item) in [2, 3]:
|
||||
translation_map[item[0]] = strip(item[1])
|
||||
|
|
|
|||
|
|
@ -4141,3 +4141,5 @@ Path,Chemin,
|
|||
Components,Composants,
|
||||
Verified By,Vérifié Par,
|
||||
Lead Conversion Time,Temps de conversion des prospects,
|
||||
Change,Changement,
|
||||
Change,la monnaie,Coins
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
from __future__ import unicode_literals
|
||||
import json
|
||||
import frappe
|
||||
from frappe import _
|
||||
from functools import wraps
|
||||
from frappe.utils import add_to_date, get_link_to_form
|
||||
from frappe.modules.import_file import import_doc
|
||||
|
||||
|
||||
def cache_source(function):
|
||||
|
|
@ -72,3 +72,42 @@ def get_from_date_from_timespan(to_date, timespan):
|
|||
years = -50
|
||||
return add_to_date(to_date, years=years, months=months, days=days,
|
||||
as_datetime=True)
|
||||
|
||||
def sync_dashboards(app=None):
|
||||
"""Import, overwrite fixtures from `[app]/fixtures`"""
|
||||
if app:
|
||||
apps = [app]
|
||||
else:
|
||||
apps = frappe.get_installed_apps()
|
||||
|
||||
for app_name in apps:
|
||||
print("Updating Dashboard for {app}".format(app=app_name))
|
||||
for module_name in frappe.local.app_modules.get(app_name) or []:
|
||||
config = get_config(app_name, module_name)
|
||||
if config:
|
||||
frappe.flags.in_import = True
|
||||
make_records(config.charts, "Dashboard Chart")
|
||||
make_records(config.number_cards, "Number Card")
|
||||
make_records(config.dashboards, "Dashboard")
|
||||
frappe.flags.in_import = False
|
||||
|
||||
def make_records(config, doctype):
|
||||
if not config:
|
||||
return
|
||||
|
||||
try:
|
||||
for item in config:
|
||||
item["doctype"] = doctype
|
||||
import_doc(item)
|
||||
frappe.db.commit()
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
def get_config(app, module):
|
||||
try:
|
||||
module_dashboards = frappe.get_module('{app}.{module}.dashboard_fixtures'.format(app=app, module=module))
|
||||
if hasattr(module_dashboards, 'get_data'):
|
||||
return frappe._dict(module_dashboards.get_data())
|
||||
return None
|
||||
except ImportError:
|
||||
return None
|
||||
|
|
@ -83,6 +83,7 @@ def get_safe_globals():
|
|||
make_post_request = frappe.integrations.utils.make_post_request,
|
||||
socketio_port=frappe.conf.socketio_port,
|
||||
get_hooks=frappe.get_hooks,
|
||||
sanitize_html=frappe.utils.sanitize_html
|
||||
),
|
||||
style=frappe._dict(
|
||||
border_color='#d1d8dd'
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ def get_context(context):
|
|||
context.title = _('Search Results for ')
|
||||
context.query = query
|
||||
context.route = '/search'
|
||||
context.update(get_search_results(query, frappe.form_dict.scope))
|
||||
context.update(get_search_results(query, frappe.utils.sanitize_html(frappe.form_dict.scope)))
|
||||
else:
|
||||
context.title = _('Search')
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue