Skip to content

Commit

Permalink
Fixes #19135 - Possibility to limit fields that are displayed
Browse files Browse the repository at this point in the history
  • Loading branch information
ofedoren committed Jun 30, 2018
1 parent f97d198 commit d395d79
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 54 deletions.
24 changes: 13 additions & 11 deletions lib/hammer_cli/output/adapter/abstract.rb
Expand Up @@ -6,10 +6,11 @@ def tags
[]
end

def initialize(context={}, formatters={})
def initialize(context = {}, formatters = {}, filters = {})
@context = context
@formatters = HammerCLI::Output::Formatters::FormatterLibrary.new(filter_formatters(formatters))
@paginate_by_default = true
@filters = field_filters(filters)
end

def paginate_by_default?
Expand Down Expand Up @@ -42,8 +43,8 @@ def print_collection(fields, collection)

protected

def field_filter
HammerCLI::Output::FieldFilter.new
def filter_fields(fields)
HammerCLI::Output::FieldFilter.new(fields, @filters)
end

def self.data_for_field(field, record)
Expand All @@ -70,14 +71,15 @@ def output_stream
$stdout
end

def displayable_fields(fields, record, compact_only: false)
fields.select do |field|
field_data = data_for_field(field, record)
if compact_only && !field_data.is_a?(HammerCLI::Output::DataMissing)
true
else
field.display?(field_data)
end
def field_filters(filters = {})
classes_filter = []
classes_filter << Fields::Id unless @context[:show_ids]
labels_filter = @context[:fields] || []
{
classes_filter: classes_filter,
labels_filter: labels_filter
}.merge(filters) do |_, old_filter, new_filter|
old_filter + new_filter
end
end

Expand Down
12 changes: 4 additions & 8 deletions lib/hammer_cli/output/adapter/base.rb
Expand Up @@ -21,17 +21,13 @@ def print_collection(fields, collection)

protected

def field_filter
filtered = []
filtered << Fields::Id unless @context[:show_ids]
HammerCLI::Output::FieldFilter.new(filtered)
end

def render_fields(fields, data)
output = ""

fields = field_filter.filter(fields)
fields = displayable_fields(fields, data)
fields = filter_fields(fields).filter_by_classes
.filter_by_labels
.filter_by_data(data)
.filtered_fields

label_width = label_width(fields)

Expand Down
10 changes: 7 additions & 3 deletions lib/hammer_cli/output/adapter/csv.rb
Expand Up @@ -135,7 +135,7 @@ def is_id?
end
end

def initialize(context={}, formatters={})
def initialize(context = {}, formatters = {}, filters = {})
super
@paginate_by_default = false
end
Expand All @@ -157,7 +157,11 @@ def print_record(fields, record)
end

def print_collection(fields, collection)
fields = displayable_fields(fields, collection.first, compact_only: true)
fields = filter_fields(fields).filter_by_classes
.filter_by_labels
.filter_by_data(collection.first,
compact_only: true)
.filtered_fields
rows = row_data(fields, collection)
# get headers using columns heuristic
headers = rows.map{ |r| Cell.headers(r, @context) }.max_by{ |headers| headers.size }
Expand Down Expand Up @@ -207,7 +211,7 @@ def generate(&block)
end

def default_headers(fields)
fields.select{ |f| !(f.class <= Fields::Id) || @context[:show_ids] }.map { |f| f.label }
fields.map(&:label)
end

end
Expand Down
19 changes: 10 additions & 9 deletions lib/hammer_cli/output/adapter/table.rb
Expand Up @@ -12,6 +12,11 @@ class Table < Abstract
LINE_SEPARATOR = '-|-'
COLUMN_SEPARATOR = ' | '

def initialize(context = {}, formatters = {}, filters = {})
super
@filters[:classes_filter] << Fields::ContainerField
end

def tags
[:screen, :flat]
end
Expand All @@ -21,9 +26,11 @@ def print_record(fields, record)
end

def print_collection(all_fields, collection)
fields = field_filter.filter(all_fields)
fields = displayable_fields(fields, collection.first, compact_only: true)

fields = filter_fields(all_fields).filter_by_classes
.filter_by_labels
.filter_by_data(collection.first,
compact_only: true)
.filtered_fields
formatted_collection = format_values(fields, collection)
# calculate hash of column widths (label -> width)
widths = calculate_widths(fields, formatted_collection)
Expand Down Expand Up @@ -101,12 +108,6 @@ def calculate_column_width(field, collection)
width
end

