datagrid 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/datagrid.gemspec +3 -2
- data/lib/datagrid/filters.rb +1 -1
- data/lib/datagrid/filters/base_filter.rb +8 -4
- data/lib/datagrid/filters/boolean_filter.rb +1 -1
- data/lib/datagrid/filters/date_filter.rb +16 -7
- data/lib/datagrid/filters/default_filter.rb +1 -1
- data/lib/datagrid/filters/enum_filter.rb +1 -1
- data/lib/datagrid/filters/float_filter.rb +1 -1
- data/lib/datagrid/filters/integer_filter.rb +1 -1
- data/lib/datagrid/filters/ranged_filter.rb +7 -2
- data/lib/datagrid/filters/string_filter.rb +1 -1
- data/lib/datagrid/form_builder.rb +23 -6
- data/spec/datagrid/filters/date_filter_spec.rb +9 -8
- data/spec/datagrid/form_builder_spec.rb +36 -14
- data/spec/support/configuration.rb +12 -0
- data/spec/support/matchers.rb +1 -1
- metadata +4 -3
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.8. | 
| 1 | 
            +
            0.8.3
         | 
    
        data/datagrid.gemspec
    CHANGED
    
    | @@ -5,11 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |s|
         | 
| 7 7 | 
             
              s.name = "datagrid"
         | 
| 8 | 
            -
              s.version = "0.8. | 
| 8 | 
            +
              s.version = "0.8.3"
         | 
| 9 9 |  | 
| 10 10 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 11 | 
             
              s.authors = ["Bogdan Gusiev"]
         | 
| 12 | 
            -
              s.date = "2013-05- | 
| 12 | 
            +
              s.date = "2013-05-20"
         | 
| 13 13 | 
             
              s.description = "This allows you to easily build datagrid aka data tables with sortable columns and filters"
         | 
| 14 14 | 
             
              s.email = "agresso@gmail.com"
         | 
| 15 15 | 
             
              s.extra_rdoc_files = [
         | 
| @@ -84,6 +84,7 @@ Gem::Specification.new do |s| | |
| 84 84 | 
             
                "spec/datagrid_spec.rb",
         | 
| 85 85 | 
             
                "spec/spec_helper.rb",
         | 
| 86 86 | 
             
                "spec/support/active_record.rb",
         | 
| 87 | 
            +
                "spec/support/configuration.rb",
         | 
| 87 88 | 
             
                "spec/support/matchers.rb",
         | 
| 88 89 | 
             
                "spec/support/mongo_mapper.rb",
         | 
| 89 90 | 
             
                "spec/support/mongoid.rb",
         | 
    
        data/lib/datagrid/filters.rb
    CHANGED
    
    
| @@ -12,8 +12,8 @@ class Datagrid::Filters::BaseFilter | |
| 12 12 | 
             
                self.block = block || default_filter_block
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 | 
            -
              def  | 
| 16 | 
            -
                raise NotImplementedError, "# | 
| 15 | 
            +
              def parse(value)
         | 
| 16 | 
            +
                raise NotImplementedError, "#parse(value) suppose to be overwritten"
         | 
| 17 17 | 
             
              end
         | 
| 18 18 |  | 
| 19 19 | 
             
              def apply(grid_object, scope, value)
         | 
| @@ -31,13 +31,13 @@ class Datagrid::Filters::BaseFilter | |
| 31 31 | 
             
                result
         | 
| 32 32 | 
             
              end
         | 
| 33 33 |  | 
| 34 | 
            -
              def  | 
| 34 | 
            +
              def parse_values(value)
         | 
| 35 35 | 
             
                if !self.multiple && value.is_a?(Array)
         | 
| 36 36 | 
             
                  raise Datagrid::ArgumentError, "#{grid}##{name} filter can not accept Array argument. Use :multiple option."
         | 
| 37 37 | 
             
                end
         | 
| 38 38 | 
             
                values = Array.wrap(value)
         | 
| 39 39 | 
             
                values.map! do |v|
         | 
| 40 | 
            -
                  self. | 
| 40 | 
            +
                  self.parse(v)
         | 
| 41 41 | 
             
                end
         | 
| 42 42 | 
             
                self.multiple ? values : values.first
         | 
| 43 43 | 
             
              end
         | 
| @@ -88,6 +88,10 @@ class Datagrid::Filters::BaseFilter | |
| 88 88 | 
             
                end
         | 
| 89 89 | 
             
              end
         | 
| 90 90 |  | 
| 91 | 
            +
              def format(value)
         | 
| 92 | 
            +
                value.nil? ? nil : value.to_s
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 91 95 | 
             
              protected
         | 
| 92 96 |  | 
| 93 97 | 
             
              def default_filter_where(driver, scope, value)
         | 
| @@ -11,15 +11,13 @@ class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter | |
| 11 11 | 
             
                super(grid_object, scope, value)
         | 
| 12 12 | 
             
              end
         | 
| 13 13 |  | 
| 14 | 
            -
              def  | 
| 14 | 
            +
              def parse(value)
         | 
| 15 15 | 
             
                return nil if value.blank?
         | 
| 16 16 | 
             
                return value if value.is_a?(Range)
         | 
| 17 | 
            -
                 | 
| 18 | 
            -
                   | 
| 19 | 
            -
                     | 
| 20 | 
            -
             | 
| 21 | 
            -
                    rescue ArgumentError
         | 
| 22 | 
            -
                    end
         | 
| 17 | 
            +
                formats.each do |format|
         | 
| 18 | 
            +
                  begin
         | 
| 19 | 
            +
                    return Date.strptime(value, format)
         | 
| 20 | 
            +
                  rescue ArgumentError
         | 
| 23 21 | 
             
                  end
         | 
| 24 22 | 
             
                end
         | 
| 25 23 | 
             
                return value.to_date if value.respond_to?(:to_date)
         | 
| @@ -29,5 +27,16 @@ class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter | |
| 29 27 | 
             
                nil
         | 
| 30 28 | 
             
              end
         | 
| 31 29 |  | 
| 30 | 
            +
              def formats
         | 
| 31 | 
            +
                Array(Datagrid.configuration.date_formats)
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def format(value)
         | 
| 35 | 
            +
                if formats.any?
         | 
| 36 | 
            +
                  value.strftime(formats.first)
         | 
| 37 | 
            +
                else
         | 
| 38 | 
            +
                  super
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 32 41 | 
             
            end
         | 
| 33 42 |  | 
| @@ -5,7 +5,7 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter | |
| 5 5 | 
             
                raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select]
         | 
