Merge branch 'develop' into event-last-update
This commit is contained in:
commit
404856bc61
15 changed files with 122 additions and 30 deletions
6
.github/workflows/patch-mariadb-tests.yml
vendored
6
.github/workflows/patch-mariadb-tests.yml
vendored
|
|
@ -32,6 +32,12 @@ jobs:
|
|||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
check-latest: true
|
||||
|
||||
- name: Check if build should be run
|
||||
id: check-build
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
// -------------
|
||||
// Menu Display
|
||||
// -------------
|
||||
|
||||
// $(cur_frm.wrapper).on("grid-row-render", function(e, grid_row) {
|
||||
// if(grid_row.doc && grid_row.doc.fieldtype=="Section Break") {
|
||||
// $(grid_row.row).css({"font-weight": "bold"});
|
||||
// }
|
||||
// })
|
||||
|
||||
frappe.ui.form.on('DocType', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('role', 'permissions', function(doc) {
|
||||
|
|
@ -129,7 +119,7 @@ frappe.ui.form.on('DocType', {
|
|||
}
|
||||
|
||||
frm.set_df_property('fields', 'reqd', frm.doc.autoname !== 'Prompt');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("DocField", {
|
||||
|
|
@ -217,5 +207,11 @@ frappe.ui.form.on("DocField", {
|
|||
$doctype_select.val(curr_value.doctype);
|
||||
update_fieldname_options();
|
||||
}
|
||||
},
|
||||
|
||||
fieldtype: function(frm) {
|
||||
frm.trigger("max_attachments");
|
||||
}
|
||||
});
|
||||
|
||||
extend_cscript(cur_frm.cscript, new frappe.model.DocTypeController({frm: cur_frm}));
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ class DocType(Document):
|
|||
self.make_repeatable()
|
||||
self.validate_nestedset()
|
||||
self.validate_website()
|
||||
self.ensure_minimum_max_attachment_limit()
|
||||
validate_links_table_fieldnames(self)
|
||||
|
||||
if not self.is_new():
|
||||
|
|
@ -246,6 +247,22 @@ class DocType(Document):
|
|||
# clear website cache
|
||||
clear_cache()
|
||||
|
||||
def ensure_minimum_max_attachment_limit(self):
|
||||
"""Ensure that max_attachments is *at least* bigger than number of attach fields."""
|
||||
from frappe.model import attachment_fieldtypes
|
||||
|
||||
|
||||
if not self.max_attachments:
|
||||
return
|
||||
|
||||
total_attach_fields = len([d for d in self.fields if d.fieldtype in attachment_fieldtypes])
|
||||
if total_attach_fields > self.max_attachments:
|
||||
self.max_attachments = total_attach_fields
|
||||
field_label = frappe.bold(self.meta.get_field("max_attachments").label)
|
||||
frappe.msgprint(_("Number of attachment fields are more than {}, limit updated to {}.")
|
||||
.format(field_label, total_attach_fields),
|
||||
title=_("Insufficient attachment limit"), alert=True)
|
||||
|
||||
def change_modified_of_parent(self):
|
||||
"""Change the timestamp of parent DocType if the current one is a child to clear caches."""
|
||||
if frappe.flags.in_import:
|
||||
|
|
|
|||
|
|
@ -332,3 +332,4 @@ frappe.customize_form.clear_locals_and_refresh = function(frm) {
|
|||
frm.refresh();
|
||||
}
|
||||
|
||||
extend_cscript(cur_frm.cscript, new frappe.model.DocTypeController({frm: cur_frm}));
|
||||
|
|
|
|||
|
|
@ -171,10 +171,10 @@ class Database(object):
|
|||
frappe.errprint(query)
|
||||
|
||||
elif self.is_deadlocked(e):
|
||||
raise frappe.QueryDeadlockError
|
||||
raise frappe.QueryDeadlockError(e)
|
||||
|
||||
elif self.is_timedout(e):
|
||||
raise frappe.QueryTimeoutError
|
||||
raise frappe.QueryTimeoutError(e)
|
||||
|
||||
if ignore_ddl and (self.is_missing_column(e) or self.is_missing_table(e) or self.cant_drop_field_or_key(e)):
|
||||
pass
|
||||
|
|
@ -583,7 +583,7 @@ class Database(object):
|
|||
|
||||
if not isinstance(fields, Criterion):
|
||||
for field in fields:
|
||||
if "(" in field or " as " in field:
|
||||
if "(" in str(field) or " as " in str(field):
|
||||
field_objects.append(PseudoColumn(field))
|
||||
else:
|
||||
field_objects.append(field)
|
||||
|
|
@ -842,7 +842,7 @@ class Database(object):
|
|||
cache_count = frappe.cache().get_value('doctype:count:{}'.format(dt))
|
||||
if cache_count is not None:
|
||||
return cache_count
|
||||
query = self.query.build_conditions(table=dt, filters=filters).select(Count("*"))
|
||||
query = self.query.get_sql(table=dt, filters=filters, fields=Count("*"))
|
||||
if filters:
|
||||
count = self.sql(query, debug=debug)[0][0]
|
||||
return count
|
||||
|
|
|
|||
|
|
@ -2,6 +2,17 @@
|
|||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Onboarding Step", {
|
||||
|
||||
setup: function(frm) {
|
||||
frm.set_query("form_tour", function() {
|
||||
return {
|
||||
filters: {
|
||||
reference_doctype: frm.doc.reference_document
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frappe.boot.developer_mode &&
|
||||
frm.set_intro(
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
"reference_document",
|
||||
"show_full_form",
|
||||
"show_form_tour",
|
||||
"form_tour",
|
||||
"is_single",
|
||||
"reference_report",
|
||||
"report_reference_doctype",
|
||||
|
|
@ -206,13 +207,21 @@
|
|||
"fieldname": "show_form_tour",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Form Tour"
|
||||
},
|
||||
{
|
||||
"depends_on": "show_form_tour",
|
||||
"fieldname": "form_tour",
|
||||
"fieldtype": "Link",
|
||||
"label": "Form Tour",
|
||||
"options": "Form Tour"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-10-30 14:54:06.646513",
|
||||
"modified": "2021-12-02 10:56:04.448580",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Onboarding Step",
|
||||
"naming_rule": "Set by user",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -186,12 +186,13 @@ class Newsletter(WebsiteGenerator):
|
|||
frappe.db.auto_commit_on_many_writes = is_auto_commit_set
|
||||
|
||||
def get_message(self) -> str:
|
||||
if self.content_type == "HTML":
|
||||
return frappe.render_template(self.message_html, {"doc": self.as_dict()})
|
||||
message = self.message
|
||||
if self.content_type == "Markdown":
|
||||
return frappe.utils.markdown(self.message_md)
|
||||
# fallback to Rich Text
|
||||
return self.message
|
||||
message = frappe.utils.md_to_html(self.message_md)
|
||||
if self.content_type == "HTML":
|
||||
message = self.message_html
|
||||
|
||||
return frappe.render_template(message, {"doc": self.as_dict()})
|
||||
|
||||
def get_recipients(self) -> List[str]:
|
||||
"""Get recipients from Email Group"""
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ def _delete_doctypes(doctypes: List[str], dry_run: bool) -> None:
|
|||
print(f"* dropping Table for '{doctype}'...")
|
||||
if not dry_run:
|
||||
frappe.delete_doc("DocType", doctype, ignore_on_trash=True)
|
||||
frappe.db.sql_ddl(f"drop table `tab{doctype}`")
|
||||
frappe.db.sql_ddl(f"DROP TABLE IF EXISTS `tab{doctype}`")
|
||||
|
||||
|
||||
def post_install(rebuild_website=False):
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ data_fieldtypes = (
|
|||
'Icon'
|
||||
)
|
||||
|
||||
attachment_fieldtypes = (
|
||||
'Attach',
|
||||
'Attach Image',
|
||||
)
|
||||
|
||||
no_value_fields = (
|
||||
'Section Break',
|
||||
'Column Break',
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@ import "./frappe/form/controls/control.js";
|
|||
import "./frappe/views/formview.js";
|
||||
import "./frappe/form/form.js";
|
||||
import "./frappe/meta_tag.js";
|
||||
|
||||
import "./frappe/doctype/"
|
||||
|
|
|
|||
23
frappe/public/js/frappe/doctype/index.js
Normal file
23
frappe/public/js/frappe/doctype/index.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
frappe.provide("frappe.model");
|
||||
|
||||
/*
|
||||
Common class for handling client side interactions that
|
||||
apply to both DocType form and customize form.
|
||||
*/
|
||||
frappe.model.DocTypeController = class DocTypeController extends frappe.ui.form.Controller {
|
||||
|
||||
max_attachments() {
|
||||
if (!this.frm.doc.max_attachments) {
|
||||
return;
|
||||
}
|
||||
const is_attach_field = (f) => ["Attach", "Attach Image"].includes(f.fieldtype);
|
||||
const no_of_attach_fields = this.frm.doc.fields.filter(is_attach_field).length;
|
||||
|
||||
if (no_of_attach_fields > this.frm.doc.max_attachments) {
|
||||
this.frm.set_value("max_attachments", no_of_attach_fields);
|
||||
const label = this.frm.get_docfield("max_attachments").label;
|
||||
frappe.show_alert(
|
||||
__("Number of attachment fields are more than {}, limit updated to {}.", [label, no_of_attach_fields]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -234,8 +234,9 @@ export default class OnboardingWidget extends Widget {
|
|||
},
|
||||
});
|
||||
};
|
||||
const tour_name = step.form_tour;
|
||||
frm.tour
|
||||
.init({ on_finish })
|
||||
.init({ tour_name, on_finish })
|
||||
.then(() => frm.tour.start());
|
||||
};
|
||||
|
||||
|
|
@ -328,8 +329,9 @@ export default class OnboardingWidget extends Widget {
|
|||
this.mark_complete(step);
|
||||
};
|
||||
};
|
||||
const tour_name = step.form_tour;
|
||||
frm.tour
|
||||
.init({ on_finish })
|
||||
.init({ tour_name, on_finish })
|
||||
.then(() => frm.tour.start());
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -266,7 +266,8 @@ h5.modal-title {
|
|||
|
||||
.login-content.container {
|
||||
background-color: var(--fg-color);
|
||||
padding: 45px 0px;
|
||||
padding-bottom: 45px;
|
||||
padding-top: 45px;
|
||||
box-shadow: var(--shadow-base);
|
||||
border-radius: var(--border-radius-md);
|
||||
max-width: 400px;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,30 @@ class TestDB(unittest.TestCase):
|
|||
self.assertNotEqual(frappe.db.get_value("User", {"name": ["!=", "Guest"]}), "Guest")
|
||||
self.assertEqual(frappe.db.get_value("User", {"name": ["<", "Adn"]}), "Administrator")
|
||||
self.assertEqual(frappe.db.get_value("User", {"name": ["<=", "Administrator"]}), "Administrator")
|
||||
self.assertEqual(frappe.db.get_value("User", {}, ["Max(name)"], order_by=None), frappe.db.sql("SELECT Max(name) FROM tabUser")[0][0])
|
||||
self.assertEqual(frappe.db.get_value("User", {}, "Min(name)", order_by=None), frappe.db.sql("SELECT Min(name) FROM tabUser")[0][0])
|
||||
self.assertIn("for update", frappe.db.get_value("User", Field("name") == "Administrator", for_update=True, run=False).lower())
|
||||
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("User", {}, ["Max(name)"], order_by=None),
|
||||
frappe.db.sql("SELECT Max(name) FROM tabUser")[0][0],
|
||||
)
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("User", {}, "Min(name)", order_by=None),
|
||||
frappe.db.sql("SELECT Min(name) FROM tabUser")[0][0],
|
||||
)
|
||||
self.assertIn(
|
||||
"for update",
|
||||
frappe.db.get_value(
|
||||
"User", Field("name") == "Administrator", for_update=True, run=False
|
||||
).lower(),
|
||||
)
|
||||
doctype = frappe.qb.DocType("User")
|
||||
self.assertEqual(
|
||||
frappe.qb.from_(doctype).select(doctype.name, doctype.email).run(),
|
||||
frappe.db.get_values(
|
||||
doctype,
|
||||
filters={},
|
||||
fieldname=[doctype.name, doctype.email],
|
||||
order_by=None,
|
||||
),
|
||||
)
|
||||
self.assertEqual(frappe.db.sql("""SELECT name FROM `tabUser` WHERE name > 's' ORDER BY MODIFIED DESC""")[0][0],
|
||||
frappe.db.get_value("User", {"name": [">", "s"]}))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue