Merge branch 'develop' into cancel-doc-with-workflow-fix
This commit is contained in:
commit
5cc6daa713
12 changed files with 93 additions and 62 deletions
97
.github/helper/documentation.py
vendored
97
.github/helper/documentation.py
vendored
|
|
@ -1,50 +1,73 @@
|
|||
import sys
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import requests
|
||||
|
||||
docs_repos = [
|
||||
"frappe_docs",
|
||||
"erpnext_documentation",
|
||||
WEBSITE_REPOS = [
|
||||
"erpnext_com",
|
||||
"frappe_io",
|
||||
]
|
||||
|
||||
DOCUMENTATION_DOMAINS = [
|
||||
"docs.erpnext.com",
|
||||
"frappeframework.com",
|
||||
]
|
||||
|
||||
def uri_validator(x):
|
||||
result = urlparse(x)
|
||||
return all([result.scheme, result.netloc, result.path])
|
||||
|
||||
def docs_link_exists(body):
|
||||
for line in body.splitlines():
|
||||
for word in line.split():
|
||||
if word.startswith('http') and uri_validator(word):
|
||||
parsed_url = urlparse(word)
|
||||
if parsed_url.netloc == "github.com":
|
||||
parts = parsed_url.path.split('/')
|
||||
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
|
||||
return True
|
||||
if parsed_url.netloc in ["docs.erpnext.com", "frappeframework.com"]:
|
||||
return True
|
||||
def is_valid_url(url: str) -> bool:
|
||||
parts = urlparse(url)
|
||||
return all((parts.scheme, parts.netloc, parts.path))
|
||||
|
||||
|
||||
def is_documentation_link(word: str) -> bool:
|
||||
if not word.startswith("http") or not is_valid_url(word):
|
||||
return False
|
||||
|
||||
parsed_url = urlparse(word)
|
||||
if parsed_url.netloc in DOCUMENTATION_DOMAINS:
|
||||
return True
|
||||
|
||||
if parsed_url.netloc == "github.com":
|
||||
parts = parsed_url.path.split("/")
|
||||
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in WEBSITE_REPOS:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def contains_documentation_link(body: str) -> bool:
|
||||
return any(
|
||||
is_documentation_link(word)
|
||||
for line in body.splitlines()
|
||||
for word in line.split()
|
||||
)
|
||||
|
||||
|
||||
def check_pull_request(number: str) -> "tuple[int, str]":
|
||||
response = requests.get(f"https://api.github.com/repos/frappe/frappe/pulls/{number}")
|
||||
if not response.ok:
|
||||
return 1, "Pull Request Not Found! ⚠️"
|
||||
|
||||
payload = response.json()
|
||||
title = (payload.get("title") or "").lower().strip()
|
||||
head_sha = (payload.get("head") or {}).get("sha")
|
||||
body = (payload.get("body") or "").lower()
|
||||
|
||||
if (
|
||||
not title.startswith("feat")
|
||||
or not head_sha
|
||||
or "no-docs" in body
|
||||
or "backport" in body
|
||||
):
|
||||
return 0, "Skipping documentation checks... 🏃"
|
||||
|
||||
if contains_documentation_link(body):
|
||||
return 0, "Documentation Link Found. You're Awesome! 🎉"
|
||||
|
||||
return 1, "Documentation Link Not Found! ⚠️"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pr = sys.argv[1]
|
||||
response = requests.get(f"https://api.github.com/repos/frappe/frappe/pulls/{pr}")
|
||||
|
||||
if response.ok:
|
||||
payload = response.json()
|
||||
title = (payload.get("title") or "").lower()
|
||||
head_sha = (payload.get("head") or {}).get("sha")
|
||||
body = (payload.get("body") or "").lower()
|
||||
|
||||
if title.startswith("feat") and head_sha and "no-docs" not in body:
|
||||
if docs_link_exists(body):
|
||||
print("Documentation Link Found. You're Awesome! 🎉")
|
||||
|
||||
else:
|
||||
print("Documentation Link Not Found! ⚠️")
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
print("Skipping documentation checks... 🏃")
|
||||
exit_code, message = check_pull_request(sys.argv[1])
|
||||
print(message)
|
||||
sys.exit(exit_code)
|
||||
|
|
|
|||
|
|
@ -54,12 +54,8 @@ context("List View", () => {
|
|||
method: "POST",
|
||||
url: "api/method/frappe.model.workflow.bulk_workflow_approval",
|
||||
}).as("bulk-approval");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "api/method/frappe.desk.reportview.get",
|
||||
}).as("real-time-update");
|
||||
cy.wrap(elements).contains("Approve").click();
|
||||
cy.wait(["@bulk-approval", "@real-time-update"]);
|
||||
cy.wait("@bulk-approval");
|
||||
cy.wait(300);
|
||||
cy.get_open_dialog().find(".btn-modal-close").click();
|
||||
cy.reload();
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@
|
|||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "beta",
|
||||
"fieldtype": "Check",
|
||||
"label": "Beta"
|
||||
|
|
@ -463,6 +464,7 @@
|
|||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"description": "Tree structures are implemented using Nested Set",
|
||||
"fieldname": "is_tree",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -539,6 +541,7 @@
|
|||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"fieldname": "is_virtual",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Virtual"
|
||||
|
|
@ -622,6 +625,7 @@
|
|||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:!doc.istable",
|
||||
"description": "Enables Calendar and Gantt views.",
|
||||
"fieldname": "is_calendar_and_gantt",
|
||||
"fieldtype": "Check",
|
||||
|
|
@ -708,7 +712,7 @@
|
|||
"link_fieldname": "reference_doctype"
|
||||
}
|
||||
],
|
||||
"modified": "2023-01-04 17:23:09.206018",
|
||||
"modified": "2023-03-23 16:15:51.067267",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocType",
|
||||
|
|
|
|||
|
|
@ -114,12 +114,16 @@ frappe.ui.form.on("User", {
|
|||
return;
|
||||
}
|
||||
|
||||
function hasChanged(doc_attr, boot_attr) {
|
||||
return (doc_attr || boot_attr) && doc_attr !== boot_attr;
|
||||
}
|
||||
|
||||
if (
|
||||
doc.name === frappe.session.user &&
|
||||
!doc.__unsaved &&
|
||||
frappe.all_timezones &&
|
||||
(doc.language || frappe.boot.user.language) &&
|
||||
doc.language !== frappe.boot.user.language
|
||||
(hasChanged(doc.language, frappe.boot.user.language) ||
|
||||
hasChanged(doc.time_zone, frappe.boot.time_zone.user))
|
||||
) {
|
||||
frappe.msgprint(__("Refreshing..."));
|
||||
window.location.reload();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import json
|
|||
import quopri
|
||||
import smtplib
|
||||
import traceback
|
||||
from contextlib import suppress
|
||||
from email.parser import Parser
|
||||
from email.policy import SMTPUTF8
|
||||
|
||||
|
|
@ -706,7 +707,10 @@ class QueueBuilder:
|
|||
if not smtp_server_instance:
|
||||
email_account = q.get_email_account()
|
||||
smtp_server_instance = email_account.get_smtp_server()
|
||||
q.send(smtp_server_instance=smtp_server_instance)
|
||||
|
||||
with suppress(Exception):
|
||||
q.send(smtp_server_instance=smtp_server_instance)
|
||||
|
||||
smtp_server_instance.quit()
|
||||
|
||||
def as_dict(self, include_recipients=True):
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
<span class="text-muted">({%= __("Primary") %})</span>{% } %}
|
||||
{% if(addr_list[i].is_shipping_address) { %}
|
||||
<span class="text-muted">({%= __("Shipping") %})</span>{% } %}
|
||||
{% if(addr_list[i].disabled) { %}
|
||||
<span class="text-muted">({%= __("Disabled") %})</span>{% } %}
|
||||
|
||||
<a href="/app/Form/Address/{%= encodeURIComponent(addr_list[i].name) %}" class="btn btn-default btn-xs pull-right"
|
||||
style="margin-top:-3px; margin-right: -5px;">
|
||||
|
|
|
|||
|
|
@ -774,6 +774,7 @@ class FilterArea {
|
|||
"Data",
|
||||
"Code",
|
||||
"Phone",
|
||||
"JSON",
|
||||
"Read Only",
|
||||
].includes(fieldtype)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1334,13 +1334,15 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
return;
|
||||
}
|
||||
frappe.socketio.doctype_subscribe(this.doctype);
|
||||
frappe.realtime.off("list_update");
|
||||
frappe.realtime.on("list_update", (data) => {
|
||||
if (data?.doctype !== this.doctype) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frappe.get_doc(data?.doctype, data?.name)?.__unsaved) {
|
||||
frappe.model.remove_from_locals(data.doctype, data.name);
|
||||
// if some bulk operation is happening by selecting list items, don't refresh
|
||||
if (this.$checks && this.$checks.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.avoid_realtime_update()) {
|
||||
|
|
|
|||
|
|
@ -508,6 +508,7 @@ frappe.ui.filter_utils = {
|
|||
"HTML Editor",
|
||||
"Tag",
|
||||
"Phone",
|
||||
"JSON",
|
||||
"Comments",
|
||||
"Barcode",
|
||||
"Dynamic Link",
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ frappe.ui.misc.about = function () {
|
|||
<p><i class='fa fa-facebook fa-fw'></i>
|
||||
Facebook: <a href='https://facebook.com/erpnext' target='_blank'>https://facebook.com/erpnext</a></p>
|
||||
<p><i class='fa fa-twitter fa-fw'></i>
|
||||
Twitter: <a href='https://twitter.com/erpnext' target='_blank'>https://twitter.com/erpnext</a></p>
|
||||
Twitter: <a href='https://twitter.com/frappetech' target='_blank'>https://twitter.com/frappetech</a></p>
|
||||
<p><i class='fa fa-youtube fa-fw'></i>
|
||||
YouTube: <a href='https://www.youtube.com/@erpnextofficial' target='_blank'>https://www.youtube.com/@erpnextofficial</a></p>
|
||||
YouTube: <a href='https://www.youtube.com/@frappetech' target='_blank'>https://www.youtube.com/@frappetech</a></p>
|
||||
<hr>
|
||||
<h4>${__("Installed Apps")}</h4>
|
||||
<div id='about-app-versions'>${__("Loading versions...")}</div>
|
||||
|
|
|
|||
|
|
@ -105,10 +105,8 @@ def get_redis_server():
|
|||
@frappe.whitelist(allow_guest=True)
|
||||
def can_subscribe_doc(doctype: str, docname: str) -> bool:
|
||||
from frappe.exceptions import PermissionError
|
||||
from frappe.sessions import Session
|
||||
|
||||
session = Session(None, resume=True).get_session_data()
|
||||
if not frappe.has_permission(user=session.user, doctype=doctype, doc=docname, ptype="read"):
|
||||
if not frappe.has_permission(doctype=doctype, doc=docname, ptype="read"):
|
||||
raise PermissionError()
|
||||
|
||||
return True
|
||||
|
|
@ -118,7 +116,7 @@ def can_subscribe_doc(doctype: str, docname: str) -> bool:
|
|||
def can_subscribe_doctype(doctype: str) -> bool:
|
||||
from frappe.exceptions import PermissionError
|
||||
|
||||
if not frappe.has_permission(user=frappe.session.user, doctype=doctype, ptype="read"):
|
||||
if not frappe.has_permission(doctype=doctype, ptype="read"):
|
||||
raise PermissionError()
|
||||
|
||||
return True
|
||||
|
|
@ -126,13 +124,9 @@ def can_subscribe_doctype(doctype: str) -> bool:
|
|||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_user_info():
|
||||
from frappe.sessions import Session
|
||||
|
||||
session = Session(None, resume=True).get_session_data()
|
||||
|
||||
return {
|
||||
"user": session.user,
|
||||
"user_type": session.user_type,
|
||||
"user": frappe.session.user,
|
||||
"user_type": frappe.session.user_type,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@
|
|||
<td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
|
||||
{% if doc.child_print_templates %}
|
||||
{%- set child_templates = doc.child_print_templates.get(df.fieldname) -%}
|
||||
<div class="value">{{ print_value(tdf, d, doc, visible_columns, child_templates) }}</div></td>
|
||||
<div class="value">{{ _(print_value(tdf, d, doc, visible_columns, child_templates)) }}</div></td>
|
||||
{% else %}
|
||||
<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
|
||||
<div class="value">{{ _(print_value(tdf, d, doc, visible_columns)) }}</div></td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue