Skip to content

Commit

Permalink
(core) Allow filtering by selected cell value in cell context menu
Browse files Browse the repository at this point in the history
Summary: Adds a command and `BaseView` method `filterByThisCellValue`.

Test Plan: Added two tests to `nbrowser/CellContextMenu.ts`

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3383
  • Loading branch information
alexmojaki committed Apr 19, 2022
1 parent ce7eb05 commit 47b77c8
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 1 deletion.
22 changes: 22 additions & 0 deletions app/client/components/BaseView.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ BaseView.commonCommands = {
insertCurrentDateTime: function() { this.insertCurrentDate(true); },

copyLink: function() { this.copyLink().catch(reportError); },

filterByThisCellValue: function() { this.filterByThisCellValue(); },
};

/**
Expand Down Expand Up @@ -305,6 +307,26 @@ BaseView.prototype.copyLink = async function() {
}
};

BaseView.prototype.filterByThisCellValue = function() {
const rowId = this.viewData.getRowId(this.cursor.rowIndex());
const col = this.viewSection.viewFields().peek()[this.cursor.fieldIndex()].column();
let value = this.tableModel.tableData.getValue(rowId, col.colId.peek());

// This mimics the logic in ColumnFilterMenu.addCountsToMap
// ChoiceList and Reflist values get 'flattened' out so we filter by each element within.
// In any other column type, complex values (even lists) get converted to JSON.
let filterValues;
if (gristTypes.isList(value) && gristTypes.isListType(col.type.peek())) {
filterValues = value.slice(1);
} else {
if (Array.isArray(value)) {
value = JSON.stringify(value);
}
filterValues = [value];
}
this.viewSection.setFilter(col.getRowId(), JSON.stringify({included: filterValues}));
};

/**
* Insert a new row immediately before the row at the given index if given an Integer. Otherwise
* insert a new row at the end.
Expand Down
9 changes: 9 additions & 0 deletions app/client/components/commandList.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,15 @@ exports.groups = [{
},

],
}, {
group: 'Filtering',
commands: [
{
name: 'filterByThisCellValue',
keys: [],
desc: `Filter this column by just this cell's value`,
},
]
}, {
group: 'Linking',
commands: [
Expand Down
4 changes: 3 additions & 1 deletion app/client/ui/CellContextMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export function CellContextMenu(rowOptions: IRowContextMenu, colOptions: IMultiC
...(
(numCols > 1 || numRows > 1) ? [] : [
menuDivider(),
menuItemCmd(allCommands.copyLink, 'Copy anchor link')
menuItemCmd(allCommands.copyLink, 'Copy anchor link'),
menuDivider(),
menuItemCmd(allCommands.filterByThisCellValue, `Filter by this value`),
]
),

Expand Down
1 change: 1 addition & 0 deletions app/client/ui/ColumnFilterMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ interface ICountOptions {
*
* The optional column type controls how complex cell values are decomposed into keys (e.g. Choice Lists have
* the possible choices as keys).
* Note that this logic is replicated in BaseView.prototype.filterByThisCellValue.
*/
function addCountsToMap(valueMap: Map<CellValue, IFilterCount>, rowIds: RowId[],
{ keyMapFunc = identity, labelMapFunc = identity, columnType,
Expand Down

0 comments on commit 47b77c8

Please sign in to comment.