def field_filter
filtered = [Fields::ContainerField]
filtered << Fields::Id unless @context[:show_ids]
HammerCLI::Output::FieldFilter.new(filtered)
end

private

def max_width_for(field)
Expand Down
14 changes: 5 additions & 9 deletions lib/hammer_cli/output/adapter/tree_structure.rb
@@ -1,7 +1,7 @@
module HammerCLI::Output::Adapter
class TreeStructure < Abstract

def initialize(context={}, formatters={})
def initialize(context = {}, formatters = {}, filters = {})
super
@paginate_by_default = false
end
Expand All @@ -14,15 +14,11 @@ def prepare_collection(fields, collection)

protected

def field_filter
filtered = []
filtered << Fields::Id unless @context[:show_ids]
HammerCLI::Output::FieldFilter.new(filtered)
end

def render_fields(fields, data)
fields = field_filter.filter(fields)
fields = displayable_fields(fields, data)
fields = filter_fields(fields).filter_by_classes
.filter_by_labels
.filter_by_data(data)
.filtered_fields
fields.reduce({}) do |hash, field|
field_data = data_for_field(field, data)
next unless field.display?(field_data)
Expand Down
56 changes: 48 additions & 8 deletions lib/hammer_cli/output/field_filter.rb
Expand Up @@ -2,20 +2,60 @@ module HammerCLI::Output

class FieldFilter

def initialize(field_classes=[])
@field_classes = field_classes
attr_reader :fields, :filtered_fields
attr_accessor :classes_filter, :labels_filter, :data_filter

def initialize(fields = [], filters = {})
self.fields = fields
@classes_filter = filters[:classes_filter] || []
@labels_filter = (filters[:labels_filter] || []).map(&:downcase)
@data_filter = filters[:data_filter]
end

def fields=(fields)
@fields = fields || []
@filtered_fields = @fields.dup
end

def filter(fields)
fields = fields.clone
@field_classes.each do |cls|
fields.reject! do |f|
def filter_by_classes(classes = nil)
classes ||= @classes_filter
classes.each do |cls|
@filtered_fields.reject! do |f|
f.is_a? cls
end
end
fields
self
end

end
def filter_by_labels(labels = nil)
labels ||= @labels_filter
return self if labels.empty?
@filtered_fields.select! do |f|
labels.include? f.label.downcase
end
self
end

def filter_by_data(data, compact_only: false)
@filtered_fields = displayable_fields(@filtered_fields,
data,
compact_only: compact_only)
self
end

private

def displayable_fields(fields, record, compact_only: false)
fields.select do |field|
field_data = HammerCLI::Output::Adapter::Abstract.data_for_field(
field, record
)
if compact_only && !field_data.is_a?(HammerCLI::Output::DataMissing)
true
else
field.display?(field_data)
end
end
end
end
end
12 changes: 6 additions & 6 deletions test/unit/output/field_filter_test.rb
Expand Up @@ -10,18 +10,18 @@
let(:field_labels) { fields.map(&:label).sort }

it "lets all fields go by default" do
f = HammerCLI::Output::FieldFilter.new
f.filter(fields).map(&:label).sort.must_equal ["field", "collection", "id"].sort
f = HammerCLI::Output::FieldFilter.new(fields)
f.filtered_fields.map(&:label).sort.must_equal ["field", "collection", "id"].sort
end

it "filters fields by class" do
f = HammerCLI::Output::FieldFilter.new([Fields::Id])
f.filter(fields).map(&:label).sort.must_equal ["field", "collection"].sort
f = HammerCLI::Output::FieldFilter.new(fields, classes_filter: [Fields::Id])
f.filter_by_classes.filtered_fields.map(&:label).sort.must_equal ["field", "collection"].sort
end

it "filters fields by superclass" do
f = HammerCLI::Output::FieldFilter.new([Fields::ContainerField])
f.filter(fields).map(&:label).sort.must_equal ["field", "id"].sort
f = HammerCLI::Output::FieldFilter.new(fields, classes_filter: [Fields::ContainerField])
f.filter_by_classes.filtered_fields.map(&:label).sort.must_equal ["field", "id"].sort
end

end

0 comments on commit d395d79

Please sign in to comment.