require_relative'utils/helpers'moduleCmAdminmoduleModelsclassFilterincludeUtils::Helpersattr_accessor:db_column_name,:filter_type,:placeholder,:collection,:filter_with,:helper_method,:display_nameVALID_FILTER_TYPES=Set[:date,:multi_select,:range,:search,:single_select].freezedefinitialize(db_column_name:,filter_type:,options: {})raiseTypeError,"Can't have array of multiple columns for #{filter_type} filter"ifdb_column_name.is_a?(Array)&&db_column_name.size>1&&!filter_type.to_sym.eql?(:search)raiseArgumentError,"Kindly select a valid filter type like #{VALID_FILTER_TYPES.sort.to_sentence(last_word_connector: ', or ')} instead of #{filter_type} for column #{db_column_name}"unlessVALID_FILTER_TYPES.include?(filter_type.to_sym)@db_column_name,@filter_type=structure_data(db_column_name,filter_type)@filter_with=nilset_default_valuesoptions.eachdo|key,value|send("#{key}=",value)endenddefstructure_data(db_column_name,filter_type)filter_type=filter_type.is_a?(Array)?filter_type[0].to_sym:filter_type.to_symdb_column_name=casefilter_typewhen:search([]<<db_column_name).flatten.map{|x|x.instance_of?(Hash)?x:x.to_sym}elsedb_column_name.is_a?(Array)?db_column_name[0].to_sym:db_column_name.to_symend[db_column_name,filter_type]end# Set default placeholder for the filter.# Date and range filter will not have any placeholder.# Else condition is added for fallback.defset_default_valuesplaceholder=casefilter_typewhen:search'Search'when:single_select,:multi_select"Select/search #{humanized_field_value(db_column_name)}"else"Enter #{humanized_field_value(db_column_name)}"endself.placeholder=placeholderself.display_name=humanized_field_value(db_column_name).titleizeend# Methods to filter the records based on the filter type.class<<selfdeffiltered_data(filter_params,records,filters)iffilter_paramsfilter_params.eachdo|scope_type,scope_value|filter_method=casescope_typewhen'date','range''date_and_range'when'single_select','multi_select''dropdown'elsescope_typeendrecords=send("cm_#{filter_method}_filter",scope_value,records,filters)ifscope_value.present?endendrecordsenddefcm_search_filter(scope_value,records,filters)returnnilifscope_value.blank?table_name=records.table_namefilters.select{|x|xifx.filter_type.eql?(:search)}.eachdo|filter|iffilter.filter_with.present?returnrecords.send(filter.filter_with,scope_value)elsequery_variables=[]filter.db_column_name.eachdo|col|casecolwhenSymbolquery_variables<<"#{table_name.pluralize}.#{col}"whenHashcol.mapdo|key,value|value.map{|val|query_variables<<"#{key.to_s.pluralize}.#{val}"}endendendterms=scope_value.downcase.split(/\s+/)terms=terms.map{|e|(e.gsub('*','%').prepend('%')+'%').gsub(/%+/,'%')}sql=''query_variables.each.with_indexdo|column,i|sql.concat("#{column}::TEXT ILIKE ?")sql.concat(' OR ')unlessquery_variables.size.eql?(i+1)endiffilter.db_column_name.map{|x|x.is_a?(Hash)}.include?(true)associations_hash=filter.db_column_name.select{|x|xifx.is_a?(Hash)}.lastrecords=records.left_joins(associations_hash.keys).distinctendrecords=records.where(terms.map{|term|sql}.join(' AND '),*terms.map{|e|[e]*query_variables.size}.flatten)returnrecordsendendenddefcm_date_and_range_filter(scope_value,records,filters)returnnilifscope_value.nil?scope_value.eachdo|key,value|filters.select{|x|xif[:date,:range].include?(x.filter_type)&&x.db_column_name.to_s==key.to_s}.eachdo|filter|nextunlessvalue.present?value=value.split(' to ')from=value[0].presenceto=value[1].presenceiffilter.filter_with.present?records=records.send(filter.filter_with,from,to)elserecords=records.where(key=>from..to)endendendrecordsenddefcm_dropdown_filter(scope_value,records,filters)returnnilifscope_value.nil?scope_value.eachdo|key,value|filters.select{|x|xif[:single_select,:multi_select].include?(x.filter_type)&&x.db_column_name.to_s==key.to_s}.eachdo|filter|iffilter.filter_with.present?records=records.send(filter.filter_with,value)ifvalue.present?elserecords=records.where(key=>value)ifvalue.present?endendendrecordsendendendendend