Skip to content

Commit

Permalink
Representation to variant
Browse files Browse the repository at this point in the history
  • Loading branch information
gryphon committed Oct 13, 2023
1 parent 3e33d0e commit 5386946
Show file tree
Hide file tree
Showing 24 changed files with 442 additions and 189 deletions.
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Invoke this in your index to display table:

Options available are:

* Second parameter is variant (can be skipped if you dont use variants)
* ```collection``` is the only required option. Contains paged collection from your controller
* ```parent``` parent resource for inherited routes
* ```skip_fields``` array of field names as symbols. Removes specific fields from table
Expand Down Expand Up @@ -120,9 +121,9 @@ If helper is not accessible table will try to render item via following methods:
* Raw text attributes
* Boolean attribute via ```boolean_icon``` helper. Uses bootstrap icons and can be overriden

If you use representation, following helper will have the priority over all options:
* ```#{singular_model_name}_#{representation}_#{field}_field```
* ```#{singular_model_name}_#{representation}_#{field}```
If you use variant, following helper will have the priority over all options:
* ```#{singular_model_name}_#{variant}_#{field}_field```
* ```#{singular_model_name}_#{variant}_#{field}```

## Displaying custom actions

Expand All @@ -138,17 +139,17 @@ Search Settings button will show up automatically if you have at least one custo

You can also use settings button separatelly. It uses Rails turbo and you need to declare ```turbo-modal``` Turbo Tag within your HTML body.

## Representations
## Variants

For each table you can declare additional representations (set of parameters to be saved to user customization).
For each table you can declare additional variants (set of parameters to be saved to user customization).

Important to note that you need to explicitly set list of available representations. Declare the following helper function:
Important to note that you need to explicitly set list of available variants. Declare the following helper function:

```{singular_model_name}_custom_table_fields```

Which returns the array of available representation.
Which returns the array of available variant.

Then just pass representation to filter and data helpers.
Then just pass variant to filter and data helpers.

## Table Stimulus helper

Expand Down Expand Up @@ -193,6 +194,10 @@ You can declare how each field is displayed. Just add it as block within field:
= fs.field :name do
= @instance.name.upcase

## Testing

Use ```custom_table_use_all_fields``` GET param with any value to show all available fields in your feature tests

## Development

Running tests: rspec
Expand Down
16 changes: 15 additions & 1 deletion app/assets/stylesheets/custom_table/table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,18 @@ table {
border-bottom: 1px solid #ddd;
margin-bottom: 4px !important;
}
}
}

.tree-opener {
.opened {
display: none;
}
&.opened {
.opened {
display: inline;
}
.closed {
display: none;
}
}
}
84 changes: 80 additions & 4 deletions app/controllers/concerns/custom_table_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,101 @@ def format_web
!(request.format.xlsx? || request.format.csv?)
end

def custom_table collection, representation = nil, default_sorts: "created_at desc", default_search: {}
def custom_table collection, variant = nil, default_sorts: "created_at desc", default_search: {}

@q = collection.ransack(params[:q])
@q = collection.ransack((params[:q] || {}).merge(default_search)) if @q.conditions.empty?

customization = helpers.custom_table_user_customization_for(collection.model, representation)
customization = helpers.custom_table_user_customization_for(collection.model, variant)
@q.sorts = customization&.dig(:sorts).presence || default_sorts if @q.sorts.empty?

collection = @q.result(distict: true)
# collection = collection.page(params[:page]).per(per_page) if format_web && paginate

if !current_user.nil?
current_user.save_custom_table_settings(collection.model, representation, per_page: params[:per]) if !params[:per].nil?
current_user.save_custom_table_settings(collection.model, representation, sorts: "#{@q.sorts[0].name} #{@q.sorts[0].dir}") if !params[:q].nil? && !params[:q][:s].nil? && !@q.nil? && !@q.sorts[0].nil? && !@q.sorts[0].name.nil?
current_user.save_custom_table_settings(collection.model, variant, per_page: params[:per]) if !params[:per].nil? && params[:do_not_save_settings].nil?
current_user.save_custom_table_settings(collection.model, variant, sorts: "#{@q.sorts[0].name} #{@q.sorts[0].dir}") if !params[:q].nil? && !params[:q][:s].nil? && !@q.nil? && !@q.sorts[0].nil? && !@q.sorts[0].name.nil? && params[:do_not_save_settings].nil?
end

return collection
end

def custom_table_export(format, collection, filename: nil)

filename ||= collection.model.model_name.plural

