Merge pull request #4731 from opf/feature/enhanced_members_screen
Enhanced Members Screenpull/4741/merge
commit
8378baeb89
@ -0,0 +1,38 @@ |
||||
module Members |
||||
class RoleFormCell < ::RailsCell |
||||
include RemovedJsHelpersHelper |
||||
|
||||
options :row, :params, :roles |
||||
|
||||
def member |
||||
model |
||||
end |
||||
|
||||
def form_url |
||||
url_for form_url_hash |
||||
end |
||||
|
||||
def form_url_hash |
||||
{ |
||||
controller: '/members', |
||||
action: 'update', |
||||
id: member.id, |
||||
page: params[:page], |
||||
per_page: params[:per_page] |
||||
} |
||||
end |
||||
|
||||
def role_checkbox(role) |
||||
check_box_tag 'member[role_ids][]', |
||||
role.id, |
||||
member.roles.include?(role), |
||||
disabled: role_disabled?(role) |
||||
end |
||||
|
||||
def role_disabled?(role) |
||||
member |
||||
.member_roles |
||||
.detect { |mr| mr.role_id == role.id && !mr.inherited_from.nil? } |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,142 @@ |
||||
module Members |
||||
class RowCell < ::RowCell |
||||
property :user |
||||
|
||||
def member |
||||
model |
||||
end |
||||
|
||||
def row_css_id |
||||
"member-#{member.id}" |
||||
end |
||||
|
||||
def row_css_class |
||||
group = user ? "" : "group" |
||||
|
||||
"member #{group}".strip |
||||
end |
||||
|
||||
def lastname |
||||
user.lastname if user |
||||
end |
||||
|
||||
def firstname |
||||
user.firstname if user |
||||
end |
||||
|
||||
def mail |
||||
if user |
||||
link = mail_to(user.mail) |
||||
|
||||
if member.user && member.user.invited? |
||||
i = content_tag "i", "", title: t("text_user_invited"), class: "icon icon-mail1" |
||||
|
||||
link + i |
||||
else |
||||
link |
||||
end |
||||
end |
||||
end |
||||
|
||||
def roles |
||||
label = h member.roles.sort.collect(&:name).join(', ') |
||||
span = content_tag "span", label, id: "member-#{member.id}-roles" |
||||
|
||||
if may_update? |
||||
span + role_form_cell.call |
||||
else |
||||
span |
||||
end |
||||
end |
||||
|
||||
def role_form_cell |
||||
Members::RoleFormCell.new( |
||||
member, |
||||
row: self, |
||||
params: controller.params, |
||||
roles: table.available_roles, |
||||
context: { controller: controller } |
||||
) |
||||
end |
||||
|
||||
def groups |
||||
if user |
||||
user.groups.map(&:name).join(", ") |
||||
else |
||||
model.principal.name |
||||
end |
||||
end |
||||
|
||||
def status |
||||
I18n.t("status_#{model.principal.status_name}") |
||||
end |
||||
|
||||
def may_update? |
||||
table.authorize_update |
||||
end |
||||
|
||||
def button_links |
||||
if may_update? |
||||
[edit_link, delete_link].compact |
||||
else |
||||
[] |
||||
end |
||||
end |
||||
|
||||
def edit_link |
||||
link_to_function( |
||||
'', |
||||
edit_javascript, |
||||
class: 'icon icon-edit', |
||||
title: t(:button_edit) |
||||
) |
||||
end |
||||
|
||||
def edit_javascript |
||||
"jQuery('##{roles_css_id}').hide(); jQuery('##{roles_css_id}-form').show();" |
||||
end |
||||
|
||||
def cancel_edit_javascript |
||||
"jQuery('##{roles_css_id}').show(); jQuery('##{roles_css_id}-form').hide();" |
||||
end |
||||
|
||||
def roles_css_id |
||||
"member-#{member.id}-roles" |
||||
end |
||||
|
||||
def delete_link |
||||
delete_class, delete_title = delete_link_class_and_title |
||||
|
||||
link_to( |
||||
'', |
||||
{ controller: '/members', action: 'destroy', id: model, page: params[:page] }, |
||||
method: :delete, |
||||
data: { confirm: delete_link_confirmation }, |
||||
title: delete_title, |
||||
class: delete_class |
||||
) if model.deletable? |
||||
end |
||||
|
||||
def delete_link_class_and_title |
||||
if model.disposable? |
||||
['icon icon-delete', I18n.t(:title_remove_and_delete_user)] |
||||
else |
||||
['icon icon-remove', I18n.t(:button_remove)] |
||||
end |
||||
end |
||||
|
||||
def delete_link_confirmation |
||||
if !User.current.admin? && model.include?(User.current) |
||||
t(:text_own_membership_delete_confirmation) |
||||
end |
||||
end |
||||
|
||||
def column_css_class(column) |
||||
if column == :mail |
||||
"email" |
||||
else |
||||
super |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,66 @@ |
||||
module Members |
||||
class TableCell < ::TableCell |
||||
options :authorize_update, :available_roles |
||||
columns :lastname, :firstname, :mail, :roles, :groups, :status |
||||
|
||||
def initial_sort |
||||
[:lastname, :desc] |
||||
end |
||||
|
||||
def headers |
||||
columns.map do |name| |
||||
[name.to_s, header_options(name)] |
||||
end |
||||
end |
||||
|
||||
def header_options(name) |
||||
{ caption: User.human_attribute_name(name) } |
||||
end |
||||
|
||||
## |
||||
# Adjusts the order so that groups always come first. |
||||
# Also implements sorting by group which is not trivial |
||||
# due to it being a relation via 3 corners (member -> group_users -> users). |
||||
def sort_collection(query) |
||||
order_by = fix_roles_order(fix_groups_order(sort_clause)) |
||||
|
||||
join_group(sort_clause, order_by_type_first(query)).order(order_by) |
||||
end |
||||
|
||||
def order_by_type_first(query) |
||||
query.order("users.type ASC") |
||||
end |
||||
|
||||
def join_group(sort_clause, query) |
||||
if sort_clause =~ /groups/ |
||||
join_group_lastname query |
||||
else |
||||
query |
||||
end |
||||
end |
||||
|
||||
def fix_groups_order(sort_clause) |
||||
sort_clause.gsub /groups/, "groups.group_name" |
||||
end |
||||
|
||||
def fix_roles_order(sort_clause) |
||||
sort_clause.gsub /roles/, "roles.name" |
||||
end |
||||
|
||||
## |
||||
# Joins the necessary columns to be able to sort by group name. |
||||
# The subquery and renaming of the column is necessary to avoid naming conflicts |
||||
# with the already joined users table. |
||||
def join_group_lastname(query) |
||||
query |
||||
.joins( |
||||
" |
||||
LEFT JOIN group_users AS group_users |
||||
ON group_users.user_id = members.user_id |
||||
LEFT JOIN (SELECT id, lastname AS group_name FROM users) AS groups |
||||
ON groups.id = group_users.group_id |
||||
" |
||||
) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,35 @@ |
||||
module Members |
||||
class UserFilterCell < ::UserFilterCell |
||||
class << self |
||||
def filter_name_condition |
||||
super.gsub /lastname|firstname|mail/, "users.\\0" |
||||
end |
||||
|
||||
def filter_name_columns |
||||
[:lastname, :firstname, :mail] |
||||
end |
||||
|
||||
def filter_status_condition |
||||
super.sub /status/, "users.\\0" |
||||
end |
||||
|
||||
def filter_group_condition |
||||
# we want to list both the filtered group itself if a member (left of OR) |
||||
# and users of that group (right of OR) |
||||
super.sub /group_id/, "users.id = :group_id OR group_users.\\0" |
||||
end |
||||
|
||||
def join_group_users(query) |
||||
query # it will be joined by the table already |
||||
end |
||||
|
||||
def filter_role_condition |
||||
super.sub /role_id/, "member_roles.\\0" |
||||
end |
||||
|
||||
def join_role(query) |
||||
query # it will be joined by the table already |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,31 @@ |
||||
class RailsCell < Cell::ViewModel |
||||
include Escaped |
||||
include ApplicationHelper |
||||
include ActionView::Helpers::TranslationHelper |
||||
|
||||
self.view_paths = ['app/cells/views'] |
||||
|
||||
# We don't include ActionView::Helpers wholesale because |
||||
# this would override Cell's own render method and |
||||
# subsequently break everything. |
||||
|
||||
def self.options(*names) |
||||
names.each do |name| |
||||
define_method(name) do |
||||
options[name] |
||||
end |
||||
end |
||||
end |
||||
|
||||
def show |
||||
render |
||||
end |
||||
|
||||
def controller |
||||
context[:controller] |
||||
end |
||||
|
||||
def get_html_title |
||||
@html_title |
||||
end |
||||
end |
@ -0,0 +1,43 @@ |
||||
## |
||||
# Abstract cell. Subclass this for a concrete row cell. |
||||
class RowCell < RailsCell |
||||
include RemovedJsHelpersHelper |
||||
|
||||
def table |
||||
options[:table] |
||||
end |
||||
|
||||
def columns |
||||
table.columns |
||||
end |
||||
|
||||
def column_value(column) |
||||
send column |
||||
end |
||||
|
||||
def row_css_id |
||||
nil |
||||
end |
||||
|
||||
def row_css_class |
||||
"" |
||||
end |
||||
|
||||
def column_css_class(column) |
||||
column_css_classes[column] |
||||
end |
||||
|
||||
def column_css_classes |
||||
entries = columns.map { |name| [name, name] } |
||||
|
||||
Hash[entries] |
||||
end |
||||
|
||||
def column_title(_column) |
||||
nil |
||||
end |
||||
|
||||
def button_links |
||||
[] |
||||
end |
||||
end |
@ -0,0 +1,121 @@ |
||||
## |
||||
# Abstract cell. Subclass this for a concrete table. |
||||
class TableCell < RailsCell |
||||
include UsersHelper |
||||
include SortHelper |
||||
include PaginationHelper |
||||
include WillPaginate::ActionView |
||||
|
||||
options :groups, :roles, :status, :project |
||||
|
||||
class << self |
||||
## |
||||
# Names used by sort logic meaning these names |
||||
# will be used directly in the generated SQL queries. |
||||
# |
||||
# This will also generate getters for these columns |
||||
# on the RowCell class for this TableCell. The getters |
||||
# are calling the same methods on the model for the Row. |
||||
# E.g.: |
||||
# |
||||
# Users::TableCell.columns :weight |
||||
# model = Struct.new(:weight).new 42 |
||||
# row_cell = Users::Table::RowCell.new model |
||||
# row_cell.weight == model.weight |
||||
def columns(*names) |
||||
return Array(@columns) if names.empty? |
||||
|
||||
@columns = names |
||||
rc = row_class |
||||
|
||||
names.each do |name| |
||||
rc.property name |
||||
end |
||||
end |
||||
|
||||
def add_column(name) |
||||
@columns = Array(@columns) + [name] |
||||
row_class.property name |
||||
end |
||||
|
||||
def row_class |
||||
mod = namespace || "Table" |
||||
class_name = "RowCell" |
||||
|
||||
"#{mod}::#{class_name}".constantize |
||||
rescue NameError |
||||
raise( |
||||
NameError, |
||||
"#{mod}::#{class_name} required by #{mod}::TableCell not defined. " + |
||||
"Expected to be defined in `app/cells/#{mod.underscore}/#{class_name.underscore}.rb`." |
||||
) |
||||
end |
||||
|
||||
def namespace |
||||
name.split("::")[0..-2].join("::").presence |
||||
end |
||||
end |
||||
|
||||
def initialize(rows, opts = {}, &block) |
||||
super |
||||
|
||||
sort_init *initial_sort.map(&:to_s) |
||||
sort_update columns.map(&:to_s) |
||||
@model = sort_and_paginate_collection model |
||||
end |
||||
|
||||
def sort_and_paginate_collection(ar_collection) |
||||
return ar_collection unless ar_collection.is_a? ActiveRecord::QueryMethods |
||||
|
||||
paginate_collection sort_collection(ar_collection) |
||||
end |
||||
|
||||
def sort_collection(query) |
||||
query.order sort_clause # sort_clause from SortHelper |
||||
end |
||||
|
||||
def paginate_collection(query) |
||||
query |
||||
.page(page_param(controller.params)) |
||||
.per_page(per_page_param) |
||||
end |
||||
|
||||
def show |
||||
render |
||||
end |
||||
|
||||
def rows |
||||
model |
||||
end |
||||
|
||||
def columns |
||||
self.class.columns |
||||
end |
||||
|
||||
def render_row(row) |
||||
prefix = (self.class.namespace || "table").split("::").map(&:downcase).join("/") |
||||
cell("#{prefix}/row", row, table: self).call |
||||
end |
||||
|
||||
def initial_sort |
||||
[columns.first, :asc] |
||||
end |
||||
|
||||
## |
||||
# An array listing each column and its respective options. |
||||
# |
||||
# @return Array<Array> |
||||
def headers |
||||
columns.map { |name| [name.to_s, {}] } |
||||
end |
||||
|
||||
# required by the sort helper |
||||
|
||||
def controller_name |
||||
controller.controller_name |
||||
end |
||||
|
||||
def action_name |
||||
controller.action_name |
||||
end |
||||
end |
@ -0,0 +1,100 @@ |
||||
class UserFilterCell < RailsCell |
||||
include UsersHelper |
||||
include ActionView::Helpers::FormOptionsHelper |
||||
|
||||
options :groups, :status, :roles |
||||
|
||||
class << self |
||||
def filter(query, params) |
||||
[query] |
||||
.map { |q| filter_name q, params[:name] } |
||||
.map { |q| filter_status q, status_param(params) } |
||||
.map { |q| filter_group q, params[:group_id] } |
||||
.map { |q| filter_role q, params[:role_id] } |
||||
.first |
||||
end |
||||
|
||||
## |
||||
# Returns the selected status from the parameters |
||||
# or the default status to be filtered by (active) |
||||
# if no status is given. |
||||
def status_param(params) |
||||
params[:status].presence || User::STATUSES[:active] |
||||
end |
||||
|
||||
def filter_name(query, name) |
||||
if name.present? |
||||
query.where(filter_name_condition, name: "%#{name.downcase}%") |
||||
else |
||||
query |
||||
end |
||||
end |
||||
|
||||
def filter_name_condition |
||||
filter_name_columns |
||||
.map { |col| "LOWER(#{col}) LIKE :name" } |
||||
.join(" OR ") |
||||
end |
||||
|
||||
def filter_name_columns |
||||
[:lastname, :firstname, :mail, :login] |
||||
end |
||||
|
||||
def filter_status(query, status) |
||||
q = specific_filter_status(query, status) || query |
||||
q = User.create_blocked_scope q, false if status.to_i == User::STATUSES[:active] |
||||
|
||||
q.where("status <> :builtin", builtin: User::STATUSES[:builtin]) |
||||
end |
||||
|
||||
def specific_filter_status(query, status) |
||||
if status.present? |
||||
if status == "blocked" |
||||
User.create_blocked_scope query, true |
||||
elsif status != "all" |
||||
query.where(filter_status_condition, status: status.to_i) |
||||
end |
||||
end |
||||
end |
||||
|
||||
def filter_status_condition |
||||
"status = :status" |
||||
end |
||||
|
||||
def filter_group(query, group_id) |
||||
if group_id.present? |
||||
join_group_users(query).where(filter_group_condition, group_id: group_id.to_i) |
||||
else |
||||
query |
||||
end |
||||
end |
||||
|
||||
def join_group_users(query) |
||||
query.joins("LEFT JOIN group_users ON group_users.user_id = users.id") |
||||
end |
||||
|
||||
def filter_group_condition |
||||
"group_id = :group_id" |
||||
end |
||||
|
||||
def filter_role(query, role_id) |
||||
if role_id.present? |
||||
join_role(query).where(filter_role_condition, role_id: role_id.to_i) |
||||
else |
||||
query |
||||
end |
||||
end |
||||
|
||||
def filter_role_condition |
||||
"role_id = :role_id" |
||||
end |
||||
|
||||
def join_role(query) |
||||
query.joins(members: { member_roles: :role }) |
||||
end |
||||
end |
||||
|
||||
def params |
||||
model |
||||
end |
||||
end |
@ -0,0 +1,58 @@ |
||||
module Users |
||||
class RowCell < ::RowCell |
||||
include AvatarHelper |
||||
include UsersHelper |
||||
|
||||
def user |
||||
model |
||||
end |
||||
|
||||
def row_css_class |
||||
status = %w(anon active registered locked)[user.status] |
||||
blocked = "blocked" if user.failed_too_many_recent_login_attempts? |
||||
|
||||
["user", status, blocked].compact.join(" ") |
||||
end |
||||
|
||||
def login |
||||
icon = avatar user, class: 'avatar-mini' |
||||
link = link_to h(user.login), edit_user_path(user) |
||||
|
||||
icon + link |
||||
end |
||||
|
||||
def mail |
||||
mail_to user.mail |
||||
end |
||||
|
||||
def admin |
||||
checked_image user.admin? |
||||
end |
||||
|
||||
def last_login_on |
||||
format_time user.last_login_on unless user.last_login_on.nil? |
||||
end |
||||
|
||||
def status |
||||
full_user_status user |
||||
end |
||||
|
||||
def button_links |
||||
[status_link].compact |
||||
end |
||||
|
||||
def status_link |
||||
change_user_status_links user unless user.id == table.current_user.id |
||||
end |
||||
|
||||
def column_css_class(column) |
||||
if column == :mail |
||||
"email" |
||||
elsif column == :login |
||||
"username" |
||||
else |
||||
super |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,28 @@ |
||||
module Users |
||||
class TableCell < ::TableCell |
||||
options :current_user # adds this option to those of the base class |
||||
columns :login, :firstname, :lastname, :mail, :admin, :created_on, :last_login_on |
||||
|
||||
def initial_sort |
||||
[:login, :asc] |
||||
end |
||||
|
||||
def headers |
||||
columns.map do |name| |
||||
[name.to_s, header_options(name)] |
||||
end |
||||
end |
||||
|
||||
def header_options(name) |
||||
options = { caption: User.human_attribute_name(name) } |
||||
|
||||
options[:default_order] = 'desc' if desc_by_default.include? name |
||||
|
||||
options |
||||
end |
||||
|
||||
def desc_by_default |
||||
[:admin, :created_on, :last_login_on] |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,7 @@ |
||||
module Users |
||||
class UserFilterCell < ::UserFilterCell |
||||
def filter_role(query, role_id) |
||||
super.uniq |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,23 @@ |
||||
<%# We're not using the rails form helper here on purpose. |
||||
# It simply doesn't mix at all with cells views. |
||||
#%> |
||||
<form action="<%= form_url %>" |
||||
method="post" |
||||
id="<%= row.roles_css_id %>-form" |
||||
class="hol" |
||||
style="display:none" |
||||
accept-charset="UTF-8" |
||||
> |
||||
<input name="utf8" type="hidden" value="✓"> |
||||
<input type="hidden" name="_method" value="put"> |
||||
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>"> |
||||
<p> |
||||
<% roles.each do |role| %> |
||||
<label><%= role_checkbox(role) %> <%= h role %></label> |
||||
<% end %> |
||||
</p> |
||||
<%= hidden_field_tag "member[role_ids][]", "" %> |
||||
<p> |
||||
<%= submit_tag t(:button_change), class: "button -highlight -small" %> |
||||
<%= link_to_function t(:button_cancel), row.cancel_edit_javascript, class: 'button -small' %> |
||||
</form> |
@ -0,0 +1,43 @@ |
||||
<%#-- copyright |
||||
OpenProject is a project management system. |
||||
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License version 3. |
||||
|
||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
Copyright (C) 2010-2013 the ChiliProject Team |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License |
||||
as published by the Free Software Foundation; either version 2 |
||||
of the License, or (at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program; if not, write to the Free Software |
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
||||
See doc/COPYRIGHT.rdoc for more details. |
||||
|
||||
++#%> |
||||
|
||||
<tr <%= "id=\"#{row_css_id}\"" if row_css_id %> class="<%= row_css_class %>"> |
||||
<% columns.each do |column| %> |
||||
<td class="<%= column_css_class(column) %>" |
||||
<%= title = column_title(column); "title=\"#{title}\"" if title %> |
||||
> |
||||
<%= column_value(column) %> |
||||
</td> |
||||
<% end %> |
||||
<td class="buttons"> |
||||
<% button_links.each do |link| %> |
||||
<%= link %> |
||||
<% end %> |
||||
</td> |
||||
</tr> |
@ -0,0 +1,58 @@ |
||||
<%#-- copyright |
||||
OpenProject is a project management system. |
||||
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License version 3. |
||||
|
||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
Copyright (C) 2010-2013 the ChiliProject Team |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License |
||||
as published by the Free Software Foundation; either version 2 |
||||
of the License, or (at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program; if not, write to the Free Software |
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
||||
See doc/COPYRIGHT.rdoc for more details. |
||||
|
||||
++#%> |
||||
|
||||
<div class="generic-table--container"> |
||||
<div class="generic-table--results-container"> |
||||
<table interactive-table class="generic-table"> |
||||
<colgroup> |
||||
<% headers.each do |_name, _options| %> |
||||
<col highlight-col> |
||||
<% end %> |
||||
<col> |
||||
</colgroup> |
||||
<thead> |
||||
<tr> |
||||
<% headers.each do |name, options| %> |
||||
<%= sort_header_tag name, options %> |
||||
<% end %> |
||||
<th> |
||||
<%# last column for buttons %> |
||||
</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% for row in rows -%> |
||||
<%= render_row row %> |
||||
<% end -%> |
||||
</tbody> |
||||
</table> |
||||
<div class="generic-table--header-background"></div> |
||||
</div> |
||||
</div> |
||||
<%= pagination_links_full rows %> |
@ -0,0 +1,85 @@ |
||||
<%#-- copyright |
||||
OpenProject is a project management system. |
||||
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License version 3. |
||||
|
||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
Copyright (C) 2010-2013 the ChiliProject Team |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License |
||||
as published by the Free Software Foundation; either version 2 |
||||
of the License, or (at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program; if not, write to the Free Software |
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
||||
See doc/COPYRIGHT.rdoc for more details. |
||||
|
||||
++#%> |
||||
|
||||
<%= form_tag({}, method: :get) do %> |
||||
<fieldset class="simple-filters--container"> |
||||
<legend><%= t(:label_filter_plural) %></legend> |
||||
<ul class="simple-filters--filters <%= groups.present? ? "-columns-3" : '' %>"> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='status'><%= User.human_attribute_name(:status) %>:</label> |
||||
<%= select_tag 'status', users_status_options_for_select(status), onchange: "this.form.submit(); return false;", class: 'simple-filters--filter-value' %> |
||||
</li> |
||||
<% if groups.present? %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='group_id'><%= Group.model_name.human %>:</label> |
||||
<%= collection_select :group, |
||||
:id, |
||||
groups, |
||||
:id, |
||||
:name, |
||||
{ include_blank: true, |
||||
selected: params[:group_id].to_i }, |
||||
{ name: "group_id", |
||||
onchange: "this.form.submit(); return false;", |
||||
class: 'simple-filters--filter-value' } %> |
||||
</li> |
||||
<% end %> |
||||
<% if roles.present? %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='role_id'><%= Role.model_name.human %>:</label> |
||||
<%= |
||||
collection_select( |
||||
:role, |
||||
:id, |
||||
roles, |
||||
:id, |
||||
:name, |
||||
{ |
||||
include_blank: true, |
||||
selected: params[:role_id].to_i |
||||
}, |
||||
{ |
||||
name: "role_id", |
||||
onchange: "this.form.submit(); return false;", |
||||
class: 'simple-filters--filter-value' |
||||
}) |
||||
%> |
||||
</li> |
||||
<% end %> |
||||
<li class="simple-filters--filter"> |
||||
<label class='simple-filters--filter-name' for='name'><%= User.human_attribute_name :name %>:</label> |
||||
<%= text_field_tag 'name', params[:name], class: 'simple-filters--filter-value' %> |
||||
</li> |
||||
<li class="simple-filters--controls"> |
||||
<%= submit_tag t(:button_apply), class: 'button -highlight -small', name: nil %> |
||||
<%= link_to t(:button_clear), users_path, class: 'button -small -with-icon icon-undo' %> |
||||
</li> |
||||
</ul> |
||||
</fieldset> |
||||
<% end %> |
@ -0,0 +1,14 @@ |
||||
module CellsHelper |
||||
## |
||||
# Use this to render cells directly as the view for a controller |
||||
# instead of a standard rails view. |
||||
def render_cell(name, model, opts = {}) |
||||
opts[:context] = { controller: self } if is_a? ActionController::Base |
||||
render_options = opts.delete(:render_options) || {} |
||||
|
||||
cell = cell(name, model, opts) |
||||
rendered = cell.call |
||||
|
||||
render render_options.merge(text: rendered) |
||||
end |
||||
end |
Loading…
Reference in new issue