Uploaded image for project: 'stripes-components'
  1. stripes-components
  2. STCOM-361

SPIKE: Research if Search&Sort can have prop that supports more than just checkbox filters.

    XMLWordPrintable

    Details

    • Template:
    • Sprint:
      stripes-force Sprint 51, stripes-force Sprint 52
    • Story Points:
      8
    • Development Team:
      Stripes Force

      Description

      Requirement: Determine if prop will accept render function to add custom fields (more than just checkboxes)

      Context: Spike is needed to support improved Search & Filter pane UX, to minimize long list of filter options, and to provide flexibility for what filters display

      Spike outcomes: Document your findings and additional work that needs to be done. Present findings to stripes-force team members.

      Spike result

      Configuration based approach

      On Front-End it is possible to add proposed filter types. To achieve this goal it is proposed to do such steps:

      1. Extend filterConfig passed to SearchAndSort component with filters type and new format for values prop. For example:
        {
            type: 'selects',
            label: 'Organization',
            name: 'organization',
            values: [
              {
                name: 'Vendor',
                records: ['vendor1', 'vendor2', 'vendor3'],
              },
              {
                name: 'Content provider',
                records: ['provider1', 'provider2', 'provider3'],
              }
            ],
          },
        {
            type: 'numberRanges',
            label: 'Annual cost',
            name: 'annualCost',
            values: ['min', 'max'],
          },
          {
            type: 'dateRanges',
            label: 'Annual cost',
            name: 'annualCost',
            cql: '',
            values: ['startDate', 'endDate', 'cancellationDeadline'],
          }
        
      2. Get rid of filterGroupNames and pass whole group data to FilterGroup component. It will allow to work with different data in values.
      3. Create render function to render a list of necessary filters depending on filtersType prop to be passed inside FilterControlGroup component. Also each filter should receive onChange callback, which may return object with changed filter name and value.
      4. handleFilterChange can be extended with one more prop called "filter". A condition can be added to update filter state using filter prop if it exists.

      Declarative approach

      • Filters
        Is a component with all necessary filters. Will be created for every particular UI-module. Gets active filters and onChange callback from SearchAndSort component. onChange callback returns an object with updated filter in a format {filterName: 'name', filterValues: []}

        . Data fetching logic such as getting data from BE can be implemented inside this component.

        <SearchAndSort
          renderFilters={
            (filters, onChange) => {
              return (
                <Filters
                  activeFilters={filters}
                  onChange={onChange}
                />
              );
            }
          }
         />
        
      • FiltersGroup
        Gets the title of the group and a set of Filter components. Wraps filters with accordion.
      • Checkbox filter
        Represents a set of checkboxes. Gets filter name, values(rendered as checkbox labels), selected values and on change callback(returns filter name and updated values).
      • Radiobox filter
        Represents a set of radio boxes. Gets filter name, values(rendered as radio box labels), selected value and on change callback(returns filter name and new value).
      • DateRange filter
        Represents a field component with two inputs. Gets filter name, min and max date and on change callback(returns filter name and updated values).
      • NumberRange filter
      • Represents a field component with two inputs. Gets filter names, min and max value and on change callback(returns filter name and new value).
      • Selection filter
        Represents a dropdown list with options to select. Gets filter name, values(to be rendered as options), selected values and on change callback(returns filterName and updated values).

      The proposed contracts for new filter components:

              <CheckboxFilter
                name="language"
                availableValues={[
                  { label: 'English', value: 'en' }, 
                  { label: 'French', value: 'fr' },
                  { label: 'Russian', value: 'ru' },
                  { label: 'German', value: 'ge' },
                ]}
                selectedValues={['ru', 'en']}
                onChange={({name, value}) => {}} // returns an object with filter name and new selected values
                // { filterName: 'language', values: ['en', 'ru', 'ge'] }
              />
      
              <RadioboxFilter
                name="language"
                availableValues={[
                  { label: 'English', value: 'en' }, 
                  { label: 'French', value: 'fr' },
                  { label: 'Russian', value: 'ru' },
                  { label: 'German', value: 'ge' },
                ]}
                selectedValue={'ru'}
                onChange={({name, value}) => {}} // returns an object with filter name and new selected value
                // { filterName: 'language', values: 'en' }
              />
      
              <SelectionFilter
                name="language"
                availableValues={[
                  { label: 'English', value: 'en' }, 
                  { label: 'French', value: 'fr' },
                  { label: 'Russian', value: 'ru' },
                  { label: 'German', value: 'ge' },
                ]}
                selectedValue={['ru', 'en']}
                onChange={({name, value}) => {}} // returns an object with filter name and new selected values
                // { filterName: 'language', values: ['en', 'ru', 'ge'] }
              />
      
              <NumberRangeFilterFilter
                names={['minAnnualCost', 'maxAnnualCost']}
                min={10}
                max={100}
                onChange={({name, value}) => {}} // returns an object with filter name and new value
                // { filterName: 'maxAnnualCost', value: 200 }
              />
      
              <DateRangeFilterFilter
                name={'startDate'}
                from={'12-20-2018'}
                to={'12-25-2018'}
                onChange={({name, value}) => {}} // returns an object with filter name and new value
                // { filterName: 'startDate', values: ['12-20-2018', '12-26-2018'] }
              />
      

      Also, it's proposed to change the structure of the active filters, transformed from the filters query param.

      Current:

      {
        'language.en': true,
        'language.fr': true,
      }           
      

      New:

      {
        language: ['en', 'ua'],
        location: ['main library', 'annex'],
        minAnnualCost: 100,
        maxAnnualCost: 200,
        startDate: ['12/03/2018', '15/03/2018'],
        isPerpetual: true,
      }           
      

      In addition, it would be better to get rid of filters state building function inside SearchAndSort component

      const filters = filterState(this.queryParam('filters'));
      

      and pass filters state structure to the props of SearchAndSort.
      It will give us a flexible way to store active filters in a browser string and don't be dependent on the particular format.

        TestRail: Results

          Attachments

          1. filterGroupNames.png
            filterGroupNames.png
            323 kB
          2. Filters.png
            Filters.png
            208 kB
          3. handleFilterChange.png
            handleFilterChange.png
            92 kB
          4. Replace with filters component.png
            Replace with filters component.png
            132 kB

            Issue Links

              Activity

                People

                Assignee:
                Yurii_Danylenko Yurii Danylenko
                Reporter:
                kgambrell Khalilah Gambrell
                Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved:

                    TestRail: Runs

                      TestRail: Cases