mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-26 02:30:21 -06:00
Some browsers don't properly support tri-state checkboxes, so create our own control to handle true/false/null. Fixes #2848
This commit is contained in:
parent
b284572afe
commit
930dd8af1f
@ -13,13 +13,14 @@
|
||||
"10": ["[61,62]", "[61,62]", "json"],
|
||||
"11": ["", "true", "bool"],
|
||||
"12": ["", "[null]", "bool"],
|
||||
"13": ["", "[null]", "text[]"],
|
||||
"14": ["{}", "{}", "text[]"],
|
||||
"15": ["{data,,'',\"\",\\'\\',\\\"\\\"}", "{data,[null],,,'',\"\"}", "text[]"],
|
||||
"16": ["{}", "{}", "int[]"],
|
||||
"17": ["{123,,456}", "{123,[null],456}", "int[]"],
|
||||
"18": ["", "[null]", "boolean[]"],
|
||||
"19": ["{false,,true}", "{false,[null],true}", "boolean[]"]
|
||||
"13": ["", "false", "bool"],
|
||||
"14": ["", "[null]", "text[]"],
|
||||
"15": ["{}", "{}", "text[]"],
|
||||
"16": ["{data,,'',\"\",\\'\\',\\\"\\\"}", "{data,[null],,,'',\"\"}", "text[]"],
|
||||
"17": ["{}", "{}", "int[]"],
|
||||
"18": ["{123,,456}", "{123,[null],456}", "int[]"],
|
||||
"19": ["", "[null]", "boolean[]"],
|
||||
"20": ["{false,,true}", "{false,[null],true}", "boolean[]"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,9 @@ CREATE TABLE public.defaults
|
||||
text_null4 text COLLATE pg_catalog."default",
|
||||
json_defaults json DEFAULT '[51, 52]'::json,
|
||||
json_null json,
|
||||
boolean_defaults boolean DEFAULT true,
|
||||
boolean_true boolean DEFAULT true,
|
||||
boolean_null boolean,
|
||||
boolean_false boolean,
|
||||
text_arr text[],
|
||||
text_arr_empty text[],
|
||||
text_arr_null text[],
|
||||
@ -194,12 +195,17 @@ CREATE TABLE public.defaults
|
||||
self.page.find_by_xpath("//*[contains(@class, 'pg_text_editor')]"
|
||||
"//button[contains(@class, 'fa-save')]").click()
|
||||
else:
|
||||
# Boolean editor test for to True click
|
||||
if data[1] == 'true':
|
||||
checkbox_el = cell_el.find_element_by_xpath(".//input")
|
||||
checkbox_el = cell_el.find_element_by_xpath(".//*[contains(@class, 'multi-checkbox')]")
|
||||
checkbox_el.click()
|
||||
ActionChains(self.driver).move_to_element(checkbox_el).double_click(
|
||||
checkbox_el
|
||||
).perform()
|
||||
# Boolean editor test for to False click
|
||||
elif data[1] == 'false':
|
||||
checkbox_el = cell_el.find_element_by_xpath(".//*[contains(@class, 'multi-checkbox')]")
|
||||
# Sets true
|
||||
checkbox_el.click()
|
||||
# Sets false
|
||||
ActionChains(self.driver).click(checkbox_el).perform()
|
||||
|
||||
def _tables_node_expandable(self):
|
||||
self.page.toggle_open_tree_item(self.server['name'])
|
||||
|
28
web/pgadmin/static/css/bootstrap.overrides.css
vendored
28
web/pgadmin/static/css/bootstrap.overrides.css
vendored
@ -1399,3 +1399,31 @@ body {
|
||||
font-size: 8px;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
/* CSS for custom checkbox editor in SlickGrid */
|
||||
.multi-checkbox .check {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border: 1px solid #333;
|
||||
margin: 3px;
|
||||
text-align: center;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.multi-checkbox .check.unchecked {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.multi-checkbox .check.partial {
|
||||
background: #cccccc;
|
||||
}
|
||||
|
||||
.multi-checkbox .check.checked:after {
|
||||
content: "\2713";
|
||||
}
|
||||
|
||||
.multi-checkbox .check.partial:after {
|
||||
content: "\fe56";
|
||||
}
|
||||
|
@ -12,10 +12,10 @@
|
||||
"pgText": pgTextEditor,
|
||||
"JsonText": JsonTextEditor,
|
||||
"CustomNumber": CustomNumberEditor,
|
||||
"Checkbox": pgCheckboxEditor,
|
||||
// Below editor will read only editors, Just to display data
|
||||
"ReadOnlyText": ReadOnlyTextEditor,
|
||||
"ReadOnlyCheckbox": ReadOnlyCheckboxEditor,
|
||||
"Checkbox": CheckboxEditor, // Override editor to implement checkbox with three states
|
||||
"ReadOnlypgText": ReadOnlypgTextEditor,
|
||||
"ReadOnlyJsonText": ReadOnlyJsonTextEditor
|
||||
}
|
||||
@ -545,7 +545,7 @@
|
||||
*/
|
||||
function CheckboxEditor(args) {
|
||||
var $select, el;
|
||||
var defaultValue;
|
||||
var defaultValue, previousState;
|
||||
var scope = this;
|
||||
|
||||
this.init = function () {
|
||||
@ -564,22 +564,31 @@
|
||||
checkbox_status = 1;
|
||||
}
|
||||
switch(checkbox_status) {
|
||||
// unchecked, going indeterminate
|
||||
// State 0 will come when we had indeterminate state
|
||||
case 0:
|
||||
el.prop('indeterminate', true);
|
||||
el.data('checked', 2); // determines next checkbox status
|
||||
// We will check now
|
||||
el.prop('checked', true);
|
||||
el.data('checked', 1);
|
||||
break;
|
||||
|
||||
// indeterminate, going checked
|
||||
// State 1 will come when we had checked state
|
||||
case 1:
|
||||
el.prop('checked', true);
|
||||
// We will uncheck now
|
||||
el.prop('checked', false);
|
||||
el.data('checked', 2);
|
||||
break;
|
||||
|
||||
// State 2 will come when we had unchecked state
|
||||
case 2:
|
||||
// We will set to indeterminate state
|
||||
el.prop('indeterminate', true);
|
||||
el.data('checked', 0);
|
||||
break;
|
||||
|
||||
// checked, going unchecked
|
||||
// Default, Set to indeterminate state
|
||||
default:
|
||||
el.prop('checked', false);
|
||||
el.data('checked', 1);
|
||||
el.prop('indeterminate', true);
|
||||
el.data('checked', 0);
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -594,18 +603,21 @@
|
||||
|
||||
this.loadValue = function (item) {
|
||||
defaultValue = item[args.column.field];
|
||||
previousState = 0;
|
||||
if (_.isNull(defaultValue)||_.isUndefined(defaultValue)) {
|
||||
$select.prop('indeterminate', true);
|
||||
$select.data('checked', 2);
|
||||
$select.data('checked', 0);
|
||||
}
|
||||
else {
|
||||
defaultValue = !!item[args.column.field];
|
||||
if (defaultValue) {
|
||||
$select.prop('checked', true);
|
||||
$select.data('checked', 0);
|
||||
$select.data('checked', 1);
|
||||
previousState = 1;
|
||||
} else {
|
||||
$select.prop('checked', false);
|
||||
$select.data('checked', 1);
|
||||
$select.data('checked', 2);
|
||||
previousState = 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -622,10 +634,8 @@
|
||||
};
|
||||
|
||||
this.isValueChanged = function () {
|
||||
// var select_value = this.serializeValue();
|
||||
var select_value = $select.data('checked');
|
||||
return (!(select_value === 2 && (defaultValue == null || defaultValue == undefined))) &&
|
||||
(select_value !== defaultValue);
|
||||
var currentState = $select.data('checked');
|
||||
return currentState !== previousState;
|
||||
};
|
||||
|
||||
this.validate = function () {
|
||||
@ -1023,4 +1033,87 @@
|
||||
this.init();
|
||||
}
|
||||
|
||||
// Custom checkbox editor, We need it for runtime as it does not render
|
||||
// indeterminate checkbox state
|
||||
function pgCheckboxEditor(args) {
|
||||
var $select, el;
|
||||
var defaultValue, previousState;
|
||||
var scope = this;
|
||||
|
||||
this.init = function () {
|
||||
$select = $("<div class='multi-checkbox'><span class='check' hideFocus></span></div>");
|
||||
$select.appendTo(args.container);
|
||||
$select.focus();
|
||||
|
||||
// The following code is taken from https://css-tricks.com/indeterminate-checkboxes/
|
||||
$select.bind("click", function (e) {
|
||||
el = $(this);
|
||||
var states = ["unchecked", "partial", "checked"];
|
||||
var curState = el.find(".check").data("state");
|
||||
curState++;
|
||||
el.find(".check")
|
||||
.removeClass("unchecked partial checked")
|
||||
.addClass(states[curState % states.length])
|
||||
.data("state", curState % states.length);
|
||||
});
|
||||
};
|
||||
|
||||
this.destroy = function () {
|
||||
$select.remove();
|
||||
};
|
||||
|
||||
this.focus = function () {
|
||||
$select.focus();
|
||||
};
|
||||
|
||||
this.loadValue = function (item) {
|
||||
defaultValue = item[args.column.field];
|
||||
previousState = 1;
|
||||
if (_.isNull(defaultValue)||_.isUndefined(defaultValue)) {
|
||||
$select.find(".check").data("state", 1).addClass("partial");
|
||||
}
|
||||
else {
|
||||
defaultValue = !!item[args.column.field];
|
||||
if (defaultValue) {
|
||||
$select.find(".check").data("state", 2).addClass("checked");
|
||||
previousState = 2;
|
||||
} else {
|
||||
$select.find(".check").data("state", 0).addClass("unchecked");
|
||||
previousState = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.serializeValue = function () {
|
||||
if ($select.find(".check").data("state") == 1) {
|
||||
return null;
|
||||
}
|
||||
return $select.find(".check").data("state") == 2 ? true : false;
|
||||
};
|
||||
|
||||
this.applyValue = function (item, state) {
|
||||
item[args.column.field] = state;
|
||||
};
|
||||
|
||||
this.isValueChanged = function () {
|
||||
var currentState = $select.find(".check").data("state");
|
||||
return currentState !== previousState;
|
||||
};
|
||||
|
||||
this.validate = function () {
|
||||
if (args.column.validator) {
|
||||
var validationResults = args.column.validator(this.serializeValue());
|
||||
if (!validationResults.valid) {
|
||||
return validationResults;
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: true,
|
||||
msg: null
|
||||
};
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
Loading…
Reference in New Issue
Block a user