| 6 6 | 
             
              end
         | 
| 7 7 |  | 
| 8 | 
            -
              def  | 
| 8 | 
            +
              def parse(value)
         | 
| 9 9 | 
             
                return nil if self.strict && !select.include?(value)
         | 
| 10 10 | 
             
                value
         | 
| 11 11 | 
             
              end
         | 
| @@ -8,7 +8,7 @@ module RangedFilter | |
| 8 8 | 
             
                end
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
              def  | 
| 11 | 
            +
              def parse_values(value)
         | 
| 12 12 | 
             
                result = super(value)
         | 
| 13 13 | 
             
                if range? 
         | 
| 14 14 | 
             
                  if result.is_a?(Array)
         | 
| @@ -18,7 +18,12 @@ module RangedFilter | |
| 18 18 | 
             
                    when 1
         | 
| 19 19 | 
             
                      result.first
         | 
| 20 20 | 
             
                    when 2
         | 
| 21 | 
            -
                      result
         | 
| 21 | 
            +
                      if result.first && result.last && result.first > result.last
         | 
| 22 | 
            +
                        # If wrong range is given - reverse it to be always valid
         | 
| 23 | 
            +
                        result.reverse
         | 
| 24 | 
            +
                      else
         | 
| 25 | 
            +
                        result
         | 
| 26 | 
            +
                      end
         | 
| 22 27 | 
             
                    else
         | 
| 23 28 | 
             
                      raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}"
         | 
| 24 29 | 
             
                    end
         | 
| @@ -52,22 +52,39 @@ module Datagrid | |
| 52 52 | 
             
                  if filter.range?
         | 
| 53 53 | 
             
                    options = options.merge(:multiple => true)
         | 
| 54 54 |  | 
| 55 | 
            -
                    from_options = Datagrid::Utils.add_html_classes(options, "from")
         | 
| 56 | 
            -
                    from_value = object[filter.name].try(:first)
         | 
| 57 55 |  | 
| 58 | 
            -
                     | 
| 59 | 
            -
                     | 
| 56 | 
            +
                    from_options = datagrid_range_filter_options(object, filter, :from, options)
         | 
| 57 | 
            +
                    to_options = datagrid_range_filter_options(object, filter, :to, options) 
         | 
| 60 58 | 
             
                    # 2 inputs: "from date" and "to date" to specify a range
         | 
