app/helpers/cmsedit_helper.rb in drg_cms-0.6.0.3 vs app/helpers/cmsedit_helper.rb in drg_cms-0.6.0.6

- old
+ new

@@ -21,873 +21,203 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ ########################################################################### # -# CmseditHelper module defines helper methods used by cmsedit actions. Output is controlled by -# data found in 3 major sections of DRG CMS form: index, result_set and form sections. +# CmseditHelper module defines common methods used for DRGCMS forms. # ########################################################################### module CmseditHelper # javascript part created by form helpers attr_reader :js ############################################################################ -# Get standard actions when actions directive contains single line. -# Subroutine of dc_actions_for_index -# -# Allows for actions: new, filter, standard syntax +# Creates code for script action type. ############################################################################ -def define_standard_actions(actions_params, standard) - actions = {} - actions_params.split(',').each do |an_action| - an_action.strip! - if an_action == 'standard' - actions.merge!(standard) - else - standard.each do |index, action| - (actions[index] = action; break) if action == an_action - end - end - end - actions +def dc_script_action(yaml) +# data = {'request' => 'script', 'script' => yaml['js'] || yaml['script'] } +# %Q[<li class="dc-link-ajax with-link dc-animate">#{ dc_link_to(yaml['caption'], yaml['icon'], '#', data: data ) }</li>] + icon = dc_icon_for_link yaml['icon'] + data = %Q[data-request="script" data-script="#{yaml['js'] || yaml['script']}"] + %Q[<li class="dc-link-ajax dc-animate" #{data}>#{icon} #{ t(yaml['caption'],yaml['caption']) }</li>] end ############################################################################ -# Creates action div for cmsedit index action. +# Will return field form definition if field is defined on form. +# Field definition will be used for input field on the form. ############################################################################ -def dc_actions_for_index() - return '' if @form['index'].nil? or @form['readonly'] - actions = @form['index']['actions'] - return '' if actions.nil? or actions.size == 0 - std_actions = {2 => 'new', 3 => 'sort', 4 => 'filter' } - if actions.class == String - actions = define_standard_actions(actions, std_actions) - elsif actions['standard'] - actions.merge!(std_actions) - actions['standard'] = nil - end +def dc_get_field_form_definition(name) #:nodoc: + return nil if @form['form'].nil? -# start div with hidden spinner image - html = <<EOT -<div id="dc-action-menu"> - <span class="dc-spinner div-hidden">#{fa_icon('spinner lg spin')}</span> - <ul class="dc-action-menu"> -EOT -# Remove actions settings and sort - only_actions = [] - actions.each { |key, value| only_actions << [key, value] if key.class == Integer } - only_actions.sort_by!(&:first) - only_actions.each do |element| - k,v = element - session[:form_processing] = "index:actions: #{k}=#{v}" - next if v.nil? # must be - url = @parms.clone - yaml = v.class == String ? {'type' => v} : v # if single definition simulate type parameter - action = yaml['type'].to_s.downcase - if action == 'url' - dc_deprecate "action: url will be deprecated. Use action: link in index: actions" - action = 'link' - end -# if return_to is present link directly to URL - if action == 'link' and yaml['url'] - url = yaml['url'] - else - url['controller'] = yaml['controller'] if yaml['controller'] - url['action'] = yaml['action'] || action - url['table'] = yaml['table'] if yaml['table'] - url['form_name'] = yaml['form_name'] if yaml['form_name'] - end -# html link options - yhtml = yaml['html'] || {} - yhtml['title'] = yaml['title'] if yaml['title'] - code = case -# sort - when action == 'sort' then - choices = [['id','id']] - if @form['index']['sort'] - @form['index']['sort'].split(',').each do |s| - s.strip! - choices << [ t("helpers.label.#{@form['table']}.#{s}"), s ] - end - end - fa_icon('sort-alpha-asc') + ' ' + t('drgcms.sort') + ' ' + - select('sort', 'sort', choices, { include_blank: true }, - { class: 'drgcms_sort', 'data-table' => @form['table']} ) -# filter - when action == 'filter' then - caption = t('drgcms.filter') - caption << '&nbsp;' + fa_icon('caret-down lg') + DcFilter.menu_filter(self) -# add filter OFF link - s = session[@form['table']] - if s and s[:filter] - caption << '&nbsp;&nbsp;' + dc_link_to(nil,'remove lg', {controller: 'cmsedit', - filter: 'off', table: @form['table']}, { title: DcFilter.title4_filter_off(s[:filter]) }) - end - caption -# new - when action == 'new' then - caption = yaml['caption'] || 'drgcms.new' - dc_link_to(caption,'plus', url, yhtml ) -# menu - when action == 'menu' then - caption = t(v['caption'], v['caption']) + '&nbsp;' + fa_icon('caret-down lg') - caption + eval(v['eval']) -=begin -# reorder - when action == 'reorder' then - caption = t('drgcms.reorder') - parms = @parms.clone - parms['operation'] = v - parms['id'] = params[:ids] - parms['table'] = @form['table'] - dc_link_to( caption, 'reorder', parms, method: :delete ) -=end - when action == 'script' - html << dc_script_action(v) - next - else - caption = yaml['caption'] || yaml['text'] - icon = yaml['icon'] ? yaml['icon'] : action - dc_link_to(caption, icon, url, yhtml) - end - html << "<li class=\"dc-animate\">#{code}</li>" - end - html << '</ul>' - html << DcFilter.get_filter_field(self) - html << '</div>' - html.html_safe + @form['form']['tabs'].each do |tab| +# Array with 2 elements. First is tabname, second is data + my_fields = tab.last + my_fields.each {|k,v| return v if (k.class == Integer and v['name'] == name) } + end if @form['form']['tabs'] # I know. But nice. +# + @form['form']['fields'].each do |field| + next unless field.first.class == Integer # options + return field.last if field.last['name'] == name + end if @form['form']['fields'] + nil end ############################################################################ -# Creates filter div for cmsedit index/filter action. +# Return field code, label and help text for a field defined on a DRG Form. +# +# Parameters: +# options : Hash : Field definition +# +# Returns: +# field_html : String : HTML code for field definition +# label : String : Label text +# help : String : Help text ############################################################################ -def dc_div_filter() - choices = [] - filter = (@form['index'] and @form['index']['filter']) ? @form['index']['filter'] + ',' : '' - filter << 'id as text_field' # filter id is added by default - filter.split(',').each do |f| - f.strip! - name = f.match(' as ') ? f.split(' ').first : f -# like another field on the form - if f.match(' like ') - a = f.split(' ') - name = a.first - f = a.last +def dc_field_label_help(options) + # no label or help in comments + unless %w(comment action).include?(options['type']) + caption = options['caption'] || options['text'] + label = if caption.blank? + t_name(options['name'], options['name'].capitalize.gsub('_',' ') ) + elsif options['name'] + t(caption, caption) end - choices << [ t("helpers.label.#{@form['table']}.#{name}", name), f ] + # help text can be defined in form or in translations starting with helpers. or as helpers.help.collection.field + help = if options['help'] + options['help'].match('helpers.') ? t(options['help']) : options['help'] + end + help ||= t('helpers.help.' + @form['table'] + '.' + options['name'],' ') if options['name'] end - choices4_operators = t('drgcms.choices4_filter_operators').chomp.split(',').inject([]) {|r,v| r << (v.match(':') ? v.split(':') : v )} -# currently selected options - if session[@form['table']] and session[@form['table']][:filter] - field_name, operators_value, dummy = session[@form['table']][:filter].split("\t") - else - field_name, operators_value = nil, nil + # create field object from class and call its render method + klass_string = options['type'].camelize + field_html = if DrgcmsFormFields.const_defined?(klass_string) # when field type defined + klass = DrgcmsFormFields.const_get(klass_string) + field = klass.new(self, @record, options).render + @js << field.js + @css << field.css + field.html + else # litle error string + "Error: Field type #{options['type']} not defined!" end - #{ form_tag :table => @form['table'], filter: :on, filter_input: 1, action: :index, method: :post } - url = url_for(table: @form['table'],form_name: params['form_name'], filter: :on, filter_input: 1, action: :index, controller: :cmsedit) - html =<<EOT - <div id="drgcms_filter" class="div-hidden"> - <h1>#{t('drgcms.filter_set')}</h1> - - #{ select(nil, 'filter_field1', options_for_select(choices, field_name), { include_blank: true }) } - #{ select(nil, 'filter_oper', options_for_select(choices4_operators, operators_value)) } - <div class="dc-menu"> - <div class="dc-link dc-animate drgcms_popup_submit" data-url="#{url}">#{fa_icon('check-square-o')} #{t('drgcms.filter_on')}</div> - <div class="dc-link dc-animate">#{dc_link_to('drgcms.filter_off','close', {action: :index, filter: 'off', table: @form['table'], form_name: params['form_name']}) }</div> - </div> - </div> -EOT - html.html_safe + [field_html, label, help] end ############################################################################ -# Creates title div for cmsedit index result set records. Title div also includes paging -# options. +# Creates code for including data entry field in index actions. ############################################################################ -def dc_table_title_for_result(result=nil) - title = if @form['title'] # form has title section - t(@form['title'], @form['title']) - else # get name from translations - t("helpers.label.#{@form['table']}.tabletitle", @form['table']) +def dc_field_action(yaml) + # assign value if value found in parameters + if params['record'] + value = params['record'][yaml['name']] + params["p_#{yaml['name']}"] = value end - dc_table_title(title, result) -end - -############################################################################ -# Creates code for link or ajax action type. Subroutine of dc_actions_for_result. -############################################################################ -def dc_link_or_ajax_action(yaml, parms) #:nodoc: - rest = {} - rest['method'] = yaml['method'] || yaml['request'] || 'get' - rest['caption'] = yaml['caption'] || yaml['text'] - rest['class'] = 'dc-animate' - rest['title'] = yaml['title'] - - if yaml['type'] == 'link' - dc_link_to(yaml['caption'], yaml['icon'], parms, rest ) + # + if ( field_definition = dc_get_field_form_definition(yaml['name']) ) + field, label, help = dc_field_label_help(field_definition) else - rest['data-url'] = url_for(parms) - rest['class'] << " fa fa-#{yaml['icon']}" - fa_icon(yaml['icon'], rest ) + yaml['type'] = yaml['field_type'] + field, label, help = dc_field_label_help(yaml) end + # input field will have label as placeholder + field = field.sub('input',"input placeholder=\"#{label}\"") + %Q[<li class="no-background">#{field}</li>] + end ############################################################################ -# Creates code for script action type. +# ############################################################################ -def dc_script_action(yaml) - data = {'request' => 'script', 'script' => yaml['js']} - %Q[<li class="dc-link-ajax dc-animate">#{ dc_link_to(yaml['caption'], yaml['icon'], '#', data: data ) }</li>] -end - -############################################################################ -# Determines actions and width of actions column -############################################################################ -def dc_actions_column() - actions = @form['result_set']['actions'] -# standard actions - actions = {'standard' => true} if actions.class == String && actions == 'standard' - std_actions = {' 2' => 'edit', ' 3' => 'delete'} - actions.merge!(std_actions) if actions['standard'] -# - width = @form['result_set']['actions_width'] || 20*actions.size - [ actions, "<div class=\"actions\" style=\"width: #{width}px;\">" ] +def dc_html_data(yaml) + return '' if yaml.blank? + yaml.inject(' ') {|result, e| result << "#{e.first}=\"#{e.last}\" "} end ############################################################################ -# Creates actions that could be performed on single row of result set. +# Creates code for link, ajax or windows action for index or form actions. +# +# Parameters: +# yaml: Hash : Action definition +# record : Object : Currently selected record if available +# action_active : Boolean : Is action active or disabled +# +# Returns: +# String : HTML code for action ############################################################################ -def dc_actions_for_result(document) - actions = @form['result_set']['actions'] - return '' if actions.nil? or @form['readonly'] -# - actions, html = dc_actions_column() - actions.each do |k,v| - session[:form_processing] = "result_set:actions: #{k}=#{v}" - next if k == 'standard' # ignore standard definition - parms = @parms.clone - yaml = v.class == String ? {'type' => v} : v # if single definition simulate type parameter - html << case - when yaml['type'] == 'edit' then - parms['action'] = 'edit' - parms['id'] = document.id - dc_link_to( nil, 'pencil lg', parms ) - when yaml['type'] == 'duplicate' then - parms['id'] = document.id -# duplicate string will be added to these fields. - parms['dup_fields'] = yaml['dup_fields'] - parms['action'] = 'create' - dc_link_to( nil, 'copy lg', parms, data: { confirm: t('drgcms.confirm_dup') }, method: :post ) - when yaml['type'] == 'delete' then - parms['action'] = 'destroy' - parms['id'] = document.id - parms['return_to'] = request.url - dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete ) -# undocumented so far - when yaml['type'] == 'edit_embedded' - parms['controller'] = 'cmsedit' - parms['table'] += ";#{yaml['table']}" - parms['ids'] ||= '' - parms['ids'] += "#{document.id};" - dc_link_to( nil, 'table lg', parms, method: :get ) - when yaml['type'] == 'link' || yaml['type'] == 'ajax' then - if yaml['url'] - parms['controller'] = yaml['url'] - parms['idr'] = document.id - else - parms['id'] = document.id - end - parms['controller'] = yaml['controller'] if yaml['controller'] - parms['action'] = yaml['action'] if yaml['action'] - parms['table'] = yaml['table'] if yaml['table'] - parms['form_name'] = yaml['form_name'] if yaml['form_name'] - parms['target'] = yaml['target'] if yaml['target'] - dc_link_or_ajax_action(yaml, parms) - else # error. - yaml['type'].to_s - end +def dc_link_ajax_window_submit_action(yaml, record=nil, action_active=true) + parms = {} + caption = yaml['caption'] ? t("#{yaml['caption'].downcase}", yaml['caption']) : nil + icon = yaml['icon'] ? "#{fa_icon(yaml['icon'])}" : '' + # action is not active + unless dc_is_action_active?(yaml) + return "<li class=\"dc-link-no\">#{icon} #{caption}</li>" end - html << '</div>' - html.html_safe -end - -############################################################################ -# Creates header div for result set. -############################################################################ -def dc_header_for_result() - html = '<div class="dc-result-header">' - if @form['result_set']['actions'] and !@form['readonly'] - ignore, code = dc_actions_column() - html << code + '</div>' - end -# preparation for sort icon - sort_field, sort_direction = nil, nil - if session[@form['table']] - sort_field, sort_direction = session[@form['table']][:sort].to_s.split(' ') - end -# - if (columns = @form['result_set']['columns']) - columns.each do |k,v| - session[:form_processing] = "result_set:columns: #{k}=#{v}" -# - th = %Q[<div class="th" style="width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};"] - v = {'name' => v} if v.class == String - caption = v['caption'] || t("helpers.label.#{@form['table']}.#{v['name']}") -# no sorting when embedded documents or custom filter is active - sort_ok = @form['result_set'].nil? || (@form['result_set'] && @form['result_set']['filter'].nil?) - sort_ok = sort_ok || (@form['index'] && @form['index']['sort']) - if @tables.size == 1 and sort_ok - icon = 'sort lg' - if v['name'] == sort_field - icon = sort_direction == '1' ? 'sort-alpha-asc lg' : 'sort-alpha-desc lg' - end - th << ">#{dc_link_to(caption, icon, sort: v['name'], table: params[:table], form_name: params[:form_name], action: :index, icon_pos: :last )}</div>" - else - th << ">#{caption}</div>" - end - html << "<div class=\"spacer\"></div>" + th - end - end - (html << '</div>').html_safe -end - -############################################################################ -# Creates link for single or double click on result column -############################################################################ -def dc_clicks_for_result(document) - html = '' - if @form['result_set']['dblclick'] - yaml = @form['result_set']['dblclick'] - opts = {} - opts[:controller] = yaml['controller'] || 'cmsedit' - opts[:action] = yaml['action'] - opts[:table] = yaml['table'] - opts[:form_name] = yaml['form_name'] - opts[:method] = yaml['method'] || 'get' - opts[:id] = document['id'] - html << ' data-dblclick=' + url_for(opts) + # set data-confirm when confirm + yaml['html'] ||= {} + confirm = yaml['html']['data-confirm'] || yaml['confirm'] + yaml['html']['data-confirm'] = t(confirm) unless confirm.blank? + # direct url + if yaml['url'] + parms['controller'] = yaml['url'] + parms['idr'] = dc_document_path(record) if record + # make url from action controller else - html << (' data-dblclick=' + - url_for(action: 'show', controller: 'cmsedit', id: document.id, - readonly: (params[:readonly] ? 2 : 1), table: params[:table], - form_name: params[:form_name], ids: params[:ids]) ) if @form['form'] + parms['controller'] = yaml['controller'] || 'cmsedit' + parms['action'] = yaml['action'] + parms['table'] = yaml['table'] + parms['form_name'] = yaml['form_name'] + parms['control'] = yaml['control'] if yaml['control'] + parms['id'] = record.id if record end - html -end - -############################################################################ -# Formats value according to format supplied or data type. There is lots of things missing here. -############################################################################ -def dc_format_value(value, format=nil) - return '' if value.nil? - klass = value.class.to_s - case when klass.match('Time') then - format ||= t('time.formats.default') - value.strftime(format) - when klass.match('Date') then - format ||= t('date.formats.default') - value.strftime(format) - when format.to_s[0] == 'N' then - dec = format[1].blank? ? nil : format[1].to_i - sep = format[2].blank? ? nil : format[2] - del = format[3].blank? ? nil : format[3] - cur = format[4].blank? ? nil : format[4] - dc_format_number(value, dec, sep, del, cur) + # add current id to parameters + parms['id'] = dc_document_path(record) if record + # overwrite with or add additional parameters from environment or record + yaml['params'].each { |k,v| parms[k] = dc_value_for_parameter(v) } if yaml['params'] + parms['table'] = parms['table'].underscore if parms['table'] # might be CamelCase + # error if controller parameter is missing + if parms['controller'].nil? && parms['url'].nil? + "<li>#{'Controller not defined'}</li>" else - value.to_s - end -end + yaml['caption'] ||= yaml['text'] + + html_data = dc_html_data(yaml['html']) + # + url = url_for(parms) rescue 'URL error' + request = yaml['request'] || yaml['method'] || 'get' + if yaml['type'] == 'ajax' # ajax button + clas = "dc-link-ajax dc-animate" + %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data} + data-request="#{request}" title="#{yaml['title']}">#{icon}#{caption}</li>] -############################################################################ -# Defines style or class for row (tr) or column (td) -############################################################################ -def dc_style_or_class(selector, yaml, value, record) - return '' if yaml.nil? -# alias record and value so both names can be used in eval - field = value - document = record - html = selector ? "#{selector}=\"" : '' - html << if yaml.class == String - yaml - else - (yaml['eval'] ? eval(yaml['eval']) : '') rescue 'background-color:red;' - end - html << '"' if selector - html -end + elsif yaml['type'] == 'submit' # submit button + # It's dirty hack, but will prevent not authorized message and render index action correctly + parms[:filter] = 'on' + url = url_for(parms) rescue 'URL error' + clas = "dc-action-submit" + %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data} + data-request="#{request}" title="#{yaml['title']}">#{icon}#{caption}</li>] -############################################################################ -# Creates tr code for each row of result set. -############################################################################ -def dc_row_for_result(document) - clas = "dc-#{cycle('odd','even')} " + dc_style_or_class(nil, @form['result_set']['tr_class'], nil, document) - style = dc_style_or_class('style', @form['result_set']['tr_style'], nil, document) - "<div class=\"dc-result-data #{clas}\" #{dc_clicks_for_result(document)} #{style}>".html_safe -end + elsif yaml['type'] == 'link' # link button + clas = "dc-link dc-animate" + link = dc_link_to(yaml['caption'],yaml['icon'], parms, {target: yaml['target'], html: yaml['html']} ) + %Q[<li class="#{clas}">#{action_active ? link : caption}</li>] -############################################################################ -# Creates column for each field of result set document. -############################################################################ -def dc_columns_for_result(document) - html = '' - return html unless @form['result_set']['columns'] -# - @form['result_set']['columns'].each do |k,v| - session[:form_processing] = "result_set:columns: #{k}=#{v}" -# convert shortcut to hash - v = {'name' => v} if v.class == String -# eval - value = if v['eval'] - if v['eval'].match('dc_name4_id') - a = v['eval'].split(',') - if a.size == 3 - dc_name4_id(a[1], a[2], nil, document[ v['name'] ]) - else - dc_name4_id(a[1], a[2], a[3], document[ v['name'] ]) - end - elsif v['eval'].match('dc_name4_value') - dc_name4_value( @form['table'], v['name'], document[ v['name'] ] ) - elsif v['eval'].match('eval ') -# evaluate with specified parameters - else - if v['params'] - if v['params'] == 'document' # pass document as parameter when all - eval( "#{v['eval']} document") - else # list of fields delimeted by , - params = v['params'].chomp.split(',').inject('') do |result,e| - result << (e.match(/\.|\:|\(/) ? e : "document['#{e.strip}']") + ',' - end - params.chomp!(',') - eval( "#{v['eval']} #{params}") - end - else - eval( "#{v['eval']} '#{document[ v['name'] ]}'") - end - end -# as field - elsif document.respond_to?(v['name']) - dc_format_value(document.send( v['name'] ), v['format']) -# as hash (dc_memory) - elsif document.class == Hash - dc_format_value(document[ v['name'] ], v['format']) -# error - else - "!!! #{v['name']}" - end -# - td = '<div class="spacer"></div><div class="td" ' - td << dc_style_or_class('class', v['td_class'], value, document) + elsif yaml['type'] == 'window' + clas = "dc-link dc-animate dc-window-open" + %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data}>#{icon}#{caption}</li>] - width_align = %Q[width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};] - style = dc_style_or_class('style', v['td_style'] || v['style'], value, document) - style = if style.size > 1 - # remove trailing " add width and add trailing " back - style.delete_suffix('"') + width_align + '"' else - # create style string - "style=\"#{width_align}\"" + '<li>Action Type error</li>' end - html << "#{td} #{style}>#{value}</div>" end - html.html_safe end ############################################################################ -# Will return value for parameter required on form +# ############################################################################ -def dc_value_for_parameter(param) - if param.class == Hash - dc_internal_var(param['object'] || 'record', param['method']) - else - param - end -end - -############################################################################ -# Creates actions div for edit form. -# -# Displaying readonly form turned out to be challenge. For now when readonly parameter -# has value 2, back link will force readonly form. Value 1 or not set will result in -# normal link. -############################################################################ -def dc_actions_for_form() -# create standard actions - std_actions = {' 1' => 'back', ' 2' => {'type' => 'submit', 'caption' => 'drgcms.save'}, - ' 3' => {'type' => 'submit', 'caption' => 'drgcms.save&back'} } -# when edit only - unless @record.id.nil? - std_actions.merge!({' 6' => 'new'} ) - std_actions.merge!(@record.active ? {' 5' => 'disable'} : {' 5' => 'enable'} ) if @record.respond_to?('active') - std_actions.merge!({' 7' => 'refresh'} ) - end - actions = @form['form']['actions'] -# shortcut for actions: standard - actions = nil if actions.class == String && actions == 'standard' -# standard actions - actions = std_actions if actions.nil? -# readonly - actions = {' 1' => 'back'} if @form['readonly'] -# Actions are strictly forbidden - if @form['form']['actions'] and dc_dont?(@form['form']['actions']) - actions = [] - elsif actions['standard'] - actions.merge!(std_actions) - actions['standard'] = nil - end -# Update save and save&back - actions.each do |k,v| - if v.class == String - if v.match(/save\&back/i) - actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save&back'} - elsif v == 'save' - actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save'} - end - end - end -# Sort so that standard actions come first - actions = actions.to_a.sort {|x,y| x[0].to_s <=> y[0].to_s} -# Add spinner to the beginning - c = %Q[<span class="dc-spinner div-hidden">#{fa_icon('spinner lg spin')}</span><ul class="dc-menu">] +def dc_log_exception(exception) + log = exception ? "\n!!!Error: #{exception.message}\n#{exception.backtrace.first.inspect}\n" : '' + log << "DRG Form processing line: #{session[:form_processing]}\n" - actions.each do |element| - session[:form_processing] = "form:actions: #{element}" - v = element[1] - next if v.nil? # yes it happends -# on_save_ok should't go inside td tags - if (element[0] == 'on_save_ok') then - c << hidden_field_tag(:on_save_ok, v) - next - end -# - action_active = !(dc_dont?(v['when_new']) and @record.new_record?) -# p [v['caption'], action_active] - parms = @parms.clone - if v.class == String - next if params[:readonly] and !(v == 'back') - - c << '<li class="dc-link dc-animate">' - c << case - when (v == 'back' or v == 'cancle') then -# If return_to is present link directly to URL - if parms['xreturn_to'] # disabled for now - dc_link_to( 'drgcms.back','arrow-left', parms['return_to'] ) - else - parms['action'] = 'index' - parms['readonly'] = parms['readonly'].to_s.to_i < 2 ? nil : 1 - dc_link_to( 'drgcms.back','arrow-left', parms ) - end - when v == 'delete' then - parms['operation'] = v - parms['id'] = @record.id - dc_link_to( 'drgcms.delete','remove', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete ) - when v == 'new' then - parms['action'] = v - dc_link_to( 'drgcms.new', 'plus', parms) - when (v == 'enable' or v == 'disable') then - parms['operation'] = v - parms['id'] = @record.id - icon = (v == 'enable' ? 'thumbs-o-up' : 'thumbs-o-down') - dc_link_to( "drgcms.#{v}",icon, parms, method: :delete ) - when v == 'edit' then - parms['operation'] = v - parms['id'] = @record.id - dc_link_to( "drgcms.#{v}",v, parms ) - when v == 'refresh' then - "<span onclick='window.location.href=window.location.href;'>#{fa_icon('refresh')} #{t('drgcms.refresh')}</span></li>" - else - "err1 #{element[0]}=>#{v}" - end - c << '</td>' - # non standard actions - else - c << case - # submit button - when v['type'] == 'submit' - caption = v['caption'] || 'drgcms.save' - icon = v['icon'] || 'save' - if action_active - '<li class="dc-link-submit dc-animate">' + - dc_submit_tag(caption, icon, {:data => v['params'], :title => v['title'] }) + - '</li>' - else - "<li class=\"dc-link-no\">#{fa_icon(icon)} #{caption}</li>" - end - - # delete with some sugar added - when v['type'] == 'delete' - parms['id'] = @record.id - parms.merge!(v['params']) - caption = v['caption'] || 'drgcms.delete' - icon = v['icon'] || 'remove' - '<li class="dc-link dc-animate">' + - dc_link_to( caption, icon, parms, data: t('drgcms.confirm_delete'), method: :delete ) + - '</li>' - - # ajax or link button - when v['type'] == 'ajax' || v['type'] == 'link' || v['type'] == 'window' - parms = {} - # direct url - if v['url'] - parms['controller'] = v['url'] - parms['idr'] = dc_document_path(@record) - # make url from action controller - else - parms['controller'] = v['controller'] - parms['action'] = v['action'] - parms['table'] = v['table'] - parms['form_name'] = v['form_name'] - end - # add current id to parameters - parms['id'] = dc_document_path(@record) - # overwrite with or add additional parameters when params defined - v['params'].each { |k,v| parms[k] = dc_value_for_parameter(v) } if v['params'] - parms['table'] = parms['table'].underscore if parms['table'] # might be CamelCase - # error if controller parameter is missing - if parms['controller'].nil? - "<li>#{t('drgcms.error')}</li>" - else - v['caption'] ||= v['text'] - caption = t("#{v['caption'].downcase}", v['caption']) - # - url = url_for(parms) rescue '' - request = v['request'] || v['method'] || 'get' - icon = v['icon'] ? "#{fa_icon(v['icon'])} " : '' - if v['type'] == 'ajax' # ajax button - clas = action_active ? "dc-link-ajax dc-animate" : "dc-link-no" - %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}" - data-request="#{request}" title="#{v['title']}">#{icon}#{caption}</li>] - elsif v['type'] == 'link' # link button - clas = action_active ? "dc-link dc-animate" : "dc-link-no" - %Q[<li class="#{clas}">#{action_active ? dc_link_to(v['caption'],v['icon'], parms, {target: v['target']} ) : caption}</li>] - elsif v['type'] == 'window' - clas = action_active ? "dc-link dc-animate dc-window-open" : "dc-link-no" - %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}">#{icon}#{caption}</li>] - else - 'Action Type error' - end - end - -# Javascript action - when v['type'] == 'script' - dc_script_action(v) - else - '<li>err2</li>' - end - end - end - (c << '</ul>').html_safe + logger.error log end - -############################################################################ -# Create background div and table definitions for result set. -############################################################################ -def dc_background_for_result(start) - if start == :start - html = '<div class="dc-result-div" ' - html << (@form['result_set']['table_style'] ? 'style="overflow-x: scroll;" >' : '>') - # - html << "\n<div class=\"dc-result #{@form['result_set']['table_class']}\" " - html << (@form['result_set']['table_style'] ? "style=\"#{@form['result_set']['table_style']}\" >" : '>') - else - html = '</div></div>' - end - html.html_safe -end - -############################################################################ -# Checks if value is defined and sets default. If values are sent it also checks -# if value is found in values. If not it will report error and set value to default. -# Subroutine of dc_fields_for_tab. -############################################################################ -def dc_check_and_default(value, default, values=nil) #:nodoc: - return default if value.nil? -# check if value is within allowed values - if values - if !values.index(value) -# parameters should be in downcase. Check downcase version. - if n = values.index(value.downcase) - return values[n] - else - logger.error("DRG Forms: Value #{value} not within values [#{values.join(',')}]. Default #{default} used!") - return default - end - end - end - value -end - -############################################################################ -# Creates top or bottom horizontal line on form. -############################################################################ -def top_bottom_line(options) - '<div class="dc-separator"></div>' -end - -############################################################################ -# Creates input fields for one tab. Subroutine of dc_fields_for_form. -############################################################################ -def dc_fields_for_tab(fields_on_tab) #:nodoc: - @js ||= '' - html = '<div class="dc-form">' - labels_pos = dc_check_and_default(@form['form']['labels_pos'], 'right', ['top','left','right']) - hidden_fields = '' - odd_even = nil - group_option, group_count = 0, 0 - reset_cycle() -# options and fields must be separated before sorting -# form_options = fields.select {|field| field.class != Integer } -# columns = form_options.try(:[],'columns') || 1 -# Select form fields and sort them by key - form_fields = fields_on_tab.select {|field| field.class == Integer } - form_fields.to_a.sort.each do |element| - options = element.last - session[:form_processing] = "form:fields: #{element.first}=#{options}" -# ignore if edit_only singe field is required - next if params[:edit_only] and params[:edit_only] != options['name'] -# hidden_fields. Add them at the end - if options['type'] == 'hidden_field' - hidden_fields << DrgcmsFormFields::HiddenField.new(self, @record, options).render - next - end -# label - caption = options['caption'] || options['text'] - label = if !caption.blank? - t(caption, caption) - elsif options['name'] - t_name(options['name'], options['name'].capitalize.gsub('_',' ') ) - end -# help text can be defined in form or in translations starting with helpers. or as helpers.help.collection.field - help = if options['help'] - options['help'].match('helpers.') ? t(options['help']) : options['help'] - end - help ||= t('helpers.help.' + @form['table'] + '.' + options['name'],' ') if options['name'] -# create field object from class and call its render method - klas_string = options['type'].camelize - field_html = if DrgcmsFormFields.const_defined?(klas_string) # check if field type is defined - klas = DrgcmsFormFields.const_get(klas_string) - field = klas.new(self, @record, options).render - @js << field.js - field.html - else # litle error string - "Error: Code for field type #{options['type']} not defined!" - end -# Line separator - html << top_bottom_line(options['top-line']) if options['top-line'] -# Begining of new row - if group_count == 0 - html << '<div class="row-div">' - odd_even = cycle('odd','even') - group_count = options['group'] || 1 - group_option = options['group'] || 1 - end -# - html << if labels_pos == 'top' -%Q[ -<div class="dc-form-label-top dc-color-#{odd_even} dc-align-left" title="#{help}"> - <label for="record_#{options['name']}">#{label} </label> - <div id="td_record_#{options['name']}">#{field_html}</div> -</div> ] - else - label_width = 14 - # less place for label when more then 1 field per row - label_width = 10 if group_option > 1 and group_option != group_count - data_width = (94 - 10*group_option)/group_option -%Q[ -<div class="dc-form-label dc-color-#{odd_even} dc-align-#{labels_pos}" style="width:#{label_width}%;" title="#{help}"> - <label for="record_#{options['name']}">#{label} </label> -</div> -<div id="td_record_#{options['name']}" class="dc-form-field dc-color-#{odd_even}" style="width:#{data_width}%;">#{field_html}</div> -] - end -# check if must go to next row - group_count -= 1 - html << '</div>' if group_count == 0 - html << top_bottom_line(options['bottom-line']) if options['bottom-line'] - end - html << '</div>' << hidden_fields -end - -############################################################################ -# Creates edit form div. -############################################################################ -def dc_fields_for_form() - html, tabs, tab_data = '',[], '' -# Only fields defined - if (form_fields = @form['form']['fields']) - html << "<div id='data_fields' " + (@form['form']['height'] ? "style=\"height: #{@form['form']['height']}px;\">" : '>') - html << dc_fields_for_tab(form_fields) + '</div>' - else -# there are multiple tabs on form - first = true # first tab - @form['form']['tabs'].keys.sort.each do |tab_name| - next if tab_name.match('actions') -# Tricky. If field name is not on the tab skip to next tab - if params[:edit_only] - is_on_tab = false - @form['form']['tabs'][tab_name].each {|k,v| is_on_tab = true if params[:edit_only] == v['name'] } - next unless is_on_tab - end -# first div is displayed, all others are hidden - tab_data << "<div id=\"data_#{tab_name.delete("\s\n")}\"" - tab_data << ' class="div-hidden"' unless first - tab_data << " style=\"height: #{@form['form']['height']}px;\"" if @form['form']['height'] - tab_data << ">#{dc_fields_for_tab(@form['form']['tabs'][tab_name])}</div>" - tab_label = @form['form']['tabs'][tab_name]['caption'] || tab_name - tabs << [tab_name, tab_label] - first = false - end -# make it all work together - html << '<ul class="dc-form-ul" >' - first = true # first tab must be selected - tabs.each do |tab_name, tab_label| - html << "<li id=\"li_#{tab_name}\" data-div=\"#{tab_name.delete("\s\n")}\" class=\"dc-form-li" - html << ' dc-form-li-selected' if first - html << "\">#{t(tab_label, t_name(tab_label))}</li>" - first = false - end - html << '</ul>' - html << tab_data - end - # add last_updated_at hidden field so controller can check if record was updated in db during editing - html << hidden_field(nil, :last_updated_at, value: @record.updated_at.to_i) if @record.respond_to?(:updated_at) - # add form time stamp to prevent double form submit - html << hidden_field(nil, :form_time_stamp, value: Time.now.to_i) - html.html_safe -end - -############################################################################ -# Returns username for id. Subroutine of dc_document_statistics -############################################################################ -def _get_user_for(field_name) #:nodoc: - if @record[field_name] - u = DcUser.find(@record[field_name]) - return u ? u.name : @record[field_name] - end -# nil -end - -############################################################################ -# Creates current document statistics div (created_by, created_at, ....) at the bottom of edit form. -# + lots of more. At the moment also adds icon for dumping current document as json text. -############################################################################ -def dc_document_statistics - return '' if @record.new_record? or dc_dont?(@form['form']['info']) - html = %Q[<div id="dc-document-info">#{fa_icon('info-circle lg')}</div> <div id="dc-document-info-popup" class="div-hidden"> ] -# - u = _get_user_for('created_by') - html << %Q[<div><span>#{t('drgcms.created_by', 'Created by')}: </span><span>#{u}</span></div>] if u - u = _get_user_for('updated_by') - html << %Q[<div><span>#{t('drgcms.updated_by', 'Updated by')}: </span><span>#{u}</span></div>] if u - html << %Q[<div><span>#{t('drgcms.created_at', 'Created at')}: </span><span>#{dc_format_value(@record.created_at)}</span></div>] if @record['created_at'] - html << %Q[<div><span>#{t('drgcms.updated_at', 'Updated at')}: </span><span>#{dc_format_value(@record.updated_at)}</span></div>] if @record['updated_at'] -# copy to clipboard icon - parms = params.clone - parms[:controller] = 'dc_common' - parms[:action] = 'copy_clipboard' - url = url_for(parms.permit!) - html << fa_icon('copy 2x', class: 'dc-link-img dc-link-ajax dc-animate', - 'data-url' => url, 'data-request' => 'get', title: t('drgcms.doc_copy_clipboard') ) - (html << '</div></div>').html_safe -end - + end