diff --git a/packages/datalib/src/GridConfig.ts b/packages/datalib/src/GridConfig.ts index ec0f29a42..71ce638f2 100644 --- a/packages/datalib/src/GridConfig.ts +++ b/packages/datalib/src/GridConfig.ts @@ -9,6 +9,10 @@ export interface GridConfigColumns { export interface GridConfig extends GridConfigColumns { filters: { [uniqueName: string]: string }; + sort: { + uniqueName: string; + order: 'ASC' | 'DESC'; + }[]; } export interface GridCache { @@ -22,6 +26,7 @@ export function createGridConfig(): GridConfig { expandedColumns: [], addedColumns: [], filters: {}, + sort: [], }; } diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index c90ab8e2f..3743da324 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -307,6 +307,20 @@ export abstract class GridDisplay { } } + applySortOnSelect(select: Select, displayedColumnInfo: DisplayedColumnInfo) { + if (this.config.sort?.length > 0) { + select.orderBy = this.config.sort + .map(col => ({ ...col, dispInfo: displayedColumnInfo[col.uniqueName] })) + .filter(col => col.dispInfo) + .map(col => ({ + exprType: 'column', + columnName: col.dispInfo.columnName, + direction: col.order, + source: { alias: col.dispInfo.sourceAlias }, + })); + } + } + getDisplayColumns(table: TableInfo, parentPath: string[]) { return ( table?.columns @@ -350,6 +364,18 @@ export abstract class GridDisplay { this.reload(); } + setSort(uniqueName, order) { + this.setConfig({ + ...this.config, + sort: [{ uniqueName, order }], + }); + this.reload(); + } + + getSortOrder(uniqueName) { + return this.config.sort.find(x => x.uniqueName == uniqueName)?.order; + } + get filterCount() { return _.compact(_.values(this.config.filters)).length; } diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index b6a2aa6a1..9487dcea9 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -53,6 +53,7 @@ export class TableGridDisplay extends GridDisplay { this.addHintsToSelect(select) ); this.applyFilterOnSelect(select, displayedColumnInfo); + this.applySortOnSelect(select, displayedColumnInfo); if (action == 'loadRequired') { return null; } diff --git a/packages/web/src/datagrid/ColumnHeaderControl.js b/packages/web/src/datagrid/ColumnHeaderControl.js index fb8464f19..9acb87f09 100644 --- a/packages/web/src/datagrid/ColumnHeaderControl.js +++ b/packages/web/src/datagrid/ColumnHeaderControl.js @@ -3,6 +3,7 @@ import styled from 'styled-components'; import ColumnLabel from './ColumnLabel'; import DropDownButton from '../widgets/DropDownButton'; import { DropDownMenuItem } from '../modals/DropDownMenu'; +import { FontIcon } from '../icons'; const HeaderDiv = styled.div` display: flex; @@ -15,15 +16,29 @@ const LabelDiv = styled.div` margin: auto; `; -export default function ColumnHeaderControl({ column }) { +const IconWrapper = styled.span` + margin-left: 3px; +`; + +export default function ColumnHeaderControl({ column, setSort, order }) { return ( + {order == 'ASC' && ( + + + + )} + {order == 'DESC' && ( + + + + )} - {}}>Sort ascending - {}}>Sort descending + setSort('ASC')}>Sort ascending + setSort('DESC')}>Sort descending ); diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 83cc1fd74..6ce81383d 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -845,7 +845,11 @@ export default function DataGridCore(props) { key={col.uniqueName} style={{ width: col.widthPx, minWidth: col.widthPx, maxWidth: col.widthPx }} > - + display.setSort(col.uniqueName, order)} + order={display.getSortOrder(col.uniqueName)} + /> ))} diff --git a/packages/web/src/datagrid/gridutil.ts b/packages/web/src/datagrid/gridutil.ts index cdba01811..59a28aeb7 100644 --- a/packages/web/src/datagrid/gridutil.ts +++ b/packages/web/src/datagrid/gridutil.ts @@ -29,7 +29,7 @@ export function countColumnSizes(loadedRows, columns, containerWidth, display) { context.font = 'bold 14px Helvetica'; let text = column.headerText; - let headerWidth = context.measureText(text).width + 50; + let headerWidth = context.measureText(text).width + 64; // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16; // if (this.getFilterOnColumn(column.uniquePath)) headerWidth += 16; diff --git a/packages/web/src/icons.js b/packages/web/src/icons.js index 4a8158901..06e828f14 100644 --- a/packages/web/src/icons.js +++ b/packages/web/src/icons.js @@ -31,7 +31,7 @@ export function FontIcon({ icon, ...props }) { if (_.includes(parts, 'spin')) className += ' fa-spin'; - const style = props.style || {}; + const style = { ...props.style }; const last = parts[parts.length - 1]; if (last && last != 'spin') {