chore: releaseversion-14
@@ -52,9 +52,6 @@ if [ "$TYPE" == "server" ]; then | |||
sed -i 's/^socketio:/# socketio:/g' Procfile; | |||
sed -i 's/^redis_socketio:/# redis_socketio:/g' Procfile; | |||
fi | |||
if [ "$TYPE" == "ui" ]; then | |||
sed -i 's/^web: bench serve/web: bench serve --with-coverage/g' Procfile; | |||
fi | |||
echo "Starting Bench..." | |||
@@ -122,17 +122,7 @@ jobs: | |||
- name: Run Tests | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' }} | |||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --use-orchestrator --with-coverage | |||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --use-orchestrator | |||
env: | |||
CI_BUILD_ID: ${{ github.run_id }} | |||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io | |||
- name: Upload coverage data | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' }} | |||
uses: codecov/codecov-action@v3 | |||
with: | |||
name: MariaDB | |||
fail_ci_if_error: true | |||
files: /home/runner/frappe-bench/sites/coverage.xml | |||
verbose: true | |||
flags: server |
@@ -125,17 +125,7 @@ jobs: | |||
- name: Run Tests | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' }} | |||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --use-orchestrator --with-coverage | |||
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --use-orchestrator | |||
env: | |||
CI_BUILD_ID: ${{ github.run_id }} | |||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io | |||
- name: Upload coverage data | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' }} | |||
uses: codecov/codecov-action@v3 | |||
with: | |||
name: Postgres | |||
fail_ci_if_error: true | |||
files: /home/runner/frappe-bench/sites/coverage.xml | |||
verbose: true | |||
flags: server |
@@ -144,42 +144,10 @@ jobs: | |||
- name: UI Tests | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' }} | |||
run: cd ~/frappe-bench/ && bench --site test_site run-ui-tests frappe --with-coverage --headless --parallel --ci-build-id $GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT | |||
run: cd ~/frappe-bench/ && bench --site test_site run-ui-tests frappe --headless --parallel --ci-build-id $GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT | |||
env: | |||
CYPRESS_RECORD_KEY: 4a48f41c-11b3-425b-aa88-c58048fa69eb | |||
- name: Stop server | |||
if: ${{ steps.check-build.outputs.build-server == 'strawberry' }} | |||
run: | | |||
ps -ef | grep "frappe serve" | awk '{print $2}' | xargs kill -s SIGINT 2> /dev/null || true | |||
sleep 5 | |||
- name: Check If Coverage Report Exists | |||
id: check_coverage | |||
uses: andstor/file-existence-action@v1 | |||
with: | |||
files: "/home/runner/frappe-bench/apps/frappe/.cypress-coverage/clover.xml" | |||
- name: Upload Coverage Data | |||
if: ${{ steps.check-build.outputs.build == 'strawberry' && steps.check_coverage.outputs.files_exists == 'true' }} | |||
uses: codecov/codecov-action@v3 | |||
with: | |||
name: Cypress | |||
fail_ci_if_error: true | |||
directory: /home/runner/frappe-bench/apps/frappe/.cypress-coverage/ | |||
verbose: true | |||
flags: ui-tests | |||
- name: Upload Server Coverage Data | |||
if: ${{ steps.check-build.outputs.build-server == 'strawberry' }} | |||
uses: codecov/codecov-action@v3 | |||
with: | |||
name: MariaDB | |||
fail_ci_if_error: true | |||
files: /home/runner/frappe-bench/sites/coverage.xml | |||
verbose: true | |||
flags: server | |||
- name: Show bench console if tests failed | |||
if: ${{ failure() }} | |||
run: cat ~/frappe-bench/bench_start.log | |||
run: cat ~/frappe-bench/bench_start.log |
@@ -26,15 +26,15 @@ context("Control Link", () => { | |||
}); | |||
} | |||
function get_dialog_with_user_link() { | |||
function get_dialog_with_gender_link() { | |||
return cy.dialog({ | |||
title: "Link", | |||
fields: [ | |||
{ | |||
label: "Select User", | |||
label: "Select Gender", | |||
fieldname: "link", | |||
fieldtype: "Link", | |||
options: "User", | |||
options: "Gender", | |||
}, | |||
], | |||
}); | |||
@@ -43,19 +43,6 @@ context("Control Link", () => { | |||
it("should set the valid value", () => { | |||
get_dialog_with_link().as("dialog"); | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "User", | |||
property: "translate_link_fields", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "0", | |||
}, | |||
true | |||
); | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
@@ -133,19 +120,6 @@ context("Control Link", () => { | |||
}); | |||
it("show title field in link", () => { | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "User", | |||
property: "translate_link_fields", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "0", | |||
}, | |||
true | |||
); | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
@@ -275,142 +249,54 @@ context("Control Link", () => { | |||
); | |||
}); | |||
it("show translated text for link with show_title_field_in_link enabled", () => { | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "ToDo", | |||
property: "translate_link_fields", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "1", | |||
}, | |||
true | |||
); | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "ToDo", | |||
property: "show_title_field_in_link", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "1", | |||
}, | |||
true | |||
); | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
cy.insert_doc("Translation", { | |||
doctype: "Translation", | |||
language: frappe.boot.lang, | |||
source_text: "this is a test todo for link", | |||
translated_text: "this is a translated test todo for link", | |||
it("show translated text for Gender link field with language de with input in de", () => { | |||
cy.call("frappe.tests.ui_test_helpers.insert_translations").then(() => { | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
cy.set_value("User", frappe.user.name, { language: "de" }); | |||
}); | |||
}); | |||
cy.clear_cache(); | |||
cy.wait(500); | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
if (!frappe.boot) { | |||
frappe.boot = { | |||
link_title_doctypes: ["ToDo"], | |||
translatable_doctypes: ["ToDo"], | |||
}; | |||
} else { | |||
frappe.boot.link_title_doctypes = ["ToDo"]; | |||
frappe.boot.translatable_doctypes = ["ToDo"]; | |||
} | |||
}); | |||
cy.clear_cache(); | |||
cy.wait(500); | |||
get_dialog_with_link().as("dialog"); | |||
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link"); | |||
get_dialog_with_gender_link().as("dialog"); | |||
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link"); | |||
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input"); | |||
cy.wait("@search_link"); | |||
cy.get("@input").type("todo for link", { delay: 100 }); | |||
cy.wait("@search_link"); | |||
cy.get(".frappe-control[data-fieldname=link] ul").should("be.visible"); | |||
cy.get(".frappe-control[data-fieldname=link] input").type("{enter}", { delay: 100 }); | |||
cy.get(".frappe-control[data-fieldname=link] input").blur(); | |||
cy.get("@dialog").then((dialog) => { | |||
cy.get("@todos").then((todos) => { | |||
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input"); | |||
cy.wait("@search_link"); | |||
cy.get("@input").type("Sonstiges", { delay: 100 }); | |||
cy.wait("@search_link"); | |||
cy.get(".frappe-control[data-fieldname=link] ul").should("be.visible"); | |||
cy.get(".frappe-control[data-fieldname=link] input").type("{enter}", { delay: 100 }); | |||
cy.get(".frappe-control[data-fieldname=link] input").blur(); | |||
cy.get("@dialog").then((dialog) => { | |||
let field = dialog.get_field("link"); | |||
let value = field.get_value(); | |||
let label = field.get_label_value(); | |||
expect(value).to.eq(todos[0]); | |||
expect(label).to.eq("this is a translated test todo for link"); | |||
expect(value).to.eq("Other"); | |||
expect(label).to.eq("Sonstiges"); | |||
}); | |||
}); | |||
}); | |||
it("show translated text for link with show_title_field_in_link disabled", () => { | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "User", | |||
property: "translate_link_fields", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "1", | |||
}, | |||
true | |||
); | |||
cy.insert_doc( | |||
"Property Setter", | |||
{ | |||
doctype: "Property Setter", | |||
doc_type: "ToDo", | |||
property: "show_title_field_in_link", | |||
property_type: "Check", | |||
doctype_or_field: "DocType", | |||
value: "0", | |||
}, | |||
true | |||
); | |||
it("show text for Gender link field with language en", () => { | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
cy.insert_doc("Translation", { | |||
doctype: "Translation", | |||
language: frappe.boot.lang, | |||
source_text: "test@erpnext.com", | |||
translated_text: "translatedtest@erpnext.com", | |||
}); | |||
cy.set_value("User", frappe.user.name, { language: "en" }); | |||
}); | |||
cy.clear_cache(); | |||
cy.wait(500); | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
if (!frappe.boot) { | |||
frappe.boot = { | |||
translatable_doctypes: ["User"], | |||
}; | |||
} else { | |||
frappe.boot.translatable_doctypes = ["User"]; | |||
} | |||
}); | |||
get_dialog_with_user_link().as("dialog"); | |||
get_dialog_with_gender_link().as("dialog"); | |||
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link"); | |||
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input"); | |||
cy.wait("@search_link"); | |||
cy.get("@input").type("test@erpnext.com", { delay: 100 }); | |||
cy.get("@input").type("Non-Conforming", { delay: 100 }); | |||
cy.wait("@search_link"); | |||
cy.get(".frappe-control[data-fieldname=link] ul").should("be.visible"); | |||
cy.get(".frappe-control[data-fieldname=link] input").type("{enter}", { delay: 100 }); | |||
@@ -420,8 +306,34 @@ context("Control Link", () => { | |||
let value = field.get_value(); | |||
let label = field.get_label_value(); | |||
expect(value).to.eq("test@erpnext.com"); | |||
expect(label).to.eq("translatedtest@erpnext.com"); | |||
expect(value).to.eq("Non-Conforming"); | |||
expect(label).to.eq("Non-Conforming"); | |||
}); | |||
}); | |||
it("show custom link option", () => { | |||
cy.window() | |||
.its("frappe") | |||
.then((frappe) => { | |||
frappe.ui.form.ControlLink.link_options = (link) => { | |||
return [ | |||
{ | |||
html: | |||
"<span class='text-primary custom-link-option'>" + | |||
"<i class='fa fa-search' style='margin-right: 5px;'></i> " + | |||
"Custom Link Option" + | |||
"</span>", | |||
label: "Custom Link Option", | |||
value: "custom__link_option", | |||
action: () => {}, | |||
}, | |||
]; | |||
}; | |||
get_dialog_with_link().as("dialog"); | |||
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input"); | |||
cy.get("@input").type("custom", { delay: 100 }); | |||
cy.get(".custom-link-option").should("be.visible"); | |||
}); | |||
}); | |||
}); |
@@ -237,7 +237,7 @@ context("Web Form", () => { | |||
cy.get(".web-form-actions a").contains("Edit").click(); | |||
cy.fill_field("last_name", "_Test User"); | |||
cy.fill_field("middle_name", "_Test User"); | |||
cy.get(".web-form-actions .btn-primary").click(); | |||
cy.url().should("include", "/me"); | |||
@@ -249,7 +249,7 @@ context("Web Form", () => { | |||
cy.get(".web-form-actions a").contains("Edit").click(); | |||
cy.fill_field("last_name", "_Test User"); | |||
cy.fill_field("middle_name", "_Test User"); | |||
cy.get(".btn-next").should("be.visible"); | |||
cy.get(".btn-next").click(); | |||
@@ -2284,14 +2284,22 @@ def safe_eval(code, eval_globals=None, eval_locals=None): | |||
def get_website_settings(key): | |||
if not hasattr(local, "website_settings"): | |||
local.website_settings = db.get_singles_dict("Website Settings", cast=True) | |||
try: | |||
local.website_settings = get_cached_doc("Website Settings") | |||
except DoesNotExistError: | |||
clear_last_message() | |||
return | |||
return local.website_settings.get(key) | |||
def get_system_settings(key): | |||
if not hasattr(local, "system_settings"): | |||
local.system_settings = db.get_singles_dict("System Settings", cast=True) | |||
try: | |||
local.system_settings = get_cached_doc("System Settings") | |||
except DoesNotExistError: # possible during new install | |||
clear_last_message() | |||
return | |||
return local.system_settings.get(key) | |||
@@ -19,7 +19,7 @@ from frappe.social.doctype.energy_point_log.energy_point_log import get_energy_p | |||
from frappe.social.doctype.energy_point_settings.energy_point_settings import ( | |||
is_energy_point_enabled, | |||
) | |||
from frappe.translate import get_lang_dict, get_messages_for_boot | |||
from frappe.translate import get_lang_dict, get_messages_for_boot, get_translated_doctypes | |||
from frappe.utils import add_user_info, cstr, get_time_zone | |||
from frappe.utils.change_log import get_versions | |||
from frappe.website.doctype.web_page_view.web_page_view import is_tracking_enabled | |||
@@ -100,7 +100,7 @@ def get_bootinfo(): | |||
bootinfo.desk_settings = get_desk_settings() | |||
bootinfo.app_logo_url = get_app_logo() | |||
bootinfo.link_title_doctypes = get_link_title_doctypes() | |||
bootinfo.translatable_doctypes = get_translatable_doctypes() | |||
bootinfo.translated_doctypes = get_translated_doctypes() | |||
return bootinfo | |||
@@ -399,14 +399,6 @@ def set_time_zone(bootinfo): | |||
} | |||
def get_translatable_doctypes(): | |||
dts = frappe.get_all("DocType", {"translate_link_fields": 1}, pluck="name") | |||
custom_dts = frappe.get_all( | |||
"Property Setter", {"property": "translate_link_fields", "value": "1"}, pluck="doc_type" | |||
) | |||
return dts + custom_dts | |||
def load_country_doc(bootinfo): | |||
country = frappe.db.get_default("country") | |||
if not country: | |||
@@ -1,113 +1,48 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"autoname": "field:gender", | |||
"beta": 0, | |||
"creation": "2017-04-10 12:11:36.526508", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"actions": [], | |||
"autoname": "field:gender", | |||
"creation": "2017-04-10 12:11:36.526508", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"gender" | |||
], | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "gender", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Gender", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
"fieldname": "gender", | |||
"fieldtype": "Data", | |||
"label": "Gender", | |||
"unique": 1 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2017-04-10 12:17:04.848338", | |||
"modified_by": "Administrator", | |||
"module": "Contacts", | |||
"name": "Gender", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
], | |||
"links": [], | |||
"modified": "2022-08-05 18:33:28.043370", | |||
"modified_by": "Administrator", | |||
"module": "Contacts", | |||
"name": "Gender", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
}, | |||
}, | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 0, | |||
"delete": 0, | |||
"email": 0, | |||
"export": 0, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 0, | |||
"read": 1, | |||
"report": 0, | |||
"role": "All", | |||
"set_user_permissions": 0, | |||
"share": 0, | |||
"submit": 0, | |||
"write": 0 | |||
"read": 1, | |||
"role": "All" | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"show_name_in_global_search": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1, | |||
"track_seen": 0 | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1, | |||
"translated_doctype": 1 | |||
} |
@@ -1,132 +1,61 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 0, | |||
"allow_rename": 1, | |||
"autoname": "field:salutation", | |||
"beta": 0, | |||
"creation": "2017-04-10 12:17:58.071915", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"actions": [], | |||
"allow_rename": 1, | |||
"autoname": "field:salutation", | |||
"creation": "2017-04-10 12:17:58.071915", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"salutation" | |||
], | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "salutation", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Salutation", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
"fieldname": "salutation", | |||
"fieldtype": "Data", | |||
"label": "Salutation", | |||
"unique": 1 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2020-09-14 12:55:18.855578", | |||
"modified_by": "Administrator", | |||
"module": "Contacts", | |||
"name": "Salutation", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
], | |||
"links": [], | |||
"modified": "2022-08-05 18:33:28.196387", | |||
"modified_by": "Administrator", | |||
"module": "Contacts", | |||
"name": "Salutation", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
}, | |||
}, | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 0, | |||
"delete": 0, | |||
"email": 0, | |||
"export": 0, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 0, | |||
"read": 1, | |||
"report": 0, | |||
"role": "All", | |||
"set_user_permissions": 0, | |||
"share": 0, | |||
"submit": 0, | |||
"write": 0 | |||
}, | |||
"read": 1, | |||
"role": "All" | |||
}, | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "Administrator", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "Administrator", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 0, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"show_name_in_global_search": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1, | |||
"track_seen": 0 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1, | |||
"translated_doctype": 1 | |||
} |
@@ -47,7 +47,7 @@ | |||
"view_settings", | |||
"title_field", | |||
"show_title_field_in_link", | |||
"translate_link_fields", | |||
"translated_doctype", | |||
"search_fields", | |||
"default_print_format", | |||
"sort_field", | |||
@@ -595,7 +595,7 @@ | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "translate_link_fields", | |||
"fieldname": "translated_doctype", | |||
"fieldtype": "Check", | |||
"label": "Translate Link Fields" | |||
} | |||
@@ -680,7 +680,7 @@ | |||
"link_fieldname": "reference_doctype" | |||
} | |||
], | |||
"modified": "2022-02-28 21:56:52.116915", | |||
"modified": "2022-08-05 18:33:27.315351", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "DocType", | |||
@@ -716,5 +716,5 @@ | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1, | |||
"translate_link_fields": 1 | |||
"translated_doctype": 1 | |||
} |
@@ -51,7 +51,7 @@ | |||
"icon": "fa fa-globe", | |||
"in_create": 1, | |||
"links": [], | |||
"modified": "2021-10-18 14:02:06.818219", | |||
"modified": "2022-08-14 18:54:03.490836", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "Language", | |||
@@ -76,8 +76,10 @@ | |||
} | |||
], | |||
"search_fields": "language_name", | |||
"show_title_field_in_link": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"title_field": "language_name", | |||
"track_changes": 1 | |||
} |
@@ -148,7 +148,7 @@ | |||
"idx": 1, | |||
"index_web_pages_for_search": 1, | |||
"links": [], | |||
"modified": "2022-01-12 20:18:18.496230", | |||
"modified": "2022-08-05 18:33:27.694065", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "Role", | |||
@@ -171,5 +171,6 @@ | |||
"sort_field": "modified", | |||
"sort_order": "ASC", | |||
"states": [], | |||
"track_changes": 1 | |||
"track_changes": 1, | |||
"translated_doctype": 1 | |||
} |
@@ -8,6 +8,7 @@ from unittest.mock import patch | |||
import frappe | |||
import frappe.exceptions | |||
from frappe.core.doctype.user.user import ( | |||
handle_password_test_fail, | |||
reset_password, | |||
sign_up, | |||
test_password_strength, | |||
@@ -191,6 +192,12 @@ class TestUser(unittest.TestCase): | |||
# Score 1; should now fail | |||
result = test_password_strength("bee2ve") | |||
self.assertEqual(result["feedback"]["password_policy_validation_passed"], False) | |||
self.assertRaises( | |||
frappe.exceptions.ValidationError, handle_password_test_fail, result["feedback"] | |||
) | |||
self.assertRaises( | |||
frappe.exceptions.ValidationError, handle_password_test_fail, result | |||
) # test backwards compatibility | |||
# Score 4; should pass | |||
result = test_password_strength("Eastern_43A1W") | |||
@@ -200,7 +207,7 @@ class TestUser(unittest.TestCase): | |||
user = frappe.get_doc("User", "test@example.com") | |||
frappe.flags.in_test = False | |||
user.new_password = "password" | |||
self.assertRaisesRegex(frappe.exceptions.ValidationError, "Invalid Password", user.save) | |||
self.assertRaises(frappe.exceptions.ValidationError, user.save) | |||
user.reload() | |||
user.new_password = "Eastern_43A1W" | |||
user.save() | |||
@@ -540,7 +540,7 @@ class User(Document): | |||
feedback = result.get("feedback", None) | |||
if feedback and not feedback.get("password_policy_validation_passed", False): | |||
handle_password_test_fail(result) | |||
handle_password_test_fail(feedback) | |||
def suggest_username(self): | |||
def _check_suggestion(suggestion): | |||
@@ -686,7 +686,7 @@ def update_password(new_password, logout_all_sessions=0, key=None, old_password= | |||
feedback = result.get("feedback", None) | |||
if feedback and not feedback.get("password_policy_validation_passed", False): | |||
handle_password_test_fail(result) | |||
handle_password_test_fail(feedback) | |||
res = _get_user_for_update_password(key, old_password) | |||
if res.get("message"): | |||
@@ -1042,13 +1042,15 @@ def notify_admin_access_to_system_manager(login_manager=None): | |||
) | |||
def handle_password_test_fail(result): | |||
suggestions = result["feedback"]["suggestions"][0] if result["feedback"]["suggestions"] else "" | |||
warning = result["feedback"]["warning"] if "warning" in result["feedback"] else "" | |||
suggestions += ( | |||
"<br>" + _("Hint: Include symbols, numbers and capital letters in the password") + "<br>" | |||
) | |||
frappe.throw(" ".join([_("Invalid Password:"), warning, suggestions])) | |||
def handle_password_test_fail(feedback: dict): | |||
# Backward compatibility | |||
if "feedback" in feedback: | |||
feedback = feedback["feedback"] | |||
suggestions = feedback.get("suggestions", []) | |||
warning = feedback.get("warning", "") | |||
frappe.throw(msg=" ".join([warning] + suggestions), title=_("Invalid Password")) | |||
def update_gravatar(name): | |||
@@ -186,10 +186,13 @@ 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 = df.copy() | |||
df["owner"] = "Administrator" | |||
create_custom_field(doctype, df, ignore_validate=ignore_validate) | |||
except frappe.exceptions.DuplicateEntryError: | |||
pass | |||
elif update: | |||
custom_field = frappe.get_doc("Custom Field", field) | |||
custom_field.flags.ignore_validate = ignore_validate | |||
@@ -29,7 +29,7 @@ | |||
"view_settings_section", | |||
"title_field", | |||
"show_title_field_in_link", | |||
"translate_link_fields", | |||
"translated_doctype", | |||
"image_field", | |||
"default_print_format", | |||
"column_break_29", | |||
@@ -315,7 +315,7 @@ | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "translate_link_fields", | |||
"fieldname": "translated_doctype", | |||
"fieldtype": "Check", | |||
"label": "Translate Link Fields" | |||
} | |||
@@ -326,7 +326,7 @@ | |||
"index_web_pages_for_search": 1, | |||
"issingle": 1, | |||
"links": [], | |||
"modified": "2022-05-13 15:36:16.772277", | |||
"modified": "2022-08-04 15:36:16.772277", | |||
"modified_by": "Administrator", | |||
"module": "Custom", | |||
"name": "Customize Form", | |||
@@ -585,7 +585,7 @@ doctype_properties = { | |||
"naming_rule": "Data", | |||
"autoname": "Data", | |||
"show_title_field_in_link": "Check", | |||
"translate_link_fields": "Check", | |||
"translated_doctype": "Check", | |||
} | |||
docfield_properties = { | |||
@@ -226,7 +226,7 @@ CREATE TABLE `tabDocType` ( | |||
`sender_field` varchar(255) DEFAULT NULL, | |||
`show_title_field_in_link` int(1) NOT NULL DEFAULT 0, | |||
`migration_hash` varchar(255) DEFAULT NULL, | |||
`translate_link_fields` int(1) NOT NULL DEFAULT 0, | |||
`translated_doctype` int(1) NOT NULL DEFAULT 0, | |||
PRIMARY KEY (`name`) | |||
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | |||
@@ -231,7 +231,7 @@ CREATE TABLE "tabDocType" ( | |||
"sender_field" varchar(255) DEFAULT NULL, | |||
"show_title_field_in_link" smallint NOT NULL DEFAULT 0, | |||
"migration_hash" varchar(255) DEFAULT NULL, | |||
"translate_link_fields" smallint NOT NULL DEFAULT 0, | |||
"translated_doctype" smallint NOT NULL DEFAULT 0, | |||
PRIMARY KEY ("name") | |||
) ; | |||
@@ -8,6 +8,7 @@ import re | |||
import frappe | |||
from frappe import _, is_whitelisted | |||
from frappe.permissions import has_permission | |||
from frappe.translate import get_translated_doctypes | |||
from frappe.utils import cint, cstr, unique | |||
@@ -115,7 +116,10 @@ def search_widget( | |||
raise e | |||
else: | |||
frappe.respond_as_web_page( | |||
title="Invalid Method", html="Method not found", indicator_color="red", http_status_code=404 | |||
title="Invalid Method", | |||
html="Method not found", | |||
indicator_color="red", | |||
http_status_code=404, | |||
) | |||
return | |||
except Exception as e: | |||
@@ -146,9 +150,22 @@ def search_widget( | |||
filters = [] | |||
or_filters = [] | |||
translated_search_doctypes = frappe.get_hooks("translated_search_doctypes") | |||
translated_doctypes = frappe.cache().hget( | |||
"translated_doctypes", "doctypes", get_translated_doctypes | |||
) | |||
# build from doctype | |||
if txt: | |||
field_types = [ | |||
"Data", | |||
"Text", | |||
"Small Text", | |||
"Long Text", | |||
"Link", | |||
"Select", | |||
"Read Only", | |||
"Text Editor", | |||
] | |||
search_fields = ["name"] | |||
if meta.title_field: | |||
search_fields.append(meta.title_field) | |||
@@ -158,13 +175,8 @@ def search_widget( | |||
for f in search_fields: | |||
fmeta = meta.get_field(f.strip()) | |||
if (doctype not in translated_search_doctypes) and ( | |||
f == "name" | |||
or ( | |||
fmeta | |||
and fmeta.fieldtype | |||
in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"] | |||
) | |||
if (doctype not in translated_doctypes) and ( | |||
f == "name" or (fmeta and fmeta.fieldtype in field_types) | |||
): | |||
or_filters.append([doctype, f.strip(), "like", f"%{txt}%"]) | |||
@@ -188,7 +200,8 @@ def search_widget( | |||
# find relevance as location of search term from the beginning of string `name`. used for sorting results. | |||
formatted_fields.append( | |||
"""locate({_txt}, `tab{doctype}`.`name`) as `_relevance`""".format( | |||
_txt=frappe.db.escape((txt or "").replace("%", "").replace("@", "")), doctype=doctype | |||
_txt=frappe.db.escape((txt or "").replace("%", "").replace("@", "")), | |||
doctype=doctype, | |||
) | |||
) | |||
@@ -206,7 +219,7 @@ def search_widget( | |||
else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) | |||
) | |||
if doctype in translated_search_doctypes: | |||
if doctype in translated_doctypes: | |||
page_length = None | |||
values = frappe.get_list( | |||
@@ -223,7 +236,7 @@ def search_widget( | |||
strict=False, | |||
) | |||
if doctype in translated_search_doctypes: | |||
if doctype in translated_doctypes: | |||
# Filtering the values array so that query is included in very element | |||
values = ( | |||
v | |||
@@ -54,7 +54,7 @@ | |||
"icon": "fa fa-globe", | |||
"idx": 1, | |||
"links": [], | |||
"modified": "2020-02-24 15:44:31.837133", | |||
"modified": "2022-08-05 18:33:27.880783", | |||
"modified_by": "Administrator", | |||
"module": "Geo", | |||
"name": "Country", | |||
@@ -84,5 +84,7 @@ | |||
"quick_entry": 1, | |||
"sort_field": "country_name", | |||
"sort_order": "ASC", | |||
"track_changes": 1 | |||
"states": [], | |||
"track_changes": 1, | |||
"translated_doctype": 1 | |||
} |
@@ -373,5 +373,3 @@ override_whitelisted_methods = { | |||
"frappe.core.doctype.file.file.move_file": "frappe.core.api.file.move_file", | |||
"frappe.core.doctype.file.file.zip_files": "frappe.core.api.file.zip_files", | |||
} | |||
translated_search_doctypes = ["DocType", "Role", "Country", "Gender", "Salutation"] |
@@ -671,10 +671,19 @@ class BaseDocument: | |||
return _("Error: Value missing for {0}: {1}").format(_(df.parent), _(df.label)) | |||
def has_content(df): | |||
value = cstr(self.get(df.fieldname)) | |||
has_text_content = strip_html(value).strip() | |||
has_img_tag = "<img" in value | |||
if df.fieldtype == "Text Editor" and (has_text_content or has_img_tag): | |||
return True | |||
else: | |||
return has_text_content | |||
missing = [] | |||
for df in self.meta.get("fields", {"reqd": ("=", 1)}): | |||
if self.get(df.fieldname) in (None, []) or not strip_html(cstr(self.get(df.fieldname))).strip(): | |||
if self.get(df.fieldname) in (None, []) or not has_content(df): | |||
missing.append((df.fieldname, get_msg(df))) | |||
# check for missing parent and parenttype | |||
@@ -71,7 +71,7 @@ frappe.db = { | |||
}, | |||
}); | |||
}, | |||
get_doc: function (doctype, name, filters = null) { | |||
get_doc: function (doctype, name, filters) { | |||
return new Promise((resolve, reject) => { | |||
frappe | |||
.call({ | |||
@@ -13,14 +13,8 @@ | |||
<div> | |||
<a class="flex" :href="file.doc.file_url" v-if="file.doc" target="_blank"> | |||
<span class="file-name">{{ file.name | file_name }}</span> | |||
<div class="ml-2" v-html="private_icon"></div> | |||
</a> | |||
<span class="flex" v-else> | |||
<span class="file-name">{{ file.name | file_name }}</span> | |||
<button class="ml-2 btn-reset" @click="$emit('toggle_private')" :title="__('Toggle Public/Private')"> | |||
<div v-html="private_icon"></div> | |||
</button> | |||
</span> | |||
<span class="file-name" v-else>{{ file.name | file_name }}</span> | |||
</div> | |||
<div> | |||
@@ -28,7 +22,11 @@ | |||
{{ file.file_obj.size | file_size }} | |||
</span> | |||
</div> | |||
<label v-if="is_optimizable" class="optimize-checkbox"><input type="checkbox" :checked="optimize" @change="$emit('toggle_optimize')">Optimize</label> | |||
<div class="flex config-area"> | |||
<label v-if="is_optimizable" class="frappe-checkbox"><input type="checkbox" :checked="optimize" @change="$emit('toggle_optimize')">Optimize</label> | |||
<label class="frappe-checkbox"><input type="checkbox" :checked="file.private" @change="$emit('toggle_private')">Private</label> | |||
</div> | |||
<div> | |||
<span v-if="file.error_message" class="file-error text-danger"> | |||
{{ file.error_message }} | |||
@@ -87,9 +85,6 @@ export default { | |||
} | |||
}, | |||
computed: { | |||
private_icon() { | |||
return frappe.utils.icon(this.is_private ? 'lock' : 'unlock'); | |||
}, | |||
is_private() { | |||
return this.file.doc ? this.file.doc.is_private : this.file.private; | |||
}, | |||
@@ -206,7 +201,7 @@ export default { | |||
opacity: 1; | |||
} | |||
.optimize-checkbox { | |||
.frappe-checkbox { | |||
font-size: var(--text-sm); | |||
color: var(--text-light); | |||
display: flex; | |||
@@ -214,6 +209,10 @@ export default { | |||
padding-top: 0.25rem; | |||
} | |||
.config-area { | |||
gap: 0.5rem; | |||
} | |||
.file-error { | |||
font-size: var(--text-sm); | |||
font-weight: var(--text-bold); | |||
@@ -228,7 +228,7 @@ export default { | |||
}); | |||
} | |||
if (this.restrictions.max_number_of_files == null && this.doctype) { | |||
this.restrictions.max_number_of_files = frappe.get_meta(self.doctype).max_attachments; | |||
this.restrictions.max_number_of_files = frappe.get_meta(this.doctype)?.max_attachments; | |||
} | |||
}, | |||
watch: { | |||
@@ -87,7 +87,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat | |||
return this.is_translatable() ? __(value) : value; | |||
} | |||
is_translatable() { | |||
return in_list(frappe.boot?.translatable_doctypes || [], this.get_options()); | |||
return in_list(frappe.boot?.translated_doctypes || [], this.get_options()); | |||
} | |||
set_link_title(value) { | |||
let doctype = this.get_options(); | |||
@@ -288,8 +288,17 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat | |||
action: me.new_doc, | |||
}); | |||
} | |||
// advanced search | |||
//custom link actions | |||
let custom__link_options = | |||
frappe.ui.form.ControlLink.link_options && | |||
frappe.ui.form.ControlLink.link_options(me); | |||
if (custom__link_options) { | |||
r.results = r.results.concat(custom__link_options); | |||
} | |||
// advanced search | |||
if (locals && locals["DocType"]) { | |||
// not applicable in web forms | |||
r.results.push({ | |||
@@ -382,22 +391,6 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat | |||
me.$input.val(""); | |||
} | |||
}); | |||
this.$input.on("focus", function () { | |||
if (!frappe.boot.translated_search_doctypes.includes(me.df.options)) { | |||
me.show_untranslated(); | |||
} | |||
}); | |||
this.$input.keydown((e) => { | |||
let BACKSPACE = 8; | |||
if ( | |||
e.keyCode === BACKSPACE && | |||
!frappe.boot.translated_search_doctypes.includes(me.df.options) | |||
) { | |||
me.show_untranslated(); | |||
} | |||
}); | |||
} | |||
show_untranslated() { | |||
@@ -160,6 +160,12 @@ frappe.ui.form.Attachments = class Attachments { | |||
this.dialog.$wrapper.remove(); | |||
} | |||
const restrictions = {}; | |||
if (this.frm.meta.max_attachments) { | |||
restrictions.max_number_of_files = | |||
this.frm.meta.max_attachments - this.frm.attachments.get_attachments().length; | |||
} | |||
new frappe.ui.FileUploader({ | |||
doctype: this.frm.doctype, | |||
docname: this.frm.docname, | |||
@@ -168,10 +174,7 @@ frappe.ui.form.Attachments = class Attachments { | |||
on_success: (file_doc) => { | |||
this.attachment_uploaded(file_doc); | |||
}, | |||
restrictions: { | |||
max_number_of_files: | |||
this.frm.meta.max_attachments - this.frm.attachments.get_attachments().length, | |||
}, | |||
restrictions, | |||
}); | |||
} | |||
get_args() { | |||
@@ -184,7 +184,6 @@ def get(): | |||
frappe.get_attr(hook)(bootinfo=bootinfo) | |||
bootinfo["lang"] = frappe.translate.get_user_lang() | |||
bootinfo["translated_search_doctypes"] = frappe.get_hooks("translated_search_doctypes") | |||
bootinfo["disable_async"] = frappe.conf.disable_async | |||
bootinfo["setup_complete"] = cint(frappe.get_system_settings("setup_complete")) | |||
@@ -101,6 +101,14 @@ class TestDocument(unittest.TestCase): | |||
d.insert() | |||
self.assertEqual(frappe.db.get_value("User", d.name), d.name) | |||
def test_text_editor_field(self): | |||
try: | |||
frappe.get_doc( | |||
doctype="Activity Log", subject="test", message='<img src="test.png" />' | |||
).insert() | |||
except frappe.MandatoryError: | |||
self.fail("Text Editor false positive mandatory error") | |||
def test_conflict_validation(self): | |||
d1 = self.test_insert() | |||
d2 = frappe.get_doc(d1.doctype, d1.name) | |||
@@ -333,3 +333,37 @@ def insert_doctype_with_child_table_record(name): | |||
insert_child(doc, "Drag", "08189DIHAA2981", 0, 0.7, 342628, "2022-05-04") | |||
doc.insert() | |||
@frappe.whitelist() | |||
def insert_translations(): | |||
translation = [ | |||
{ | |||
"doctype": "Translation", | |||
"language": "de", | |||
"source_text": "Other", | |||
"translated_text": "Sonstiges", | |||
}, | |||
{ | |||
"doctype": "Translation", | |||
"language": "de", | |||
"source_text": "Genderqueer", | |||
"translated_text": "Nichtbinär", | |||
}, | |||
{ | |||
"doctype": "Translation", | |||
"language": "de", | |||
"source_text": "Non-Conforming", | |||
"translated_text": "Nicht konform", | |||
}, | |||
{ | |||
"doctype": "Translation", | |||
"language": "de", | |||
"source_text": "Prefer not to say", | |||
"translated_text": "Keine Angabe", | |||
}, | |||
] | |||
for doc in translation: | |||
if not frappe.db.exists("doc"): | |||
frappe.get_doc(doc).insert() |
@@ -23,7 +23,7 @@ from pypika.terms import PseudoColumn | |||
import frappe | |||
from frappe.model.utils import InvalidIncludePath, render_include | |||
from frappe.query_builder import DocType, Field | |||
from frappe.utils import cstr, get_bench_path, is_html, strip, strip_html_tags | |||
from frappe.utils import cstr, get_bench_path, is_html, strip, strip_html_tags, unique | |||
TRANSLATE_PATTERN = re.compile( | |||
r"_\(\s*" # starts with literal `_(`, ignore following whitespace/newlines | |||
@@ -1294,3 +1294,11 @@ def set_preferred_language_cookie(preferred_language): | |||
def get_preferred_language_cookie(): | |||
return frappe.request.cookies.get("preferred_language") | |||
def get_translated_doctypes(): | |||
dts = frappe.get_all("DocType", {"translated_doctype": 1}, pluck="name") | |||
custom_dts = frappe.get_all( | |||
"Property Setter", {"property": "translated_doctype", "value": "1"}, pluck="doc_type" | |||
) | |||
return unique(dts + custom_dts) |
@@ -79,7 +79,8 @@ def is_valid_title(title) -> bool: | |||
def _create_app_boilerplate(dest, hooks, no_git=False): | |||
frappe.create_folder( | |||
os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)), with_init=True | |||
os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)), | |||
with_init=True, | |||
) | |||
frappe.create_folder( | |||
os.path.join(dest, hooks.app_name, hooks.app_name, "templates"), with_init=True | |||
@@ -249,8 +250,8 @@ app_license = "{app_license}" | |||
# add methods and filters to jinja environment | |||
# jinja = {{ | |||
# "methods": "{app_name}.utils.jinja_methods", | |||
# "filters": "{app_name}.utils.jinja_filters" | |||
# "methods": "{app_name}.utils.jinja_methods", | |||
# "filters": "{app_name}.utils.jinja_filters" | |||
# }} | |||
# Installation | |||
@@ -276,11 +277,11 @@ app_license = "{app_license}" | |||
# Permissions evaluated in scripted ways | |||
# permission_query_conditions = {{ | |||
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", | |||
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", | |||
# }} | |||
# | |||
# has_permission = {{ | |||
# "Event": "frappe.desk.doctype.event.event.has_permission", | |||
# "Event": "frappe.desk.doctype.event.event.has_permission", | |||
# }} | |||
# DocType Class | |||
@@ -288,7 +289,7 @@ app_license = "{app_license}" | |||
# Override standard doctype classes | |||
# override_doctype_class = {{ | |||
# "ToDo": "custom_app.overrides.CustomToDo" | |||
# "ToDo": "custom_app.overrides.CustomToDo" | |||
# }} | |||
# Document Events | |||
@@ -296,10 +297,10 @@ app_license = "{app_license}" | |||
# Hook on document methods and events | |||
# doc_events = {{ | |||
# "*": {{ | |||
# "on_update": "method", | |||
# "on_cancel": "method", | |||
# "on_trash": "method" | |||
# "*": {{ | |||
# "on_update": "method", | |||
# "on_cancel": "method", | |||
# "on_trash": "method" | |||
# }} | |||
# }} | |||
@@ -307,21 +308,21 @@ app_license = "{app_license}" | |||
# --------------- | |||
# scheduler_events = {{ | |||
# "all": [ | |||
# "{app_name}.tasks.all" | |||
# ], | |||
# "daily": [ | |||
# "{app_name}.tasks.daily" | |||
# ], | |||
# "hourly": [ | |||
# "{app_name}.tasks.hourly" | |||
# ], | |||
# "weekly": [ | |||
# "{app_name}.tasks.weekly" | |||
# ], | |||
# "monthly": [ | |||
# "{app_name}.tasks.monthly" | |||
# ], | |||
# "all": [ | |||
# "{app_name}.tasks.all" | |||
# ], | |||
# "daily": [ | |||
# "{app_name}.tasks.daily" | |||
# ], | |||
# "hourly": [ | |||
# "{app_name}.tasks.hourly" | |||
# ], | |||
# "weekly": [ | |||
# "{app_name}.tasks.weekly" | |||
# ], | |||
# "monthly": [ | |||
# "{app_name}.tasks.monthly" | |||
# ], | |||
# }} | |||
# Testing | |||
@@ -333,14 +334,14 @@ app_license = "{app_license}" | |||
# ------------------------------ | |||
# | |||
# override_whitelisted_methods = {{ | |||
# "frappe.desk.doctype.event.event.get_events": "{app_name}.event.get_events" | |||
# "frappe.desk.doctype.event.event.get_events": "{app_name}.event.get_events" | |||
# }} | |||
# | |||
# each overriding function accepts a `data` argument; | |||
# generated from the base implementation of the doctype dashboard, | |||
# along with any modifications made in other Frappe apps | |||
# override_doctype_dashboards = {{ | |||
# "Task": "{app_name}.task.get_dashboard_data" | |||
# "Task": "{app_name}.task.get_dashboard_data" | |||
# }} | |||
# exempt linked doctypes from being automatically cancelled | |||
@@ -352,40 +353,32 @@ app_license = "{app_license}" | |||
# -------------------- | |||
# user_data_fields = [ | |||
# {{ | |||
# "doctype": "{{doctype_1}}", | |||
# "filter_by": "{{filter_by}}", | |||
# "redact_fields": ["{{field_1}}", "{{field_2}}"], | |||
# "partial": 1, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_2}}", | |||
# "filter_by": "{{filter_by}}", | |||
# "partial": 1, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_3}}", | |||
# "strict": False, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_4}}" | |||
# }} | |||
# {{ | |||
# "doctype": "{{doctype_1}}", | |||
# "filter_by": "{{filter_by}}", | |||
# "redact_fields": ["{{field_1}}", "{{field_2}}"], | |||
# "partial": 1, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_2}}", | |||
# "filter_by": "{{filter_by}}", | |||
# "partial": 1, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_3}}", | |||
# "strict": False, | |||
# }}, | |||
# {{ | |||
# "doctype": "{{doctype_4}}" | |||
# }} | |||
# ] | |||
# Authentication and authorization | |||
# -------------------------------- | |||
# auth_hooks = [ | |||
# "{app_name}.auth.validate" | |||
# "{app_name}.auth.validate" | |||
# ] | |||
# Translation | |||
# -------------------------------- | |||
# Make link fields search translated document names for these DocTypes | |||
# Recommended only for DocTypes which have limited documents with untranslated names | |||
# For example: Role, Gender, etc. | |||
# translated_search_doctypes = [] | |||
""" | |||
desktop_template = """from frappe import _ | |||