From 21f2dd5896e5685f8213cfcb1173ffc696e57425 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 19 Jan 2022 18:55:27 +1100 Subject: [PATCH 1/3] Use modal "depth" to construct form fields - Top level modals are not changed --- InvenTree/templates/js/translated/forms.js | 52 ++++++++++++++++------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index 43e8d5ce62..e9e03f04fc 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -835,7 +835,9 @@ function updateFieldValue(name, value, field, options) { // Find the named field element in the modal DOM function getFormFieldElement(name, options) { - var el = $(options.modal).find(`#id_${name}`); + var field_name = getFieldName(name, options); + + var el = $(options.modal).find(`#id_${field_name}`); if (!el.exists) { console.log(`ERROR: Could not find form element for field '${name}'`); @@ -1148,7 +1150,9 @@ function handleFormErrors(errors, fields, options) { /* * Add a rendered error message to the provided field */ -function addFieldErrorMessage(field_name, error_text, error_idx, options) { +function addFieldErrorMessage(name, error_text, error_idx, options) { + + field_name = getFieldName(name, options); // Add the 'form-field-error' class $(options.modal).find(`#div_id_${field_name}`).addClass('form-field-error'); @@ -1226,7 +1230,9 @@ function addClearCallbacks(fields, options) { function addClearCallback(name, field, options) { - var el = $(options.modal).find(`#clear_${name}`); + var field_name = getFieldName(name, options); + + var el = $(options.modal).find(`#clear_${field_name}`); if (!el) { console.log(`WARNING: addClearCallback could not find field '${name}'`); @@ -1376,6 +1382,8 @@ function addSecondaryModal(field, fields, options) { var name = field.name; + var depth = options.depth || 0; + var secondary = field.secondary; var html = ` @@ -1419,6 +1427,8 @@ function addSecondaryModal(field, fields, options) { // Method should be "POST" for creation secondary.method = secondary.method || 'POST'; + secondary.depth = depth + 1; + constructForm( url, secondary @@ -1757,6 +1767,20 @@ function renderModelData(name, model, data, parameters, options) { } +/* + * Construct a field name for the given field + */ +function getFieldName(name, options) { + var field_name = name; + + if (options.depth) { + field_name += `_${options.depth}`; + } + + return field_name; +} + + /* * Construct a single form 'field' for rendering in a form. * @@ -1783,7 +1807,7 @@ function constructField(name, parameters, options) { return constructCandyInput(name, parameters, options); } - var field_name = `id_${name}`; + var field_name = getFieldName(name, options); // Hidden inputs are rendered without label / help text / etc if (parameters.hidden) { @@ -1803,6 +1827,8 @@ function constructField(name, parameters, options) { var group = parameters.group; + var group_id = getFieldName(group, options); + var group_options = options.groups[group] || {}; // Are we starting a new group? @@ -1810,12 +1836,12 @@ function constructField(name, parameters, options) { if (parameters.group != options.current_group) { html += ` -
-
`; +
+
`; if (group_options.collapsible) { html += ` -
- + -
+
`; } @@ -1848,7 +1874,7 @@ function constructField(name, parameters, options) { html += parameters.before; } - html += `
`; + html += `
`; // Add a label if (!options.hideLabels) { @@ -1886,13 +1912,13 @@ function constructField(name, parameters, options) { } } - html += constructInput(name, parameters, options); + html += constructInput(field_name, parameters, options); if (extra) { if (!parameters.required) { html += ` - + `; } @@ -1909,7 +1935,7 @@ function constructField(name, parameters, options) { } // Div for error messages - html += `
`; + html += `
`; html += `
`; // controls From 3c328feb658b947b497fc6e07236635b7b8def6b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 19 Jan 2022 19:03:47 +1100 Subject: [PATCH 2/3] Donate keyboard focus when creating a secondary modal --- InvenTree/templates/js/translated/forms.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index e9e03f04fc..4e6e2fd162 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -1424,6 +1424,11 @@ function addSecondaryModal(field, fields, options) { }; } + // Relinquish keyboard focus for this modal + $(options.modal).modal({ + keyboard: false, + }); + // Method should be "POST" for creation secondary.method = secondary.method || 'POST'; From 9ffcdbc4172844cbb23bdd785ac74aa53f631166 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 19 Jan 2022 19:18:20 +1100 Subject: [PATCH 3/3] Fix issues when re-opening a secondary modal --- InvenTree/templates/js/translated/forms.js | 19 ++++++++++--------- InvenTree/templates/js/translated/modals.js | 3 +++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index 4e6e2fd162..50ae39df2f 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -1380,23 +1380,23 @@ function initializeRelatedFields(fields, options) { */ function addSecondaryModal(field, fields, options) { - var name = field.name; + var field_name = getFieldName(field.name, options); var depth = options.depth || 0; - var secondary = field.secondary; - var html = ` -
- ${secondary.label || secondary.title} +
+ ${field.secondary.label || field.secondary.title}
`; - $(options.modal).find(`label[for="id_${name}"]`).append(html); + $(options.modal).find(`label[for="id_${field_name}"]`).append(html); // Callback function when the secondary button is pressed - $(options.modal).find(`#btn-new-${name}`).click(function() { + $(options.modal).find(`#btn-new-${field_name}`).click(function() { + + var secondary = field.secondary; // Determine the API query URL var url = secondary.api_url || field.api_url; @@ -1417,8 +1417,7 @@ function addSecondaryModal(field, fields, options) { // Force refresh from the API, to get full detail inventreeGet(`${url}${data.pk}/`, {}, { success: function(responseData) { - - setRelatedFieldData(name, responseData, options); + setRelatedFieldData(field.name, responseData, options); } }); }; @@ -1432,6 +1431,8 @@ function addSecondaryModal(field, fields, options) { // Method should be "POST" for creation secondary.method = secondary.method || 'POST'; + secondary.modal = null; + secondary.depth = depth + 1; constructForm( diff --git a/InvenTree/templates/js/translated/modals.js b/InvenTree/templates/js/translated/modals.js index ad5e1c2742..539ce61912 100644 --- a/InvenTree/templates/js/translated/modals.js +++ b/InvenTree/templates/js/translated/modals.js @@ -127,6 +127,9 @@ function createNewModal(options={}) { $(modal_name).find('#modal-form-cancel').hide(); } + // Steal keyboard focus + $(modal_name).focus(); + // Return the "name" of the modal return modal_name; }