mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) add + button to the filter bar
				
					
				
			Summary:
 - Adds a + button to the filter. Button triggers a menu that allow to
add one of the column that does not already have a filter set.
Caveats:
 - for now menu only allows to choose from visible column.
 - This diff introduces a slight change of behavior of how filter works:
     - Filter used to be automatically removed when user set them to all
inclusive (ie: by clicking the `All` button).
     - With this diff, it is no longer the case.
     - indeed, when filter are added to the filter bar with the `+` btn they are initially in the `all inclusive` state, hence would have been removed with the above mention behaviour.
Test Plan: Added new test to nbrowser/FilterBar
Reviewers: paulfitz
Reviewed By: paulfitz
Differential Revision: https://phab.getgrist.com/D2776
			
			
This commit is contained in:
		
							parent
							
								
									8a26550312
								
							
						
					
					
						commit
						5479159960
					
				@ -264,6 +264,7 @@ export function createFilterMenu(openCtl: IOpenController, sectionFilter: Sectio
 | 
			
		||||
  const labelGetter = tableData.getRowPropFunc(field.displayColModel().colId())!;
 | 
			
		||||
  const formatter = field.createVisibleColFormatter();
 | 
			
		||||
  const valueMapFunc = (rowId: number) => formatter.formatAny(labelGetter(rowId));
 | 
			
		||||
  const activeFilterBar = field.viewSection.peek().activeFilterBar;
 | 
			
		||||
 | 
			
		||||
  const valueCounts: Map<CellValue, {label: string, count: number}> = new Map();
 | 
			
		||||
  // TODO: as of now, this is not working for non text-or-numeric columns, ie: for Date column it is
 | 
			
		||||
@ -282,7 +283,8 @@ export function createFilterMenu(openCtl: IOpenController, sectionFilter: Sectio
 | 
			
		||||
    onClose: () => openCtl.close(),
 | 
			
		||||
    doSave: (reset: boolean = false) => {
 | 
			
		||||
      const spec = columnFilter.makeFilterJson();
 | 
			
		||||
      field.activeFilter(spec === allInclusive ? '' : spec);
 | 
			
		||||
      // If filter is moot and filter bar is hidden, let's remove the filter.
 | 
			
		||||
      field.activeFilter((spec === allInclusive && !activeFilterBar.peek()) ? '' : spec);
 | 
			
		||||
      if (reset) {
 | 
			
		||||
        sectionFilter.resetTemporaryRows();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,17 @@
 | 
			
		||||
import { allInclusive } from "app/client/models/ColumnFilter";
 | 
			
		||||
import { ViewFieldRec, ViewSectionRec } from "app/client/models/DocModel";
 | 
			
		||||
import { attachColumnFilterMenu } from "app/client/ui/ColumnFilterMenu";
 | 
			
		||||
import { cssButton, cssButtonGroup } from "app/client/ui2018/buttons";
 | 
			
		||||
import { colors, testId } from "app/client/ui2018/cssVars";
 | 
			
		||||
import { icon } from "app/client/ui2018/icons";
 | 
			
		||||
import { menu, menuItemAsync } from "app/client/ui2018/menus";
 | 
			
		||||
import { dom, IDisposableOwner, IDomArgs, styled } from "grainjs";
 | 
			
		||||
 | 
			
		||||
export function filterBar(_owner: IDisposableOwner, viewSection: ViewSectionRec) {
 | 
			
		||||
  return cssFilterBar(
 | 
			
		||||
    testId('filter-bar'),
 | 
			
		||||
    dom.forEach(viewSection.filteredFields, (field) => makeFilterField(viewSection, field)),
 | 
			
		||||
    makePlusButton(viewSection),
 | 
			
		||||
    cssSpacer(),
 | 
			
		||||
    dom.maybe(viewSection.filterSpecChanged, () => [
 | 
			
		||||
      primaryButton(
 | 
			
		||||
@ -30,18 +33,38 @@ function makeFilterField(viewSection: ViewSectionRec, field: ViewFieldRec) {
 | 
			
		||||
      testId('btn'),
 | 
			
		||||
      cssIcon('FilterSimple'),
 | 
			
		||||
      cssMenuTextLabel(dom.text(field.label)),
 | 
			
		||||
      cssBtn.cls('-disabled', field.activeFilter.isSaved),
 | 
			
		||||
      cssBtn.cls('-saved', field.activeFilter.isSaved),
 | 
			
		||||
      attachColumnFilterMenu(viewSection, field, {placement: 'bottom-start', attach: 'body'}),
 | 
			
		||||
    ),
 | 
			
		||||
    deleteButton(
 | 
			
		||||
      testId('delete'),
 | 
			
		||||
      cssIcon('CrossSmall'),
 | 
			
		||||
      cssBtn.cls('-disabled', field.activeFilter.isSaved),
 | 
			
		||||
      cssBtn.cls('-saved', field.activeFilter.isSaved),
 | 
			
		||||
      dom.on('click', () => field.activeFilter('')),
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function makePlusButton(viewSectionRec: ViewSectionRec) {
 | 
			
		||||
  return dom.domComputed((use) => {
 | 
			
		||||
    const fields = use(use(viewSectionRec.viewFields).getObservable());
 | 
			
		||||
    const anyFilter = fields.find((f) => use(f.isFiltered));
 | 
			
		||||
    return cssPlusButton(
 | 
			
		||||
      cssBtn.cls('-saved'),
 | 
			
		||||
      cssIcon('Plus'),
 | 
			
		||||
      menu(() => fields.map((f) => (
 | 
			
		||||
        menuItemAsync(
 | 
			
		||||
          () => f.activeFilter(allInclusive),
 | 
			
		||||
          f.label.peek(),
 | 
			
		||||
          dom.cls('disabled', f.isFiltered)
 | 
			
		||||
        )
 | 
			
		||||
      ))),
 | 
			
		||||
      anyFilter ? null : cssPlusLabel('Add Filter'),
 | 
			
		||||
      testId('add-filter-btn')
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const cssFilterBar = styled('div', `
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
@ -75,13 +98,13 @@ const cssBtn = styled('div', `
 | 
			
		||||
  .${cssFilterBar.className} > & {
 | 
			
		||||
    margin: 0 4px;
 | 
			
		||||
  }
 | 
			
		||||
  &-disabled {
 | 
			
		||||
  &-saved {
 | 
			
		||||
    color:        ${colors.light};
 | 
			
		||||
    --icon-color: ${colors.light};
 | 
			
		||||
    background-color: ${colors.slate};
 | 
			
		||||
    border-color: ${colors.slate};
 | 
			
		||||
  }
 | 
			
		||||
  &-disabled:hover {
 | 
			
		||||
  &-saved:hover {
 | 
			
		||||
    background-color: ${colors.darkGrey};
 | 
			
		||||
    border-color: ${colors.darkGrey};
 | 
			
		||||
  }
 | 
			
		||||
@ -100,3 +123,9 @@ const cssSpacer = styled('div', `
 | 
			
		||||
  width: 8px;
 | 
			
		||||
  flex-shrink: 0;
 | 
			
		||||
`);
 | 
			
		||||
const cssPlusButton = styled(primaryButton, `
 | 
			
		||||
  padding: 3px 3px
 | 
			
		||||
`);
 | 
			
		||||
const cssPlusLabel = styled('span', `
 | 
			
		||||
  margin: 0 12px 0 4px;
 | 
			
		||||
`);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user