diff --git a/misc/yaml_to_json.py b/misc/yaml_to_json.py index a7d5bd62a7a1ccc50766b797ef6710466e9bee11..e77e5efc56b2cea39b0a7b6f90236fb5b39da24e 100755 --- a/misc/yaml_to_json.py +++ b/misc/yaml_to_json.py @@ -6,4 +6,4 @@ import json import yaml with open(sys.argv[1], 'r') as infile: - print(json.dumps(yaml.load(infile))) + print(json.dumps(yaml.safe_load(infile))) diff --git a/src/core/js/form_elements.js b/src/core/js/form_elements.js index d4cd4234a28953140fcc1f62104e2c43a3460cdb..006edcfa0b89903e2f566d73c459c5fb51bc4fd5 100644 --- a/src/core/js/form_elements.js +++ b/src/core/js/form_elements.js @@ -118,7 +118,7 @@ var form_elements = new function () { this.get_cache_value = function (field) { var ret = $(field) .find(":input") - .val(); + .val() if (!ret) { return null; } else { @@ -293,12 +293,15 @@ var form_elements = new function () { if (typeof desc == "undefined") { desc = entity_id; } - var opt_str = '<option value="' + entity_id + '">' + desc + + return form_elements._make_option(entity_id, desc); + } + + this._make_option = function(value, label) { + const opt_str = '<option value="' + value + '">' + label + "</option>"; return $(opt_str)[0]; } - /** * (Re-)set this module's functions to standard implementation. */ @@ -333,12 +336,7 @@ var form_elements = new function () { caosdb_utils.assert_type(make_value, "function", "param `make_value`"); } - const ret = $('<select class="selectpicker form-control" title="Nothing selected"/>'); - if (multiple) { - ret.attr("multiple", ""); - } else { - ret.append('<option style="display: none" selected="selected" value="" disabled="disabled"></option>'); - } + const ret = $(form_elements._make_select(multiple)); for (let entity of entities) { this.logger.trace("add option", entity); let entity_id = getEntityID(entity); @@ -351,6 +349,16 @@ var form_elements = new function () { return ret[0]; } + this._make_select = function (multiple) { + const ret = $('<select class="selectpicker form-control" title="Nothing selected"/>'); + if (multiple) { + ret.attr("multiple", ""); + } else { + ret.append('<option style="display: none" selected="selected" value="" disabled="disabled"></option>'); + } + return ret[0]; + } + /** * Configuration object for a drop down menu for selecting references. * `make_reference_drop_down` generates such a drop down menu using a @@ -673,6 +681,8 @@ var form_elements = new function () { field = await this.make_range_input(config); } else if (type === "reference_drop_down") { field = this.make_reference_drop_down(config); + } else if (type === "select") { + field = this.make_select_input(config); } else if (type === "subform") { // TODO handle cache and required for subforms return await this.make_subform(config); @@ -1223,6 +1233,32 @@ var form_elements = new function () { } + /** + * Return a select field. + * + * @param {form_elements.input_config} config + * @returns {HTMLElement} a select field. + */ + this.make_select_input = function (config) { + const options = config.options; + const multiple = config.multiple; + const select = $(form_elements._make_select(multiple)); + for (let option of options) { + select.append(form_elements._make_option(option.value, option.label)); + } + + const ret = $(form_elements._make_field_wrapper(config.name)); + const label = form_elements._make_input_label_str(config); + select.change(function () { + ret[0].dispatchEvent(form_elements.field_changed_event); + }); + + const input_col = $('<div class="caosdb-f-property-value col-sm-9"/>'); + input_col.append(select); + return ret.append(label, input_col)[0]; + } + + /** * Return a checkbox input field. * diff --git a/test/core/js/modules/form_elements.js.js b/test/core/js/modules/form_elements.js.js index f8bf1ed1ac1495a8a3688aeb7b0cce387c8b69fb..1fc734cd26881416338add2b7ca4a243495829a9 100644 --- a/test/core/js/modules/form_elements.js.js +++ b/test/core/js/modules/form_elements.js.js @@ -628,4 +628,52 @@ QUnit.test("make_alert - remember", async function(assert) { assert.equal(typeof _alert, "undefined", "alert was not created, proceed callback was called third time"); }); +QUnit.test("make_select_input", function(assert) { + const config = { + name: "sex", label: "Sex", multiple: true, options: [ + {"value": "f", "label": "female"}, + {"value": "d", "label": "diverse"}, + {"value": "m", "label": "male"}, + ], + } + const select = $(form_elements.make_select_input(config)); + assert.equal(select.find("select").length, 1, "select input there"); + assert.equal(select.find("select option").length, 3, "three options there"); +}); + +QUnit.test("select_input caching", async function (assert) { + const config = { + "name": "test-form", + "fields": [ + { + type: "select", + required: true, + cached: true, + name: "sex", + label: "Sex", + options: [ + {"value": "f", "label": "female"}, + {"value": "d", "label": "diverse"}, + {"value": "m", "label": "male"}, + ], + }, + ], + } + const form_wrapper = $(form_elements.make_form(config)); + await sleep(500); + const form = form_wrapper.find("form"); + assert.equal(form.find("select").length, 1); + assert.equal(xml2str(form[0]), ""); + + + var cache = {}; + var field = $(form_elements.get_fields(form[0], "sex")); + field.find("select").val("f"); + assert.equal(form_elements.get_cache_value(field[0]), "f", "value set"); + assert.equal(form_elements.get_cache_key(form[0], field[0]), "form_elements.cache.test-form.sex", "cache key correct"); + + form_elements.cache_form(cache, form[0]); + assert.equal(cache[form_elements.get_cache_key(form[0], field[0])], "f"); +}); + }