@@ -0,0 +1,57 @@ | |||||
context('Control Autocomplete', () => { | |||||
before(() => { | |||||
cy.login(); | |||||
cy.visit('/app/website'); | |||||
}); | |||||
function get_dialog_with_autocomplete(options) { | |||||
cy.visit('/app/website'); | |||||
return cy.dialog({ | |||||
title: 'Autocomplete', | |||||
fields: [ | |||||
{ | |||||
'label': 'Select an option', | |||||
'fieldname': 'autocomplete', | |||||
'fieldtype': 'Autocomplete', | |||||
'options': options || ['Option 1', 'Option 2', 'Option 3'], | |||||
} | |||||
] | |||||
}); | |||||
} | |||||
it('should set the valid value', () => { | |||||
get_dialog_with_autocomplete().as('dialog'); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').focus().as('input'); | |||||
cy.wait(1000); | |||||
cy.get('@input').type('2', { delay: 300 }); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete]').findByRole('listbox').should('be.visible'); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').type('{enter}', { delay: 300 }); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').blur(); | |||||
cy.get('@dialog').then(dialog => { | |||||
let value = dialog.get_value('autocomplete'); | |||||
expect(value).to.eq('Option 2'); | |||||
dialog.clear(); | |||||
}); | |||||
}); | |||||
it('should set the valid value with different label', () => { | |||||
const options_with_label = [ | |||||
{ label: "Option 1", value: "option_1" }, | |||||
{ label: "Option 2", value: "option_2" } | |||||
]; | |||||
get_dialog_with_autocomplete(options_with_label).as('dialog'); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').focus().as('input'); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete]').findByRole('listbox').should('be.visible'); | |||||
cy.get('@input').type('2', { delay: 300 }); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').type('{enter}', { delay: 300 }); | |||||
cy.get('.frappe-control[data-fieldname=autocomplete] input').blur(); | |||||
cy.get('@dialog').then(dialog => { | |||||
let value = dialog.get_value('autocomplete'); | |||||
expect(value).to.eq('option_2'); | |||||
dialog.clear(); | |||||
}); | |||||
}); | |||||
}); |
@@ -99,7 +99,7 @@ | |||||
"label": "Type", | "label": "Type", | ||||
"oldfieldname": "fieldtype", | "oldfieldname": "fieldtype", | ||||
"oldfieldtype": "Select", | "oldfieldtype": "Select", | ||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSignature\nSmall Text\nTab Break\nTable\nTable MultiSelect\nText\nText Editor\nTime", | |||||
"options": "Autocomplete\nAttach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSignature\nSmall Text\nTab Break\nTable\nTable MultiSelect\nText\nText Editor\nTime", | |||||
"reqd": 1, | "reqd": 1, | ||||
"search_index": 1 | "search_index": 1 | ||||
}, | }, | ||||
@@ -547,7 +547,7 @@ | |||||
"index_web_pages_for_search": 1, | "index_web_pages_for_search": 1, | ||||
"istable": 1, | "istable": 1, | ||||
"links": [], | "links": [], | ||||
"modified": "2022-01-27 21:22:20.529072", | |||||
"modified": "2022-02-14 11:56:19.812863", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Core", | "module": "Core", | ||||
"name": "DocField", | "name": "DocField", | ||||
@@ -330,7 +330,8 @@ result = [ | |||||
} | } | ||||
] | ] | ||||
result = add_total_row(result, columns, meta=None, report_settings=report_settings) | |||||
result = add_total_row(result, columns, meta=None, is_tree=report_settings['tree'], | |||||
parent_field=report_settings['parent_field']) | |||||
self.assertEqual(result[-1][0], "Total") | self.assertEqual(result[-1][0], "Total") | ||||
self.assertEqual(result[-1][1], 200) | self.assertEqual(result[-1][1], 200) | ||||
self.assertEqual(result[-1][2], 150.50) | self.assertEqual(result[-1][2], 150.50) |
@@ -122,7 +122,7 @@ | |||||
"label": "Field Type", | "label": "Field Type", | ||||
"oldfieldname": "fieldtype", | "oldfieldname": "fieldtype", | ||||
"oldfieldtype": "Select", | "oldfieldtype": "Select", | ||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature\nTab Break", | |||||
"options": "Autocomplete\nAttach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature\nTab Break", | |||||
"reqd": 1 | "reqd": 1 | ||||
}, | }, | ||||
{ | { | ||||
@@ -431,7 +431,7 @@ | |||||
"idx": 1, | "idx": 1, | ||||
"index_web_pages_for_search": 1, | "index_web_pages_for_search": 1, | ||||
"links": [], | "links": [], | ||||
"modified": "2022-01-27 21:47:01.065556", | |||||
"modified": "2022-02-14 15:42:21.885999", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Custom", | "module": "Custom", | ||||
"name": "Custom Field", | "name": "Custom Field", | ||||
@@ -85,7 +85,7 @@ | |||||
"label": "Type", | "label": "Type", | ||||
"oldfieldname": "fieldtype", | "oldfieldname": "fieldtype", | ||||
"oldfieldtype": "Select", | "oldfieldtype": "Select", | ||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTab Break\nTable\nTable MultiSelect\nText\nText Editor\nTime", | |||||
"options": "Autocomplete\nAttach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTab Break\nTable\nTable MultiSelect\nText\nText Editor\nTime", | |||||
"reqd": 1, | "reqd": 1, | ||||
"search_index": 1 | "search_index": 1 | ||||
}, | }, | ||||
@@ -450,7 +450,7 @@ | |||||
"index_web_pages_for_search": 1, | "index_web_pages_for_search": 1, | ||||
"istable": 1, | "istable": 1, | ||||
"links": [], | "links": [], | ||||
"modified": "2022-02-08 19:38:16.111199", | |||||
"modified": "2022-02-25 16:01:12.616736", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Custom", | "module": "Custom", | ||||
"name": "Customize Form Field", | "name": "Customize Form Field", | ||||
@@ -460,4 +460,4 @@ | |||||
"sort_field": "modified", | "sort_field": "modified", | ||||
"sort_order": "ASC", | "sort_order": "ASC", | ||||
"states": [] | "states": [] | ||||
} | |||||
} |
@@ -52,7 +52,8 @@ class MariaDBDatabase(Database): | |||||
'Barcode': ('longtext', ''), | 'Barcode': ('longtext', ''), | ||||
'Geolocation': ('longtext', ''), | 'Geolocation': ('longtext', ''), | ||||
'Duration': ('decimal', '21,9'), | 'Duration': ('decimal', '21,9'), | ||||
'Icon': ('varchar', self.VARCHAR_LEN) | |||||
'Icon': ('varchar', self.VARCHAR_LEN), | |||||
'Autocomplete': ('varchar', self.VARCHAR_LEN), | |||||
} | } | ||||
def get_connection(self): | def get_connection(self): | ||||
@@ -62,7 +62,8 @@ class PostgresDatabase(Database): | |||||
'Barcode': ('text', ''), | 'Barcode': ('text', ''), | ||||
'Geolocation': ('text', ''), | 'Geolocation': ('text', ''), | ||||
'Duration': ('decimal', '21,9'), | 'Duration': ('decimal', '21,9'), | ||||
'Icon': ('varchar', self.VARCHAR_LEN) | |||||
'Icon': ('varchar', self.VARCHAR_LEN), | |||||
'Autocomplete': ('varchar', self.VARCHAR_LEN), | |||||
} | } | ||||
def get_connection(self): | def get_connection(self): | ||||
@@ -11,8 +11,10 @@ from frappe.model.utils.user_settings import get_user_settings | |||||
from frappe.permissions import get_doc_permissions | from frappe.permissions import get_doc_permissions | ||||
from frappe.desk.form.document_follow import is_document_followed | from frappe.desk.form.document_follow import is_document_followed | ||||
from frappe import _ | from frappe import _ | ||||
from frappe import _dict | |||||
from urllib.parse import quote | from urllib.parse import quote | ||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def getdoc(doctype, name, user=None): | def getdoc(doctype, name, user=None): | ||||
""" | """ | ||||
@@ -50,8 +52,11 @@ def getdoc(doctype, name, user=None): | |||||
doc.add_seen() | doc.add_seen() | ||||
set_link_titles(doc) | set_link_titles(doc) | ||||
if frappe.response.docs is None: | |||||
frappe.response = _dict({"docs": []}) | |||||
frappe.response.docs.append(doc) | frappe.response.docs.append(doc) | ||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def getdoctype(doctype, with_parent=False, cached_timestamp=None): | def getdoctype(doctype, with_parent=False, cached_timestamp=None): | ||||
"""load doctype""" | """load doctype""" | ||||
@@ -392,7 +392,7 @@ def make_records(records, debug=False): | |||||
doc.flags.ignore_mandatory = True | doc.flags.ignore_mandatory = True | ||||
try: | try: | ||||
doc.insert(ignore_permissions=True, ignore_if_duplicate=True) | |||||
doc.insert(ignore_permissions=True) | |||||
frappe.db.commit() | frappe.db.commit() | ||||
except frappe.DuplicateEntryError as e: | except frappe.DuplicateEntryError as e: | ||||
@@ -73,7 +73,7 @@ def get_report_result(report, filters): | |||||
return res | return res | ||||
@frappe.read_only() | @frappe.read_only() | ||||
def generate_report_result(report, filters=None, user=None, custom_columns=None, report_settings=None): | |||||
def generate_report_result(report, filters=None, user=None, custom_columns=None, is_tree=False, parent_field=None): | |||||
user = user or frappe.session.user | user = user or frappe.session.user | ||||
filters = filters or [] | filters = filters or [] | ||||
@@ -108,7 +108,7 @@ def generate_report_result(report, filters=None, user=None, custom_columns=None, | |||||
result = get_filtered_data(report.ref_doctype, columns, result, user) | result = get_filtered_data(report.ref_doctype, columns, result, user) | ||||
if cint(report.add_total_row) and result and not skip_total_row: | if cint(report.add_total_row) and result and not skip_total_row: | ||||
result = add_total_row(result, columns, report_settings=report_settings) | |||||
result = add_total_row(result, columns, is_tree=is_tree, parent_field=parent_field) | |||||
return { | return { | ||||
"result": result, | "result": result, | ||||
@@ -210,7 +210,7 @@ def get_script(report_name): | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
@frappe.read_only() | @frappe.read_only() | ||||
def run(report_name, filters=None, user=None, ignore_prepared_report=False, custom_columns=None, report_settings=None): | |||||
def run(report_name, filters=None, user=None, ignore_prepared_report=False, custom_columns=None, is_tree=False, parent_field=None): | |||||
report = get_report_doc(report_name) | report = get_report_doc(report_name) | ||||
if not user: | if not user: | ||||
user = frappe.session.user | user = frappe.session.user | ||||
@@ -238,7 +238,7 @@ def run(report_name, filters=None, user=None, ignore_prepared_report=False, cust | |||||
dn = "" | dn = "" | ||||
result = get_prepared_report_result(report, filters, dn, user) | result = get_prepared_report_result(report, filters, dn, user) | ||||
else: | else: | ||||
result = generate_report_result(report, filters, user, custom_columns, report_settings) | |||||
result = generate_report_result(report, filters, user, custom_columns, is_tree, parent_field) | |||||
result["add_total_row"] = report.add_total_row and not result.get( | result["add_total_row"] = report.add_total_row and not result.get( | ||||
"skip_total_row", False | "skip_total_row", False | ||||
@@ -435,18 +435,9 @@ def build_xlsx_data(columns, data, visible_idx, include_indentation, ignore_visi | |||||
return result, column_widths | return result, column_widths | ||||
def add_total_row(result, columns, meta=None, report_settings=None): | |||||
def add_total_row(result, columns, meta=None, is_tree=False, parent_field=None): | |||||
total_row = [""] * len(columns) | total_row = [""] * len(columns) | ||||
has_percent = [] | has_percent = [] | ||||
is_tree = False | |||||
parent_field = '' | |||||
if report_settings: | |||||
if isinstance(report_settings, (str,)): | |||||
report_settings = json.loads(report_settings) | |||||
is_tree = report_settings.get('tree') | |||||
parent_field = report_settings.get('parent_field') | |||||
for i, col in enumerate(columns): | for i, col in enumerate(columns): | ||||
fieldtype, options, fieldname = None, None, None | fieldtype, options, fieldname = None, None, None | ||||
@@ -35,7 +35,8 @@ data_fieldtypes = ( | |||||
'Barcode', | 'Barcode', | ||||
'Geolocation', | 'Geolocation', | ||||
'Duration', | 'Duration', | ||||
'Icon' | |||||
'Icon', | |||||
'Autocomplete', | |||||
) | ) | ||||
attachment_fieldtypes = ( | attachment_fieldtypes = ( | ||||
@@ -1154,7 +1154,7 @@ class Document(BaseDocument): | |||||
for f in hooks: | for f in hooks: | ||||
add_to_return_value(self, f(self, method, *args, **kwargs)) | add_to_return_value(self, f(self, method, *args, **kwargs)) | ||||
return self._return_value | |||||
return self.__dict__.pop("_return_value", None) | |||||
return runner | return runner | ||||
@@ -11,7 +11,26 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
set_options() { | set_options() { | ||||
if (this.df.options) { | if (this.df.options) { | ||||
let options = this.df.options || []; | let options = this.df.options || []; | ||||
this._data = this.parse_options(options); | |||||
this.set_data(options); | |||||
} | |||||
} | |||||
format_for_input(value) { | |||||
if (value == null) { | |||||
return ""; | |||||
} else if (this._data && this._data.length) { | |||||
const item = this._data.find(i => i.value == value); | |||||
return item ? item.label : value; | |||||
} else { | |||||
return value; | |||||
} | |||||
} | |||||
get_input_value() { | |||||
if (this.$input) { | |||||
const label = this.$input.val(); | |||||
const item = this._data?.find(i => i.label == label); | |||||
return item ? item.value : label; | |||||
} | } | ||||
} | } | ||||
@@ -23,7 +42,7 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
autoFirst: true, | autoFirst: true, | ||||
list: this.get_data(), | list: this.get_data(), | ||||
data: function(item) { | data: function(item) { | ||||
if (!(item instanceof Object)) { | |||||
if (typeof item !== 'object') { | |||||
var d = { value: item }; | var d = { value: item }; | ||||
item = d; | item = d; | ||||
} | } | ||||
@@ -65,6 +84,18 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
}; | }; | ||||
} | } | ||||
init_option_cache() { | |||||
if (!this.$input.cache) { | |||||
this.$input.cache = {}; | |||||
} | |||||
if (!this.$input.cache[this.doctype]) { | |||||
this.$input.cache[this.doctype] = {}; | |||||
} | |||||
if (!this.$input.cache[this.doctype][this.df.fieldname]) { | |||||
this.$input.cache[this.doctype][this.df.fieldname] = {}; | |||||
} | |||||
} | |||||
setup_awesomplete() { | setup_awesomplete() { | ||||
this.awesomplete = new Awesomplete( | this.awesomplete = new Awesomplete( | ||||
this.input, | this.input, | ||||
@@ -75,12 +106,18 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
.find('.awesomplete ul') | .find('.awesomplete ul') | ||||
.css('min-width', '100%'); | .css('min-width', '100%'); | ||||
this.$input.on( | |||||
'input', | |||||
frappe.utils.debounce(() => { | |||||
this.init_option_cache(); | |||||
this.$input.on('input', frappe.utils.debounce((e) => { | |||||
const cached_options = this.$input.cache[this.doctype][this.df.fieldname][e.target.value]; | |||||
if (cached_options && cached_options.length) { | |||||
this.set_data(cached_options); | |||||
} else if (this.get_query || this.df.get_query) { | |||||
this.execute_query_if_exists(e.target.value); | |||||
} else { | |||||
this.awesomplete.list = this.get_data(); | this.awesomplete.list = this.get_data(); | ||||
}, 500) | |||||
); | |||||
} | |||||
}, 500)); | |||||
this.$input.on('focus', () => { | this.$input.on('focus', () => { | ||||
if (!this.$input.val()) { | if (!this.$input.val()) { | ||||
@@ -89,6 +126,17 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
} | } | ||||
}); | }); | ||||
this.$input.on("blur", () => { | |||||
if(this.selected) { | |||||
this.selected = false; | |||||
return; | |||||
} | |||||
var value = this.get_input_value(); | |||||
if(value!==this.last_value) { | |||||
this.parse_validate_and_set_in_model(value); | |||||
} | |||||
}); | |||||
this.$input.on("awesomplete-open", () => { | this.$input.on("awesomplete-open", () => { | ||||
this.autocomplete_open = true; | this.autocomplete_open = true; | ||||
}); | }); | ||||
@@ -127,6 +175,75 @@ frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui | |||||
return options; | return options; | ||||
} | } | ||||
execute_query_if_exists(term) { | |||||
const args = { txt: term }; | |||||
let get_query = this.get_query || this.df.get_query; | |||||
if (!get_query) { | |||||
return; | |||||
} | |||||
let set_nulls = function(obj) { | |||||
$.each(obj, function(key, value) { | |||||
if (value !== undefined) { | |||||
obj[key] = value; | |||||
} | |||||
}); | |||||
return obj; | |||||
}; | |||||
let process_query_object = function(obj) { | |||||
if (obj.query) { | |||||
args.query = obj.query; | |||||
} | |||||
if (obj.params) { | |||||
set_nulls(obj.params); | |||||
Object.assign(args, obj.params); | |||||
} | |||||
// turn off value translation | |||||
if (obj.translate_values !== undefined) { | |||||
this.translate_values = obj.translate_values; | |||||
} | |||||
}; | |||||
if ($.isPlainObject(get_query)) { | |||||
process_query_object(get_query); | |||||
} else if (typeof get_query === "string") { | |||||
args.query = get_query; | |||||
} else { | |||||
// get_query by function | |||||
var q = get_query( | |||||
(this.frm && this.frm.doc) || this.doc, | |||||
this.doctype, | |||||
this.docname | |||||
); | |||||
if (typeof q === "string") { | |||||
// returns a string | |||||
args.query = q; | |||||
} else if ($.isPlainObject(q)) { | |||||
// returns an object | |||||
process_query_object(q); | |||||
} | |||||
} | |||||
if (args.query) { | |||||
frappe.call({ | |||||
method: args.query, | |||||
args: args, | |||||
callback: ({ message }) => { | |||||
if(!this.$input.is(":focus")) { | |||||
return; | |||||
} | |||||
this.$input.cache[this.doctype][this.df.fieldname][term] = message; | |||||
this.set_data(message); | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
get_data() { | get_data() { | ||||
return this._data || []; | return this._data || []; | ||||
} | } | ||||
@@ -21,6 +21,9 @@ frappe.form.formatters = { | |||||
} | } | ||||
return value==null ? "" : value; | return value==null ? "" : value; | ||||
}, | }, | ||||
Autocomplete: function(value) { | |||||
return __(frappe.form.formatters["Data"](value)); | |||||
}, | |||||
Select: function(value) { | Select: function(value) { | ||||
return __(frappe.form.formatters["Data"](value)); | return __(frappe.form.formatters["Data"](value)); | ||||
}, | }, | ||||
@@ -183,21 +183,20 @@ export default class GridRow { | |||||
render_template() { | render_template() { | ||||
this.set_row_index(); | this.set_row_index(); | ||||
if(this.row_display) { | |||||
if (this.row_display) { | |||||
this.row_display.remove(); | this.row_display.remove(); | ||||
} | } | ||||
// row index | // row index | ||||
if(this.doc) { | |||||
if(!this.row_index) { | |||||
this.row_index = $('<div style="float: left; margin-left: 15px; margin-top: 8px; \ | |||||
margin-right: -20px;">'+this.row_check_html+' <span></span></div>').appendTo(this.row); | |||||
} | |||||
if (!this.row_index) { | |||||
this.row_index = $(`<div class="template-row-index">${this.row_check_html}<span></span></div>`).appendTo(this.row); | |||||
} | |||||
if (this.doc) { | |||||
this.row_index.find('span').html(this.doc.idx); | this.row_index.find('span').html(this.doc.idx); | ||||
} | } | ||||
this.row_display = $('<div class="row-data sortable-handle template-row">'+ | |||||
+'</div>').appendTo(this.row) | |||||
this.row_display = $('<div class="row-data sortable-handle template-row"></div>').appendTo(this.row) | |||||
.html(frappe.render(this.grid.template, { | .html(frappe.render(this.grid.template, { | ||||
doc: this.doc ? frappe.get_format_helper(this.doc) : null, | doc: this.doc ? frappe.get_format_helper(this.doc) : null, | ||||
frm: this.frm, | frm: this.frm, | ||||
@@ -578,7 +578,8 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { | |||||
args: { | args: { | ||||
report_name: this.report_name, | report_name: this.report_name, | ||||
filters: filters, | filters: filters, | ||||
report_settings: this.report_settings | |||||
is_tree: this.report_settings.tree, | |||||
parent_field: this.report_settings.parent_field | |||||
}, | }, | ||||
callback: resolve, | callback: resolve, | ||||
always: () => this.page.btn_secondary.prop('disabled', false) | always: () => this.page.btn_secondary.prop('disabled', false) | ||||
@@ -54,7 +54,7 @@ | |||||
} | } | ||||
.form-grid .grid-heading-row .template-row { | .form-grid .grid-heading-row .template-row { | ||||
margin-left: 20px; | |||||
margin-left: 8px; | |||||
} | } | ||||
.form-grid .template-row { | .form-grid .template-row { | ||||
@@ -88,6 +88,17 @@ | |||||
margin-top: 2px; | margin-top: 2px; | ||||
} | } | ||||
.template-row-index { | |||||
float: left; | |||||
margin-left: 15px; | |||||
margin-top: 8px; | |||||
margin-right: -20px; | |||||
span { | |||||
margin-left: 5px; | |||||
} | |||||
} | |||||
.editable-form .grid-static-col.bold { | .editable-form .grid-static-col.bold { | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
@@ -164,6 +164,7 @@ def get_alert_dict(doc): | |||||
return alert_dict | return alert_dict | ||||
def create_energy_points_log(ref_doctype, ref_name, doc, apply_only_once=False): | def create_energy_points_log(ref_doctype, ref_name, doc, apply_only_once=False): | ||||
doc = frappe._dict(doc) | doc = frappe._dict(doc) | ||||
@@ -171,7 +172,7 @@ def create_energy_points_log(ref_doctype, ref_name, doc, apply_only_once=False): | |||||
ref_name, doc.rule, None if apply_only_once else doc.user) | ref_name, doc.rule, None if apply_only_once else doc.user) | ||||
if log_exists: | if log_exists: | ||||
return | |||||
return frappe.get_doc('Energy Point Log', log_exists) | |||||
new_log = frappe.new_doc('Energy Point Log') | new_log = frappe.new_doc('Energy Point Log') | ||||
new_log.reference_doctype = ref_doctype | new_log.reference_doctype = ref_doctype | ||||