module Anoubis module Core module Data ## # Module gets system data for {DataController} module Get ## # Get frame buttons data based on passed arguments. # @param [Hash] args additional parameters are used for define frame buttons. # @option args [String] :tab tab is used for generation buttons # @return [Hash] returns resulting button hash def get_frame_buttons(args = {}) buttons = self.frame_buttons(args) buttons.each do |key, button| buttons[key] = self.get_frame_button key, button end buttons end ## # Get frame button # @param [String] key button identificator # @param [Hash] button initial button options # @option button [String] :type ('default') type of the button ('primary', 'danger', 'default') # @option button [String] :mode ('single') button action object ('single', 'multiple') # @option button [String] :title title of the frame. If title isn't defined then system is trying to take # value from yml translation file at path [..frame.buttons..title] (eg. # *en.anubis.tenants.frame.buttons.new.title* for english language 'anubis/tenants' controller 'new' button). # If path absents then value isn't set. # @option button [String] :hint hint of the frame. If hint isn't defined then system is trying to take # value from yml translation file at path [..frame.buttons..hint] (eg. # *en.anubis.tenants.frame.buttons.new.hint* for english language 'anubis/tenants' controller 'new' button). # If path absents then value isn't set. # @return [Hash] resulting button options def get_frame_button(key, button) button[:key] = key.to_s button[:type] = 'default' unless button.has_key? :type button[:mode] = 'single' unless button.has_key? :mode button[:decoration] = 'none' unless button.has_key? :decoration text = I18n.t('.buttons.'+button[:key]+'.title', default: '') button[:title] = text if text != '' text = I18n.t('.buttons.'+button[:key]+'.hint', default: '') button[:hint] = text if text != '' button end ## # Get tab parameters # @param [String] tab identifier # @param [Hash] options initial tab options # @option options [String] :title title of the frame. If title isn't defined then value is taken from yml # translation file at path [..frame.tabs..title] (eg. # *en.anubis.tenants.frame.tabs.all.title* for english language 'anubis/tenants' controller 'all' tab). # If path absents then value is set into humanized form of tab identifier (eg. 'All' for 'all' tab). # @option options [String] :hint hint of the frame. If hint isn't defined then system is trying to take # value from yml translation file at path [..frame.tabs..hint] (eg. # *en.anubis.tenants.frame.tabs.all.hint* for english language 'anubis/tenants' controller 'all' tab). # If path absents then value isn't set. def get_tab(tab, options = {}) options[:tab] = tab.to_s options[:title] = I18n.t('.tabs.'+options[:tab]+'.title', default: options[:tab].humanize) if !options.key? :title if !options.has_key? :hint hint = I18n.t('.tabs.'+options[:tab]+'.hint', default: '') options[:hint] = hint if hint != '' end if options.key? :export options[:export] = true if options[:export].class != FalseClass else options[:export] = self.is_export({ tab: tab.to_s }) end if options.key? :filter options[:filter] = true if options[:filter].class != FalseClass else options[:filter] = self.is_filter({ tab: tab.to_s }) end options[:buttons] = self.get_frame_buttons({ tab: options[:tab] }) #options[:where] = self.where if !options.key? :where options end ## # Get model that is used for controller action def get_model return self.etc.data.model if self.etc.data.model if defined? self.model self.etc.data.model = self.model self.etc.data.eager_load = self.eager_load end return self.etc.data.model end ## # Get default eager load definition for controller action def get_eager_load return self.etc.data.eager_load if self.etc.data.model self.get_model return self.etc.data.eager_load end ## # Get where for controller action fro defined tab def get_tab_where return self.etc.tab.where if self.etc.tab.where [] end ## # Get where for controller action def get_where self.where end def get_tenant_where(model) return { tenant_id: self.current_user.tenant_id } if model.new.respond_to? :tenant_id return {} end def get_filter_where #puts 'get_filter_where!' #puts self.etc.data.filter.to_h return if self.etc.data.filter filter = {} if params.key? :filter begin filter = JSON.parse(params[:filter]).with_indifferent_access.to_h rescue filter = {} end end self.setup_fields #puts 'get_filter_where' #puts self.etc.data.fields self.etc.data.filter = Anoubis::Etc::Filter.new({ data: filter, fields: self.etc.data.fields }) #puts self.etc.data.filter.to_h end def get_filter_where_hash self.get_filter_where return self.etc.data.filter.hash end def get_filter_where_array self.get_filter_where return self.etc.data.filter.array end ## # @!group Block of table data getters ## # Get total number of rows in defined model. Also sets additional system properties {Etc::Data#limit self.etc.data.limit}, # {Etc::Data#offset self.etc.data.offset} and {Etc::Data#count self.etc.data.count} # @return [Integer] the total number of rows. def get_table_data_count self.load_table_data_count self.etc.data.limit = params[:limit] if params.has_key? :limit self.etc.data.offset = params[:offset] if params.has_key? :offset if self.etc.data.offset >= self.etc.data.count if self.etc.data.count > 0 self.etc.data.offset = ((self.etc.data.count-1) / self.etc.data.limit).truncate * self.etc.data.limit else self.etc.data.offset = 0 end end self.etc.data.count end ## # Returns fields for table output. # @return [Hash] calculated hash for fields properties for current action def get_fields_properties(fields = nil) fields = fields_order if !fields result = [] fields.each do |value| if self.etc.data.fields if self.etc.data.fields.key? value.to_sym result.push self.etc.data.fields[value.to_sym].properties(self.etc.data.model, self.etc.action) if self.etc.data.fields[value.to_sym].visible end end end result end ## # Returns fields for filter form. # @return [Hash] calculated hash for fields properties for current action def get_filter_properties fields = filter_order self.get_fields_properties fields end ## # Load data into the system variable {Etc::Data#data self.etc.data.data} and return fields defined in controller. def get_table_data self.load_table_data self.etc.data.limit, self.etc.data.offset data = [] if self.etc.data.data self.etc.data.data.each do |row| data.push get_data_row row end end data end ## # Get data fields defined in custom controller for single row # @param row [ActiveRecord] single row of model data # @return [Hash] calculated hash of model row def get_data_row(row) fields = self.get_fields new_row = {} case self.etc.action when 'show' new_row = { id: row.id, sys_title: row.sys_title } when 'index', 'export' new_row = { id: row.id, sys_title: row.sys_title, actions: self.get_table_actions(row) } when 'new', 'create' new_row = {} when 'edit', 'update' new_row = { id: row.id, sys_title: row.sys_title } end fields.each_key do |key| begin value = eval 'row.' + fields[key].field error = false rescue new_row[key] = fields[key].error_text error = true if fields[key].type == 'key' error = false end end new_row = new_row.merge(self.convert_db_to_view_value(key, value)) if !error end return new_row end ## # Returns current table actions for selected row # @param row [ActiveRecord] single row of model data # @return [Hash] resulting has of buttons def get_table_actions(row) self.etc.data.actions = self.table_actions if !self.etc.data.actions result = {} self.etc.data.actions.each do |value| if self.get_table_action value, row result[value.to_sym] = I18n.t(params[:controller].sub('/', '.')+'.table.actions.'+value, title: row.sys_title, default: I18n.t('actions.'+value, title: row.sys_title)) end end result end ## # Returns posibility of using action for table data # @param action [String] desired action # @param row [ActiveRecord] single active record row # @return [Boolean] is action present or not def get_table_action(action, row) result = false if self.respond_to?(('table_action_'+action).to_sym) result = send 'table_action_'+action, row else result = true end result end # @!endgroup ## # @!group Block of {Anoubis::Data::Actions#edit edit} and {Anoubis::Data::Actions#update update} getters ## # Get model that is used for {Anoubis::Data::Actions#edit edit} or {Anoubis::Data::Actions#update update} actions. def get_edit_model return self.etc.data.model if self.etc.data.model self.etc.data.model = self.edit_model self.etc.data.eager_load = self.edit_eager_load return self.etc.data.model end ## # Get default eager load definition for {Anoubis::Data::Actions#edit edit} or # {Anoubis::Data::Actions#update update} actions. def get_edit_eager_load return self.etc.data.eager_load if self.etc.data.model self.get_edit_model return self.etc.data.eager_load end ## # Return current table fields hash for {Anoubis::Data::Actions#edit edit} or # {Anoubis::Data::Actions#update update} actions. # @return [Hash] current defined table fields def get_edit_fields self.setup_edit_fields self.etc.data.fields end ## # Get table data for single row for {Anoubis::Data::Actions#edit edit} or {Anoubis::Data::Actions#update update} # actions. # @param row [ActiveRecord] single row of model data # @return [Hash] calculated hash of model row def get_edit_data_row(row) self.setup_edit_fields new_row = { id: row.id, sys_title: row.sys_title } self.etc.data.fields.each do |key, field| if row.respond_to? field.field value = row.send field.field error = false else new_row[key] = field.error_text error = true end new_row = new_row.merge(self.convert_db_to_edit_value(key, value)) if !error end return new_row end # @!endgroup ## # @!group Block of {Anoubis::Data::Actions#new new} or {Anoubis::Data::Actions#create create} getters ## # Return current table fields hash for {Anoubis::Data::Actions#new new} or {Anoubis::Data::Actions#create create} # actions # @return [Hash] current defined table fields def get_new_fields self.setup_new_fields self.etc.data.fields end ## # Get table data for single row for {Anoubis::Data::Actions#new new} or {Anoubis::Data::Actions#create create} # actions. # @param row [ActiveRecord] single row of model data # @return [Hash] calculated hash of model row def get_new_data_row1(row) self.setup_new_fields new_row = {} self.etc.data.fields.each do |key, field| if row.respond_to? field.field value = row.send field.field error = false else new_row[key] = field.error_text error = true end new_row = new_row.merge(self.convert_db_to_new_value(key, value)) if !error end return new_row end # @!endgroup ## # Get defined fields options # @param time [Number] last execution time of action # @return [Hash] hash of fields options def get_data_options(time) time = time.to_s.to_i self.setup_fields result = {} self.etc.data.fields.each do |key, field| if field.options if field.options.list if time == 0 result[key] = field.options.list if field.options.show != 'never' else if field.model if field.options.show == 'always' result[key] = field.options.list else if field.options.show == 'update' && field.model.updated_at > time result[key] = field.options.list end end else result[key] = field.options.list if field.options.show == 'update' || field.options.show == 'always' end end end end end result end ## # Returns order for current tab # @return [Hash, String] order fore current tab def get_order return {id: :desc} if self.etc.tab.sort == nil result = {} field = self.etc.data.fields[self.etc.tab.sort.to_sym].order if field.field.class == Symbol result[field.field] = self.etc.tab.order else if field.field.class == String if field.field.index(',') result = field.field.gsub(',', ' ' + self.etc.tab.order.to_s.upcase + ',') + ' ' + self.etc.tab.order.to_s.upcase else result = field.field + ' ' + self.etc.tab.order.to_s.upcase end else if field.field.class == Array field.field.each do |item| if item.class == Symbol result[item] = self.etc.tab.order end end end end end result end ## # Return current fields hash for defined action. # @return [Hash] current defined table fields def get_fields self.setup_fields self.etc.data.fields end ## # Returns permitted parameters. Parameters is got from standard parameters output and checks according # by described {Anoubis::Etc::Data#fields self.etc.data.fields}. # @return [Hash] permitted paramters' collection def get_permited_params permit = [] allowed = self.fields_order self.etc.data.fields.each_key do | key | single = true if self.etc.data.fields[key].type == 'listbox' single = false if self.etc.data.fields[key].format == 'multiple' end if single permit.push key else data = {} data[key] = [] permit.push data end end params[:data].permit(permit).to_h.symbolize_keys end ## # Returns formatted field hash for field type 'string' # @param [Hash] options initial filed options # @option options [String] :min defines minimum string length (default: 0) # @option options [String] :max defines maximum string length (default: 0) # @return [Hash] resulting hash for field type 'string' def get_formatted_string_field(options) field = {} return field end ## # Get autocomplete data for field # @param field [Anoubis::Etc::Field] - field for loading data # @param value [String] - search value for load data # @return [Hash] resulting hash for selected data def get_autocomplete_data(field, value) value = value.to_s if value.index(' ') words = value.split(' ') max_count = 0; words.each do |word| max_count = word.length if word.length > max_count if field.autocomplete[:where].count == 0 field.autocomplete[:where].push field.table_field+' LIKE ?' else field.autocomplete[:where][0] += ' AND '+field.table_field+' LIKE ?' end field.autocomplete[:where].push("%#{word}%") end if max_count < field.autocomplete[:count] field.autocomplete[:where] = [] end else if value.length >= field.autocomplete[:count] field.autocomplete[:where] = [field.table_field+' LIKE ?', '%'+value+'%'] end end if field.autocomplete[:where].count > 0 self.load_autocomplete_data field end if self.etc.data.data self.etc.data.data.each do |item| if item.respond_to? field.model.title self.output.values.push( #id: item.id, value: item.send(field.model.title) ) else self.output.values.push( #id: item.id, value: item.id ) end end end return self.output.values end ## # Returns current parent data. If data not loaded then load it. # @return [ActiveRecord] resulting parent data def get_parent_data if !self.etc.data.parent self.load_parent_data end self.etc.data.parent end end end end end