require "action_view" module Datagrid # @!visibility private class Renderer def self.for(template) new(template) end def initialize(template) @template = template end def format_value(grid, column, asset) if column.is_a?(String) || column.is_a?(Symbol) column = grid.column_by_name(column) end value = grid.html_value(column, @template, asset) url = column.options[:url] && column.options[:url].call(asset) if url @template.link_to(value, url) else value end end def form_for(grid, options = {}) options[:method] ||= :get options[:html] ||= {} options[:html][:class] ||= "datagrid-form #{@template.dom_class(grid)}" options[:as] ||= grid.param_name _render_partial('form', options[:partials], {:grid => grid, :options => options}) end def table(grid, assets, **options) options[:html] ||= {} options[:html][:class] ||= "datagrid #{@template.dom_class(grid)}" _render_partial('table', options[:partials], { grid: grid, options: options, assets: assets }) end def header(grid, options = {}) options[:order] = true unless options.has_key?(:order) _render_partial('head', options[:partials], { :grid => grid, :options => options }) end def rows(grid, assets = grid.assets, **options, &block) result = assets.map do |asset| row(grid, asset, **options, &block) end.to_a.join _safe(result) end def row(grid, asset, **options, &block) Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row| if block_given? return @template.capture(row, &block) end end end def order_for(grid, column, options = {}) _render_partial('order_for', options[:partials], { :grid => grid, :column => column }) end def order_path(grid, column, descending, request) column = grid.column_by_name(column) query = request ? request.query_parameters : {} ActionDispatch::Http::URL.path_for( path: request ? request.path : '/', params: query.merge(grid.query_params(order: column.name, descending: descending)) ) end private def _safe(string) string.respond_to?(:html_safe) ? string.html_safe : string end def _render_partial(partial_name, partials_path, locals = {}) @template.render({ :partial => File.join(partials_path || 'datagrid', partial_name), :locals => locals }) end end module Helper # Represents a datagrid row that provides access to column values for the given asset # @example # row = datagrid_row(grid, user) # row.class # => Datagrid::Helper::HtmlRow # row.first_name # => "<strong>Bogdan</strong>" # row.grid # => Grid object # row.asset # => User object # row.each do |value| # puts value # end class HtmlRow include Enumerable attr_reader :grid, :asset, :options # @!visibility private def initialize(renderer, grid, asset, options) @renderer = renderer @grid = grid @asset = asset @options = options end # @return [Object] a column value for given column name def get(column) @renderer.format_value(@grid, column, @asset) end # Iterates over all column values that are available in the row # param block [Proc] column value iterator def each(&block) (@options[:columns] || @grid.html_columns).each do |column| block.call(get(column)) end end def to_s @renderer.send(:_render_partial, 'row', options[:partials], { :grid => grid, :options => options, :asset => asset }) end protected def method_missing(method, *args, &blk) if column = @grid.column_by_name(method) get(column) else super end end end end end