Skip to content

Commit

Permalink
Merge pull request #26357 from frappe/version-15-hotfix
Browse files Browse the repository at this point in the history
chore: release v15
  • Loading branch information
ankush committed May 7, 2024
2 parents 587438d + e8195e9 commit cd6f6ba
Show file tree
Hide file tree
Showing 69 changed files with 840 additions and 301 deletions.
6 changes: 6 additions & 0 deletions cypress/fixtures/form_builder_doctype.js
Expand Up @@ -10,6 +10,12 @@ export default {
fieldtype: "Data",
label: "Data 3",
},
{
fieldname: "gender",
fieldtype: "Link",
label: "Gender",
options: "Gender",
},
{
fieldname: "tab",
fieldtype: "Tab Break",
Expand Down
11 changes: 9 additions & 2 deletions cypress/integration/control_link.js
Expand Up @@ -27,7 +27,7 @@ context("Control Link", () => {
}

function get_dialog_with_gender_link() {
return cy.dialog({
let dialog = cy.dialog({
title: "Link",
fields: [
{
Expand All @@ -38,6 +38,8 @@ context("Control Link", () => {
},
],
});
cy.wait(500);
return dialog;
}

it("should set the valid value", () => {
Expand All @@ -62,6 +64,7 @@ context("Control Link", () => {
cy.wait("@search_link");
cy.get("@input").type("todo for link", { delay: 200 });
cy.wait("@search_link");
cy.wait(500);
cy.get(".frappe-control[data-fieldname=link]").findByRole("listbox").should("be.visible");
cy.get(".frappe-control[data-fieldname=link] input").type("{enter}", { delay: 100 });
cy.get(".frappe-control[data-fieldname=link] input").blur();
Expand All @@ -82,6 +85,7 @@ context("Control Link", () => {
.type("invalid value", { delay: 100 })
.blur();
cy.wait("@validate_link");
cy.wait(500);
cy.get(".frappe-control[data-fieldname=link] input").should("have.value", "");
});

Expand All @@ -92,6 +96,7 @@ context("Control Link", () => {

cy.get(".frappe-control[data-fieldname=link] input").type(" ", { delay: 100 }).blur();
cy.wait("@validate_link");
cy.wait(500);
cy.get(".frappe-control[data-fieldname=link] input").should("have.value", "");
cy.window()
.its("cur_dialog")
Expand Down Expand Up @@ -262,6 +267,7 @@ context("Control Link", () => {
cy.wait("@search_link");
cy.get("@input").type("Sonstiges", { delay: 200 });
cy.wait("@search_link");
cy.wait(500);
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();
Expand All @@ -284,7 +290,7 @@ context("Control Link", () => {
});

cy.clear_cache();
cy.wait(500);
cy.wait(1000);

get_dialog_with_gender_link().as("dialog");
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
Expand All @@ -293,6 +299,7 @@ context("Control Link", () => {
cy.wait("@search_link");
cy.get("@input").type("Non-Conforming", { delay: 200 });
cy.wait("@search_link");
cy.wait(500);
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();
Expand Down
41 changes: 5 additions & 36 deletions cypress/integration/file_uploader.js
@@ -1,7 +1,11 @@
context("FileUploader", () => {
before(() => {
cy.login();
});

beforeEach(() => {
cy.visit("/app");
cy.wait(2000); // workspace can load async and clear active dialog
});

function open_upload_dialog() {
Expand All @@ -10,6 +14,7 @@ context("FileUploader", () => {
.then((frappe) => {
new frappe.ui.FileUploader();
});
cy.wait(500);
}

it("upload dialog api works", () => {
Expand Down Expand Up @@ -47,40 +52,4 @@ context("FileUploader", () => {
.should("have.property", "file_name", "example.json");
cy.get(".modal:visible").should("not.exist");
});

it("should accept web links", () => {
open_upload_dialog();

cy.get_open_dialog().findByRole("button", { name: "Link" }).click();
cy.get_open_dialog()
.findByPlaceholderText("Attach a web link")
.type("https://github.com", { delay: 100, force: true });
cy.intercept("POST", "/api/method/upload_file").as("upload_file");
cy.get_open_dialog().findByRole("button", { name: "Upload" }).click();
cy.wait("@upload_file")
.its("response.body.message")
.should("have.property", "file_url", "https://github.com");
cy.get(".modal:visible").should("not.exist");
});

it("should allow cropping and optimization for valid images", () => {
open_upload_dialog();

cy.get_open_dialog()
.find(".file-upload-area")
.selectFile("cypress/fixtures/sample_image.jpg", {
action: "drag-drop",
});

cy.get_open_dialog().findAllByText("sample_image.jpg").should("exist");
cy.get_open_dialog().find(".btn-crop").first().click();
cy.get_open_dialog().findByRole("button", { name: "Crop" }).click();
cy.get_open_dialog().findAllByRole("checkbox", { name: "Optimize" }).should("exist");
cy.get_open_dialog().findAllByLabelText("Optimize").first().click();

cy.intercept("POST", "/api/method/upload_file").as("upload_file");
cy.get_open_dialog().findByRole("button", { name: "Upload" }).click();
cy.wait("@upload_file").its("response.statusCode").should("eq", 200);
cy.get(".modal:visible").should("not.exist");
});
});
34 changes: 34 additions & 0 deletions cypress/integration/form_builder.js
Expand Up @@ -35,6 +35,40 @@ context("Form Builder", () => {
cy.get(".title-area .indicator-pill.orange").should("have.text", "Not Saved");
});

it("Check if Filters are applied to the link field", () => {
// Visit the Form Builder
cy.visit(`/app/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click();

cy.get("[data-fieldname='gender']").click();

// click on filter action button
cy.get('[data-fieldname="gender"] .field-actions button:first').click();

// add filter
cy.get(".modal-body .clear-filters").click();
cy.get(".modal-body .filter-action-buttons .add-filter").click();
cy.wait(100);
cy.get(".modal-body .filter-box .list_filter .filter-field .link-field input").type(
"Male"
);
cy.get(".btn-modal-primary").click();

// Save the document
cy.click_doc_primary_button("Save");

// Open a new Form
cy.new_form(doctype_name);
// Click on the "salutation" field
cy.get_field("gender").clear().click();

cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
cy.wait("@search_link").then((data) => {
expect(data.response.body.message.length).to.eq(1);
expect(data.response.body.message[0].value).to.eq("Male");
});
});

it("Add empty section and save", () => {
cy.visit(`/app/doctype/${doctype_name}`);
cy.findByRole("tab", { name: "Form" }).click();
Expand Down
31 changes: 19 additions & 12 deletions frappe/__init__.py
Expand Up @@ -1013,7 +1013,11 @@ def clear_cache(user: str | None = None, doctype: str | None = None):
frappe.cache_manager.clear_user_cache(user)
else: # everything
# Delete ALL keys associated with this site.
frappe.cache.delete_keys("")
keys_to_delete = set(frappe.cache.get_keys(""))
for key in frappe.get_hooks("persistent_cache_keys"):
keys_to_delete.difference_update(frappe.cache.get_keys(key))
frappe.cache.delete_value(list(keys_to_delete), make_keys=False)

reset_metadata_version()
local.cache = {}
local.new_doc_templates = {}
Expand Down Expand Up @@ -1673,34 +1677,37 @@ def setup_module_map(include_all_apps: bool = True) -> None:
"""
if include_all_apps:
local.app_modules = cache.get_value("app_modules")
local.module_app = cache.get_value("module_app")
else:
local.app_modules = cache.get_value("installed_app_modules")
local.module_app = cache.get_value("module_installed_app")

if not (local.app_modules and local.module_app):
local.module_app, local.app_modules = {}, {}
if not local.app_modules:
local.app_modules = {}
if include_all_apps:
apps = get_all_apps(with_internal_apps=True)
else:
apps = get_installed_apps(_ensure_on_bench=True)

for app in apps:
local.app_modules.setdefault(app, [])
for module in get_module_list(app):
module = scrub(module)
if module in local.module_app:
print(
f"WARNING: module `{module}` found in apps `{local.module_app[module]}` and `{app}`"
)
local.module_app[module] = app
local.app_modules[app].append(module)

if include_all_apps:
cache.set_value("app_modules", local.app_modules)
cache.set_value("module_app", local.module_app)
else:
cache.set_value("installed_app_modules", local.app_modules)
cache.set_value("module_installed_app", local.module_app)

# Init module_app (reverse mapping)
local.module_app = {}
for app, modules in local.app_modules.items():
for module in modules:
if module in local.module_app:
warnings.warn(
f"WARNING: module `{module}` found in apps `{local.module_app[module]}` and `{app}`",
stacklevel=1,
)
local.module_app[module] = app


def get_file_items(path, raise_not_found=False, ignore_empty_lines=True):
Expand Down
32 changes: 18 additions & 14 deletions frappe/boot.py
Expand Up @@ -24,6 +24,7 @@
)
from frappe.utils import add_user_info, cstr, get_system_timezone
from frappe.utils.change_log import get_versions
from frappe.utils.frappecloud import on_frappecloud
from frappe.website.doctype.web_page_view.web_page_view import is_tracking_enabled


Expand Down Expand Up @@ -164,7 +165,9 @@ def get_user_pages_or_reports(parent, cache=False):
page = DocType("Page")
report = DocType("Report")

if parent == "Report":
is_report = parent == "Report"

if is_report:
columns = (report.name.as_("title"), report.ref_doctype, report.report_type)
else:
columns = (page.title.as_("title"),)
Expand Down Expand Up @@ -206,7 +209,7 @@ def get_user_pages_or_reports(parent, cache=False):
.distinct()
)

if parent == "Report":
if is_report:
pages_with_standard_roles = pages_with_standard_roles.where(report.disabled == 0)

pages_with_standard_roles = pages_with_standard_roles.run(as_dict=True)
Expand All @@ -221,19 +224,20 @@ def get_user_pages_or_reports(parent, cache=False):
frappe.qb.from_(hasRole).select(Count("*")).where(hasRole.parent == parentTable.name)
)

# pages with no role are allowed
if parent == "Page":
pages_with_no_roles = (
frappe.qb.from_(parentTable)
.select(parentTable.name, parentTable.modified, *columns)
.where(no_of_roles == 0)
).run(as_dict=True)
# pages and reports with no role are allowed
rows_with_no_roles = (
frappe.qb.from_(parentTable)
.select(parentTable.name, parentTable.modified, *columns)
.where(no_of_roles == 0)
).run(as_dict=True)

for p in pages_with_no_roles:
if p.name not in has_role:
has_role[p.name] = {"modified": p.modified, "title": p.title}
for r in rows_with_no_roles:
if r.name not in has_role:
has_role[r.name] = {"modified": r.modified, "title": r.title}
if is_report:
has_role[r.name] |= {"ref_doctype": r.ref_doctype}

elif parent == "Report":
if is_report:
if not has_permission("Report", raise_exception=False):
return {}

Expand Down Expand Up @@ -445,7 +449,7 @@ def get_marketplace_apps():
apps = []
cache_key = "frappe_marketplace_apps"

if frappe.conf.developer_mode:
if frappe.conf.developer_mode or not on_frappecloud():
return apps

def get_apps_from_fc():
Expand Down
5 changes: 1 addition & 4 deletions frappe/contacts/doctype/address/address.py
Expand Up @@ -214,15 +214,12 @@ def get_address_list(doctype, txt, filters, limit_start, limit_page_length=20, o
from frappe.www.list import get_list

user = frappe.session.user
ignore_permissions = True

if not filters:
filters = []
filters.append(("Address", "owner", "=", user))

return get_list(
doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions
)
return get_list(doctype, txt, filters, limit_start, limit_page_length)


def has_website_permission(doc, ptype, user, verbose=False):
Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/comment/comment.py
Expand Up @@ -192,7 +192,7 @@ def update_comments_in_parent(reference_doctype, reference_name, _comments):
)

except Exception as e:
if frappe.db.is_column_missing(e) and getattr(frappe.local, "request", None):
if frappe.db.is_missing_column(e) and getattr(frappe.local, "request", None):
pass
elif frappe.db.is_data_too_long(e):
raise frappe.DataTooLongException
Expand Down
12 changes: 3 additions & 9 deletions frappe/core/doctype/data_import/data_import.js
Expand Up @@ -409,15 +409,9 @@ frappe.ui.form.on("Data Import", {

render_import_log(frm) {
frappe.call({
method: "frappe.client.get_list",
method: "frappe.core.doctype.data_import.data_import.get_import_logs",
args: {
doctype: "Data Import Log",
filters: {
data_import: frm.doc.name,
},
fields: ["success", "docname", "messages", "exception", "row_indexes"],
limit_page_length: 5000,
order_by: "log_index",
data_import: frm.doc.name,
},
callback: function (r) {
let logs = r.message;
Expand Down Expand Up @@ -508,7 +502,7 @@ frappe.ui.form.on("Data Import", {
show_import_log(frm) {
frm.toggle_display("import_log_section", false);

if (frm.import_in_progress) {
if (frm.is_new() || frm.import_in_progress) {
return;
}

Expand Down

0 comments on commit cd6f6ba

Please sign in to comment.