| 61 59 | 
             
                    [
         | 
| 62 | 
            -
                      text_field(filter.name, from_options | 
| 60 | 
            +
                      text_field(filter.name, from_options),
         | 
| 63 61 | 
             
                      I18n.t("datagrid.misc.#{type}_range_separator", :default => "<span class=\"separator #{type}\"> - </span>"),
         | 
| 64 | 
            -
                      text_field(filter.name, to_options | 
| 62 | 
            +
                      text_field(filter.name, to_options)
         | 
| 65 63 | 
             
                    ].join.html_safe
         | 
| 66 64 | 
             
                  else
         | 
| 67 65 | 
             
                    text_field(filter.name, options)
         | 
| 68 66 | 
             
                  end
         | 
| 69 67 | 
             
                end
         | 
| 70 68 |  | 
| 69 | 
            +
             | 
| 70 | 
            +
                def datagrid_range_filter_options(object, filter, type, options)
         | 
| 71 | 
            +
                  type_method_map = {:from => :first, :to => :last}
         | 
| 72 | 
            +
                  options = Datagrid::Utils.add_html_classes(options, type)
         | 
| 73 | 
            +
                  options[:value] = filter.format(object[filter.name].try(type_method_map[type]))
         | 
| 74 | 
            +
                  # In case of datagrid ranged filter 
         | 
| 75 | 
            +
                  # from and to input will have same id
         | 
| 76 | 
            +
                  options[:id] = if !options.key?(:id) 
         | 
| 77 | 
            +
                     # Rails provides it's own default id for all inputs
         | 
| 78 | 
            +
                     # In order to prevent that we assign no id by default 
         | 
| 79 | 
            +
                    options[:id] = nil
         | 
| 80 | 
            +
                  elsif options[:id].present?
         | 
| 81 | 
            +
                    # If the id was given we prefix it
         | 
| 82 | 
            +
                    # with from_ and to_ accordingly
         | 
| 83 | 
            +
                    options[:id] = [type, options[:id]].join("_")
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                  options
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 71 88 | 
             
                def datagrid_string_filter(attribute_or_filter, options = {})
         | 
| 72 89 | 
             
                  datagrid_default_filter(attribute_or_filter, options)
         | 
| 73 90 | 
             
                end
         | 
| @@ -94,19 +94,20 @@ describe Datagrid::Filters::DateFilter do | |
| 94 94 | 
             
              end
         | 
| 95 95 |  | 
| 96 96 | 
             
              it "should have configurable date format" do
         | 
| 97 | 
            -
                 | 
| 98 | 
            -
                  Datagrid.configure do |config|
         | 
| 99 | 
            -
                    config.date_formats = "%m/%d/%Y"
         | 
| 100 | 
            -
                  end
         | 
| 97 | 
            +
                with_date_format do
         | 
| 101 98 | 
             
                  report = test_report(:created_at => "10/01/2013") do
         | 
| 102 99 | 
             
                    scope  {Entry}
         | 
| 103 100 | 
             
                    filter(:created_at, :date)
         | 
| 104 101 | 
             
                  end
         | 
| 105 102 | 
             
                  report.created_at.should == Date.new(2013,10,01)
         | 
| 106 | 
            -
                ensure
         | 
| 107 | 
            -
                  Datagrid.configure do |config|
         | 
| 108 | 
            -
                    config.date_formats = nil
         | 
| 109 | 
            -
                  end
         | 
| 110 103 | 
             
                end
         | 
| 111 104 | 
             
              end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              it "should automatically reverse Array if first more than last" do
         | 
| 107 | 
            +
                report = test_report(:created_at => ["2013-01-01", "2012-01-01"]) do
         | 
| 108 | 
            +
                  scope  {Entry}
         | 
| 109 | 
            +
                  filter(:created_at, :date, :range => true)
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
                report.created_at.should == [Date.new(2012, 01, 01), Date.new(2013, 01, 01)]
         | 
| 112 | 
            +
              end
         | 
| 112 113 | 
             
            end
         | 
| @@ -25,7 +25,8 @@ describe Datagrid::FormBuilder do | |
| 25 25 | 
             
                  end
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 | 
            -
                subject { view.datagrid_filter(_filter)}
         | 
| 28 | 
            +
                subject { view.datagrid_filter(_filter, _filter_options)}
         | 
| 29 | 
            +
                let(:_filter_options) { {} }
         | 
| 29 30 | 
             
                context "with default filter type" do
         | 
| 30 31 | 
             
                  let(:_grid) {
         | 
| 31 32 | 
             
                    test_report do
         | 
| @@ -72,23 +73,31 @@ describe Datagrid::FormBuilder do | |
| 72 73 | 
             
                      filter(:group_id, :integer, :range => true)
         | 
| 73 74 | 
             
                    end
         | 
| 74 75 | 
             
                  }
         | 
| 76 | 
            +
                  context "when datagrid_filter options has id" do
         | 
| 77 | 
            +
                    let(:_filter_options) { {:id => "hello"} }
         | 
| 78 | 
            +
                    let(:_range) { [1,2]}
         | 
| 79 | 
            +
                    it { should equal_to_dom(
         | 
| 80 | 
            +
                      '<input class="group_id integer_filter from" id="from_hello" multiple name="report[group_id][]" size="30" type="text" value="1"/>' +
         | 
| 81 | 
            +
                      '<span class="separator integer"> - </span>' +
         | 
| 82 | 
            +
                      '<input class="group_id integer_filter to" id="to_hello" multiple name="report[group_id][]" size="30" type="text" value="2"/>'
         | 
| 83 | 
            +
                    )}
         | 
| 84 | 
            +
                  end
         | 
| 75 85 | 
             
                  context "with only left bound" do
         | 
| 76 86 |  | 
| 77 87 | 
             
                    let(:_range) { [10, nil]}
         | 
| 78 88 | 
             
                    it { should equal_to_dom(
         | 
| 79 | 
            -
                      '<input class="group_id integer_filter from"  | 
| 89 | 
            +
                      '<input class="group_id integer_filter from" multiple name="report[group_id][]" size="30" type="text" value="10"/>' +
         | 
| 80 90 | 
             
                      '<span class="separator integer"> - </span>' +
         | 
| 81 | 
            -
                      '<input class="group_id integer_filter to"  | 
| 91 | 
            +
                      '<input class="group_id integer_filter to" multiple name="report[group_id][]" size="30" type="text"/>'
         | 
| 82 92 | 
             
                    )}
         | 
| 83 93 | 
             
                    it { should be_html_safe }
         | 
| 84 94 | 
             
                  end
         | 
| 85 95 | 
             
                  context "with only right bound" do
         | 
| 86 | 
            -
                    
         | 
| 87 96 | 
             
                    let(:_range) { [nil, 10]}
         | 
| 88 97 | 
             
                    it { should equal_to_dom(
         | 
| 89 | 
            -
                      '<input class="group_id integer_filter from"  | 
| 98 | 
            +
                      '<input class="group_id integer_filter from" multiple name="report[group_id][]" size="30" type="text"/>' +
         | 
| 90 99 | 
             
                      '<span class="separator integer"> - </span>' +
         | 
| 91 | 
            -
                      '<input class="group_id integer_filter to"  | 
| 100 | 
            +
                      '<input class="group_id integer_filter to" multiple name="report[group_id][]" size="30" type="text" value="10"/>'
         | 
| 92 101 | 
             
                    )}
         | 
| 93 102 | 
             
                    it { should be_html_safe }
         | 
| 94 103 | 
             
                  end
         | 
| @@ -96,9 +105,9 @@ describe Datagrid::FormBuilder do | |
| 96 105 | 
             
                  context "with invalid range value" do
         | 
| 97 106 | 
             
                    let(:_range) { 2..1 }
         | 
| 98 107 | 
             
                    it { should equal_to_dom(
         | 
| 99 | 
            -
                      '<input class="group_id integer_filter from"  | 
| 108 | 
            +
                      '<input class="group_id integer_filter from" multiple name="report[group_id][]" size="30" type="text" value="2"/>' +
         | 
| 100 109 | 
             
                      '<span class="separator integer"> - </span>' +
         | 
| 101 | 
            -
                      '<input class="group_id integer_filter to"  | 
| 110 | 
            +
                      '<input class="group_id integer_filter to" multiple name="report[group_id][]" size="30" type="text" value="1"/>'
         | 
| 102 111 | 
             
                    )}
         | 
| 103 112 | 
             
                  end
         | 
| 104 113 | 
             
                end
         | 
| @@ -116,19 +125,32 @@ describe Datagrid::FormBuilder do | |
| 116 125 |  | 
| 117 126 | 
             
                    let(:_range) { ["2012-01-03", nil]}
         | 
| 118 127 | 
             
                    it { should equal_to_dom(
         | 
| 119 | 
            -
                      '<input class="created_at date_filter from"  | 
| 128 | 
            +
                      '<input class="created_at date_filter from" multiple name="report[created_at][]" size="30" type="text" value="2012-01-03"/>' +
         | 
| 120 129 | 
             
                      '<span class="separator date"> - </span>' +
         | 
| 121 | 
            -
                      '<input class="created_at date_filter to"  | 
| 130 | 
            +
                      '<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text"/>'
         | 
| 122 131 | 
             
                    )}
         | 
| 123 132 | 
             
                    it { should be_html_safe }
         | 
| 124 133 | 
             
                  end
         | 
| 134 | 
            +
                  context "when special date format specified" do
         | 
| 135 | 
            +
                    around(:each) do |example|
         | 
| 136 | 
            +
                      with_date_format do
         | 
| 137 | 
            +
                        example.run
         | 
| 138 | 
            +
                      end
         | 
| 139 | 
            +
                    end
         | 
| 140 | 
            +
                    let(:_range) { ["2013/01/01", '2013/02/02']}
         | 
| 141 | 
            +
                    it { should equal_to_dom(
         | 
| 142 | 
            +
                      '<input class="created_at date_filter from" multiple name="report[created_at][]" size="30" type="text" value="01/01/2013"/>' +
         | 
| 143 | 
            +
                      '<span class="separator date"> - </span>' +
         | 
| 144 | 
            +
                      '<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text" value="02/02/2013"/>'
         | 
| 145 | 
            +
                    )}
         | 
| 146 | 
            +
                  end
         | 
| 125 147 | 
             
                  context "with only right bound" do
         | 
| 126 148 |  | 
| 127 149 | 
             
                    let(:_range) { [nil, "2012-01-03"]}
         | 
| 128 150 | 
             
                    it { should equal_to_dom(
         | 
| 129 | 
            -
                      '<input class="created_at date_filter from"  | 
| 151 | 
            +
                      '<input class="created_at date_filter from" multiple name="report[created_at][]" size="30" type="text"/>' +
         | 
| 130 152 | 
             
                      '<span class="separator date"> - </span>' +
         | 
| 131 | 
            -
                      '<input class="created_at date_filter to"  | 
| 153 | 
            +
                      '<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text" value="2012-01-03"/>'
         | 
| 132 154 | 
             
                    )}
         | 
| 133 155 | 
             
                    it { should be_html_safe }
         | 
| 134 156 | 
             
                  end
         | 
| @@ -136,9 +158,9 @@ describe Datagrid::FormBuilder do | |
| 136 158 | 
             
                  context "with invalid range value" do
         | 
| 137 159 | 
             
                    let(:_range) { Date.parse('2012-01-02')..Date.parse('2012-01-01') }
         | 
| 138 160 | 
             
                    it { should equal_to_dom(
         | 
| 139 | 
            -
                      '<input class="created_at date_filter from"  | 
| 161 | 
            +
                      '<input class="created_at date_filter from" multiple name="report[created_at][]" size="30" type="text" value="2012-01-02"/>' +
         | 
| 140 162 | 
             
                      '<span class="separator date"> - </span>' +
         | 
| 141 | 
            -
                      '<input class="created_at date_filter to"  | 
| 163 | 
            +
                      '<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text" value="2012-01-01"/>'
         | 
| 142 164 | 
             
                    )}
         | 
| 143 165 | 
             
                  end
         | 
| 144 166 | 
             
                end
         | 
    
        data/spec/support/matchers.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: datagrid
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.8. | 
| 4 | 
            +
              version: 0.8.3
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-05- | 
| 12 | 
            +
            date: 2013-05-20 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rails
         | 
| @@ -311,6 +311,7 @@ files: | |
| 311 311 | 
             
            - spec/datagrid_spec.rb
         | 
| 312 312 | 
             
            - spec/spec_helper.rb
         | 
| 313 313 | 
             
            - spec/support/active_record.rb
         | 
| 314 | 
            +
            - spec/support/configuration.rb
         | 
| 314 315 | 
             
            - spec/support/matchers.rb
         | 
| 315 316 | 
             
            - spec/support/mongo_mapper.rb
         | 
| 316 317 | 
             
            - spec/support/mongoid.rb
         | 
| @@ -334,7 +335,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 334 335 | 
             
                  version: '0'
         | 
| 335 336 | 
             
                  segments:
         | 
| 336 337 | 
             
                  - 0
         | 
| 337 | 
            -
                  hash:  | 
| 338 | 
            +
                  hash: -1396287359807292106
         | 
| 338 339 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 339 340 | 
             
              none: false
         | 
| 340 341 | 
             
              requirements:
         |