format.xlsx do
if collection.count > 1000
redirect_to params.permit!.merge({:format => :html}), alert: t("custom_table.huge_xlsx_alert", csv: helpers.link_to(t("custom_table.download_as_csv"), params.permit!.merge({:format => :csv})))
else
response.headers['Content-Disposition'] = "attachment; filename=\"#{filename}.xlsx\""
end
end

format.csv do
# Delete this header so that Rack knows to stream the content.
headers.delete("Content-Length")
# Do not cache results from this action.
headers["Cache-Control"] = "no-cache"
# Let the browser know that this file is a CSV.
headers['Content-Type'] = 'text/csv'
# Do not buffer the result when using proxy servers.
headers['X-Accel-Buffering'] = 'no'
# Set the filename
headers['Content-Disposition'] = "attachment; filename=\"#{filename}.csv\""

global_model_name = collection.model.model_name.singular

fields = helpers.custom_table_fields_definition_for(collection.model)

# Allow pre-defined fields for export
if !@fields.nil?
fields = fields.select { |k, _v| local_assigns[:fields].include?(k) }
end

@csv_enumerator ||= Enumerator.new do |yielder|

head = []

fields.each do |field, defs|
head.push (defs[:label].nil? ? collection.model.human_attribute_name(field) : defs[:label])
end

yielder << CSV.generate_line(head)

collection.find_each do |item|

row = []
model_name = item.model_name.singular # Allows to show different class models in one table!

fields.each do |field, defs|
next if defs[:table] == false

value = helpers.raw_field_value_for(item, field)

if [Date, ActiveSupport::TimeWithZone].include?(value.class)
value = value.to_date
end

row.push value
end

# Extra cols definition
if defined?(@extra_cols)
row += @extra_cols.call(item)
end

yielder << CSV.generate_line(row)
end
end

self.response_body = @csv_enumerator
end

end



private


Expand Down
30 changes: 15 additions & 15 deletions app/controllers/custom_table/settings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ class SettingsController < ::ApplicationController

def edit
@search_model = params[:id].constantize
@representation = params[:representation].presence
if !@representation.nil? && !helpers.custom_table_representations_for(@search_model).include?(@representation)
render status: 404, html: "No such representation: #{@representation}"
@variant = params[:variant].presence
if !@variant.nil? && !helpers.custom_table_variants_for(@search_model).include?(@variant)
render status: 404, html: "No such variant: #{@variant}"
return
end
end
Expand All @@ -21,13 +21,13 @@ def update
p = settings_params.to_h

model = p[:model].constantize
representation = p[:representation].presence
variant = p[:variant].presence

defs = helpers.custom_table_fields_definition_for(model, representation)
representations = helpers.custom_table_representations_for(model)
defs = helpers.custom_table_fields_definition_for(model, variant)
variants = helpers.custom_table_variants_for(model)

if !representation.nil? && !representations.include?(representation)
render status: 422, html: "No such representation: #{representation}"
if !variant.nil? && !variants.include?(variant)
render status: 422, html: "No such variant: #{variant}"
return
end

Expand All @@ -38,7 +38,7 @@ def update
p[:fields].reject!{|k,v| defs[k.to_sym].nil?} # Clearing unknown fields
p[:fields].each { |k, v| p[:fields][k] = (defs[k.to_sym][:appear] == :always) ? true : ActiveModel::Type::Boolean.new.cast(v) }

if current_user.save_custom_table_settings(model, representation, fields: p[:fields])
if current_user.save_custom_table_settings(model, variant, fields: p[:fields])
flash[:notice] = t("custom_table.customization_saved")
else
# optional_redirect_to main_app.root_path, alert: t("custom_table.cannot_save_customization")
Expand All @@ -50,17 +50,17 @@ def update
def destroy

model = params[:id].constantize
representation = params[:representation].presence
variant = params[:variant].presence

defs = helpers.custom_table_fields_definition_for(model)
representations = helpers.custom_table_representations_for(model)
variants = helpers.custom_table_variants_for(model)

if !representation.nil? && !representations.include?(representation)
render status: 422, html: "No such representation: #{representation}"
if !variant.nil? && !variants.include?(variant)
render status: 422, html: "No such variant: #{variant}"
return
end

if current_user.destroy_custom_table_settings(model, representation)
if current_user.destroy_custom_table_settings(model, variant)
flash[:notice] = t("custom_table.customization_saved")
else
# optional_redirect_to main_app.root_path, alert: t("custom_table.cannot_save_customization")
Expand All @@ -73,7 +73,7 @@ def destroy

# Only allow a list of trusted parameters through.
def settings_params
params.require(:user).permit(:model, :representation, { fields: {} })
params.require(:user).permit(:model, :variant, { fields: {} })
end

end
Expand Down

0 comments on commit 5386946

Please sign in to comment.