From 015aafe0fbe8de86f5d72dd7e45b2c02e16d4ade Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 30 Jan 2017 13:57:13 -0800 Subject: [PATCH] make table additions in DS settings clearer --- domain-server/resources/web/css/style.css | 4 + .../resources/web/settings/js/settings.js | 249 +++++++++++------- 2 files changed, 162 insertions(+), 91 deletions(-) diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index ad426671a4..553f408e15 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -125,6 +125,10 @@ tr.new-row { background-color: #dff0d8; } +tr.invalid-input { + background-color: #f2dede; +} + .graphable-stat { text-align: center; color: #5286BC; diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index 659372267c..fbc2aefceb 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -38,14 +38,15 @@ var Settings = { DOMAIN_ID_SELECTOR: '[name="metaverse.id"]', ACCESS_TOKEN_SELECTOR: '[name="metaverse.access_token"]', PLACES_TABLE_ID: 'places-table', - FORM_ID: 'settings-form' + FORM_ID: 'settings-form', + INVALID_ROW_CLASS: 'invalid-input' }; var viewHelpers = { getFormGroup: function(keypath, setting, values, isAdvanced) { form_group = "
"; setting_value = _(values).valueForKeyPath(keypath); @@ -891,23 +892,105 @@ function reloadSettings(callback) { }); } +function validateInputs() { + // check if any new values are bad + var tables = $('table'); + + var inputsValid = true; + + var tables = $('table'); + + // clear any current invalid rows + $('tr.' + Settings.INVALID_ROW_CLASS).removeClass(Settings.INVALID_ROW_CLASS); + + function markParentRowInvalid(rowChild) { + $(rowChild).closest('tr').addClass(Settings.INVALID_ROW_CLASS); + } + + _.each(tables, function(table) { + var inputs = $(table).find('tr.' + Settings.NEW_ROW_CLASS + ' input[data-changed="true"]'); + + var empty = false; + + _.each(inputs, function(input){ + var inputVal = $(input).val(); + + if (inputVal.length === 0) { + empty = true + markParentRowInvalid(input); + return; + } + }); + + if (empty) { + showErrorMessage("Error", "Empty field(s)"); + inputsValid = false; + return + } + + // validate keys specificially for spaces and equality to an existing key + var newKeys = $(table).find('tr.' + Settings.NEW_ROW_CLASS + ' td.key'); + + var keyWithSpaces = false; + var duplicateKey = false; + + _.each(newKeys, function(keyCell) { + var keyVal = $(keyCell).children('input').val(); + + if (keyVal.indexOf(' ') !== -1) { + keyWithSpaces = true; + markParentRowInvalid(keyCell); + return; + } + + // make sure we don't have duplicate keys in the table + var otherKeys = $(table).find('td.key').not(keyCell); + _.each(otherKeys, function(otherKeyCell) { + var keyInput = $(otherKeyCell).children('input'); + + if (keyInput.length) { + if ($(keyInput).val() == keyVal) { + duplicateKey = true; + } + } else if ($(otherKeyCell).html() == keyVal) { + duplicateKey = true; + } + + if (duplicateKey) { + markParentRowInvalid(keyCell); + return; + } + }); + + }); + + if (keyWithSpaces) { + showErrorMessage("Error", "Key contains spaces"); + inputsValid = false; + return + } + + if (duplicateKey) { + showErrorMessage("Error", "Two keys cannot be identical"); + inputsValid = false; + return; + } + }); + + return inputsValid; +} var SETTINGS_ERROR_MESSAGE = "There was a problem saving domain settings. Please try again!"; function saveSettings() { - // disable any inputs not changed - $("input:not([data-changed])").each(function(){ - $(this).prop('disabled', true); - }); - // grab a JSON representation of the form via form2js - var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); - - // check if we've set the basic http password - if so convert it to base64 + // verify that the password and confirmation match before saving var canPost = true; + if (formJSON["security"]) { var password = formJSON["security"]["http_password"]; var verify_password = formJSON["security"]["verify_http_password"]; + if (password && password.length > 0) { if (password != verify_password) { bootbox.alert({"message": "Passwords must match!", "title":"Password Error"}); @@ -919,23 +1002,46 @@ function saveSettings() { } } - console.log("----- SAVING ------"); - console.log(formJSON); + if (canPost && validateInputs()) { + // POST the form JSON to the domain-server settings.json endpoint so the settings are saved - // re-enable all inputs - $("input").each(function(){ - $(this).prop('disabled', false); - }); + // disable any inputs not changed + $("input:not([data-changed])").each(function(){ + $(this).prop('disabled', true); + }); - // remove focus from the button - $(this).blur(); + // grab a JSON representation of the form via form2js + var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); - // POST the form JSON to the domain-server settings.json endpoint so the settings are saved - if (canPost) { + // check if we've set the basic http password - if so convert it to base64 + if (formJSON["security"]) { + var password = formJSON["security"]["http_password"]; + if (password && password.length > 0) { + formJSON["security"]["http_password"] = sha256_digest(password); + } + } + + console.log("----- SAVING ------"); + console.log(formJSON); + + // re-enable all inputs + $("input").each(function(){ + $(this).prop('disabled', false); + }); + + // remove focus from the button + $(this).blur(); + + // POST the form JSON to the domain-server settings.json endpoint so the settings are saved postSettings(formJSON); } } +// disable any inputs not changed +$("input:not([data-changed])").each(function(){ + $(this).prop('disabled', true); +}); + $('body').on('click', '.save-button', function(e){ saveSettings(); return false; @@ -1110,8 +1216,9 @@ function makeTable(setting, keypath, setting_value) { if (setting.can_add_new_categories) { html += makeTableCategoryInput(setting, numVisibleColumns); } + if (setting.can_add_new_rows || setting.can_add_new_categories) { - html += makeTableInputs(setting, {}, ""); + html += makeTableHiddenInputs(setting, {}, ""); } } html += "" @@ -1137,7 +1244,7 @@ function makeTableCategoryHeader(categoryKey, categoryValue, numVisibleColumns, return html; } -function makeTableInputs(setting, initialValues, categoryValue) { +function makeTableHiddenInputs(setting, initialValues, categoryValue) { var html = ""; @@ -1148,7 +1255,7 @@ function makeTableInputs(setting, initialValues, categoryValue) { if (setting.key) { html += "\ - \ + \ " } @@ -1157,14 +1264,14 @@ function makeTableInputs(setting, initialValues, categoryValue) { if (col.type === "checkbox") { html += "" + - "" + ""; } else { html += "" + - "" + ""; @@ -1244,49 +1351,17 @@ function addTableRow(row) { var columns = row.parent().children('.' + Settings.DATA_ROW_CLASS); + var input_clone = row.clone(); + if (!isArray) { - // Check key spaces - var key = row.children(".key").children("input").val() - if (key.indexOf(' ') !== -1) { - showErrorMessage("Error", "Key contains spaces") - return - } - // Check keys with the same name - var equals = false; - _.each(columns.children(".key"), function(element) { - if ($(element).text() === key) { - equals = true - return - } - }) - if (equals) { - showErrorMessage("Error", "Two keys cannot be identical") - return - } + // show the key input + var keyInput = row.children(".key").children("input"); } - // Check empty fields - var empty = false; - _.each(row.children('.' + Settings.DATA_COL_CLASS + ' input'), function(element) { - if ($(element).val().length === 0) { - empty = true - return - } - }) - - if (empty) { - showErrorMessage("Error", "Empty field(s)") - return - } - - var input_clone = row.clone() - // Change input row to data row - var table = row.parents("table") - var setting_name = table.attr("name") - var full_name = setting_name + "." + key - row.addClass(Settings.DATA_ROW_CLASS + " " + Settings.NEW_ROW_CLASS) - row.removeClass("inputs") + var table = row.parents("table"); + var setting_name = table.attr("name"); + row.addClass(Settings.DATA_ROW_CLASS + " " + Settings.NEW_ROW_CLASS); _.each(row.children(), function(element) { if ($(element).hasClass("numbered")) { @@ -1308,34 +1383,17 @@ function addTableRow(row) { anchor.addClass(Settings.DEL_ROW_SPAN_CLASSES) } else if ($(element).hasClass("key")) { var input = $(element).children("input") - $(element).html(input.val()) - input.remove() + input.show(); } else if ($(element).hasClass(Settings.DATA_COL_CLASS)) { - // Hide inputs - var input = $(element).find("input") - var isCheckbox = false; - var isTime = false; - if (input.hasClass("table-checkbox")) { - input = $(input).parent(); - isCheckbox = true; - } else if (input.hasClass("table-time")) { - input = $(input).parent(); - isTime = true; - } + // show inputs + var input = $(element).find("input"); + input.show(); - var val = input.val(); - if (isCheckbox) { - // don't hide the checkbox - val = $(input).find("input").is(':checked'); - } else if (isTime) { - // don't hide the time - } else { - input.attr("type", "hidden") - } + var isCheckbox = input.hasClass("table-checkbox"); if (isArray) { var row_index = row.siblings('.' + Settings.DATA_ROW_CLASS).length - var key = $(element).attr('name') + var key = $(element).attr('name'); // are there multiple columns or just one? // with multiple we have an array of Objects, with one we have an array of whatever the value type is @@ -1347,17 +1405,21 @@ function addTableRow(row) { input.attr("name", setting_name + "[" + row_index + "]" + (num_columns > 1 ? "." + key : "")) } } else { - input.attr("name", full_name + "." + $(element).attr("name")) + // because the name of the setting in question requires the key + // setup a hook to change the HTML name of the element whenever the key changes + var colName = $(element).attr("name"); + keyInput.on('change', function(){ + input.attr("name", setting_name + "." + $(this).val() + "." + colName); + }); } if (isCheckbox) { $(input).find("input").attr("data-changed", "true"); } else { input.attr("data-changed", "true"); - $(element).append(val); } } else { - console.log("Unknown table element") + console.log("Unknown table element"); } }); @@ -1387,7 +1449,12 @@ function deleteTableRow($row) { $row.empty(); if (!isArray) { - $row.html(""); + if ($row.attr('name')) { + $row.html(""); + } else { + // for rows that didn't have a key, simply remove the row + $row.remove(); + } } else { if ($table.find('.' + Settings.DATA_ROW_CLASS + "[data-category='" + categoryName + "']").length <= 1) { // This is the last row of the category, so delete the header