-
+
-
diff --git a/frappe/public/js/frappe/utils/utils.js b/frappe/public/js/frappe/utils/utils.js
index 1486e819fc..00b6f95f06 100644
--- a/frappe/public/js/frappe/utils/utils.js
+++ b/frappe/public/js/frappe/utils/utils.js
@@ -725,6 +725,19 @@ Object.assign(frappe.utils, {
},
is_rtl() {
return ["ar", "he", "fa"].includes(frappe.boot.lang);
+ },
+ bind_actions_with_object($el, object) {
+ // remove previously bound event
+ $($el).off('click.class_actions');
+ // attach new event
+ $($el).on('click.class_actions', '[data-action]', e => {
+ let $target = $(e.currentTarget);
+ let action = $target.data('action');
+ let method = object[action];
+ method ? object[action](e, $target) : null;
+ });
+
+ return $el;
}
});
diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js
index a2016296fa..6503f1c7ac 100644
--- a/frappe/public/js/frappe/views/reports/report_view.js
+++ b/frappe/public/js/frappe/views/reports/report_view.js
@@ -772,21 +772,20 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
get_columns_for_picker() {
let out = {};
- const standard_fields_filter = df =>
- !in_list(frappe.model.no_value_type, df.fieldtype) && !df.report_hide;
+ const standard_fields_filter = df => !in_list(frappe.model.no_value_type, df.fieldtype);
let doctype_fields = frappe.meta.get_docfields(this.doctype).filter(standard_fields_filter);
doctype_fields = [{
label: __('ID'),
fieldname: 'name',
- fieldtype: 'Data'
+ fieldtype: 'Data',
+ reqd: 1
}].concat(doctype_fields, frappe.model.std_fields);
out[this.doctype] = doctype_fields;
- const table_fields = frappe.meta.get_table_fields(this.doctype)
- .filter(df => !df.hidden);
+ const table_fields = frappe.meta.get_table_fields(this.doctype);
table_fields.forEach(df => {
const cdt = df.options;
diff --git a/frappe/public/less/filters.less b/frappe/public/less/filters.less
index 30894eea19..95580857e7 100644
--- a/frappe/public/less/filters.less
+++ b/frappe/public/less/filters.less
@@ -31,9 +31,17 @@
float: none;
}
-.filter-box {
+.frappe-list .filter-box {
border-bottom: 1px solid @border-color;
- padding: 10px 15px 3px;
+ padding: 10px 15px;
+}
+
+.filter-box {
+ .form-group {
+ @media (min-width: @screen-xs) {
+ margin-bottom: 0;
+ }
+ }
.remove-filter {
margin-top: 6px;
@@ -41,11 +49,9 @@
}
.filter-field {
- padding-right: 15px;
- width: calc(100% - 36px);
-
.frappe-control {
position: relative;
+ margin-bottom: 0;
}
}
}
@@ -56,8 +62,6 @@
padding-right: 0px;
}
.filter-field {
- width: 65% !important;
-
.frappe-control {
position: relative;
}
diff --git a/frappe/public/less/form.less b/frappe/public/less/form.less
index fb8b9c3d49..77fe4b8f17 100644
--- a/frappe/public/less/form.less
+++ b/frappe/public/less/form.less
@@ -984,3 +984,11 @@ body[data-route^="Form/Communication"] textarea[data-fieldname="subject"] {
.followed-by-label{
margin-top: 30px;
}
+
+.map-columns .form-section {
+ padding: 0 7px 7px;
+}
+
+.map-columns .form-section:first-child {
+ padding-top: 7px;
+}
diff --git a/frappe/test_runner.py b/frappe/test_runner.py
index cde743643f..76140e442c 100644
--- a/frappe/test_runner.py
+++ b/frappe/test_runner.py
@@ -250,10 +250,11 @@ def _add_test(app, path, filename, verbose, test_suite=None, ui_tests=False):
if os.path.basename(os.path.dirname(path))=="doctype":
txt_file = os.path.join(path, filename[5:].replace(".py", ".json"))
- with open(txt_file, 'r') as f:
- doc = json.loads(f.read())
- doctype = doc["name"]
- make_test_records(doctype, verbose)
+ if os.path.exists(txt_file):
+ with open(txt_file, 'r') as f:
+ doc = json.loads(f.read())
+ doctype = doc["name"]
+ make_test_records(doctype, verbose)
test_suite.addTest(unittest.TestLoader().loadTestsFromModule(module))
@@ -417,4 +418,4 @@ def get_test_record_log():
else:
frappe.flags.test_record_log = []
- return frappe.flags.test_record_log
\ No newline at end of file
+ return frappe.flags.test_record_log
diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py
index df96111f20..80bcad3ddb 100644
--- a/frappe/utils/__init__.py
+++ b/frappe/utils/__init__.py
@@ -670,3 +670,11 @@ def get_safe_filters(filters):
pass
return filters
+
+def create_batch(iterable, batch_size):
+ """
+ Convert an iterable to multiple batches of constant size of batch_size
+ """
+ total_count = len(iterable)
+ for i in range(0, total_count, batch_size):
+ yield iterable[i:min(i + batch_size, total_count)]
diff --git a/frappe/utils/xlsxutils.py b/frappe/utils/xlsxutils.py
index 82d631af4c..2814c5ff40 100644
--- a/frappe/utils/xlsxutils.py
+++ b/frappe/utils/xlsxutils.py
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
import openpyxl
+import xlrd
import re
from openpyxl.styles import Font
from openpyxl import load_workbook
@@ -95,3 +96,19 @@ def read_xlsx_file_from_attached_file(file_url=None, fcontent=None, filepath=Non
tmp_list.append(cell.value)
rows.append(tmp_list)
return rows
+
+def read_xls_file_from_attached_file(content):
+ book = xlrd.open_workbook(file_contents=content)
+ sheets = book.sheets()
+ sheet = sheets[0]
+ rows = []
+ for i in range(sheet.nrows):
+ rows.append(sheet.row_values(i))
+ return rows
+
+def build_xlsx_response(data, filename):
+ xlsx_file = make_xlsx(data, filename)
+ # write out response as a xlsx type
+ frappe.response['filename'] = filename + '.xlsx'
+ frappe.response['filecontent'] = xlsx_file.getvalue()
+ frappe.response['type'] = 'binary'
diff --git a/package.json b/package.json
index 7a5ccfe3e4..f2cc7b1cca 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
"express": "^4.16.2",
"fast-deep-equal": "^2.0.1",
"frappe-charts": "^1.3.0",
- "frappe-datatable": "^1.13.5",
+ "frappe-datatable": "^1.14.0",
"frappe-gantt": "^0.1.0",
"fuse.js": "^3.2.0",
"highlight.js": "^9.12.0",
diff --git a/requirements.txt b/requirements.txt
index da0c87d655..c11b023c54 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -64,3 +64,4 @@ sqlparse==0.2.4
Pygments==2.2.0
frontmatter
PyYAML==3.13
+xlrd
diff --git a/yarn.lock b/yarn.lock
index 3752d00516..0838f3f255 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1770,10 +1770,10 @@ frappe-charts@^1.3.0:
resolved "https://registry.yarnpkg.com/frappe-charts/-/frappe-charts-1.3.0.tgz#9ed033fa64833906bba16554187fa2f8a3a54ef6"
integrity sha512-hdLv4fOIVgIL5eV9KYlsQaEpxkcJvuEVVDJewJL8PG0ySPy5EEiG5KZGL2uj7YegVWbtsqJ4Oq/74mjgQoMdag==
-frappe-datatable@^1.13.5:
- version "1.13.5"
- resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.13.5.tgz#6f507fe7a84c22b1eab6b08e7b6fccbcdf7bb936"
- integrity sha512-k3Y8ScfxSD6Kj3Ch98kY2EWBnHUm0oPuPZonkslq4w5689iUhduy/ZynmLgOYDVjXXajBZG3oh5ycnx1gCwY5Q==
+frappe-datatable@^1.14.0:
+ version "1.14.0"
+ resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.14.0.tgz#8e5a0f61764fd634ae01f6767ce055b04ec5c3e1"
+ integrity sha512-rxePE/UpYFnWzAFIpiLrVGFHxh+fIbpDI98gAZfraZOgO4Dz6qDcJMaeSKDosQ1Zq6imt15KyKoaePXNpsCVfg==
dependencies:
hyperlist "^1.0.0-beta"
lodash "^4.17.5"