Skip to content

Commit

Permalink
fix(plugins/plugin-client-common): restore Table sorting
Browse files Browse the repository at this point in the history
Fixes #6729
  • Loading branch information
myan9 authored and starpit committed Feb 5, 2021
1 parent 4ac42d3 commit d1dac89
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 35 deletions.
Expand Up @@ -26,9 +26,9 @@ import {
} from '@kui-shell/core'

import React from 'react'
import { TableComposable } from '@patternfly/react-table'
import { SortByDirection, TableComposable } from '@patternfly/react-table'

// import sortRow from './sort'
import sortRow from './sort'
import Card from '../../spi/Card'
import Timeline from './Timeline'
import renderBody from './TableBody'
Expand Down Expand Up @@ -90,6 +90,10 @@ export type State<T extends KuiTable = KuiTable> = ToolbarProps & {

page: number
pageSize: number

/* sorting */
activeSortIdx: number
activeSortDir: SortByDirection
}

export function getBreadcrumbsFromTable(response: KuiTable, prefixBreadcrumbs: BreadcrumbView[]) {
Expand Down Expand Up @@ -165,6 +169,8 @@ export default class PaginatedTable<P extends Props, S extends State> extends Re
footer,
header,
asSequence,
activeSortIdx: -1,
activeSortDir: undefined,
response: props.response,
pageSize: props.pageSize || defaults.pageSize
}
Expand Down Expand Up @@ -334,6 +340,17 @@ export default class PaginatedTable<P extends Props, S extends State> extends Re
: 'compact' */

const isSortable = response.body.length > 1

const onSort = (key: string, cidx: number, clickColIdx: number, clickDir: SortByDirection) => {
response.body.sort((a, b) => sortRow(a, b, key, cidx, clickDir))

this.setState({
body,
activeSortDir: clickDir,
activeSortIdx: clickColIdx
})
}

