User Grid (basic) Time Sheets Grid (advanced)

Developer Project Report hours
Eleonore Wisozk repudiandae officiis qui 54.0
Imelda Heidenreich repudiandae officiis qui 54.0
Tami Gibson suscipit consectetur beatae 54.0
Li Considine repudiandae officiis qui 54.0
Rossana Schneider perspiciatis totam perferendis 54.0
Gwendolyn Satterfield repudiandae officiis qui 54.0
Jarvis Ryan quibusdam sed sit 55.0
Blake Hoppe animi aperiam tenetur 55.0
Clifton Hintz animi aperiam tenetur 55.0
Tami Gibson odio velit repudiandae 55.0
Almeta Adams perspiciatis totam perferendis 55.0
Tess Nikolaus quibusdam sed sit 55.0
Jon Lindgren suscipit consectetur beatae 55.0
Reinaldo Heidenreich animi aperiam tenetur 55.0
Myriam Von doloribus hic corporis 55.0
Elenora Brakus eum amet quia 55.0
Verla Friesen eum amet quia 55.0
Milagros Lemke repudiandae officiis qui 55.0
Gonzalo Blanda animi aperiam tenetur 55.0
Cathey Prohaska quibusdam sed sit 55.0
Carlota Gottlieb quibusdam sed sit 55.0
Bridgett Reilly eum amet quia 55.0
Thaddeus Stanton vitae eum pariatur 55.0
Shane Glover eum amet quia 55.0
Felisa Jaskolski saepe hic temporibus 55.0

Grid:

class TimeEntriesGrid < BaseGrid

  #
  # Scope
  #

  scope do
    User.select(
      "users.name",
      "projects.name as project_name",
      "accounts.name as account_name",
      "sum(time_entries.hours) as report_hours"
    ).joins(
      time_entries: {project: :account}
    ).group("projects.name", "users.name", "accounts.name").
    order("users.name")
  end


  #
  # Filters
  #

  filter(
    :project_id, :enum,
    :select => :project_id_select,
    :multiple => true,
    :include_blank => false
  ) do |value|
    self.where(:time_entries => {:project_id => value})
  end


  filter(
    :year, :enum,
    :select => :year_select,
    :include_blank => false,
    :default => lambda {Date.today.year}
  ) do |value|
    self.where([
      "extract(year from time_entries.date) = ?",
      value.to_i
    ])
  end

  filter(
    :month, :enum,
    :select => :month_select,
    :include_blank => false,
    :default => lambda {Date.today.month}
  ) do |value|

    self.where([
      "extract(month from time_entries.date) = ?",
      value.to_i
    ])
  end


  #
  # Columns
  #

  column(:user_name, :header => "Developer", :order => "users.name") do
    self.name
  end
  column(:project_name, :header => "Project", :order => "projects.name")
  column(
    :account_name,
    :header => "Company",
    :order => "accounts.name",
  ) do |model|
    format(model.account_name) do
      render :partial => "time_entries/company", :locals => {:model => model}
    end
  end

  column(:report_hours, order: "sum(time_entries.hours)")

  protected

  def year_select
    TimeEntry.all.any? ? (TimeEntry.minimum(:date).year..TimeEntry.maximum(:date).year) : []
  end
  def month_select
    Date::MONTHNAMES[1..12].enum_for(:each_with_index).collect {|name, index| [name, index + 1]}
  end

  def project_id_select
    Project.all.map {|p| [p.name, p.id]}
  end
end

Controller:

class TimeEntriesController < ApplicationController

  def index
    @time_entries_grid = TimeEntriesGrid.new(params[:g]) do |scope|
      scope.page(params[:page] )
    end
  end
end

View:

.grid-index-grid
  %div{class: 'overflow-x-auto p-4'}
    = datagrid_form_for @time_entries_grid, url: time_entries_path
    %br/
    = datagrid_table(@time_entries_grid)
    = paginate @time_entries_grid.assets, window: 2
  %div
    = render :partial => "shared/source", :object => @time_entries_grid