[Multicheck control] (#4529)
* multicheck control * [checkboxes] replace in domain settings * [checkboxes] use in setup_wizard domains * [multicheck] minor * [multicheck] set and get value as an array * [multicheck] make controls.less * basic view control with value as array object * load active domains * selenium helper: multicheck * [multicheck] make field if not present * [multicheck] append control in an HTML field
This commit is contained in:
parent
816f045f75
commit
d1aa5c60b4
15 changed files with 1546 additions and 1508 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -2,58 +2,62 @@
|
|||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Domain Settings', {
|
||||
onload: function(frm) {
|
||||
let domains = $('<div class="domain-editor">')
|
||||
.appendTo(frm.fields_dict.domains_html.wrapper);
|
||||
|
||||
if(!frm.domain_editor) {
|
||||
frm.domain_editor = new frappe.DomainsEditor(domains, frm);
|
||||
before_load: function(frm) {
|
||||
if(!frm.domains_multicheck) {
|
||||
frm.domains_multicheck = frappe.ui.form.make_control({
|
||||
parent: frm.fields_dict.domains_html.$wrapper,
|
||||
df: {
|
||||
fieldname: "domains_multicheck",
|
||||
fieldtype: "MultiCheck",
|
||||
get_data: () => {
|
||||
let active_domains = (frm.doc.active_domains || []).map(row => row.domain);
|
||||
return frappe.boot.all_domains.map(domain => {
|
||||
return {
|
||||
label: domain,
|
||||
value: domain,
|
||||
checked: active_domains.includes(domain)
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
render_input: true
|
||||
});
|
||||
frm.domains_multicheck.refresh_input();
|
||||
}
|
||||
|
||||
frm.domain_editor.show();
|
||||
},
|
||||
|
||||
validate: function(frm) {
|
||||
if(frm.domain_editor) {
|
||||
frm.domain_editor.set_items_in_table();
|
||||
}
|
||||
frm.trigger('set_options_in_table');
|
||||
},
|
||||
});
|
||||
|
||||
frappe.DomainsEditor = frappe.CheckboxEditor.extend({
|
||||
init: function(wrapper, frm) {
|
||||
var opts = {};
|
||||
$.extend(opts, {
|
||||
wrapper: wrapper,
|
||||
frm: frm,
|
||||
field_mapper: {
|
||||
child_table_field: "active_domains",
|
||||
item_field: "domain",
|
||||
cdt: "Has Domain"
|
||||
},
|
||||
attribute: 'data-domain',
|
||||
checkbox_selector: false,
|
||||
get_items: this.get_all_domains,
|
||||
editor_template: this.get_template()
|
||||
set_options_in_table: function(frm) {
|
||||
let selected_options = frm.domains_multicheck.get_value();
|
||||
let unselected_options = frm.domains_multicheck.options
|
||||
.map(option => option.value)
|
||||
.filter(value => {
|
||||
return !selected_options.includes(value);
|
||||
});
|
||||
|
||||
let map = {}, list = [];
|
||||
(frm.doc.active_domains || []).map(row => {
|
||||
map[row.domain] = row.name;
|
||||
list.push(row.domain);
|
||||
});
|
||||
|
||||
this._super(opts);
|
||||
},
|
||||
unselected_options.map(option => {
|
||||
if(list.includes(option)) {
|
||||
frappe.model.clear_doc("Has Domain", map[option]);
|
||||
}
|
||||
});
|
||||
|
||||
get_template: function() {
|
||||
return `
|
||||
<div class="checkbox" data-domain="{{item}}">
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<span class="label-area small">{{ __(item) }}</span>
|
||||
</label>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
selected_options.map(option => {
|
||||
if(!list.includes(option)) {
|
||||
frappe.model.clear_doc("Has Domain", map[option]);
|
||||
let row = frappe.model.add_child(frm.doc, "Has Domain", "active_domains");
|
||||
row.domain = option;
|
||||
}
|
||||
});
|
||||
|
||||
get_all_domains: function() {
|
||||
// return all the domains available in the system
|
||||
this.items = frappe.boot.all_domains;
|
||||
this.render_items();
|
||||
},
|
||||
});
|
||||
refresh_field('active_domains');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "domains",
|
||||
"fieldname": "active_domains_sb",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Domains",
|
||||
"label": "Active Domains",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Domains",
|
||||
"label": "Domains HTML",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-05-12 17:01:18.615000",
|
||||
"modified": "2017-12-05 17:36:46.842134",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Domain Settings",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ frappe.setup = {
|
|||
events: {},
|
||||
data: {},
|
||||
utils: {},
|
||||
domains: [],
|
||||
|
||||
on: function(event, fn) {
|
||||
if(!frappe.setup.events[event]) {
|
||||
|
|
@ -26,7 +27,8 @@ frappe.setup = {
|
|||
}
|
||||
|
||||
frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
|
||||
var requires = (frappe.boot.setup_wizard_requires || []);
|
||||
let requires = (frappe.boot.setup_wizard_requires || []);
|
||||
|
||||
|
||||
frappe.require(requires, function() {
|
||||
frappe.call({
|
||||
|
|
@ -216,10 +218,10 @@ frappe.setup.SetupWizard = class SetupWizard extends frappe.ui.Slides {
|
|||
get_setup_slides_filtered_by_domain() {
|
||||
var filtered_slides = [];
|
||||
frappe.setup.slides.forEach(function(slide) {
|
||||
if(frappe.setup.domain) {
|
||||
var domains = slide.domains;
|
||||
if (domains.indexOf('all') !== -1 ||
|
||||
domains.indexOf(frappe.setup.domain.toLowerCase()) !== -1) {
|
||||
if(frappe.setup.domains) {
|
||||
let active_domains = frappe.setup.domains;
|
||||
if (!slide.domains ||
|
||||
slide.domains.filter(d => active_domains.includes(d)).length > 0) {
|
||||
filtered_slides.push(slide);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -311,7 +313,6 @@ frappe.setup.slides_settings = [
|
|||
{
|
||||
// Welcome (language) slide
|
||||
name: "welcome",
|
||||
domains: ["all"],
|
||||
title: __("Hello!"),
|
||||
icon: "fa fa-world",
|
||||
// help: __("Let's prepare the system for first use."),
|
||||
|
|
@ -344,7 +345,6 @@ frappe.setup.slides_settings = [
|
|||
{
|
||||
// Region slide
|
||||
name: 'region',
|
||||
domains: ["all"],
|
||||
title: __("Select Your Region"),
|
||||
icon: "fa fa-flag",
|
||||
// help: __("Select your Country, Time Zone and Currency"),
|
||||
|
|
@ -376,7 +376,6 @@ frappe.setup.slides_settings = [
|
|||
{
|
||||
// Profile slide
|
||||
name: 'user',
|
||||
domains: ["all"],
|
||||
title: __("The First User: You"),
|
||||
icon: "fa fa-user",
|
||||
fields: [
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@
|
|||
"public/js/frappe/form/controls/autocomplete.js",
|
||||
"public/js/frappe/form/controls/barcode.js",
|
||||
"public/js/frappe/form/controls/geolocation.js",
|
||||
"public/js/frappe/form/controls/multiselect.js"
|
||||
"public/js/frappe/form/controls/multiselect.js",
|
||||
"public/js/frappe/form/controls/multicheck.js"
|
||||
],
|
||||
"js/dialog.min.js": [
|
||||
"public/js/frappe/dom.js",
|
||||
|
|
@ -120,7 +121,8 @@
|
|||
"public/css/desktop.css",
|
||||
"public/css/form.css",
|
||||
"public/css/mobile.css",
|
||||
"public/css/kanban.css"
|
||||
"public/css/kanban.css",
|
||||
"public/css/controls.css"
|
||||
],
|
||||
"css/frappe-rtl.css": [
|
||||
"public/css/bootstrap-rtl.css",
|
||||
|
|
@ -168,7 +170,6 @@
|
|||
"public/js/frappe/socketio_client.js",
|
||||
"public/js/frappe/router.js",
|
||||
"public/js/frappe/defaults.js",
|
||||
"public/js/frappe/checkbox_editor.js",
|
||||
"public/js/frappe/roles_editor.js",
|
||||
"public/js/lib/microtemplate.js",
|
||||
|
||||
|
|
|
|||
6
frappe/public/css/controls.css
Normal file
6
frappe/public/css/controls.css
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.unit-checkbox {
|
||||
color: #36414c;
|
||||
}
|
||||
.frappe-control .select-all {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
// opts:
|
||||
// frm
|
||||
// wrapper
|
||||
// get_items
|
||||
// add_btn_label
|
||||
// remove_btn_label
|
||||
// field_mapper:
|
||||
// cdt
|
||||
// child_table_field
|
||||
// item_field
|
||||
// attribute
|
||||
|
||||
frappe.CheckboxEditor = Class.extend({
|
||||
init: function(opts) {
|
||||
$.extend(this, opts);
|
||||
|
||||
this.doctype = this.field_mapper.cdt;
|
||||
this.fieldname = this.field_mapper.child_table_field;
|
||||
this.item_fieldname = this.field_mapper.item_field;
|
||||
|
||||
$(this.wrapper).html('<div class="help">' + __("Loading") + '...</div>');
|
||||
|
||||
if(this.get_items) {
|
||||
this.get_items();
|
||||
}
|
||||
},
|
||||
render_items: function(callback) {
|
||||
let me = this;
|
||||
$(this.wrapper).empty();
|
||||
|
||||
if(this.checkbox_selector) {
|
||||
let toolbar = $('<p><button class="btn btn-default btn-add btn-sm" style="margin-right: 5px;"></button>\
|
||||
<button class="btn btn-sm btn-default btn-remove"></button></p>').appendTo($(this.wrapper));
|
||||
|
||||
toolbar.find(".btn-add")
|
||||
.html(__(this.add_btn_label))
|
||||
.on("click", function() {
|
||||
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
|
||||
if(!$(check).is(":checked")) {
|
||||
check.checked = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
toolbar.find(".btn-remove")
|
||||
.html(__(this.remove_btn_label))
|
||||
.on("click", function() {
|
||||
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
|
||||
if($(check).is(":checked")) {
|
||||
check.checked = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$.each(this.items, function(i, item) {
|
||||
$(me.wrapper).append(frappe.render(me.editor_template, {'item': item}));
|
||||
});
|
||||
|
||||
$(this.wrapper).find('input[type="checkbox"]').change(function() {
|
||||
if(me.fieldname && me.doctype && me.item_field) {
|
||||
me.set_items_in_table();
|
||||
me.frm.dirty();
|
||||
}
|
||||
});
|
||||
|
||||
callback && callback()
|
||||
},
|
||||
show: function() {
|
||||
let me = this;
|
||||
|
||||
// uncheck all items
|
||||
$(this.wrapper).find('input[type="checkbox"]')
|
||||
.each(function(i, checkbox) { checkbox.checked = false; });
|
||||
|
||||
// set user items as checked
|
||||
$.each((me.frm.doc[this.fieldname] || []), function(i, row) {
|
||||
let selector = repl('[%(attribute)s="%(value)s"] input[type="checkbox"]', {
|
||||
attribute: me.attribute,
|
||||
value: row[me.item_fieldname]
|
||||
});
|
||||
|
||||
let checkbox = $(me.wrapper)
|
||||
.find(selector).get(0);
|
||||
if(checkbox) checkbox.checked = true;
|
||||
});
|
||||
},
|
||||
|
||||
get_selected_unselected_items: function() {
|
||||
let checked_items = [];
|
||||
let unchecked_items = [];
|
||||
let selector = repl('[%(attribute)s]', { attribute: this.attribute });
|
||||
let me = this;
|
||||
|
||||
$(this.wrapper).find(selector).each(function() {
|
||||
if($(this).find('input[type="checkbox"]:checked').length) {
|
||||
checked_items.push($(this).attr(me.attribute));
|
||||
} else {
|
||||
unchecked_items.push($(this).attr(me.attribute));
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
checked_items: checked_items,
|
||||
unchecked_items: unchecked_items
|
||||
}
|
||||
},
|
||||
|
||||
set_items_in_table: function() {
|
||||
let opts = this.get_selected_unselected_items();
|
||||
let existing_items_map = {};
|
||||
let existing_items_list = [];
|
||||
let me = this;
|
||||
|
||||
$.each(me.frm.doc[this.fieldname] || [], function(i, row) {
|
||||
existing_items_map[row[me.item_fieldname]] = row.name;
|
||||
existing_items_list.push(row[me.item_fieldname]);
|
||||
});
|
||||
|
||||
// remove unchecked items
|
||||
$.each(opts.unchecked_items, function(i, item) {
|
||||
if(existing_items_list.indexOf(item)!=-1) {
|
||||
frappe.model.clear_doc(me.doctype, existing_items_map[item]);
|
||||
}
|
||||
});
|
||||
|
||||
// add new items that are checked
|
||||
$.each(opts.checked_items, function(i, item) {
|
||||
if(existing_items_list.indexOf(item)==-1) {
|
||||
let row = frappe.model.add_child(me.frm.doc, me.doctype, me.fieldname);
|
||||
row[me.item_fieldname] = item;
|
||||
}
|
||||
});
|
||||
|
||||
refresh_field(this.fieldname);
|
||||
}
|
||||
});
|
||||
|
|
@ -38,6 +38,7 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
|
|||
} else {
|
||||
this.label_area = this.label_span = this.$wrapper.find("label").get(0);
|
||||
this.input_area = this.$wrapper.find(".control-input").get(0);
|
||||
this.$input_wrapper = this.$wrapper.find(".control-input-wrapper");
|
||||
// keep a separate display area to rendered formatted values
|
||||
// like links, currencies, HTMLs etc.
|
||||
this.disp_area = this.$wrapper.find(".control-value").get(0);
|
||||
|
|
|
|||
139
frappe/public/js/frappe/form/controls/multicheck.js
Normal file
139
frappe/public/js/frappe/form/controls/multicheck.js
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({
|
||||
// UI: multiple checkboxes
|
||||
// Value: Array of values
|
||||
// Options: Array of label/value/checked option objects
|
||||
|
||||
make() {
|
||||
this._super();
|
||||
// this.$label = $(`<label class="control-label">${this.df.label}</label>`).appendTo(this.wrapper);
|
||||
this.$load_state = $('<div class="load-state text-muted small">' + __("Loading") + '...</div>');
|
||||
this.$select_buttons = this.get_select_buttons().appendTo(this.wrapper);
|
||||
this.$load_state.appendTo(this.wrapper);
|
||||
|
||||
this.$checkbox_area = $('<div class="checkbox-options"></div>').appendTo(this.wrapper);
|
||||
this.set_options();
|
||||
this.bind_checkboxes();
|
||||
},
|
||||
|
||||
refresh_input() {
|
||||
this.options.map(option => option.value).forEach(value => {
|
||||
$(this.wrapper)
|
||||
.find(`:checkbox[data-unit=${value}]`)
|
||||
.prop("checked", this.selected_options.includes(value));
|
||||
});
|
||||
},
|
||||
|
||||
set_options() {
|
||||
this.$load_state.show();
|
||||
this.$select_buttons.hide();
|
||||
this.parse_df_options();
|
||||
|
||||
if(this.df.get_data) {
|
||||
if(typeof this.df.get_data().then == 'function') {
|
||||
this.df.get_data().then(results => {
|
||||
this.options = results;
|
||||
this.make_checkboxes();
|
||||
});
|
||||
} else {
|
||||
this.options = this.df.get_data();
|
||||
this.make_checkboxes();
|
||||
}
|
||||
} else {
|
||||
this.make_checkboxes();
|
||||
}
|
||||
},
|
||||
|
||||
parse_df_options() {
|
||||
if(Array.isArray(this.df.options)) {
|
||||
this.options = this.df.options;
|
||||
} else if(this.df.options && this.df.options.length>0 && frappe.utils.is_json(this.df.options)) {
|
||||
let args = JSON.parse(this.df.options);
|
||||
if(Array.isArray(args)) {
|
||||
this.options = args;
|
||||
} else if(Array.isArray(args.options)) {
|
||||
if(args.select_all) {
|
||||
this.select_all = true;
|
||||
}
|
||||
this.options = args.options;
|
||||
}
|
||||
} else {
|
||||
this.options = [];
|
||||
}
|
||||
},
|
||||
|
||||
make_checkboxes() {
|
||||
this.set_checked_options();
|
||||
this.$load_state.hide();
|
||||
this.$checkbox_area.empty();
|
||||
this.options.forEach(option => {
|
||||
this.get_checkbox_element(option).appendTo(this.$checkbox_area);
|
||||
});
|
||||
if(this.select_all) {
|
||||
this.setup_select_all();
|
||||
}
|
||||
},
|
||||
|
||||
bind_checkboxes() {
|
||||
$(this.wrapper).on('change', ':checkbox', e => {
|
||||
const $checkbox = $(e.target);
|
||||
const option_name = $checkbox.attr("data-unit");
|
||||
if($checkbox.is(':checked')) {
|
||||
this.selected_options.push(option_name);
|
||||
} else {
|
||||
let index = this.selected_options.indexOf(option_name);
|
||||
this.selected_options.splice(index, 1);
|
||||
}
|
||||
this.df.on_change && this.df.on_change();
|
||||
});
|
||||
},
|
||||
|
||||
set_checked_options() {
|
||||
this.selected_options = this.options
|
||||
.filter(o => o.checked)
|
||||
.map(o => o.value);
|
||||
},
|
||||
|
||||
setup_select_all() {
|
||||
this.$select_buttons.show();
|
||||
let select_all = (deselect=false) => {
|
||||
$(this.wrapper).find(`:checkbox`).prop("checked", deselect).trigger('click');
|
||||
};
|
||||
this.$select_buttons.find('.select-all').on('click', () => {
|
||||
select_all();
|
||||
});
|
||||
this.$select_buttons.find('.deselect-all').on('click', () => {
|
||||
select_all(true);
|
||||
});
|
||||
},
|
||||
|
||||
get_value() {
|
||||
return this.selected_options;
|
||||
},
|
||||
|
||||
get_checked_options() {
|
||||
return this.get_value();
|
||||
},
|
||||
|
||||
get_unchecked_options() {
|
||||
return this.options.map(o => o.value)
|
||||
.filter(value => !this.selected_options.includes(value));
|
||||
},
|
||||
|
||||
get_checkbox_element(option) {
|
||||
return $(`
|
||||
<div class="checkbox unit-checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-unit="${option.value}">
|
||||
</input>
|
||||
<span class="label-area small" data-unit="${option.value}">${__(option.label)}</span>
|
||||
</label>
|
||||
</div>`);
|
||||
},
|
||||
|
||||
get_select_buttons() {
|
||||
return $(`<div><button class="btn btn-xs btn-default select-all">
|
||||
${__("Select All")}</button>
|
||||
<button class="btn btn-xs btn-default deselect-all">
|
||||
${__("Unselect All")}</button></div>`);
|
||||
}
|
||||
});
|
||||
|
|
@ -239,6 +239,26 @@ frappe.ui.form.Layout = Class.extend({
|
|||
});
|
||||
},
|
||||
|
||||
refresh_fields: function(fields) {
|
||||
let fieldnames = fields.map((field) => {
|
||||
if(field.fieldname) return field.fieldname;
|
||||
});
|
||||
|
||||
this.fields_list.map(fieldobj => {
|
||||
if(fieldnames.includes(fieldobj.df.fieldname)) {
|
||||
fieldobj.refresh();
|
||||
if(fieldobj.df["default"]) {
|
||||
fieldobj.set_input(fieldobj.df["default"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
add_fields: function(fields) {
|
||||
this.render(fields);
|
||||
this.refresh_fields(fields);
|
||||
},
|
||||
|
||||
refresh_section_collapse: function() {
|
||||
if(!this.doc) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ frappe.utils = {
|
|||
is_md: function() {
|
||||
return $(document).width() < 1199 && $(document).width() >= 991;
|
||||
},
|
||||
is_json: function(str) {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
strip_whitespace: function(html) {
|
||||
return (html || "").replace(/<p>\s*<\/p>/g, "").replace(/<br>(\s*<br>\s*)+/g, "<br><br>");
|
||||
},
|
||||
|
|
|
|||
|
|
@ -41,24 +41,6 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({
|
|||
|
||||
}
|
||||
},
|
||||
add_fields: function(fields) {
|
||||
this.render(fields);
|
||||
this.refresh_fields(fields);
|
||||
},
|
||||
refresh_fields: function(fields) {
|
||||
let fieldnames = fields.map((field) => {
|
||||
if(field.fieldname) return field.fieldname;
|
||||
});
|
||||
|
||||
this.fields_list.map(fieldobj => {
|
||||
if(fieldnames.includes(fieldobj.df.fieldname)) {
|
||||
fieldobj.refresh();
|
||||
if(fieldobj.df["default"]) {
|
||||
fieldobj.set_input(fieldobj.df["default"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
first_button: false,
|
||||
focus_on_first_input: function() {
|
||||
if(this.no_focus) return;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,10 @@ frappe.ui.Slide = class Slide {
|
|||
return this.form.get_field(fieldname);
|
||||
}
|
||||
|
||||
get_value(fieldname) {
|
||||
return this.form.get_value(fieldname);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.$body.remove();
|
||||
}
|
||||
|
|
|
|||
7
frappe/public/less/controls.less
Normal file
7
frappe/public/less/controls.less
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.unit-checkbox{
|
||||
color: #36414c;
|
||||
}
|
||||
|
||||
.frappe-control .select-all {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
|
@ -93,6 +93,13 @@ class TestDriver(object):
|
|||
time.sleep(0.2)
|
||||
elem.send_keys(text)
|
||||
|
||||
def set_multicheck(self, fieldname, values):
|
||||
for value in values:
|
||||
path = '//div[@data-fieldname="{0}"]//span[@data-unit="{1}"]'.format(fieldname, value)
|
||||
elem = self.wait_for(xpath=path)
|
||||
time.sleep(0.2)
|
||||
elem.click()
|
||||
|
||||
def set_text_editor(self, fieldname, text):
|
||||
elem = self.wait_for(xpath='//div[@data-fieldname="{0}"]//div[@contenteditable="true"]'.format(fieldname))
|
||||
time.sleep(0.2)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue