Merge branch 'develop' of github.com:frappe/frappe into report-key-error-dev

This commit is contained in:
Shivam Mishra 2020-02-17 15:36:38 +05:30
commit 8e5fbb033c
17 changed files with 98 additions and 60 deletions

View file

@ -25,9 +25,8 @@ context('Awesome Bar', () => {
cy.get('h1').should('contain', 'To Do');
cy.get('.toggle-filter')
.should('have.length', 1)
.should('contain', 'ID like %test%');
cy.get('[data-original-title="Name"] > .input-with-feedback')
.should('have.value', '%test%');
});
it('navigates to new form', () => {

View file

@ -437,7 +437,7 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message
:param recipients: List of recipients.
:param sender: Email sender. Default is current user.
:param sender: Email sender. Default is current user or default outgoing account.
:param subject: Email Subject.
:param message: (or `content`) Email Content.
:param as_markdown: Convert content markdown to HTML.
@ -459,7 +459,6 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message
:param args: Arguments for rendering the template
:param header: Append header in email
"""
text_content = None
if template:
message, text_content = get_email_from_template(template, args)

View file

@ -10,8 +10,8 @@ import logging
from werkzeug.wrappers import Request
from werkzeug.local import LocalManager
from werkzeug.exceptions import HTTPException, NotFound
from werkzeug.contrib.profiler import ProfilerMiddleware
from werkzeug.wsgi import SharedDataMiddleware
from werkzeug.middleware.profiler import ProfilerMiddleware
from werkzeug.middleware.shared_data import SharedDataMiddleware
import frappe
import frappe.handler

View file

@ -523,7 +523,7 @@ def run_ui_tests(context, app, headless=False):
# run for headless mode
run_or_open = 'run' if headless else 'open'
command = '{site_env} {password_env} yarn run cypress:{run_or_open}'
command = '{site_env} {password_env} yarn run cypress {run_or_open}'
formatted_command = command.format(site_env=site_env, password_env=password_env, run_or_open=run_or_open)
frappe.commands.popen(formatted_command, cwd=app_base_path, raise_err=True)

View file

@ -24,6 +24,15 @@ frappe.ui.form.on("Address", {
}
});
frm.refresh_field("links");
if (frm.doc.links) {
for (let i in frm.doc.links) {
let link = frm.doc.links[i];
frm.add_custom_button(__("{0}: {1}", [__(link.link_doctype), __(link.link_name)]), function() {
frappe.set_route("Form", link.link_doctype, link.link_name);
}, __("Links"));
}
}
},
validate: function(frm) {
// clear linked customer / supplier / sales partner on saving...
@ -38,9 +47,13 @@ frappe.ui.form.on("Address", {
() => frappe.timeout(1),
() => {
const last_doc = frappe.contacts.get_last_doc(frm);
if(frappe.dynamic_link && frappe.dynamic_link.doc
&& frappe.dynamic_link.doc.name == last_doc.docname){
frappe.set_route('Form', last_doc.doctype, last_doc.docname);
if (frappe.dynamic_link && frappe.dynamic_link.doc && frappe.dynamic_link.doc.name == last_doc.docname) {
for (let i in frm.doc.links) {
let link = frm.doc.links[i];
if (last_doc.doctype == link.link_doctype && last_doc.docname == link.link_name) {
frappe.set_route('Form', last_doc.doctype, last_doc.docname);
}
}
}
}
]);

View file

@ -42,7 +42,7 @@ frappe.ui.form.on("Contact", {
});
frm.refresh_field("links");
if (frm.doc.links.length > 0) {
if (frm.doc.links) {
frappe.call({
method: "frappe.contacts.doctype.contact.contact.address_query",
args: {links: frm.doc.links},
@ -58,6 +58,13 @@ frappe.ui.form.on("Contact", {
}
}
});
for (let i in frm.doc.links) {
let link = frm.doc.links[i];
frm.add_custom_button(__("{0}: {1}", [__(link.link_doctype), __(link.link_name)]), function() {
frappe.set_route("Form", link.link_doctype, link.link_name);
}, __("Links"));
}
}
},
validate: function(frm) {
@ -73,9 +80,13 @@ frappe.ui.form.on("Contact", {
() => frappe.timeout(1),
() => {
const last_doc = frappe.contacts.get_last_doc(frm);
if(frappe.dynamic_link && frappe.dynamic_link.doc
&& frappe.dynamic_link.doc.name == last_doc.docname){
frappe.set_route('Form', last_doc.doctype, last_doc.docname);
if (frappe.dynamic_link && frappe.dynamic_link.doc && frappe.dynamic_link.doc.name == last_doc.docname) {
for (let i in frm.doc.links) {
let link = frm.doc.links[i];
if (last_doc.doctype == link.link_doctype && last_doc.docname == link.link_name) {
frappe.set_route('Form', last_doc.doctype, last_doc.docname);
}
}
}
}
]);

View file

@ -98,8 +98,6 @@ class User(Document):
clear_notifications(user=self.name)
frappe.clear_cache(user=self.name)
self.send_password_notification(self.__new_password)
if self.__new_password:
self.reset_password_key = ''
create_contact(self, ignore_mandatory=True)
if self.name not in ('Administrator', 'Guest') and not self.user_image:
frappe.enqueue('frappe.core.doctype.user.user.update_gravatar', name=self.name)

View file

@ -43,6 +43,8 @@ def get_diff(old, new, for_child=False):
if not new:
return None
blacklisted_fields = ["Markdown Editor", "Text Editor", "Code", "HTML Editor"]
# capture data import if set
data_import = new.flags.via_data_import
out = frappe._dict(changed = [], added = [], removed = [], row_changed = [], data_import=data_import)
@ -75,12 +77,12 @@ def get_diff(old, new, for_child=False):
out.removed.append([df.fieldname, d.as_dict()])
elif (old_value != new_value):
# Check for None values
old_data = old.get_formatted(df.fieldname) if old_value else old_value
new_data = new.get_formatted(df.fieldname) if new_value else new_value
if df.fieldtype not in blacklisted_fields:
old_value = old.get_formatted(df.fieldname) if old_value else old_value
new_value = new.get_formatted(df.fieldname) if new_value else new_value
if old_data != new_data:
out.changed.append((df.fieldname, old_data, new_data))
if old_value != new_value:
out.changed.append((df.fieldname, old_value, new_value))
# docstatus
if not for_child and old.docstatus != new.docstatus:

View file

@ -20,7 +20,8 @@ frappe.ui.form.on("Customize Form", {
frm.set_query("default_print_format", function() {
return {
filters: {
'print_format_type': ['!=', 'JS']
'print_format_type': ['!=', 'JS'],
'doc_type': ['=', frm.doc.doc_type]
}
}
});

View file

@ -106,9 +106,8 @@ def send_email(success, service_name, error_status=None):
if not frappe.db:
frappe.connect()
if frappe.db.get_value("S3 Backup Settings", None, "notification_email"):
recipients = split_emails(frappe.db.get_value("S3 Backup Settings", None, "notification_email"))
frappe.sendmail(recipients=recipients, subject=subject, message=message)
recipients = split_emails(frappe.db.get_value("S3 Backup Settings", None, "notify_email"))
frappe.sendmail(recipients=recipients, subject=subject, message=message)
def backup_to_s3():

View file

@ -10,9 +10,20 @@ from frappe import _
import requests
import json
error_messages = {
400: "400: Invalid Payload or User not found",
403: "403: Action Prohibited",
404: "404: Channel not found",
410: "410: The Channel is Archived",
500: "500: Rollup Error, Slack seems to be down"
}
class SlackWebhookURL(Document):
pass
def send_slack_message(webhook_url, message, reference_doctype, reference_name):
slack_url = frappe.db.get_value("Slack Webhook URL", webhook_url, "webhook_url")
doc_url = get_url_to_form(reference_doctype, reference_name)
@ -21,10 +32,10 @@ def send_slack_message(webhook_url, message, reference_doctype, reference_name):
"fallback": _("See the document at {0}").format(doc_url),
"actions": [
{
"type": "button",
"text": _("Go to the document"),
"url": doc_url,
"style": "primary"
"type": "button",
"text": _("Go to the document"),
"url": doc_url,
"style": "primary"
}
]
}
@ -32,10 +43,9 @@ def send_slack_message(webhook_url, message, reference_doctype, reference_name):
data = {"text": message, "attachments": attachments}
r = requests.post(slack_url, data=json.dumps(data))
if r.ok == True:
return 'success'
elif r.ok == False:
frappe.log_error(r.error, _('Slack Webhook Error'))
if not r.ok:
message = error_messages.get(r.status_code, r.status_code)
frappe.log_error(message, _('Slack Webhook Error'))
return 'error'
return 'success'

View file

@ -6,8 +6,9 @@ from __future__ import unicode_literals
import frappe
import os
from werkzeug.exceptions import NotFound
from werkzeug.wsgi import SharedDataMiddleware
from frappe.utils import get_site_name, get_site_path, get_site_base_path, get_path, cstr
from werkzeug.middleware.shared_data import SharedDataMiddleware
from frappe.utils import get_site_name, cstr
class StaticDataMiddleware(SharedDataMiddleware):
def __call__(self, environ, start_response):

View file

@ -205,13 +205,7 @@ frappe.form.formatters = {
return html;
},
Comment: function(value) {
var html = "";
$.each(JSON.parse(value || "[]"), function(i, v) {
if(v) html+= '<span class="label label-warning" \
style="margin-right: 7px;"\
data-field="_comments" data-label="'+v.name+'">'+v.comment+'</span>';
});
return html;
return value;
},
Assign: function(value) {
var html = "";

View file

@ -540,7 +540,7 @@ class FilterArea {
out.promise = out.promise || Promise.resolve();
out.non_standard_filters = out.non_standard_filters || [];
if (fields_dict[fieldname] && condition === '=') {
if (fields_dict[fieldname] && (condition === '=' || condition === "like")) {
// standard filter
out.promise = out.promise.then(
() => fields_dict[fieldname].set_value(value)

View file

@ -791,7 +791,13 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
let std_fields = frappe.model.std_fields.filter( df => df.fieldname !== 'docstatus');
// add status field derived from docstatus, if status is not a standard field
if (!frappe.meta.has_field(this.doctype, 'status')) {
let has_status_values = false;
if (this.data) {
has_status_values = frappe.get_indicator(this.data[0], this.doctype);
}
if (!frappe.meta.has_field(this.doctype, 'status') && has_status_values) {
doctype_fields = [{
label: __('Status'),
fieldname: 'docstatus',
@ -1038,18 +1044,23 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
if (col.field === 'docstatus' && !frappe.meta.has_field(this.doctype, 'status')) {
// get status from docstatus
let status = frappe.get_indicator(d, this.doctype);
if (!status[0]) {
// get_indicator returns the dependent field's condition as the 3rd parameter
let dependent_col = status[2].split(',')[0];
// add status dependency column
this.add_status_dependency_column(dependent_col, this.doctype);
if (status) {
if (!status[0]) {
// get_indicator returns the dependent field's condition as the 3rd parameter
let dependent_col = status[2].split(',')[0];
// add status dependency column
this.add_status_dependency_column(dependent_col, this.doctype);
}
return {
name: d.name,
doctype: col.docfield.parent,
content: status[0],
editable: false
};
} else {
// no status values found
this.remove_column_from_datatable(col);
}
return {
name: d.name,
doctype: col.docfield.parent,
content: status[0],
editable: false
};
} else if (col.field in d) {
const value = d[col.field];
return {

View file

@ -112,4 +112,4 @@ def generate_theme_files_if_not_exist():
doc.generate_theme_if_not_exist()
doc.save()
except Exception:
pass
frappe.log_error(frappe.get_traceback(), "Theme File Generation Failed")

View file

@ -61,6 +61,6 @@ stripe==2.40.0
unittest-xml-reporting==2.5.2
urllib3==1.25.7
watchdog==0.8.0
Werkzeug==0.16.0
Werkzeug==0.16.1
xlrd==1.2.0
zxcvbn-python==4.4.24