'
if !@templateFill.key?('')
@templateFill[''] = out
else
@templateFill[''] += out
end
end
if $_REQUEST.key?('export_widget_list')
csv = ''
@csv.each{ |v|
csv += v.to_csv
}
return csv
else
return WidgetList::Utils::fill(@templateFill, @items['template'])
end
end
def get_radius_value()
@items['cornerRadius'].to_s.include?('px') ? @items['cornerRadius'].to_s : @items['cornerRadius'].to_s + 'px'
end
def get_shadow_inset_value()
@items['shadowInset'].to_s.include?('px') ? @items['shadowInset'].to_s : @items['shadowInset'].to_s + 'px'
end
def get_shadow_spread_value()
@items['shadowSpread'].to_s.include?('px') ? @items['shadowSpread'].to_s : @items['shadowSpread'].to_s + 'px'
end
def get_header_px_value()
@items['titleFontSize'].to_s.include?('px') ? @items['titleFontSize'].to_s : @items['titleFontSize'].to_s + 'px'
end
def get_header_pieces()
@headerPieces
end
def build_pagination()
pageRange = 3
pageNext = 1
pagePrev = 1
showPrev = false
showNext = true
prevUrl = ''
nextUrl = ''
tags = ''
urlTags = {}
templates = {}
urlTags['SQL_HASH'] = @sqlHash
urlTags['PAGE_ID'] = @items['pageId']
urlTags['LIST_NAME'] = @items['name']
urlTags['BUTTON_VALUE'] = @items['buttonVal']
urlTags['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
templates['btn_previous'] = @items['template_pagination_previous_disabled']
templates['btn_next'] = @items['template_pagination_next_active']
if $_REQUEST.key?('search_filter') && ! $_REQUEST['search_filter'].empty?
urlTags['search_filter'] = $_REQUEST['search_filter']
end
if @items['LIST_COL_SORT'].empty?
urlTags['LIST_COL_SORT'] = @items['LIST_COL_SORT']
urlTags['LIST_COL_SORT_ORDER'] = @items['LIST_COL_SORT_ORDER']
urlTags['ROW_LIMIT'] = @items['ROW_LIMIT']
end
if @items['links'].key?('paginate') && @items['links']['paginate'].class.name == 'Hash'
@items['links']['paginate'].each { |tagName, tag|
urlTags[tagName] = tag
}
end
@items['carryOverRequsts'].each { |value|
if $_REQUEST.key?(value)
urlTags[value] = $_REQUEST[value]
end
}
if (@sequence == @totalPages || ! (@totalPages > 0))
showNext = false
else
urlTags['LIST_SEQUENCE'] = @sequence + 1
nextUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
end
if @sequence > 1
pagePrev = @sequence - 1
urlTags['LIST_SEQUENCE'] = pagePrev
prevUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
showPrev = true
end
if !showNext
templates['btn_next'] = @items['template_pagination_next_disabled']
end
if showPrev
templates['btn_previous'] = @items['template_pagination_previous_active']
end
#Assemble navigation buttons
#
pieces = {
'' => nextUrl,
'' => @items['name'],
'' => prevUrl,
'' => @items['ajaxFunction'],
'' => @items['ajaxFunctionAll'],
}
templates['btn_next'] = WidgetList::Utils::fill(pieces,templates['btn_next'])
templates['btn_previous'] = WidgetList::Utils::fill(pieces,templates['btn_previous'])
#
# Sequence Range Drop Down
#
# Show x per page
#
urlTags['LIST_SEQUENCE'] = @sequence
urlTags['ROW_LIMIT'] = 10
@items['carryOverRequsts'].each { |value|
if $_REQUEST.key?(value)
urlTags[value] = $_REQUEST[value]
end
}
# Automate select box and rules
#
rowLimitSelect = [10,20,50,100,500,1000]
rowLimitSelectData = {}
rowLimitSelectConfigs = {}
#Set a default of 10
#
urlTags['ROW_LIMIT'] = 10
options = ''
rowLimitSelect.each_with_index { |jumpCount, key|
if (@totalRows >= jumpCount || @totalRows > rowLimitSelect[key-1])
urlTags['ROW_LIMIT'] = jumpCount
rowLimitUrl = WidgetList::Utils::build_url(@items['pageId'],urlTags,(!$_REQUEST.key?('BUTTON_VALUE')))
selected = ''
if (@items['rowLimit'] == jumpCount)
selected = 'selected'
end
options += " "
end
}
# WidgetSelect( todo)
pageSelect = <<-EOD
EOD
#Ensure the range does not exceed the actual number of pages
#
if @totalPages < pageRange
pageRange = @totalPages
end
###
# Create a range of x or less numbers.
#
# Take 2 off and add 2 or as much as possible either way
###
startingPoint = @sequence
vkill = pageRange
while vkill > 0 do
vkill = vkill - 1
if startingPoint <= 1
break
else
startingPoint = startingPoint-1
end
end
endPoint = @sequence
vkill = pageRange
while vkill > 0 do
vkill = vkill - 1
if endPoint <= 1
endPoint = endPoint+1
else
break
end
end
jumpSection = []
#Builds jump section previous 4 5 6 7 next
#
for page in startingPoint..endPoint
urlTags['LIST_SEQUENCE'] = page
urlTags['SQL_HASH'] = @sqlHash
jumpTemplate = ''
jumpUrl = ''
jumpUrl = WidgetList::Utils::build_url(@items['pageId'], urlTags, (!$_REQUEST.key?('BUTTON_VALUE')))
if page == @sequence
jumpTemplate = @items['template_pagination_jump_active']
else
jumpTemplate = @items['template_pagination_jump_unactive']
end
jumpSection << WidgetList::Utils::fill({
'' => page,
'' => jumpUrl,
'' => @items['name'],
'' => @items['ajaxFunction'],
'' => @items['ajaxFunctionAll'],
}, jumpTemplate)
end
pieces = {
'' => templates['btn_previous'],
'' => @sequence,
'' => templates['btn_next'],
'' => @totalPages,
'' => @totalRows,
'' => pageSelect,
'' => jumpSection.join(''),
'' => @items['name'],
}
paginationOutput = WidgetList::Utils::fill(pieces,@items['template_pagination_wrapper'])
if (@items['showPagination'])
return paginationOutput
else
return ''
end
end
def self.build_search_button_click(list_parms)
extra_get_vars = ''
extra_func = ''
filterParameters = {}
if list_parms.key?('ajaxFunctionAll')
extra_func = list_parms['ajaxFunctionAll']
end
if list_parms.key?('carryOverRequsts')
list_parms['carryOverRequsts'].each { |value|
if $_REQUEST.key?(value)
filterParameters[value] = $_REQUEST[value]
end
}
extra_get_vars = WidgetList::Utils::build_query_string(filterParameters)
end
"ListJumpMin(jQuery('##{list_parms['name']}_jump_url').val() + '&advanced_search=1&' + jQuery('#list_search_id_#{list_parms['name']}_results *').serialize() + '{extra_get_vars}', '#{list_parms['name']}');HideAdvancedSearch(this);" + extra_func
end
def build_headers()
headers = []
ii = 0
@items['fields'].each { |field, fieldTitle|
colWidthStyle = '';
colClass = '';
popupTitle = '';
templateIdx = 'templateNoSortColumn'
#Column class
#
if ! @items['headerClass'].empty?
if @items['headerClass'].key?(field.downcase)
colClass = @items['headerClass'][field.downcase]
end
end
#Column width
#
if ! @items['columnWidth'].empty?
if @items['columnWidth'].key?(field.downcase)
colWidthStyle = "width:" + @items['columnWidth'][field.downcase] + ";"
end
end
if @items['borderedColumns']
colWidthStyle += 'border-right: ' + @items['borderColumnStyle'] + ';'
end
colWidthStyle += @items['borderHeadFoot'] ? 'border-bottom:' + @items['headFootBorderStyle'] + ';' : ''
$_SESSION.deep_merge!({'LIST_SEQUENCE' => { @sqlHash => @sequence} })
#Hover Title
#
if @items['columnPopupTitle'].key?(field.downcase)
popupTitle = @items['columnPopupTitle'][field.downcase]
end
#
# Column is an input
#
if @items['inputs'].key?(fieldTitle) && @items['inputs'][fieldTitle].class.name == 'Hash'
#
# Default checkbox hover to "Select All"
#
# Do specific input type functions
#
case @items['inputs'][fieldTitle]['type']
when 'checkbox'
if popupTitle.empty? && @items['inputs'][fieldTitle]['items']['check_all']
popupTitle = 'Select All'
end
#
# No sort on this column
#
if ! @items['columnNoSort'].key?(fieldTitle)
@items['columnNoSort'][field] = field
end
if colClass.empty?
@items['headerClass'] = { fieldTitle => 'widgetlist-checkbox-header'}
colClass = @items['headerClass'][fieldTitle]
end
end
#
# Build the input
#
fieldTitle = build_column_input(fieldTitle)
else
if $_REQUEST.key?('export_widget_list') && !skip_column(field)
@csv[0] << fieldTitle
end
end
#Add in radius
if ii == @items['fields'].length - 1 && @items['listDescription'] == ''
colWidthStyle += '-moz-border-radius-topright:' + get_radius_value() + ';-webkit-border-top-right-radius:' + get_radius_value() + ';border-top-right-radius:' + get_radius_value() + ';'
end
if ii == 0 && @items['listDescription'] == ''
colWidthStyle += '-moz-border-radius-topleft:' + get_radius_value() + ';-webkit-border-top-left-radius:' + get_radius_value() + ';border-top-left-radius:' + get_radius_value() + ';'
end
if (@items['useSort'] && (@items['columnSort'].include?(field) || (@items['columnSort'].key?(field)) && !@items['columnNoSort'].include?(field)) || (@items['columnSort'].empty? && !@items['columnNoSort'].include?(field)))
templateIdx = 'templateSortColumn'
colSort = {}
#Assign the column to be sorted
#
if !@items['columnSort'].empty? && @items['columnSort'].key?(field)
colSort['LIST_COL_SORT'] = @items['columnSort'][field]
elsif (!@items['columnSort'].empty? && @items['columnSort'].include?(field)) || @items['columnSort'].empty?
colSort['LIST_COL_SORT'] = field
end
colSort['PAGE_ID'] = @items['pageId']
colSort['LIST_NAME'] = @items['name']
colSort['BUTTON_VALUE'] = @items['buttonVal']
colSort['LIST_COL_SORT_ORDER'] = @listSortNext
colSort['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
colSort['ROW_LIMIT'] = @items['ROW_LIMIT']
colSort['LIST_SEQUENCE'] = @sequence
icon = ""
if (
( (@items.key?('LIST_COL_SORT') && !@items['LIST_COL_SORT'].empty?) && @items['LIST_COL_SORT'] == colSort['LIST_COL_SORT']) ||
( $_SESSION.key?('LIST_COL_SORT') && !$_SESSION['LIST_COL_SORT'].nil? && $_SESSION['LIST_COL_SORT'].key?(@sqlHash) && $_SESSION['LIST_COL_SORT'][@sqlHash].key?(field))
)
changedSession = false
if @items.key?('LIST_COL_SORT') && !@items['LIST_COL_SORT'].empty?
changedSession = ( $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash) && ! $_SESSION['LIST_COL_SORT'][@sqlHash].key?(@items['LIST_COL_SORT']) )
if $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
$_SESSION['LIST_COL_SORT'].delete(@sqlHash)
end
$_SESSION.deep_merge!({'LIST_COL_SORT' => { @sqlHash => {@items['LIST_COL_SORT']=> @items['LIST_COL_SORT_ORDER'] } } })
end
if !changedSession && @items.key?('LIST_COL_SORT') && ! @items['LIST_COL_SORT'].empty?
if @items['LIST_COL_SORT_ORDER'] == 'DESC'
icon = "↑"
else
icon = "↓"
end
elsif !changedSession && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
#load sort from session
$_SESSION['LIST_COL_SORT'][@sqlHash].each_with_index { |order,void|
if order[1] == 'DESC'
colSort['LIST_COL_SORT_ORDER'] = "ASC"
icon = "↑"
else
colSort['LIST_COL_SORT_ORDER'] = "DESC"
icon = "↓"
end
}
end
end
#Carry over any search criteria on a sort to SORT URL
#
if $_REQUEST.key?('search_filter') && ! $_REQUEST['search_filter'].empty?
if $_REQUEST['search_filter'].empty?
colSort['search_filter'] = $_REQUEST['search_filter']
end
end
@items['carryOverRequsts'].each { |value|
if $_REQUEST.key?(value)
colSort[value] = $_REQUEST[value]
end
}
colSort['SQL_HASH'] = @sqlHash
pieces = { '' => WidgetList::Utils::build_url(@items['pageId'],colSort,(!$_REQUEST.key?('BUTTON_VALUE'))),
'' => @items['name'],
'' => strip_tags(field).gsub(/\s/,'_'),
'' => colWidthStyle,
'' => popupTitle,
'' => colClass,
'' => fieldTitle,
'' => @items['ajaxFunction'],
'' => @items['ajaxFunctionAll'],
}
headers << WidgetList::Utils::fill(pieces, @items[templateIdx])
else
pieces = { '' => fieldTitle,
'' => colWidthStyle,
'' => popupTitle,
'' => colClass,
'' => strip_tags(field).gsub(/\s/,'_')
}
headers << WidgetList::Utils::fill(pieces, @items[templateIdx])
end
ii = ii + 1
}
@templateFill[''] = headers.count()
@templateFill[''] = build_pagination()
@templateFill[''] = headers.join('')
if ! @items['listDescription'].empty?
fillDesc = {}
fillDesc[''] = headers.count()
fillDesc[''] = @items['listDescription']
fillDesc[''] = @items['name']
@templateFill[''] = WidgetList::Utils::fill(fillDesc,@items['list_description'])
else
@templateFill[''] = ''
end
end
# @param [String] column (the name)
# @param [Fixnum] row (the id or pointer in the loop to fetch the data)
def build_column_input(column, row='')
content = ''
inputManager = @items['inputs'][column]
case inputManager['type']
when "checkbox"
input = {}
input['name'] = 'widget_check_name'
input['id'] = 'widget_check_id'
input['check_all'] = false
input['value'] = ''
input['checked'] = ''
input['onclick'] = ''
input['input_class'] = 'widgetlist-checkbox-input'
input['class_handle'] = ''
input = WidgetList::Widgets::populate_items(inputManager['items'],input)
onClick = []
checkAllId = ''
#
# Get a value. Assumes it is a column initially.
#
# @note headers are ignored and would fail as row would be null
#
if @results.key?(input['value'].upcase) && !@results[input['value'].upcase][row].to_s.empty?
input['value'] = @results[ input['value'].upcase ][row]
end
if input.key?('disabled_if') && input['disabled_if'].class.name == 'Proc'
row_tmp = {}
@results.map { |column| column }.each { |col|
row_tmp[ col[0] ] = col[1][row]
}
if input['disabled_if'].call(row_tmp)
input['disabled'] = true
end
end
#
# Append class handle
#
input['input_class'] = "#{input['input_class']} #{input['class_handle']}"
if input['check_all']
checkAllId = input['id']
if $_SESSION.key?('list_checks') && !$_SESSION['list_checks'].nil? && $_SESSION['list_checks'].key?('check_all_' + @sqlHash.to_s + @items['name'].to_s + @sequence.to_s)
input['checked'] = true
end
#
# Set header class
#
if @items['headerClass'].class.name == 'Array' && @items['headerClass'].key?('checkbox')
if $_SESSION['list_checks'].key?('check_all_' + @sqlHash.to_s + @items['name'].to_s + @sequence.to_s)
input['checked'] = true
end
end
else
input['input_class'] = "#{input['input_class']} #{input['class_handle']} #{input['class_handle']}_list"
end
#
# Setup onclick action
#
if input['onclick'].empty?
listJumpUrl = {}
listJumpUrl['BUTTON_VALUE'] = @items['buttonVal']
listJumpUrl['LIST_COL_SORT'] = @items['LIST_COL_SORT']
listJumpUrl['LIST_COL_SORT_ORDER'] = @items['LIST_COL_SORT_ORDER']
listJumpUrl['LIST_FILTER_ALL'] = @items['LIST_FILTER_ALL']
listJumpUrl['ROW_LIMIT'] = @items['ROW_LIMIT']
listJumpUrl['LIST_SEQUENCE'] = @sequence
listJumpUrl['LIST_NAME'] = @items['name']
listJumpUrl['SQL_HASH'] = @sqlHash
listJumpUrl['list_action'] = 'ajax_widgetlist_checks'
onClick << "AjaxMaintainChecks(this, '#{input['class_handle']}', '#{@items['name']}', '" + WidgetList::Utils::build_url(@items['pageId'],listJumpUrl,(!$_REQUEST.key?('BUTTON_VALUE'))) + "', '#{checkAllId}');"
end
input['onclick'] = onClick.join(' ')
#
# Checkbox is checked or not per query value
#
if ! @items['checkedFlag'].empty?
if @items['checkedFlag'].key?(column)
input['checked'] = !!@results[ @items['checkedFlag'][column].upcase ][row]
end
end
#
# Checkbox is checked or not per session (overwrites query)
#
if $_SESSION.key?('list_checks') && !$_SESSION['list_checks'].nil? && $_SESSION['list_checks'].key?(@items['name'] + @sqlHash + input['value'].to_s)
input['checked'] = true
end
content = WidgetList::Widgets::widget_check(input)
#todo never implemented
when "text"
a=1
#content = WidgetInput()
when "select"
a=1
#content = WidgetSelect()
end
return content
end
# build_list controls a default AJAX/Export and full HTML return output
# in some cases you should copy and paste this logic for custom scenarios in your controller, but in most cases, this is okay
def self.build_list(list_parms)
list = WidgetList::List.new(list_parms)
#
# If AJAX, send back JSON
#
if $_REQUEST.key?('BUTTON_VALUE') && $_REQUEST['LIST_NAME'] == list_parms['name']
if $_REQUEST.key?('export_widget_list')
return ['export',list.render()]
end
ret = {}
if $_REQUEST['list_action'] != 'ajax_widgetlist_checks'
ret['list'] = list.render()
ret['search_bar'] = list.get_header_pieces['searchBar']
ret['group_by_items'] = list.get_header_pieces['groupByItems']
ret['export_button'] = list.get_header_pieces['exportButton']
ret['list_id'] = list_parms['name']
ret['callback'] = 'ListSearchAheadResponse'
end
return ['json',WidgetList::Utils::json_encode(ret)]
else
#
# Else assign to variable for view
#
if list.isAdministrating
return list.render()
else
return ['html', list.render() ]
end
end
end
# checkbox_helper just builds the proper Hashes to setup a checkbox widget row
# it assumes you have a fake column called '' AS checkbox to fill in with the widget_check
def self.checkbox_helper(list_parms,primary_key)
list_parms.deep_merge!({'inputs' =>
{'checkbox'=>
{'type' => 'checkbox'
}
}
})
list_parms.deep_merge!({'inputs' =>
{'checkbox'=>
{'items' =>
{
'name' => list_parms['name'] + '_visible_checks[]',
'value' => primary_key, #the value should be a column name mapping
'class_handle' => list_parms['name'] + '_info_tables',
}
}
}
})
list_parms.deep_merge!({'inputs' =>
{'checkbox_header'=>
{'type' => 'checkbox'
}
}
})
list_parms.deep_merge!({'inputs' =>
{'checkbox_header'=>
{'items' =>
{
'check_all' => true,
'id' => list_parms['name'] + '_info_tables_check_all',
'class_handle' => list_parms['name'] + '_info_tables',
}
}
}
})
return list_parms
end
def self.group_by_max_each_field(list_parms,group_by_filter)
#
# Oracle needs MAX on most fields when grouping in order to shy away from 'not a GROUP BY expression' errors
#
if group_by_filter != 'none'
if list_parms.key?('fieldFunction') && !list_parms['fieldFunction'].empty?
list_parms['fieldFunction'].each { |k, v|
if !k.include?('_linked') && k != 'cnt'
list_parms['fieldFunction'][k] = "MAX(#{v})"
end
}
end
if list_parms.key?('fieldsHidden') && !list_parms['fieldsHidden'].empty?
list_parms['fieldsHidden'].each { |k|
if (list_parms.key?('fieldFunction') && !list_parms['fieldFunction'].empty? && !list_parms['fieldFunction'].key?(k)) || list_parms['fieldFunction'].empty?
list_parms['fieldFunction'][k] = "MAX(#{k})"
end
}
end
list_parms['fields'].each { |k|
if !k.include?('_linked') && k != 'cnt'
if (list_parms.key?('fieldFunction') && !list_parms['fieldFunction'].empty? && !list_parms['fieldFunction'].key?(k)) || list_parms['fieldFunction'].empty?
list_parms['fieldFunction'][k] = "MAX(#{k})"
end
end
}
end
return list_parms
end
def self.drill_down_back(list_name='')
''
end
def self.build_drill_down(*params)
required_params = {
:list_id => true, # -- your widget_list name (used for JS)
:drill_down_name => true, # -- an identifier that is pass for the "column" or "type of drill down" which is passed as $_REQUEST['drill_down'] when the user clicks and returned from get_filter_and_drilldown based on session or request
:data_to_pass_from_view => true, # -- Any SQL function or column name/value in the resultset in which would be the value passed when the user clicks the drill down
:column_to_show => true, # -- The visible column or SQL functions to display to user for the link
}
optional_params = {
:column_alias => '', # -- AS XXXX
:extra_function => '', # -- Onclick of link, call another JS function after the drill down function is called
:js_function_name => 'ListDrillDown', # -- name of JS Function
:column_class => '', # -- custom class on the tag
:link_color => 'blue', # -- whatever color you want the link to be
:extra_js_func_params => '', # -- Add extra params to ListDrillDown outside of the default
:primary_database => true, # -- Since this function builds a column before widget_list is instantiated, tell which connection you are using
}
valid = WidgetList::Widgets::validate_items(params[0],required_params)
items = WidgetList::Widgets::populate_items(params[0],optional_params)
if items[:column_alias].empty?
items[:column_alias] = items[:column_to_show]
end
if !items[:column_class].empty?
items[:column_class] = ' "' + WidgetList::List::concat_string(items[:primary_database]) + items[:column_class] + WidgetList::List::concat_string(items[:primary_database]) + '"'
end
if WidgetList::List.get_db_type(items[:primary_database]) == 'oracle'
link = %[q'[]' #{WidgetList::List::concat_string(items[:primary_database])}#{items[:column_to_show]}#{WidgetList::List::concat_string(items[:primary_database])}q'[]' #{WidgetList::List::concat_outer(items[:primary_database])} #{WidgetList::List::is_sequel(items[:primary_database]) ? " as #{items[:column_alias]} " : ""}]
else
if WidgetList::List.get_db_type(items[:primary_database]) == 'postgres'
link = %['"' #{WidgetList::List::concat_string(items[:primary_database])}#{items[:column_to_show]}#{WidgetList::List::concat_string(items[:primary_database])}'' #{WidgetList::List::is_sequel(items[:primary_database]) ? " as #{items[:column_alias]} " : ""}]
else
link = %[#{WidgetList::List::concat_inner(items[:primary_database])}""#{WidgetList::List::concat_string(items[:primary_database])}#{items[:column_to_show]}#{WidgetList::List::concat_string(items[:primary_database])}""#{WidgetList::List::concat_outer(items[:primary_database])} #{WidgetList::List::is_sequel(items[:primary_database]) ? " as #{items[:column_alias]} " : ""}]
end
end
if $_REQUEST.key?('export_widget_list')
link = "#{items[:column_to_show]} #{WidgetList::List::is_sequel(items[:primary_database]) ? " as #{items[:column_alias]} " : ""}"
end
return link
end
def self.concat_string(primary)
case WidgetList::List.get_db_type(primary)
when 'mysql'
' , '
when 'oracle','sqlite','postgres'
' || '
else
','
end
end
def self.double_quote(primary)
case WidgetList::List.get_db_type(primary)
when 'mysql'
'\\"'
when 'oracle','sqlite'
'""'
else
'"'
end
end
def self.concat_outer(primary)
case WidgetList::List.get_db_type(primary)
when 'mysql'
')'
else
''
end
end
def self.concat_inner(primary)
case WidgetList::List.get_db_type(primary)
when 'mysql'
'CONCAT('
else
''
end
end
def build_column_button(column,j)
buttons = @items['buttons'][column]
columnValue = @results[column.upcase][j]
btnOut = []
strCnt = 0
nameId = ''
buttons.each { |buttonId,buttonAttribs|
function = @items['linkFunction']
parameters = ''
renderButton = true
page = buttonAttribs['page'].dup
if buttonAttribs.key?('tags')
tags = buttonAttribs['tags'].dup
all_wildcard = false
if buttonAttribs['tags'].first[0] == 'all'
all_wildcard = true
tags = {}
@results.keys.each { |tag|
tags[tag.downcase] = tag.downcase
}
end
tags.each { | tagName , tag |
if @results.key?(tag.upcase) && @results[tag.upcase][j]
#
# Data exists, lets check to see if page has any lowercase tags for restful URLs
#
if buttonAttribs.key?('page') && buttonAttribs['page'].include?(tag.downcase)
page.gsub!(tag.downcase,@results[tag.upcase][j])
else
#
# Will build ?tagname=XXXX based on your hash passed to your page
#
buttonAttribs.deep_merge!({ 'args' => { tagName => @results[tag.upcase][j] } }) unless all_wildcard
end
else
#
# User is passing hard coded tags such as 'tags' => {'my_static_var' => '1234'}
# Just fill in normally wherever anything is matched
#
if buttonAttribs.key?('page') && buttonAttribs['page'].include?(tag.downcase)
page.gsub!(tagName,tag)
else
buttonAttribs.deep_merge!({ 'args' => { tagName => tag } })
end
end
}
end
nameId = buttonId.to_s + '_' + j.to_s
buttonAttribs['name'] = nameId
buttonAttribs['id'] = nameId
if buttonAttribs.key?('hide_if') && input['hide_if'].class.name == 'Proc'
row_tmp = {}
@results.map { |column| column }.each { |col|
row_tmp[ col[0] ] = col[1][row]
}
if buttonAttribs['hide_if'].call(row_tmp)
renderButton = false
end
end
if (renderButton)
strCnt += (buttonAttribs['text'].length * 15)
attributes = buttonAttribs.dup
attributes['page'] = page
attributes['innerClass'] = @items['defaultButtonClass'] if !attributes.key?('innerClass')
btnOut << WidgetList::Widgets::widget_button(buttonAttribs['text'], attributes , true)
end
}
#BS width algorithm. HACK/TWEAK/OMG Get it working.
#
colWidth = ((strCnt + (btnOut.count * 35)) / 2) + 10
return '
' + btnOut.join('') + '
'
end
# @param [String] column
def build_column_link(column,j)
links = @items['links'][column]
url = {'PAGE_ID' => @items['pageId']}
function = @items['linkFunction']
parameters = ''
#todo unit test this and all of column links
if links.key?('tags')
links['tags'].each { | tagName, tag |
if @results[tag][j]
url[tagName] = @results[tag][j]
else
url[tagName] = tag
end
}
end
if links.key?('onclick') && links['onclick'].class.name == 'Hash'
if links['onclick'].key?('function') && !links['onclick']['function'].empty?
function = links['onclick']['function']
end
if links['onclick'].key?('tags') && !links['onclick']['tags'].empty?
links['onclick']['tags'].each { | tagName , tag|
if @results.key?(tag.upcase)
parameters = ", '" + @results[tag.upcase][j] + "'"
end
}
end
end
url['SQL_HASH'] = @sqlHash
linkUrl = WidgetList::Utils::build_url(@items['pageId'], url, (!$_REQUEST.key?('BUTTON_VALUE')))
"#{function}('#{linkUrl}'#{parameters})"
end
def build_rows()
sql = build_statement()
if @totalResultCount > 0
if @items['data'].empty?
#Run the actual statement
#
@totalRowCount = get_database._select(sql , @items['bindVars'], @items['bindVarsLegacy'], @active_record_model)
end
if @totalRowCount > 0
if @items['data'].empty?
@results = get_database.final_results
else
@results = @items['data']
end
#Build each row
#
max = @totalRowCount-1
rows = []
j = 0
for j in j..max
columns = []
row_values = []
customRowColor = ''
customRowStyle = ''
#
# For each column (field) in this row
#
changedFontColor = false
@items['fields'].each { |column , fieldTitle|
column = strip_aliases(column)
colPieces = {}
colClasses = []
theStyle = ''
colData = ''
colClass = ''
onClick = ''
colWidthStyle = ''
content = ''
contentTitle = ''
#todo unit test build_column_link
#
# Column is a Link
#
if @items['links'].key?(column) && @items['links'][column].class.name == 'Hash'
onClick = build_column_link(column,j)
end
#
# Column is a Button
#
if @items['buttons'].key?(column) && @items['buttons'][column].class.name == 'Hash'
content = build_column_button(column, j)
#
# Column is an input
#
elsif @items['inputs'].key?(column) && @items['inputs'][column].class.name == 'Hash'
colClasses << @items['checkedClass']
content = build_column_input(column, j)
#
# Column is text
#
else
cleanData = strip_tags(@results[column.upcase][j].to_s)
row_values << cleanData
#
# For now disable length parser
#
if false && cleanData.length > @items['strlength']
content = @results[column.upcase][j].to_s[ 0, @items['strlength'] ] + '...'
else
content = @results[column.upcase][j].to_s
end
#
#Strip HTML
#
if !@items['allowHTML']
content = strip_tags(content)
end
content = get_database._bind(content, @items['bindVarsLegacy'])
# Column color
#
if ! @items['columnStyle'].empty?
if @items['columnStyle'].key?(column.downcase)
colHeader = @items['columnStyle'][column.downcase]
if @results.key?(colHeader.upcase)
theStyle = @results[colHeader.upcase][j]
else
theStyle = colHeader
end
end
end
# Column width
#
if ! @items['columnWidth'].empty?
if @items['columnWidth'].key?(column.downcase)
colWidthStyle = "width:" + @items['columnWidth'][column.downcase] + ";"
end
end
# Column Class
#
if !@items['columnClass'].empty?
if @items['columnClass'].key?(column.downcase)
colClasses << @items['columnClass'][column.downcase]
end
end
end
#
# Setup any column classes
#
colClasses << @items['collClass']
colClass = colClasses.join(' ')
#
# Row Color
#
if !@items['rowColorByStatus'].empty? && @items['rowColorByStatus'].key?(column) && !@items['rowColorByStatus'][column].empty?
@items['rowColorByStatus'][column].each { |status,color|
if status === content
customRowColor = color
end
}
end
#
# Row Style
#
if !@items['rowStylesByStatus'].empty? && @items['rowStylesByStatus'].key?(column) && !@items['rowStylesByStatus'][column].empty?
@items['rowStylesByStatus'][column].each { |status,inlineStyle|
if status === content
customRowStyle = inlineStyle
if inlineStyle.include?('color:') || inlineStyle.include?('color :')
changedFontColor = true
end
end
}
end
#
# Set up Column Pieces
#
colPieces[''] = colClass
colPieces[''] = @items['collAlign']
colPieces[''] = theStyle + colWidthStyle
if @items['borderedColumns']
colPieces[''] += 'border-right: ' + @items['borderColumnStyle'] + ';'
end
if @items['borderedRows']
colPieces[''] += 'border-top: ' + @items['borderRowStyle'] + ';'
end
colPieces[''] = onClick
colPieces[''] = contentTitle #todo htmlentities needed ?
colPieces[''] = content
#
# Assemble the Column
#
columns << WidgetList::Utils::fill(colPieces, @items['col'])
}
if $_REQUEST.key?('export_widget_list')
@csv << row_values
end
#Draw the row
#
pieces = {'' => columns.join('') }
if @items['rowColorByStatus'].empty? && @items['rowStylesByStatus'].empty?
#Set the row color
#
if( j % 2 ==0)
rowColor = @items['rowOffsets'][1]
else
rowColor = @items['rowOffsets'][0]
end
#Draw default color
#
pieces[''] = rowColor
pieces[''] = ''
pieces[''] = @items['rowClass']
else
pieces[''] = !customRowColor.empty? ? customRowColor : @items['rowColor']
pieces[''] = !customRowStyle.empty? ? customRowStyle : ''
pieces[''] = @items['rowClass']
end
pieces[''] += 'font-size:' + @items['dataFontSize'] + ';'
if !changedFontColor
pieces[''] += 'color:' + @items['rowFontColor'] + ';'
end
rows << WidgetList::Utils::fill(pieces, @items['row'])
end
@templateFill[''] = rows.join('')
else
err_message = (get_database.errors) ? @items['noDataMessage'] + ' (An error occurred)' : @items['noDataMessage']
@templateFill[''] = '
'
end
end
def generate_error_output(ex='')
sqlDebug = ""
if !@items['errors'].empty?
sqlDebug += "
(" + @items['errors'].join(', ') + ")"
end
if Rails.env == 'development'
sqlDebug += "
"
end
if Rails.env == 'development' && get_database.errors
sqlDebug += "
(" + get_database.last_error.to_s + ")"
end
if Rails.env == 'development' && ex != ''
sqlDebug += "
(" + ex.to_s + ")
" + $!.backtrace.join("\n\n") + "
"
end
if Rails.env != 'development'
if get_database.errors
Rails.logger.info get_database.last_error.to_s
end
if ex != ''
Rails.logger.info $!.backtrace.join("\n\n")
end
end
Rails.logger.info sqlDebug
sqlDebug
end
def build_statement()
statement = ''
@fieldList = []
@fieldListPlain = []
pieces = { '' => '',
'' => '',
'' => '',
'' => '',
'' => '',
'' => '',
'' => ''}
#Build out a list of columns to select from
#
@items['fields'].each { |column, fieldTitle|
@fieldListPlain << strip_aliases(column)
if @items['fieldFunction'].key?(column) && !@items['fieldFunction'][column].empty?
# fieldFunction's should not have an alias, just the database functions
column = @items['fieldFunction'][column] + " " + column
end
@fieldList << column
}
if get_database.db_type == 'oracle'
if !@items['groupBy'].empty?
@fieldList << 'MAX(rn) as rn'
else
@fieldList << 'rn'
end
@fieldListPlain << 'rn'
end
if @items['fieldsHidden'].class.name == 'Array'
@items['fieldsHidden'].each { |column|
if !@items['fields'].key?(column)
@fieldListPlain << strip_aliases(column)
if @items['fieldFunction'].key?(column) && !@items['fieldFunction'][column].empty?
# fieldFunction's should not have an alias, just the database functions
column = @items['fieldFunction'][column] + " " + column
end
@fieldList << column
end
}
elsif @items['fieldsHidden'].class.name == 'Hash'
@items['fieldsHidden'].each { |column|
col = column[0]
if !@items['fields'].key?(col)
@fieldListPlain << strip_aliases(col)
if @items['fieldFunction'].key?(column[0]) && !@items['fieldFunction'][column[0]].empty?
# fieldFunction's should not have an alias, just the database functions
col = @items['fieldFunction'][column[0]] + " " + column[0]
end
@fieldList << col
end
}
end
viewPieces = {}
viewPieces[''] = @fieldListPlain.join(',')
viewPieces[''] = @fieldList.join(',')
viewPieces[''] = get_view()
statement = WidgetList::Utils::fill(viewPieces, @items['statement']['select']['view'])
@sqlHash = Digest::SHA2.hexdigest( WidgetList::Utils::fill(pieces, statement) )
if @items['searchClear'] || @items['searchClearAll']
clear_sql_session(@items.key?('searchClearAll'))
end
if !$_REQUEST.key?('BUTTON_VALUE') && !$_SESSION['LIST_SEQUENCE'].nil? && $_SESSION.key?('LIST_SEQUENCE') && $_SESSION['LIST_SEQUENCE'].key?(@sqlHash) && $_SESSION['LIST_SEQUENCE'][@sqlHash] > 0
@sequence = $_SESSION['LIST_SEQUENCE'][@sqlHash]
generate_limits
end
if !@filter.empty?
pieces[''] = ' WHERE ' + @filter
end
if !@items['groupBy'].empty?
pieces[''] = ' GROUP BY ' + @items['groupBy']
else
pieces[''] = ''
end
if !@items['LIST_COL_SORT'].empty? || ($_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash))
pieces[''] += ' ORDER BY '
foundColumn = false
if ! @items['LIST_COL_SORT'].empty?
foundColumn = true
pieces[''] += tick_field() + strip_aliases(@items['LIST_COL_SORT']) + tick_field() + " " + @items['LIST_COL_SORT_ORDER']
else
$_SESSION['LIST_COL_SORT'][@sqlHash].each_with_index { |order,void|
if @items['fields'].key?(order[0])
foundColumn = true
pieces[''] += tick_field() + strip_aliases(order[0]) + tick_field() + " " + order[1]
end
} if $_SESSION.key?('LIST_COL_SORT') && $_SESSION['LIST_COL_SORT'].class.name == 'Hash' && $_SESSION['LIST_COL_SORT'].key?(@sqlHash)
end
# Add base order by
if ! @items['orderBy'].empty?
pieces[''] += ',' if foundColumn == true
pieces[''] += @items['orderBy']
end
elsif !@items['orderBy'].empty?
pieces[''] += ' ORDER BY ' + @items['orderBy']
end
if get_database.db_type == 'oracle' && pieces[''].empty?
#oracle needs a field to perform the rank() over
#if field is not an "inputs" or a "buttons"
#if field is all NULL, then you better watch out as paging will NOT work
tmp = @items['fields'].dup.reject { |val|
if (!@items['inputs'].key?(val) && !@items['buttons'].key?(val))
false
else
true
end
}
keys = tmp.keys
pieces[''] += ' ORDER BY ' + strip_aliases(keys[0]) + ' ASC' unless keys[0].nil?
end
case get_database.db_type
when 'postgres'
pieces[''] = ' LIMIT :HIGH OFFSET :LOW'
when 'oracle'
pieces[''] =
'
WHERE
(
rn >' + (@sequence > 1 ? '' : '=') + ' :LOW
AND
rn <= :HIGH
)
'
else
pieces[''] = ' LIMIT :LOW, :HIGH'
end
statement = WidgetList::Utils::fill(pieces, statement)
if @items['rowLimit'].to_i >= @totalRows
@items['bindVarsLegacy']['LOW'] = 0
@sequence = 1
end
statement
end
def strip_aliases(name='')
name = (name.include?(' ') ? name.split(' ').last : name)
((name.include?('.')) ? name.split('.').last.gsub(/'||"/,'') : name.gsub(/'||"/,''))
end
def auto_column_name(name='')
name.gsub(/\_/,' ').gsub(/\-/,' ').capitalize
end
def get_total_records()
filter = ''
fields = {}
sql = ''
hashed = false
if !get_view().empty?
sql = WidgetList::Utils::fill({'' => get_view(),'' => !@items['groupBy'].empty? ? ' GROUP BY ' + @items['groupBy'] : '' }, @items['statement']['count']['view'])
end
if ! @filter.empty?
filter = ' WHERE ' + @filter
end
sql = WidgetList::Utils::fill({'' => filter}, sql)
if ! sql.empty?
if @items['showPagination']
cnt = get_database._select(sql, @items['bindVars'], @items['bindVarsLegacy'], @active_record_model)
if cnt > 0
if cnt > get_database.final_results['TOTAL'][0].to_i
#sometimes databases and queries run do not count(1) and group properly and instead
rows = cnt
else
rows = get_database.final_results['TOTAL'][0].to_i
end
else
rows = 0
end
if rows > 0
@totalRows = rows.to_i
end
else
rows = 1
end
else
rows = 0
end
if @totalRows > 0
@totalPages = (@totalRows.to_f / @items['rowLimit'].to_f).ceil()
end
rows
end
def self.determine_db_type(db_type)
if db_type.include?('://')
the_type, void = db_type.split("://")
if the_type == 'sqlite:/'
the_type = 'sqlite'
end
return the_type.downcase
else
begin
WidgetList::List::load_widget_list_database_yml()
if $widget_list_db_conf.key?(db_type)
if $widget_list_db_conf[db_type]['adapter'].include?('mysql')
return 'mysql'
elsif $widget_list_db_conf[db_type]['adapter'].include?('postgres')
return 'postgres'
elsif $widget_list_db_conf[db_type]['adapter'].include?('oracle')
return 'oracle'
elsif $widget_list_db_conf[db_type]['adapter'].include?('sqlite')
return 'sqlite'
elsif $widget_list_db_conf[db_type]['adapter'].include?('sqlserver')
return 'sqlserver'
elsif $widget_list_db_conf[db_type]['adapter'].include?('ibm')
return 'db2'
end
end
rescue
return ''
end
end
end
def self.load_widget_list_yml
if $widget_list_conf.nil?
$widget_list_conf = YAML.load(ERB.new(File.new(Rails.root.join("config", "widget-list.yml")).read).result)[Rails.env]
end
end
def self.load_widget_list_database_yml
if $widget_list_db_conf.nil?
$widget_list_db_conf = YAML.load(ERB.new(File.new(Rails.root.join("config", "database.yml")).read).result)
end
end
def self.get_db_type(primary=true)
WidgetList::List::load_widget_list_yml()
if primary
database_conn = $widget_list_conf[:primary]
else
database_conn = $widget_list_conf[:secondary]
end
WidgetList::List::determine_db_type(database_conn)
end
def get_db_type(primary=true)
WidgetList::List::get_db_type(primary)
end
def get_view
@active_record_model = false
if (@is_primary_sequel && @items['database'] == 'primary') || (@is_secondary_sequel && @items['database'] == 'secondary')
return @items['view']
elsif @items['view'].respond_to?('scoped') && @items['view'].scoped.respond_to?('to_sql')
@active_record_model = @items['view'].name.constantize
new_columns = []
@items['fields'].each { |column, fieldTitle|
if @items['fieldFunction'].key?(column) && !@items['fieldFunction'][column].empty?
# fieldFunction's should not have an alias, just the database functions
column = @items['fieldFunction'][column] + " " + column
end
new_columns << column
}
if @items['fieldsHidden'].class.name == 'Array' && !@items['fieldsHidden'].empty?
@items['fieldsHidden'].each { |columnPivot|
if !@items['fields'].key?(columnPivot)
if @items['fieldFunction'].key?(columnPivot) && !@items['fieldFunction'][columnPivot].empty?
# fieldFunction's should not have an alias, just the database functions
columnPivot = @items['fieldFunction'][columnPivot] + " " + columnPivot
end
new_columns << columnPivot
end
}
elsif @items['fieldsHidden'].class.name == 'Hash' && !@items['fieldsHidden'].empty?
@items['fieldsHidden'].each { |columnPivot|
if !@items['fields'].key?(columnPivot[0])
if @items['fieldFunction'].key?(columnPivot[0]) && !@items['fieldFunction'][columnPivot[0]].empty?
# fieldFunction's should not have an alias, just the database functions
columnPivot[0] = @items['fieldFunction'][columnPivot[0]] + " " + columnPivot[0]
end
new_columns << columnPivot[0]
end
}
end
view = @items['view'].scoped.to_sql
sql_from = view[view.index(/FROM/),view.length]
view = "SELECT #{new_columns.join(',')} " + sql_from
where = ''
if !@items['groupBy'].empty?
where = ''
end
return "( #{view} #{where} ) a"
else
return ""
end
end
def connect
@has_connected = true
begin
if Rails.root.join("config", "widget-list.yml").file?
WidgetList::List::load_widget_list_yml()
if $widget_list_conf.nil?
throw 'Configuration file widget-list.yml has no data. Check that (' + Rails.env + ') Rails.env matches the pointers in the file'
end
@primary_conn = $widget_list_conf[:primary]
@secondary_conn = $widget_list_conf[:secondary]
else
throw 'widget-list.yml not found'
end
@is_primary_sequel = true
@is_secondary_sequel = true
if @primary_conn != false && ! @primary_conn.include?(':/')
@is_primary_sequel = false
end
if @secondary_conn != false && !@secondary_conn.include?(':/')
@is_secondary_sequel = false
end
if @primary_conn != false
if @primary_conn.include?(':/')
@widget_list_sequel_conn = Sequel.connect(@primary_conn)
@widget_list_sequel_conn.db_type = WidgetList::List::determine_db_type(@primary_conn)
else
@widget_list_ar_conn = WidgetListActiveRecord.new
@widget_list_ar_conn.db_type = WidgetList::List::determine_db_type(@primary_conn)
end
end
if @secondary_conn != false
if @secondary_conn.include?(':/')
@widget_list_sequel_conn2 = Sequel.connect(@secondary_conn)
@widget_list_sequel_conn2.db_type = WidgetList::List::determine_db_type(@secondary_conn)
else
@widget_list_ar_conn2 = WidgetListActiveRecord.new
@widget_list_ar_conn2.db_type = WidgetList::List::determine_db_type(@secondary_conn)
end
end
rescue Exception => e
Rails.logger.info "widget-list.yml and connection to @widget_list_sequel_conn or @widget_list_sequel_conn2 failed. Please fix and try again (" + e.to_s + ")"
end
end
def self.is_sequel(primary)
WidgetList::List::load_widget_list_yml()
if primary
database_conn = $widget_list_conf[:primary]
else
database_conn = $widget_list_conf[:secondary]
end
is_sequel = true
if database_conn != false && ! database_conn.include?('://')
is_sequel = false
end
return is_sequel
end
def self.get_sequel(primary=true)
WidgetList::List::load_widget_list_yml()
if primary
Sequel.connect($widget_list_conf[:primary])
else
Sequel.connect($widget_list_conf[:secondary])
end
end
def get_database
if @has_connected.nil?
connect
end
if @is_primary_sequel && @widget_list_sequel_conn.class.name.to_s.split('::').first == 'Sequel' && @current_db_selection == 'primary' || @current_db_selection.nil?
@widget_list_sequel_conn.test_connection
end
if @is_secondary_sequel && @widget_list_sequel_conn2.class.name.to_s.split('::').first == 'Sequel' && @current_db_selection == 'secondary'
@widget_list_sequel_conn2.test_connection
end
case @current_db_selection
when 'primary'
return (@is_primary_sequel) ? @widget_list_sequel_conn : @widget_list_ar_conn
when 'secondary'
return (@is_secondary_sequel) ? @widget_list_sequel_conn2 : @widget_list_ar_conn2
else
return (@is_primary_sequel) ? @widget_list_sequel_conn : @widget_list_ar_conn
end
end
end
end