diff --git a/assets/javascripts/discourse/services/user-field-validations.js b/assets/javascripts/discourse/services/user-field-validations.js index a9607ed..34fa1ea 100644 --- a/assets/javascripts/discourse/services/user-field-validations.js +++ b/assets/javascripts/discourse/services/user-field-validations.js @@ -9,8 +9,27 @@ export default class UserFieldValidations extends Service { @tracked totalCustomValidationFields = 0; currentCustomValidationFieldCount = 0; + constructor() { + super(...arguments); + + this._initializeOriginallyRequired(); + } + + _initializeOriginallyRequired() { + this.site?.user_fields?.forEach((field) => { + if (field.has_custom_validation && field.originally_required === undefined) { + field.originally_required = field.required; + } + }); + } + @action setValidation(userField, value) { + // Initialize originally_required for userField if not done yet + if (userField.originally_required === undefined) { + userField.originally_required = userField.required; + } + this._bumpTotalCustomValidationFields(); if ( @@ -59,12 +78,26 @@ export default class UserFieldValidations extends Service { .toLowerCase() .replace(/\s+/g, "-")}`; const userFieldElement = document.querySelector(`.${className}`); + + // Save original required value on first call + if (userField.originally_required === undefined) { + userField.originally_required = userField.required; + } + if (userFieldElement && !shouldShow) { // Clear and hide nested fields userFieldElement.style.display = "none"; this._clearUserField(userField); + + // Remove required for hidden field + userField.required = false; } else { userFieldElement.style.display = ""; + + //Restore original required for visible field + if (userField.originally_required !== undefined) { + userField.required = userField.originally_required; + } } }); } diff --git a/plugin.rb b/plugin.rb index a20dac7..9a4d6b5 100644 --- a/plugin.rb +++ b/plugin.rb @@ -19,6 +19,10 @@ module ::DiscourseAuthenticationValidations require_relative "lib/discourse_authentication_validations/engine" after_initialize do + class ::DiscourseAuthenticationValidations::Current < ActiveSupport::CurrentAttributes + attribute :user_fields_params + end + add_to_serializer(:user_field, :has_custom_validation) { object.has_custom_validation } add_to_serializer(:user_field, :show_values) { object.show_values } add_to_serializer(:user_field, :target_user_field_ids) { object.target_user_field_ids } @@ -33,4 +37,62 @@ module ::DiscourseAuthenticationValidations ) columns end + + # Add helper method for UserField - check if field should be hidden + class ::UserField + def should_be_hidden? + # Get user_fields_params from CurrentAttributes + user_fields_params = DiscourseAuthenticationValidations::Current.user_fields_params + return false unless user_fields_params.present? + + # Find all parent fields that have THIS field (self) in target_user_field_ids + parent_fields = UserField.where("? = ANY(target_user_field_ids)", self.id) + + # If no parent fields with custom validation - field is not hidden + return false if parent_fields.empty? + + parent_fields.any? do |parent_field| + # Skip if parent doesn't have custom validation + next unless parent_field.has_custom_validation + + # Get parent field value from user_fields_params + parent_value = user_fields_params[parent_field.id.to_s] + + # If parent field value is NOT in show_values - field should be hidden + !parent_field.show_values.include?(parent_value.to_s) + end + end + end + + # Minimally invasive UsersController patch via prepend + module UsersControllerHiddenFieldsPatch + def create + # Save user_fields to CurrentAttributes (automatically cleaned up after request) + if params[:user_fields].present? + DiscourseAuthenticationValidations::Current.user_fields_params = params[:user_fields] + Rails.logger.info("[discourse-authentication-validations] Saved user_fields for validation") + end + + # Call original method + super + end + end + + # Patch UserField#required? to check should_be_hidden + class ::UserField + alias_method :original_required?, :required? + + def required? + # If field should be hidden - ignore required + if should_be_hidden? + return false + end + + # Otherwise use original method + original_required? + end + end + + require_dependency 'users_controller' + ::UsersController.prepend(UsersControllerHiddenFieldsPatch) end