mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) close sort&filter menu when clicking Save/Revert buttons
Summary: - close sort&filter menu when clicking Save/Revert buttons - also closes when clicking Apply/Cancel from a nested filter menu Test Plan: - updated existing test to match new spec - added new test to cover new behaviour Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2799
This commit is contained in:
parent
570baa95a5
commit
8056bb0069
@ -650,8 +650,8 @@ BaseView.prototype.getLastDataRowIndex = function() {
|
||||
/**
|
||||
* Creates and opens ColumnFilterMenu for a given field, and returns its PopupControl.
|
||||
*/
|
||||
BaseView.prototype.createFilterMenu = function(openCtl, field) {
|
||||
return createFilterMenu(openCtl, this._sectionFilter, field, this._filteredRowSource, this.tableModel.tableData);
|
||||
BaseView.prototype.createFilterMenu = function(openCtl, field, onClose) {
|
||||
return createFilterMenu(openCtl, this._sectionFilter, field, this._filteredRowSource, this.tableModel.tableData, onClose);
|
||||
};
|
||||
|
||||
/**
|
||||
|
2
app/client/declarations.d.ts
vendored
2
app/client/declarations.d.ts
vendored
@ -60,7 +60,7 @@ declare module "app/client/components/BaseView" {
|
||||
|
||||
constructor(gristDoc: GristDoc, viewSectionModel: any);
|
||||
public setCursorPos(cursorPos: CursorPos): void;
|
||||
public createFilterMenu(ctl: IOpenController, field: ViewFieldRec): HTMLElement;
|
||||
public createFilterMenu(ctl: IOpenController, field: ViewFieldRec, onClose?: () => void): HTMLElement;
|
||||
public buildTitleControls(): DomArg;
|
||||
public getLoadingDonePromise(): Promise<void>;
|
||||
public onResize(): void;
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import {allInclusive, ColumnFilter, isEquivalentFilter} from 'app/client/models/ColumnFilter';
|
||||
import {ColumnFilterMenuModel, IFilterCount} from 'app/client/models/ColumnFilterMenuModel';
|
||||
import {ViewFieldRec, ViewSectionRec} from 'app/client/models/DocModel';
|
||||
import {FilteredRowSource} from 'app/client/models/rowset';
|
||||
import {SectionFilter} from 'app/client/models/SectionFilter';
|
||||
@ -17,9 +18,8 @@ import {menuCssClass, menuDivider} from 'app/client/ui2018/menus';
|
||||
import {CellValue} from 'app/common/DocActions';
|
||||
import {Computed, Disposable, dom, DomElementMethod, IDisposableOwner, input, makeTestId, styled} from 'grainjs';
|
||||
import identity = require('lodash/identity');
|
||||
import noop = require('lodash/noop');
|
||||
import {IOpenController, IPopupOptions, setPopupToCreateDom} from 'popweasel';
|
||||
import {ColumnFilterMenuModel, IFilterCount} from '../models/ColumnFilterMenuModel';
|
||||
|
||||
|
||||
interface IFilterMenuOptions {
|
||||
model: ColumnFilterMenuModel;
|
||||
@ -258,7 +258,7 @@ function buildSummary(label: string, SummaryModelCtor: SummaryModelCreator, mode
|
||||
* Returns content for the newly created columnFilterMenu; for use with setPopupToCreateDom().
|
||||
*/
|
||||
export function createFilterMenu(openCtl: IOpenController, sectionFilter: SectionFilter, field: ViewFieldRec,
|
||||
rowSource: FilteredRowSource, tableData: TableData) {
|
||||
rowSource: FilteredRowSource, tableData: TableData, onClose: () => void = noop) {
|
||||
// Go through all of our shown and hidden rows, and count them up by the values in this column.
|
||||
const valueGetter = tableData.getRowPropFunc(field.column().colId())!;
|
||||
const labelGetter = tableData.getRowPropFunc(field.displayColModel().colId())!;
|
||||
@ -280,7 +280,7 @@ export function createFilterMenu(openCtl: IOpenController, sectionFilter: Sectio
|
||||
return columnFilterMenu(openCtl, {
|
||||
model,
|
||||
valueCounts,
|
||||
onClose: () => openCtl.close(),
|
||||
onClose: () => { openCtl.close(); onClose(); },
|
||||
doSave: (reset: boolean = false) => {
|
||||
const spec = columnFilter.makeFilterJson();
|
||||
// If filter is moot and filter bar is hidden, let's remove the filter.
|
||||
@ -321,14 +321,19 @@ const defaultPopupOptions: IPopupOptions = {
|
||||
trigger: ['click'],
|
||||
};
|
||||
|
||||
interface IColumnFilterMenuOptions extends IPopupOptions {
|
||||
// callback for when the content of the menu is closed by clicking the apply or revert buttons
|
||||
onCloseContent?: () => void;
|
||||
}
|
||||
|
||||
// Helper to attach the column filter menu.
|
||||
export function attachColumnFilterMenu(viewSection: ViewSectionRec, field: ViewFieldRec,
|
||||
popupOptions: IPopupOptions): DomElementMethod {
|
||||
popupOptions: IColumnFilterMenuOptions): DomElementMethod {
|
||||
const options = {...defaultPopupOptions, ...popupOptions};
|
||||
return (elem) => {
|
||||
const instance = viewSection.viewInstance();
|
||||
if (instance && instance.createFilterMenu) { // Should be set if using BaseView
|
||||
setPopupToCreateDom(elem, ctl => instance.createFilterMenu(ctl, field), options);
|
||||
setPopupToCreateDom(elem, ctl => instance.createFilterMenu(ctl, field, popupOptions.onCloseContent), options);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import {flipColDirection, parseSortColRefs} from 'app/client/lib/sortUtil';
|
||||
import {reportError} from 'app/client/models/AppModel';
|
||||
import {ColumnRec, DocModel, ViewFieldRec, ViewRec, ViewSectionRec} from 'app/client/models/DocModel';
|
||||
import {CustomComputed} from 'app/client/models/modelUtil';
|
||||
import {attachColumnFilterMenu} from 'app/client/ui/ColumnFilterMenu';
|
||||
import {addFilterMenu} from 'app/client/ui/FilterBar';
|
||||
import {makeViewLayoutMenu} from 'app/client/ui/ViewLayoutMenu';
|
||||
import {hoverTooltip} from 'app/client/ui/tooltips';
|
||||
import {makeViewLayoutMenu} from 'app/client/ui/ViewLayoutMenu';
|
||||
import {basicButton, primaryButton} from 'app/client/ui2018/buttons';
|
||||
import {colors, vars} from 'app/client/ui2018/cssVars';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
@ -43,7 +44,7 @@ export function viewSectionMenu(owner: IDisposableOwner, docModel: DocModel, vie
|
||||
|| !use(viewSection.activeFilterBar.isSaved)
|
||||
));
|
||||
|
||||
const save = () => doSave(docModel, viewSection);
|
||||
const save = () => { doSave(docModel, viewSection).catch(reportError); };
|
||||
const revert = () => doRevert(viewSection);
|
||||
|
||||
return [
|
||||
@ -58,23 +59,23 @@ export function viewSectionMenu(owner: IDisposableOwner, docModel: DocModel, vie
|
||||
cssFilterIconWrapper.cls('-any', anyFilter),
|
||||
cssFilterIcon('Filter')
|
||||
),
|
||||
menu(_ctl => [
|
||||
menu(ctl => [
|
||||
dom.domComputed(use => {
|
||||
use(viewSection.activeSortJson.isSaved); // Rebuild sort panel if sort gets saved. A little hacky.
|
||||
return makeSortPanel(viewSection, use(viewSection.activeSortSpec),
|
||||
(row: number) => docModel.columns.getRowModel(row));
|
||||
}),
|
||||
dom.domComputed(viewSection.filteredFields, fields =>
|
||||
makeFilterPanel(viewSection, fields, popupControls)),
|
||||
makeFilterPanel(viewSection, fields, popupControls, () => ctl.close())),
|
||||
makeAddFilterButton(viewSection, popupControls),
|
||||
makeFilterBarToggle(viewSection.activeFilterBar),
|
||||
dom.domComputed(displaySaveObs, displaySave => [
|
||||
displaySave ? cssMenuInfoHeader(
|
||||
cssSaveButton('Save', testId('btn-save'),
|
||||
dom.on('click', save),
|
||||
dom.on('click', () => { save(); ctl.close(); }),
|
||||
dom.boolAttr('disabled', isReadonly)),
|
||||
basicButton('Revert', testId('btn-revert'),
|
||||
dom.on('click', revert))
|
||||
dom.on('click', () => { revert(); ctl.close(); }))
|
||||
) : null,
|
||||
]),
|
||||
]),
|
||||
@ -180,7 +181,8 @@ export function makeFilterBarToggle(activeFilterBar: CustomComputed<boolean>) {
|
||||
|
||||
|
||||
function makeFilterPanel(section: ViewSectionRec, filteredFields: ViewFieldRec[],
|
||||
popupControls: WeakMap<ViewFieldRec, PopupControl>) {
|
||||
popupControls: WeakMap<ViewFieldRec, PopupControl>,
|
||||
onCloseContent: () => void) {
|
||||
const fields = filteredFields.map(field => {
|
||||
const fieldChanged = Computed.create(null, fromKo(field.activeFilter.isSaved), (_use, isSaved) => !isSaved);
|
||||
return cssMenuText(
|
||||
@ -191,6 +193,7 @@ function makeFilterPanel(section: ViewSectionRec, filteredFields: ViewFieldRec[]
|
||||
attachColumnFilterMenu(section, field, {
|
||||
placement: 'bottom-end',
|
||||
trigger: ['click', (_el, popupControl) => popupControls.set(field, popupControl)],
|
||||
onCloseContent,
|
||||
}),
|
||||
testId('filter-icon'),
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user