const dataTable = (visibleRows: KuiRow[], offset = 0) => (
<div
className={
Expand All @@ -347,7 +364,8 @@ export default class PaginatedTable<P extends Props, S extends State> extends Re
data-is-empty={response.body.length === 0}
>
<TableComposable className="kui--table-like-wrapper" variant={variant} isStickyHeader gridBreakPoint="">
{header && renderHeader(header)}
{header &&
renderHeader(header, isSortable, this.state.activeSortIdx, this.state.activeSortDir, onSort.bind(this))}
{renderBody(response, this.justUpdatedMap(), tab, repl, offset)}
</TableComposable>
</div>
Expand Down
Expand Up @@ -17,31 +17,58 @@
import { Table } from '@kui-shell/core'

import React from 'react'
import { Thead, Th, Tr } from '@patternfly/react-table'
import { SortByDirection, Thead, Th, Tr } from '@patternfly/react-table'

function th(key: string, value: string, outerCSS: string, css?: string) {
// nowrap seems to be needed to avoid PatternFly using a "truncate"
// mode; see TableCell, where we set "fitContent" as the modifier
// for the cells; but that alone seems to cause truncation in the
// header :( hence this "nowrap". A bit puzzling.
return (
<Th key={key || value} data-key={key || value} className={`kui--header-cell ${outerCSS || ''}`} modifier="nowrap">
{css ? <span className={css}>{value}</span> : value}
</Th>
)
}
import { isSortableCol } from './sort'

/**
* Render the TableHeader part
*
*/
export default function renderHeader(kuiHeader: Table['header']) {
// isSortable: cidx > 0 || kuiHeader.isSortable,
export default function renderHeader(
kuiHeader: Table['header'],
isSortable: boolean,
activeSortIdx: number,
direction: SortByDirection,
onSort: (key: string, cidx: number, sortCIdx: number, sortDir: SortByDirection) => void
) {
const th = (key: string, value: string, cidx: number, outerCSS: string, css?: string) => {
const dataKey = key || value

const sortParam =
isSortable && isSortableCol(dataKey)
? {
sort: {
sortBy: { index: activeSortIdx, direction },
onSort: (_, clickColIdx: number, clickDir: SortByDirection) =>
onSort(dataKey, cidx, clickColIdx, clickDir),
columnIndex: cidx
}
}
: {}

// nowrap seems to be needed to avoid PatternFly using a "truncate"
// mode; see TableCell, where we set "fitContent" as the modifier
// for the cells; but that alone seems to cause truncation in the
// header :( hence this "nowrap". A bit puzzling.
return (
<Th
key={key || value}
data-key={key || value}
className={`kui--header-cell ${outerCSS || ''}`}
modifier="nowrap"
{...sortParam}
>
{css ? <span className={css}>{value}</span> : value}
</Th>
)
}

return (
<Thead>
<Tr>
{th(kuiHeader.key, kuiHeader.name, kuiHeader.outerCSS, kuiHeader.css)}
{kuiHeader.attributes.map(attr => th(attr.key, attr.value, attr.outerCSS, attr.css))}
{th(kuiHeader.key, kuiHeader.name, 0, kuiHeader.outerCSS, kuiHeader.css)}
{kuiHeader.attributes.map((attr, cidx) => th(attr.key, attr.value, cidx + 1, attr.outerCSS, attr.css))}
</Tr>
</Thead>
)
Expand Down
30 changes: 19 additions & 11 deletions plugins/plugin-client-common/src/components/Content/Table/sort.ts
@@ -1,5 +1,5 @@
/*
* Copyright 2020 IBM Corporation
* Copyright 2021 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,10 @@
* limitations under the License.
*/

/* const byte = 1
import { Row } from '@kui-shell/core'
import { SortByDirection } from '@patternfly/react-table'

const byte = 1
const kilobyte = 1024 * byte
const megabyte = 1024 * kilobyte
const gigabyte = 1024 * megabyte
Expand All @@ -30,21 +33,26 @@ function toSize(val: string): number {
return mult * parseInt(val.slice(0, val.length - 2), 10)
}

function sortBySize(cellA: string, cellB, dir: number): number {
function sortBySize(rowA: Row, rowB: Row, cidx: number, dir: number): number {
const cellA = rowA.attributes[cidx - 1].value
const cellB = rowB.attributes[cidx - 1].value

return (toSize(cellA) - toSize(cellB)) * dir
}

function sortRowWithDir(cellA: string, cellB: string, key: string, state: DataTableSortState): number {
const dir = state === 'ASC' ? 1 : state === 'NONE' ? 0 : -1
function sortRowWithDir(rowA: Row, rowB: Row, key: string, cidx: number, direction: SortByDirection): number {
const dir = direction === 'asc' ? 1 : -1
if (key === 'SIZE') {
return sortBySize(cellA, cellB, dir)
return sortBySize(rowA, rowB, cidx, dir)
} else {
return cellA.localeCompare(cellB) * dir
return rowA.name.localeCompare(rowB.name) * dir
}
}

export default function sortRow(cellA: string, cellB: string, data: SortRowData): number {
return sortRowWithDir(cellA, cellB, data.key, data.sortDirection)
export default function sortRow(rowA: Row, rowB: Row, key: string, cidx: number, direction: SortByDirection): number {
return sortRowWithDir(rowA, rowB, key.toUpperCase(), cidx, direction)
}

export function isSortableCol(key: string) {
return /NAME|SIZE|NAMESPACE|OBJECT/i.test(key.toUpperCase())
}
*/
Expand Up @@ -26,6 +26,14 @@

@include TableHeadCell {
color: var(--color-text-01);
& .pf-c-table__button {
.pf-c-table__text {
color: var(--color-text-01);
}
.pf-c-table__sort-indicator {
color: var(--color-ui-05);
}
}
}
@include TableCell {
color: var(--color-text-01);
Expand Down
Expand Up @@ -160,10 +160,6 @@ body .bx--data-table {
width: 100%;
}

.kui--header-cell svg {
display: none;
}

.bx--data-table-container {
width: 100%;
.bx--data-table {
Expand Down
Expand Up @@ -93,7 +93,8 @@ describe('command history plain', function(this: Common.ISuite) {
try {
const res = await CLI.command('history 5 lls', this.app)
const N = ((await ReplExpect.okWithCustom({ passthrough: true })(res)) as any) as number
const selector = `${Selectors.LIST_RESULTS_N(N)}:last-child .entity-name`
const selector = `${Selectors.LIST_RESULTS_N(N)}:last-child .entity-name .clickable`
await this.app.client.$(selector).then(_ => _.waitForDisplayed())
await this.app.client.$(selector).then(_ => _.click())
return ReplExpect.okWith('README.md')(await CLI.lastBlock(this.app, 2))
} catch (err) {
Expand Down

0 comments on commit d1dac89

Please sign in to comment.