diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 592bef396a..74b3b63169 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -730,6 +730,13 @@ padding: 10px; } +.form-panel { + border-radius: 5px; + border: 1px solid #ccc; + padding: 5px; +} + + .modal input { width: 100%; } diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index b149fd28ed..af07952a7e 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -276,6 +276,7 @@ constructForm('{% url "api-part-list" %}', { method: 'POST', fields: fields, + groups: partGroups(), title: '{% trans "Create Part" %}', onSuccess: function(data) { // Follow the new part diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js index 4b41623fbf..914eb93dec 100644 --- a/InvenTree/templates/js/translated/forms.js +++ b/InvenTree/templates/js/translated/forms.js @@ -264,6 +264,10 @@ function constructForm(url, options) { // Default HTTP method options.method = options.method || 'PATCH'; + // Default "groups" definition + options.groups = options.groups || {}; + options.current_group = null; + // Construct an "empty" data object if not provided if (!options.data) { options.data = {}; @@ -413,6 +417,11 @@ function constructFormBody(fields, options) { fields[field].choices = field_options.choices; } + // Group + if (field_options.group) { + fields[field].group = field_options.group; + } + // Field prefix if (field_options.prefix) { fields[field].prefix = field_options.prefix; @@ -465,8 +474,12 @@ function constructFormBody(fields, options) { html += constructField(name, field, options); } - // TODO: Dynamically create the modals, - // so that we can have an infinite number of stacks! + if (options.current_group) { + // Close out the current group + html += ``; + + console.log(`finally, ending group '${console.current_group}'`); + } // Create a new modal if one does not exists if (!options.modal) { @@ -535,6 +548,8 @@ function constructFormBody(fields, options) { submitFormData(fields, options); } }); + + initializeGroups(fields, options); } @@ -960,6 +975,49 @@ function addClearCallback(name, field, options) { } +// Initialize callbacks and initial states for groups +function initializeGroups(fields, options) { + + var modal = options.modal; + + // Callback for when the group is expanded + $(modal).find('.form-panel-content').on('show.bs.collapse', function() { + + var panel = $(this).closest('.form-panel'); + var group = panel.attr('group'); + + var icon = $(modal).find(`#group-icon-${group}`); + + icon.removeClass('fa-angle-right'); + icon.addClass('fa-angle-up'); + }); + + // Callback for when the group is collapsed + $(modal).find('.form-panel-content').on('hide.bs.collapse', function() { + + var panel = $(this).closest('.form-panel'); + var group = panel.attr('group'); + + var icon = $(modal).find(`#group-icon-${group}`); + + icon.removeClass('fa-angle-up'); + icon.addClass('fa-angle-right'); + }); + + // Set initial state of each specified group + for (var group in options.groups) { + + var group_options = options.groups[group]; + + if (group_options.collapsed) { + $(modal).find(`#form-panel-content-${group}`).collapse("hide"); + } else { + $(modal).find(`#form-panel-content-${group}`).collapse("show"); + } + } +} + + function initializeRelatedFields(fields, options) { var field_names = options.field_names; @@ -1353,6 +1411,8 @@ function renderModelData(name, model, data, parameters, options) { */ function constructField(name, parameters, options) { + var html = ''; + // Shortcut for simple visual fields if (parameters.type == 'candy') { return constructCandyInput(name, parameters, options); @@ -1365,13 +1425,62 @@ function constructField(name, parameters, options) { return constructHiddenInput(name, parameters, options); } + // Are we ending a group? + if (options.current_group && parameters.group != options.current_group) { + html += ``; + + console.log(`ending group '${options.current_group}'`); + + // Null out the current "group" so we can start a new one + options.current_group = null; + } + + // Are we starting a new group? + if (parameters.group) { + + var group = parameters.group; + + var group_options = options.groups[group] || {}; + + // Are we starting a new group? + // Add HTML for the start of a separate panel + if (parameters.group != options.current_group) { + + console.log(`starting group '${group}'`); + + html += ` +