mirror of
https://github.com/apache/superset.git
synced 2024-09-12 08:39:45 -04:00
feat(Explore): add sort to edit dataset modal (#14872)
* inital commit * refac * fix ui issues and sort * fix lint * add suggestions * lint * add suggestions * add enum * add enum to inter
This commit is contained in:
parent
7a21f9afa7
commit
e2abf59534
@ -42,12 +42,28 @@ interface CRUDCollectionProps {
|
|||||||
) => ReactNode)[];
|
) => ReactNode)[];
|
||||||
onChange?: (arg0: any) => void;
|
onChange?: (arg0: any) => void;
|
||||||
tableColumns: Array<any>;
|
tableColumns: Array<any>;
|
||||||
|
sortColumns: Array<string>;
|
||||||
stickyHeader?: boolean;
|
stickyHeader?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Sort = number | string | boolean | any;
|
||||||
|
|
||||||
|
enum SortOrder {
|
||||||
|
asc = 1,
|
||||||
|
desc = 2,
|
||||||
|
unsort = 0,
|
||||||
|
}
|
||||||
|
|
||||||
interface CRUDCollectionState {
|
interface CRUDCollectionState {
|
||||||
collection: object;
|
collection: object;
|
||||||
|
collectionArray: Array<object>;
|
||||||
expandedColumns: object;
|
expandedColumns: object;
|
||||||
|
sortColumn: string;
|
||||||
|
sort: SortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCollectionArray(collection: object) {
|
||||||
|
return Object.keys(collection).map(k => collection[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createKeyedCollection(arr: Array<object>) {
|
function createKeyedCollection(arr: Array<object>) {
|
||||||
@ -67,15 +83,23 @@ const CrudTableWrapper = styled.div<{ stickyHeader?: boolean }>`
|
|||||||
stickyHeader &&
|
stickyHeader &&
|
||||||
`
|
`
|
||||||
height: 350px;
|
height: 350px;
|
||||||
overflow: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
|
.table {
|
||||||
|
min-width: 800px;
|
||||||
|
}
|
||||||
thead th {
|
thead th {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
|
min
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
|
th span {
|
||||||
|
vertical-align: ${({ theme }) => theme.gridUnit * -2}px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const CrudButtonWrapper = styled.div`
|
const CrudButtonWrapper = styled.div`
|
||||||
@ -89,9 +113,14 @@ export default class CRUDCollection extends React.PureComponent<
|
|||||||
> {
|
> {
|
||||||
constructor(props: CRUDCollectionProps) {
|
constructor(props: CRUDCollectionProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
const collection = createKeyedCollection(props.collection);
|
||||||
this.state = {
|
this.state = {
|
||||||
expandedColumns: {},
|
expandedColumns: {},
|
||||||
collection: createKeyedCollection(props.collection),
|
collection,
|
||||||
|
collectionArray: createCollectionArray(collection),
|
||||||
|
sortColumn: '',
|
||||||
|
sort: 0,
|
||||||
};
|
};
|
||||||
this.renderItem = this.renderItem.bind(this);
|
this.renderItem = this.renderItem.bind(this);
|
||||||
this.onAddItem = this.onAddItem.bind(this);
|
this.onAddItem = this.onAddItem.bind(this);
|
||||||
@ -100,12 +129,16 @@ export default class CRUDCollection extends React.PureComponent<
|
|||||||
this.onFieldsetChange = this.onFieldsetChange.bind(this);
|
this.onFieldsetChange = this.onFieldsetChange.bind(this);
|
||||||
this.renderTableBody = this.renderTableBody.bind(this);
|
this.renderTableBody = this.renderTableBody.bind(this);
|
||||||
this.changeCollection = this.changeCollection.bind(this);
|
this.changeCollection = this.changeCollection.bind(this);
|
||||||
|
this.sortColumn = this.sortColumn.bind(this);
|
||||||
|
this.renderSortIcon = this.renderSortIcon.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps: CRUDCollectionProps) {
|
UNSAFE_componentWillReceiveProps(nextProps: CRUDCollectionProps) {
|
||||||
if (nextProps.collection !== this.props.collection) {
|
if (nextProps.collection !== this.props.collection) {
|
||||||
|
const collection = createKeyedCollection(nextProps.collection);
|
||||||
this.setState({
|
this.setState({
|
||||||
collection: createKeyedCollection(nextProps.collection),
|
collection,
|
||||||
|
collectionArray: createCollectionArray(collection),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,15 +214,73 @@ export default class CRUDCollection extends React.PureComponent<
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortColumn(col: string, sort = SortOrder.unsort) {
|
||||||
|
const { sortColumns } = this.props;
|
||||||
|
// default sort logic sorting string, boolean and number
|
||||||
|
const compareSort = (m: Sort, n: Sort) => {
|
||||||
|
if (typeof m === 'string') {
|
||||||
|
return (m || ' ').localeCompare(n);
|
||||||
|
}
|
||||||
|
return m - n;
|
||||||
|
};
|
||||||
|
return () => {
|
||||||
|
if (sortColumns?.includes(col)) {
|
||||||
|
// display in unsorted order if no sort specified
|
||||||
|
if (sort === SortOrder.unsort) {
|
||||||
|
const collection = createKeyedCollection(this.props.collection);
|
||||||
|
this.setState({
|
||||||
|
collectionArray: createCollectionArray(collection),
|
||||||
|
sortColumn: '',
|
||||||
|
sort,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(prevState => {
|
||||||
|
// newly ordered collection
|
||||||
|
const sorted = [
|
||||||
|
...prevState.collectionArray,
|
||||||
|
].sort((a: object, b: object) => compareSort(a[col], b[col]));
|
||||||
|
const newCollection =
|
||||||
|
sort === SortOrder.asc ? sorted : sorted.reverse();
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
collectionArray: newCollection,
|
||||||
|
sortColumn: col,
|
||||||
|
sort,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSortIcon(col: string) {
|
||||||
|
if (this.state.sortColumn === col && this.state.sort === SortOrder.asc) {
|
||||||
|
return <Icons.SortAsc onClick={this.sortColumn(col, 2)} />;
|
||||||
|
}
|
||||||
|
if (this.state.sortColumn === col && this.state.sort === SortOrder.desc) {
|
||||||
|
return <Icons.SortDesc onClick={this.sortColumn(col, 0)} />;
|
||||||
|
}
|
||||||
|
return <Icons.Sort onClick={this.sortColumn(col, 1)} />;
|
||||||
|
}
|
||||||
|
|
||||||
renderHeaderRow() {
|
renderHeaderRow() {
|
||||||
const cols = this.effectiveTableColumns();
|
const cols = this.effectiveTableColumns();
|
||||||
const { allowDeletes, expandFieldset, extraButtons } = this.props;
|
const {
|
||||||
|
allowDeletes,
|
||||||
|
expandFieldset,
|
||||||
|
extraButtons,
|
||||||
|
sortColumns,
|
||||||
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{expandFieldset && <th aria-label="Expand" className="tiny-cell" />}
|
{expandFieldset && <th aria-label="Expand" className="tiny-cell" />}
|
||||||
{cols.map(col => (
|
{cols.map(col => (
|
||||||
<th key={col}>{this.getLabel(col)}</th>
|
<th key={col}>
|
||||||
|
{this.getLabel(col)}
|
||||||
|
{sortColumns?.includes(col) && this.renderSortIcon(col)}
|
||||||
|
</th>
|
||||||
))}
|
))}
|
||||||
{extraButtons}
|
{extraButtons}
|
||||||
{allowDeletes && (
|
{allowDeletes && (
|
||||||
@ -298,9 +389,7 @@ export default class CRUDCollection extends React.PureComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTableBody() {
|
renderTableBody() {
|
||||||
const data = Object.keys(this.state.collection).map(
|
const data = this.state.collectionArray;
|
||||||
k => this.state.collection[k],
|
|
||||||
);
|
|
||||||
const content = data.length
|
const content = data.length
|
||||||
? data.map(d => this.renderItem(d))
|
? data.map(d => this.renderItem(d))
|
||||||
: this.renderEmptyCell();
|
: this.renderEmptyCell();
|
||||||
|
@ -141,6 +141,7 @@ function ColumnCollectionTable({
|
|||||||
<CollectionTable
|
<CollectionTable
|
||||||
collection={columns}
|
collection={columns}
|
||||||
tableColumns={['column_name', 'type', 'is_dttm', 'filterable', 'groupby']}
|
tableColumns={['column_name', 'type', 'is_dttm', 'filterable', 'groupby']}
|
||||||
|
sortColumns={['column_name', 'type', 'is_dttm', 'filterable', 'groupby']}
|
||||||
allowDeletes
|
allowDeletes
|
||||||
allowAddItem={allowAddItem}
|
allowAddItem={allowAddItem}
|
||||||
itemGenerator={itemGenerator}
|
itemGenerator={itemGenerator}
|
||||||
@ -881,6 +882,7 @@ class DatasourceEditor extends React.PureComponent {
|
|||||||
return (
|
return (
|
||||||
<CollectionTable
|
<CollectionTable
|
||||||
tableColumns={['metric_name', 'verbose_name', 'expression']}
|
tableColumns={['metric_name', 'verbose_name', 'expression']}
|
||||||
|
sortColumns={['metric_name', 'verbose_name', 'expression']}
|
||||||
columnLabels={{
|
columnLabels={{
|
||||||
metric_name: t('Metric'),
|
metric_name: t('Metric'),
|
||||||
verbose_name: t('Label'),
|
verbose_name: t('Label'),
|
||||||
|
Loading…
Reference in New Issue
Block a user