From a9c4bac95089e850badf48bc38700481c749688d Mon Sep 17 00:00:00 2001
From: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
Date: Mon, 1 Dec 2025 19:31:27 +0100
Subject: [PATCH] fix: speed up link field (#34689)
---
cypress/integration/control_dynamic_link.js | 15 +-
cypress/integration/control_link.js | 88 +++++---
cypress/integration/customize_form.js | 3 +-
cypress/integration/dashboard_chart.js | 10 +-
cypress/integration/form_builder.js | 35 ++-
cypress/integration/number_card.js | 2 +-
cypress/integration/web_form.js | 8 +-
cypress/integration/workspace_blocks.js | 11 +-
cypress/support/commands.js | 19 +-
frappe/public/js/frappe/form/controls/link.js | 210 +++++++++---------
10 files changed, 234 insertions(+), 167 deletions(-)
diff --git a/cypress/integration/control_dynamic_link.js b/cypress/integration/control_dynamic_link.js
index d3343a56a3..aaf7137ea9 100644
--- a/cypress/integration/control_dynamic_link.js
+++ b/cypress/integration/control_dynamic_link.js
@@ -93,6 +93,7 @@ context("Dynamic Link", () => {
it("Creating a dynamic link and verifying it in a dialog", () => {
get_dialog_with_dynamic_link().as("dialog");
+ cy.wait(500);
cy.get_field("doc_type").clear();
cy.fill_field("doc_type", "User", "Link");
cy.get_field("doc_id").click();
@@ -106,7 +107,7 @@ context("Dynamic Link", () => {
cy.get(".btn-modal-close").click({ force: true, multiple: true });
});
- it("Creating a dynamic link and verifying it", () => {
+ it("Shows dynamic link options in list filters", () => {
cy.visit("/desk/test-dynamic-link");
//Clicking on the Document ID field
@@ -122,7 +123,9 @@ context("Dynamic Link", () => {
.find("div")
.its("length")
.should("be.gte", 0);
+ });
+ it("Shows dynamic link options in new form", () => {
//Opening a new form for dynamic link doctype
cy.new_form("Test Dynamic Link");
cy.get_field("doc_type").clear();
@@ -138,14 +141,14 @@ context("Dynamic Link", () => {
.its("length")
.should("be.gte", 0);
cy.get_field("doc_type").clear();
+ });
+
+ it("Shows error when invalid DocType is passed", () => {
+ cy.new_form("Test Dynamic Link");
+ cy.get_field("doc_type").clear();
//Entering System Settings in the Doctype field
- cy.intercept("/api/method/frappe.desk.search.search_link").as("search_query");
cy.fill_field("doc_type", "System Settings", "Link", { delay: 500 });
- cy.wait("@search_query");
- cy.get(`[data-fieldname="doc_type"] ul:visible div:first-child`).click({
- scrollBehavior: false,
- });
cy.get_field("doc_id").click();
diff --git a/cypress/integration/control_link.js b/cypress/integration/control_link.js
index 2633a5bca8..2e2cf92deb 100644
--- a/cypress/integration/control_link.js
+++ b/cypress/integration/control_link.js
@@ -62,12 +62,13 @@ context("Control Link", () => {
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
cy.wait("@search_link");
- cy.get("@input").type("todo for link", { delay: 200 });
+ cy.wait(500);
+ cy.get("@input").type("todo for link", { delay: 100 });
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();
+ cy.get("@input").parent().findByRole("listbox").should("be.visible");
+ cy.get("@input").type("{enter}");
+ cy.get("@input").blur();
cy.get("@dialog").then((dialog) => {
cy.get("@todos").then((todos) => {
let value = dialog.get_value("link");
@@ -80,24 +81,27 @@ context("Control Link", () => {
get_dialog_with_link().as("dialog");
cy.intercept("/api/method/frappe.client.validate_link*").as("validate_link");
-
- cy.get(".frappe-control[data-fieldname=link] input")
- .type("invalid value", { delay: 100 })
- .blur();
- cy.wait("@validate_link");
+ 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.wait(500);
- cy.get(".frappe-control[data-fieldname=link] input").should("have.value", "");
+ cy.get("@input").type("invalid value", { delay: 100 }).blur();
+ cy.wait("@validate_link");
+ cy.get("@input").should("have.value", "");
});
it("should be possible set empty value explicitly", () => {
get_dialog_with_link().as("dialog");
cy.intercept("/api/method/frappe.client.validate_link*").as("validate_link");
+ cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
- cy.get(".frappe-control[data-fieldname=link] input").type(" ", { delay: 100 }).blur();
- cy.wait("@validate_link");
+ cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
+ cy.wait("@search_link");
cy.wait(500);
- cy.get(".frappe-control[data-fieldname=link] input").should("have.value", "");
+ cy.get("@input").type(" ", { delay: 100 }).blur();
+ cy.wait("@validate_link");
+ cy.get("@input").should("have.value", "");
cy.window()
.its("cur_dialog")
.then((dialog) => {
@@ -111,10 +115,10 @@ context("Control Link", () => {
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
cy.get("@todos").then((todos) => {
- cy.get(".frappe-control[data-fieldname=link] input").as("input");
- cy.get("@input").focus();
+ cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
cy.wait("@search_link");
- cy.get("@input").type(todos[0]).blur();
+ cy.wait(500);
+ cy.get("@input").type(todos[0], { delay: 100 }).blur();
// not waiting for validate_link because it will not get called
cy.get("@input").trigger("mouseover");
cy.get(".frappe-control[data-fieldname=link] .btn-open")
@@ -156,11 +160,13 @@ context("Control Link", () => {
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
cy.wait("@search_link");
- cy.get("@input").type("todo for link", { delay: 200 });
+ cy.wait(500);
+ cy.get("@input").type("todo for link", { delay: 100 });
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();
+ cy.get("@input").type("{enter}");
+ cy.get("@input").blur();
cy.get("@dialog").then((dialog) => {
cy.get("@todos").then((todos) => {
let field = dialog.get_field("link");
@@ -179,13 +185,18 @@ context("Control Link", () => {
cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
cy.intercept("/api/method/frappe.client.validate_link*").as("validate_link");
- cy.get(".frappe-control[data-fieldname=assigned_by] input").focus().as("input");
- cy.get("@input").clear().type(cy.config("testUser"), { delay: 300 }).blur();
- cy.wait("@validate_link");
- cy.get(".frappe-control[data-fieldname=assigned_by_full_name] .control-value").should(
- "contain",
- "Frappe"
- );
+ cy.fill_field("assigned_by", cy.config("testUser"), "Link");
+ cy.call("frappe.client.get_value", {
+ doctype: "User",
+ filters: {
+ name: cy.config("testUser"),
+ },
+ fieldname: "full_name",
+ }).then((r) => {
+ cy.get(
+ ".frappe-control[data-fieldname=assigned_by_full_name] .control-value"
+ ).should("contain", r.message.full_name);
+ });
cy.window().its("cur_frm.doc.assigned_by").should("eq", cy.config("testUser"));
@@ -234,10 +245,19 @@ context("Control Link", () => {
cy.new_form("ToDo");
cy.fill_field("description", "new", "Text Editor").blur().wait(200);
cy.save();
- cy.get(".frappe-control[data-fieldname=assigned_by_full_name] .control-value").should(
- "contain",
- "Frappe"
- );
+ cy.call("frappe.client.get_value", {
+ doctype: "User",
+ filters: {
+ name: cy.config("testUser"),
+ },
+ fieldname: "full_name",
+ }).then((r) => {
+ cy.get(".frappe-control[data-fieldname=assigned_by_full_name] .control-value").should(
+ "contain",
+ r.message.full_name
+ );
+ });
+
// if user clears default value explicitly, system should not reset default again
cy.get_field("assigned_by").clear().blur();
cy.save();
@@ -264,11 +284,11 @@ context("Control Link", () => {
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
cy.wait("@search_link");
- cy.get("@input").type("Sonstiges", { delay: 200 });
+ cy.get("@input").type("Sonstiges", { delay: 100 });
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").type("{enter}");
cy.get(".frappe-control[data-fieldname=link] input").blur();
cy.get("@dialog").then((dialog) => {
let field = dialog.get_field("link");
@@ -296,11 +316,11 @@ context("Control Link", () => {
cy.get(".frappe-control[data-fieldname=link] input").focus().as("input");
cy.wait("@search_link");
- cy.get("@input").type("Non-Conforming", { delay: 200 });
+ cy.get("@input").type("Non-Conforming", { delay: 100 });
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").type("{enter}");
cy.get(".frappe-control[data-fieldname=link] input").blur();
cy.get("@dialog").then((dialog) => {
let field = dialog.get_field("link");
diff --git a/cypress/integration/customize_form.js b/cypress/integration/customize_form.js
index a8cd4f767f..a072240993 100644
--- a/cypress/integration/customize_form.js
+++ b/cypress/integration/customize_form.js
@@ -4,8 +4,7 @@ context("Customize Form", () => {
cy.visit("/desk/customize-form");
});
it("Changing to naming rule should update autoname", () => {
- cy.fill_field("doc_type", "ToDo", "Link").blur();
- cy.wait(2000);
+ cy.fill_field("doc_type", "ToDo", "Link");
cy.findByRole("tab", { name: "Details" }).click();
cy.click_form_section("Naming");
const naming_rule_default_autoname_map = {
diff --git a/cypress/integration/dashboard_chart.js b/cypress/integration/dashboard_chart.js
index 487a0ea42e..8a2fb91d08 100644
--- a/cypress/integration/dashboard_chart.js
+++ b/cypress/integration/dashboard_chart.js
@@ -8,13 +8,13 @@ context("Dashboard Chart", () => {
cy.new_form("Dashboard Chart");
cy.get('[data-fieldname="parent_document_type"]').should("have.css", "display", "none");
- cy.get_field("document_type", "Link");
- cy.fill_field("document_type", "Workspace Link", "Link").focus().blur();
- cy.get_field("document_type", "Link").should("have.value", "Workspace Link");
-
+ cy.get_field("chart_name", "Data").should("be.visible");
cy.fill_field("chart_name", "Test Chart", "Data");
+ cy.fill_field("document_type", "Workspace Link", "Link");
+
+ cy.get('[data-fieldname="filters_json"]').click();
+ cy.get(".modal-dialog", { timeout: 500 }).should("be.visible");
- cy.get('[data-fieldname="filters_json"]').click().wait(200);
cy.get(".modal-body .filter-action-buttons .add-filter").click();
cy.get(".modal-body .fieldname-select-area").click();
cy.get(".modal-actions .btn-modal-close").click();
diff --git a/cypress/integration/form_builder.js b/cypress/integration/form_builder.js
index da4b9e75fb..8677710bc4 100644
--- a/cypress/integration/form_builder.js
+++ b/cypress/integration/form_builder.js
@@ -49,23 +49,34 @@ context("Form Builder", () => {
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.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
+ cy.get(".modal-body .filter-box .list_filter .filter-field .link-field input")
+ .focus()
+ .as("input");
+ cy.wait("@search_link");
+ cy.wait(500);
+ cy.get("@input").type("Male", { delay: 100 });
+ cy.wait("@search_link");
+ cy.wait(500);
+ cy.get("@input").type("{enter}", { delay: 100 });
+ cy.get("@input").blur();
+
cy.get(".btn-modal-primary").click();
+ cy.wait(500);
// Save the document
cy.click_doc_primary_button("Save");
+ cy.wait(1000);
- // 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");
+ cy.compare_document({
+ fields: [
+ {},
+ {
+ fieldname: "gender",
+ link_filters: '[["Gender","name","=","Male"]]',
+ },
+ ],
});
});
diff --git a/cypress/integration/number_card.js b/cypress/integration/number_card.js
index c3e3edcf5e..fd7b6a9d9d 100644
--- a/cypress/integration/number_card.js
+++ b/cypress/integration/number_card.js
@@ -9,7 +9,7 @@ context("Number Card", () => {
cy.get('[data-fieldname="parent_document_type"]').should("have.css", "display", "none");
cy.get_field("document_type", "Link");
- cy.fill_field("document_type", "Workspace Link", "Link").focus().blur();
+ cy.fill_field("document_type", "Workspace Link", "Link");
cy.get_field("document_type", "Link").should("have.value", "Workspace Link");
cy.fill_field("label", "Test Number Card", "Data");
diff --git a/cypress/integration/web_form.js b/cypress/integration/web_form.js
index 03bd244c94..e56c420f3e 100644
--- a/cypress/integration/web_form.js
+++ b/cypress/integration/web_form.js
@@ -19,12 +19,18 @@ context("Web Form", () => {
cy.fill_field("doc_type", "Note", "Link");
cy.fill_field("module", "Website", "Link");
cy.click_custom_action_button("Get Fields");
+ // wait until Get Fields finishes populating the grid
+ cy.get('[data-fieldname="web_form_fields"] .grid-row').should(($rows) => {
+ expect($rows.length, "web form fields").to.be.greaterThan(0);
+ });
cy.click_custom_action_button("Publish");
cy.wait("@save_form");
cy.get_field("route").should("have.value", "note");
- cy.get(".title-area .indicator-pill").contains("Published");
+ cy.get(".title-area .indicator-pill")
+ .should("contain.text", "Published")
+ .should("have.class", "green");
});
it("Open Web Form", () => {
diff --git a/cypress/integration/workspace_blocks.js b/cypress/integration/workspace_blocks.js
index 05e03903ae..842103ec83 100644
--- a/cypress/integration/workspace_blocks.js
+++ b/cypress/integration/workspace_blocks.js
@@ -72,7 +72,7 @@ context("Workspace Blocks", () => {
cy.get(".block-list-container .block-list-item").contains("Quick List").click();
cy.fill_field("label", "ToDo", "Data");
- cy.fill_field("document_type", "ToDo", "Link").blur();
+ cy.fill_field("document_type", "ToDo", "Link");
cy.wait("@get_doctype");
cy.get_open_dialog().find(".filter-edit-area").should("contain", "No filters selected");
@@ -143,6 +143,7 @@ context("Workspace Blocks", () => {
});
it("Number Card Block", () => {
+ cy.visit("/app/private/test-block-page");
cy.create_records([
{
doctype: "Number Card",
@@ -155,12 +156,16 @@ context("Workspace Blocks", () => {
cy.get(".codex-editor__redactor .ce-block");
cy.get(".btn-edit-workspace").click();
- cy.get(".ce-block").first().click({ force: true }).type("{enter}");
+ cy.get(".ce-block")
+ .first()
+ .realHover()
+ .find(".new-block-button")
+ .should("be.visible")
+ .click();
cy.get(".block-list-container .block-list-item").contains("Number Card").click();
// add number card
cy.fill_field("number_card_name", "Test Number Card", "Link");
- cy.get('[data-fieldname="number_card_name"] ul div').contains("Test Number Card").click();
cy.click_modal_primary_button("Add");
cy.get(".ce-block .number-widget-box").first().as("number_card");
cy.get("@number_card").find(".widget-title").should("contain", "Test Number Card");
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index 5731a0050c..f774dc9872 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -171,7 +171,24 @@ Cypress.Commands.add("fill_field", (fieldname, value, fieldtype = "Data") => {
cy.get("@input").clear().wait(200);
}
- if (fieldtype === "Select") {
+ if (["Link", "Dynamic Link"].includes(fieldtype)) {
+ cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link");
+ cy.get("@input").clear().focus();
+ cy.wait("@search_link");
+ cy.get("@input").parent().findByRole("listbox").as("dropdown");
+ cy.get("@dropdown").should("be.visible");
+ cy.get("@input").type(value, { delay: 100 });
+ cy.wait("@search_link");
+ cy.get("@dropdown")
+ .should("be.visible")
+ .find("div[role='option']")
+ .first()
+ .should("include.text", value);
+ cy.get("@input").type("{enter}");
+ cy.get("@input").blur();
+ cy.get("@dropdown").should("not.exist");
+ cy.get("@input").should("have.value", value);
+ } else if (fieldtype === "Select") {
cy.get("@input").select(value);
} else {
cy.get("@input").type(value, {
diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js
index ba5bf18022..abb5e6ae21 100644
--- a/frappe/public/js/frappe/form/controls/link.js
+++ b/frappe/public/js/frappe/form/controls/link.js
@@ -26,7 +26,14 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
this.set_input_attributes();
this.$input.on("focus", function () {
if (!me.$input.val()) {
- me.$input.val("").trigger("input");
+ me.$input.val("");
+
+ // Create a fake input event
+ const e = $.Event("input");
+ e.target = me.$input[0];
+
+ // Pass it to on_input directly, bypassing debounce, so the dropdown opens immediately
+ me.on_input(e);
}
me.show_link_and_clear_buttons();
@@ -259,107 +266,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
this.custom_awesomplete_filter && this.custom_awesomplete_filter(this.awesomplete);
- this.$input.on(
- "input",
- frappe.utils.debounce(function (e) {
- var doctype = me.get_options();
- if (!doctype) return;
- if (!me.$input.cache[doctype]) {
- me.$input.cache[doctype] = {};
- }
-
- var term = e.target.value;
-
- if (me.$input.cache[doctype][term] != null) {
- // immediately show from cache
- me.awesomplete.list = me.$input.cache[doctype][term];
- }
- var args = {
- txt: term,
- doctype: doctype,
- ignore_user_permissions: me.df.ignore_user_permissions,
- reference_doctype: me.get_reference_doctype() || "",
- page_length: cint(frappe.boot.sysdefaults?.link_field_results_limit) || 10,
- form_doctype: me.doctype,
- link_fieldname: me.df.fieldname,
- };
-
- me.set_custom_query(args);
-
- frappe.call({
- type: "POST",
- method: "frappe.desk.search.search_link",
- no_spinner: true,
- args: args,
- callback: function (r) {
- if (!window.Cypress && !me.$input.is(":focus")) {
- return;
- }
- r.message = me.merge_duplicates(r.message);
-
- // show filter description in awesomplete
- let filter_string = me.df.filter_description
- ? me.df.filter_description
- : args.filters
- ? me.get_filter_description(args.filters)
- : null;
- if (filter_string) {
- r.message.push({
- html: `${filter_string}`,
- value: "",
- action: () => {},
- });
- }
-
- if (!me.df.only_select) {
- if (frappe.model.can_create(doctype)) {
- // new item
- r.message.push({
- html:
- "" +
- " " +
- __("Create a new {0}", [__(me.get_options())]) +
- "",
- label: __("Create a new {0}", [__(me.get_options())]),
- value: "create_new__link_option",
- action: me.new_doc,
- });
- }
-
- //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.message = r.message.concat(custom__link_options);
- }
-
- // advanced search
- if (locals && locals["DocType"]) {
- // not applicable in web forms
- r.message.push({
- html:
- "" +
- " " +
- __("Advanced Search") +
- "",
- label: __("Advanced Search"),
- value: "advanced_search__link_option",
- action: me.open_advanced_search,
- });
- }
- }
- me.$input.cache[doctype][term] = r.message;
- me.awesomplete.list = me.$input.cache[doctype][term];
- me.toggle_href(doctype);
- r.message.forEach((item) => {
- frappe.utils.add_link_title(doctype, item.value, item.label);
- });
- },
- });
- }, 500)
- );
+ this.$input.on("input", frappe.utils.debounce(this.on_input.bind(this), 500));
this.$input.on("blur", function () {
if (me.selected) {
@@ -433,6 +340,105 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
});
}
+ on_input(e) {
+ var doctype = this.get_options();
+ if (!doctype) return;
+ if (!this.$input.cache[doctype]) {
+ this.$input.cache[doctype] = {};
+ }
+
+ var term = e.target.value;
+
+ if (this.$input.cache[doctype][term] != null) {
+ // immediately show from cache
+ this.awesomplete.list = this.$input.cache[doctype][term];
+ }
+ var args = {
+ txt: term,
+ doctype: doctype,
+ ignore_user_permissions: this.df.ignore_user_permissions,
+ reference_doctype: this.get_reference_doctype() || "",
+ page_length: cint(frappe.boot.sysdefaults?.link_field_results_limit) || 10,
+ form_doctype: this.doctype,
+ link_fieldname: this.df.fieldname,
+ };
+
+ this.set_custom_query(args);
+
+ frappe.call({
+ type: "POST",
+ method: "frappe.desk.search.search_link",
+ no_spinner: true,
+ args: args,
+ callback: (r) => {
+ if (!window.Cypress && !this.$input.is(":focus")) {
+ return;
+ }
+ r.message = this.merge_duplicates(r.message);
+
+ // show filter description in awesomplete
+ let filter_string = this.df.filter_description
+ ? this.df.filter_description
+ : args.filters
+ ? this.get_filter_description(args.filters)
+ : null;
+ if (filter_string) {
+ r.message.push({
+ html: `${filter_string}`,
+ value: "",
+ action: () => {},
+ });
+ }
+
+ if (!this.df.only_select) {
+ if (frappe.model.can_create(doctype)) {
+ // new item
+ r.message.push({
+ html:
+ "" +
+ " " +
+ __("Create a new {0}", [__(this.get_options())]) +
+ "",
+ label: __("Create a new {0}", [__(this.get_options())]),
+ value: "create_new__link_option",
+ action: this.new_doc,
+ });
+ }
+
+ //custom link actions
+ let custom__link_options =
+ frappe.ui.form.ControlLink.link_options &&
+ frappe.ui.form.ControlLink.link_options(this);
+
+ if (custom__link_options) {
+ r.message = r.message.concat(custom__link_options);
+ }
+
+ // advanced search
+ if (locals && locals["DocType"]) {
+ // not applicable in web forms
+ r.message.push({
+ html:
+ "" +
+ " " +
+ __("Advanced Search") +
+ "",
+ label: __("Advanced Search"),
+ value: "advanced_search__link_option",
+ action: this.open_advanced_search,
+ });
+ }
+ }
+ this.$input.cache[doctype][term] = r.message;
+ this.awesomplete.list = this.$input.cache[doctype][term];
+ this.toggle_href(doctype);
+ r.message.forEach((item) => {
+ frappe.utils.add_link_title(doctype, item.value, item.label);
+ });
+ },
+ });
+ }
+
show_untranslated() {
let value = this.get_input_value();
this.is_translatable() && this.set_input_value(value);