mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-25 09:34:18 +08:00
feat: show sorting icons CB-23
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
GridOptions,
|
||||
CellEditingStoppedEvent,
|
||||
} from 'ag-grid-community';
|
||||
import { SortChangedEvent } from 'ag-grid-community/dist/lib/events';
|
||||
import { RowDataTransaction } from 'ag-grid-community/dist/lib/interfaces/rowDataTransaction';
|
||||
import { computed, observable } from 'mobx';
|
||||
|
||||
@@ -24,14 +25,16 @@ import { injectable, IInitializableController, IDestructibleController } from '@
|
||||
|
||||
import { AgGridContext } from './AgGridContext';
|
||||
import {
|
||||
AgGridRow, IAgGridActions, IAgGridCol, IAgGridModel,
|
||||
AgGridRow, IAgGridActions, IAgGridCol, IAgGridModel, SortMode,
|
||||
} from './IAgGridModel';
|
||||
import { RowSelection } from './TableSelection/RowSelection';
|
||||
import { TableSelection } from './TableSelection/TableSelection';
|
||||
|
||||
|
||||
@injectable()
|
||||
export class AgGridTableController implements IInitializableController, IDestructibleController {
|
||||
@observable refreshId = 0;
|
||||
@observable sortingOrder: SortMode[] = [];
|
||||
|
||||
private readonly datasource: IDatasource = {
|
||||
getRows: this.getRows.bind(this),
|
||||
@@ -68,6 +71,7 @@ export class AgGridTableController implements IInitializableController, IDestruc
|
||||
onBodyScroll: this.handleBodyScroll.bind(this),
|
||||
|
||||
onCellEditingStopped: this.handleCellEditingStopped.bind(this),
|
||||
onSortChanged: this.handleSortChanged.bind(this),
|
||||
};
|
||||
|
||||
@observable columns: ColDef[] = [];
|
||||
@@ -75,9 +79,10 @@ export class AgGridTableController implements IInitializableController, IDestruc
|
||||
/**
|
||||
* use this object to dynamically change ag-grid properties
|
||||
*/
|
||||
@computed get dynamicOptions() {
|
||||
@computed get dynamicOptions(): GridOptions {
|
||||
return {
|
||||
enableRangeSelection: !!this.selection,
|
||||
sortingOrder: this.sortingOrder,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,6 +108,7 @@ export class AgGridTableController implements IInitializableController, IDestruc
|
||||
this.gridOptions.cacheBlockSize = gridModel.chunkSize;
|
||||
if (gridModel.initialColumns?.length) {
|
||||
this.columns = mapDataToColumns(gridModel.initialColumns);
|
||||
this.sortingOrder = this.columns.map(() => null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +196,11 @@ export class AgGridTableController implements IInitializableController, IDestruc
|
||||
this.setInitialRow(this.gridModel.initialRows);
|
||||
}
|
||||
|
||||
private handleSortChanged(event: SortChangedEvent) {
|
||||
console.log(event);
|
||||
this.sortingOrder = event.columnApi.getAllGridColumns().map(col => col.getSort() as SortMode || null);
|
||||
}
|
||||
|
||||
/* Actions */
|
||||
|
||||
private resetData(columns?: IAgGridCol[], rows?: AgGridRow[]): void {
|
||||
@@ -257,6 +268,7 @@ export const INDEX_COLUMN_DEF: ColDef = {
|
||||
suppressNavigable: true,
|
||||
suppressMenu: true,
|
||||
editable: false,
|
||||
sortable: false,
|
||||
cellRenderer: row => row.rowIndex + 1,
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@ import { RowSelection } from './TableSelection/RowSelection';
|
||||
|
||||
export type AgGridRow = any[];
|
||||
|
||||
export type SortMode = 'asc' | 'desc' | null;
|
||||
|
||||
export interface IRequestDataOptions {
|
||||
sortMode?: SortMode[];
|
||||
}
|
||||
|
||||
|
||||
export interface IAgGridModel {
|
||||
initialRows: AgGridRow[];
|
||||
@@ -19,7 +25,7 @@ export interface IAgGridModel {
|
||||
|
||||
actions: IAgGridActions | null;
|
||||
// hooks
|
||||
onRequestData(rowOffset: number, count: number): Promise<IRequestedData>;
|
||||
onRequestData(rowOffset: number, count: number, options?: IRequestDataOptions): Promise<IRequestedData>;
|
||||
onCellEditingStopped?(rowNumber: number, colNumber: number, value: any): void;
|
||||
onEditSave(): void;
|
||||
onEditCancel(): void;
|
||||
|
||||
+64
-4
@@ -6,11 +6,13 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { useCallback } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { AgEvent, GridApi, Column } from '@ag-grid-community/core';
|
||||
import { StaticImage } from '@dbeaver/core/blocks';
|
||||
import { StaticImage, Icon } from '@dbeaver/core/blocks';
|
||||
|
||||
import { SortMode } from '../IAgGridModel';
|
||||
|
||||
type HeaderProps = {
|
||||
api: GridApi;
|
||||
@@ -21,7 +23,7 @@ type HeaderProps = {
|
||||
menuIcon: string;
|
||||
displayName: string;
|
||||
showColumnMenu: (button?: HTMLDivElement) => void;
|
||||
setSort: (order: string, shiftKey: boolean) => void;
|
||||
setSort: (order: SortMode, shiftKey: boolean) => void;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
@@ -42,6 +44,28 @@ const headerStyles = css`
|
||||
margin-left: 8px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
sort-icon {
|
||||
margin-left: 4px;
|
||||
display: flex;
|
||||
padding: 2px 4px;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
}
|
||||
sort-icon > Icon {
|
||||
width: 8px;
|
||||
fill: #cbcbcb;
|
||||
}
|
||||
sort-icon > Icon:last-child {
|
||||
transform: scaleY(-1);
|
||||
}
|
||||
sort-icon > Icon[|active] {
|
||||
fill: #338ECC;
|
||||
}
|
||||
sort-icon:hover > Icon {
|
||||
width: 9px;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -63,12 +87,48 @@ export function TableColumnHeader(props: HeaderProps) {
|
||||
props.api.dispatchEvent(event);
|
||||
}, []);
|
||||
|
||||
const [sortMode, setSortMode] = useState<SortMode>(() => props.column.getSort() as SortMode);
|
||||
useEffect(() => {
|
||||
function onSortChanged() {
|
||||
setSortMode(props.column.getSort() as SortMode);
|
||||
}
|
||||
|
||||
props.column.addEventListener('sortChanged', onSortChanged);
|
||||
return function cleanup() {
|
||||
props.column.removeEventListener('sortChanged', onSortChanged);
|
||||
};
|
||||
});
|
||||
|
||||
const handleSort = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const sort = props.column.getSort() as SortMode;
|
||||
let nextSort: SortMode;
|
||||
switch (sort) {
|
||||
case 'asc':
|
||||
nextSort = 'desc';
|
||||
break;
|
||||
case 'desc':
|
||||
nextSort = null;
|
||||
break;
|
||||
default:
|
||||
nextSort = 'asc';
|
||||
}
|
||||
props.setSort(nextSort, e.shiftKey);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
console.log(props.displayName, props.column.getSort(), props);
|
||||
return styled(headerStyles)(
|
||||
<table-header as="div" onClick={handleClick}>
|
||||
<icon as="div">
|
||||
<StaticImage icon={props.icon} />
|
||||
</icon>
|
||||
<name as="div">{props.displayName}</name>
|
||||
{props.enableSorting && <sort-icon as="div" onClick={handleSort}>
|
||||
<Icon name="sort-arrow" viewBox="0 0 6 6" {...use({ active: sortMode === 'asc' })} />
|
||||
<Icon name="sort-arrow" viewBox="0 0 6 6" {...use({ active: sortMode === 'desc' })} />
|
||||
</sort-icon>}
|
||||
</table-header>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,11 @@ require('yargs')
|
||||
const watcher = rollup.watch(watchOptions);
|
||||
|
||||
watcher.on('event', event => {
|
||||
console.log(event.code, event.input)
|
||||
if (event.code === 'ERROR') {
|
||||
console.error(event.error);
|
||||
} else {
|
||||
console.log(event.code, event.input)
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -137,4 +137,10 @@
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
<symbol id="sort-arrow" viewBox="0 0 6 6">
|
||||
<g>
|
||||
<path d="M2.564 0L0 2.383 1.832 2.383 1.832 4.582 3.297 4.582 3.297 2.383 5.128 2.383z" transform="translate(-5 -.222) translate(5 .389)"/>
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Reference in New Issue
Block a user