web: migrate pages to react-table

This migrates the Labels, Nodes and
Projects pages to using the react-table
component from patternfly.

Change-Id: Iaa75e70f4b0c25113369939f97a297571f2ea7a5
This commit is contained in:
Tobias Urdin 2023-03-22 16:10:08 +00:00
parent 0e3c05ab47
commit de9dfa2bc4
3 changed files with 174 additions and 119 deletions

View File

@ -15,8 +15,15 @@
import * as React from 'react' import * as React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Table } from 'patternfly-react'
import { PageSection, PageSectionVariants } from '@patternfly/react-core' import { PageSection, PageSectionVariants } from '@patternfly/react-core'
import {
Table,
TableVariant,
TableHeader,
TableBody,
} from '@patternfly/react-table'
import { TagIcon } from '@patternfly/react-icons'
import { IconProperty } from '../Misc'
import { fetchLabelsIfNeeded } from '../actions/labels' import { fetchLabelsIfNeeded } from '../actions/labels'
import { Fetchable, Fetching } from '../containers/Fetching' import { Fetchable, Fetching } from '../containers/Fetching'
@ -54,18 +61,22 @@ class LabelsPage extends React.Component {
return <Fetching /> return <Fetching />
} }
const headerFormat = value => <Table.Heading>{value}</Table.Heading> const columns = [
const cellFormat = value => <Table.Cell>{value}</Table.Cell> {
const columns = [] title: (
const myColumns = ['name'] <IconProperty icon={<TagIcon />} value="Name" />
myColumns.forEach(column => { ),
let formatter = cellFormat dataLabel: 'name'
let prop = column }
columns.push({ ]
header: {label: column, formatters: [headerFormat]}, let rows = []
property: prop, labels.forEach((label) => {
cell: {formatters: [formatter]} let r = {
}) cells: [
{title: label.name, props: {column: 'Name'}}
],
}
rows.push(r)
}) })
return ( return (
<PageSection variant={PageSectionVariants.light}> <PageSection variant={PageSectionVariants.light}>
@ -75,18 +86,16 @@ class LabelsPage extends React.Component {
fetchCallback={this.updateData} fetchCallback={this.updateData}
/> />
</PageSection> </PageSection>
<Table.PfProvider <Table
striped aria-label="Labels Table"
bordered variant={TableVariant.compact}
hover cells={columns}
columns={columns} rows={rows}
className="zuul-table"
> >
<Table.Header/> <TableHeader />
<Table.Body <TableBody />
rows={labels} </Table>
rowKey="name"
/>
</Table.PfProvider>
</PageSection> </PageSection>
) )
} }

View File

@ -15,9 +15,29 @@
import * as React from 'react' import * as React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Table } from 'patternfly-react' import {
Table,
TableVariant,
TableHeader,
TableBody,
} from '@patternfly/react-table'
import * as moment from 'moment' import * as moment from 'moment'
import { PageSection, PageSectionVariants } from '@patternfly/react-core' import {
PageSection,
PageSectionVariants,
ClipboardCopy,
} from '@patternfly/react-core'
import {
BuildIcon,
ClusterIcon,
ConnectedIcon,
OutlinedCalendarAltIcon,
TagIcon,
RunningIcon,
PencilAltIcon,
ZoneIcon,
} from '@patternfly/react-icons'
import { IconProperty } from '../Misc'
import { fetchNodesIfNeeded } from '../actions/nodes' import { fetchNodesIfNeeded } from '../actions/nodes'
import { Fetchable } from '../containers/Fetching' import { Fetchable } from '../containers/Fetching'
@ -51,43 +71,69 @@ class NodesPage extends React.Component {
const { remoteData } = this.props const { remoteData } = this.props
const nodes = remoteData.nodes const nodes = remoteData.nodes
const headerFormat = value => <Table.Heading>{value}</Table.Heading> const columns = [
const cellFormat = value => <Table.Cell>{value}</Table.Cell> {
const cellLabelsFormat = value => <Table.Cell>{value.join(',')}</Table.Cell> title: (
const cellPreFormat = value => ( <IconProperty icon={<BuildIcon />} value="ID" />
<Table.Cell style={{fontFamily: 'Menlo,Monaco,Consolas,monospace'}}> ),
{value} dataLabel: 'id',
</Table.Cell>) },
const cellAgeFormat = value => ( {
<Table.Cell style={{fontFamily: 'Menlo,Monaco,Consolas,monospace'}}> title: (
{moment.unix(value).fromNow()} <IconProperty icon={<TagIcon />} value="Labels" />
</Table.Cell>) ),
dataLabel: 'labels',
const columns = [] },
const myColumns = [ {
'id', 'labels', 'connection', 'server', 'provider', 'state', title: (
'age', 'comment' <IconProperty icon={<ConnectedIcon />} value="Connection" />
] ),
myColumns.forEach(column => { dataLabel: 'connection',
let formatter = cellFormat },
let prop = column {
if (column === 'labels') { title: (
prop = 'type' <IconProperty icon={<ClusterIcon />} value="Server" />
formatter = cellLabelsFormat ),
} else if (column === 'connection') { dataLabel: 'server',
prop = 'connection_type' },
} else if (column === 'server') { {
prop = 'external_id' title: (
formatter = cellPreFormat <IconProperty icon={<ZoneIcon />} value="Provider" />
} else if (column === 'age') { ),
prop = 'state_time' dataLabel: 'provider',
formatter = cellAgeFormat },
{
title: (
<IconProperty icon={<RunningIcon />} value="State" />
),
dataLabel: 'state',
},
{
title: (
<IconProperty icon={<OutlinedCalendarAltIcon />} value="Age" />
),
dataLabel: 'age',
},
{
title: (
<IconProperty icon={<PencilAltIcon />} value="Comment" />
),
dataLabel: 'comment',
} }
columns.push({ ]
header: {label: column, formatters: [headerFormat]}, let rows = []
property: prop, nodes.forEach((node) => {
cell: {formatters: [formatter]} let r = [
}) {title: node.id, props: {column: 'ID'}},
{title: node.type.join(','), props: {column: 'Label' }},
{title: node.connection_type, props: {column: 'Connection'}},
{title: <ClipboardCopy hoverTip="Copy" clickTip="Copied" variant="inline-compact">{node.external_id}</ClipboardCopy>, props: {column: 'Server'}},
{title: node.provider, props: {column: 'Provider'}},
{title: node.state, props: {column: 'State'}},
{title: moment.unix(node.state_time).fromNow(), props: {column: 'Age'}},
{title: node.comment, props: {column: 'Comment'}},
]
rows.push({cells: r})
}) })
return ( return (
<PageSection variant={PageSectionVariants.light}> <PageSection variant={PageSectionVariants.light}>
@ -97,18 +143,17 @@ class NodesPage extends React.Component {
fetchCallback={this.updateData} fetchCallback={this.updateData}
/> />
</PageSection> </PageSection>
<Table.PfProvider
striped <Table
bordered aria-label="Nodes Table"
hover variant={TableVariant.compact}
columns={columns} cells={columns}
rows={rows}
className="zuul-table"
> >
<Table.Header/> <TableHeader />
<Table.Body <TableBody />
rows={nodes} </Table>
rowKey="id"
/>
</Table.PfProvider>
</PageSection> </PageSection>
) )
} }

View File

@ -16,8 +16,18 @@ import * as React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Table } from 'patternfly-react'
import { PageSection, PageSectionVariants } from '@patternfly/react-core' import { PageSection, PageSectionVariants } from '@patternfly/react-core'
import {
Table,
TableVariant,
TableHeader,
TableBody,
} from '@patternfly/react-table'
import {
CubeIcon,
ConnectedIcon,
} from '@patternfly/react-icons'
import { IconProperty } from '../Misc'
import { fetchProjectsIfNeeded } from '../actions/projects' import { fetchProjectsIfNeeded } from '../actions/projects'
import { Fetchable, Fetching } from '../containers/Fetching' import { Fetchable, Fetching } from '../containers/Fetching'
@ -59,42 +69,35 @@ class ProjectsPage extends React.Component {
return <Fetching /> return <Fetching />
} }
const headerFormat = value => <Table.Heading>{value}</Table.Heading> const columns = [
const cellFormat = (value) => ( {
<Table.Cell>{value}</Table.Cell>) title: <IconProperty icon={<CubeIcon />} value="Name" />,
const cellProjectFormat = (value, row) => ( dataLabel: 'name',
<Table.Cell> },
<Link to={this.props.tenant.linkPrefix + '/project/' + row.rowData.canonical_name}> {
{value} title: <IconProperty icon={<ConnectedIcon />} value="Connection" />,
</Link> dataLabel: 'connection',
</Table.Cell>) },
const cellBuildFormat = (value) => ( {
<Table.Cell> title: 'Type',
<Link to={this.props.tenant.linkPrefix + '/builds?project=' + value}> dataLabel: 'type',
builds },
</Link> {
</Table.Cell>) title: 'Last builds',
const columns = [] dataLabel: 'last-builds',
const myColumns = ['name', 'connection', 'type', 'last builds']
myColumns.forEach(column => {
let formatter = cellFormat
let prop = column
if (column === 'name') {
formatter = cellProjectFormat
} }
if (column === 'connection') { ]
prop = 'connection_name' let rows = []
projects.forEach((project) => {
let r = {
cells: [
{title: <Link to={this.props.tenant.linkPrefix + '/project/' + project.canonical_name}>{project.name}</Link>, props: {column: 'Name'}},
{title: project.connection_name, props: {column: 'Connection'}},
{title: project.type, props: {column: 'Type'}},
{title: <Link to={this.props.tenant.linkPrefix + '/builds?project=' + project.name}>Builds</Link>, props: {column: 'Last builds'}},
]
} }
if (column === 'last builds') { rows.push(r)
prop = 'name'
formatter = cellBuildFormat
}
columns.push({
header: {label: column,
formatters: [headerFormat]},
property: prop,
cell: {formatters: [formatter]}
})
}) })
return ( return (
<PageSection variant={PageSectionVariants.light}> <PageSection variant={PageSectionVariants.light}>
@ -104,18 +107,16 @@ class ProjectsPage extends React.Component {
fetchCallback={this.updateData} fetchCallback={this.updateData}
/> />
</PageSection> </PageSection>
<Table.PfProvider <Table
striped aria-label="Projects Table"
bordered variant={TableVariant.compact}
hover cells={columns}
columns={columns} rows={rows}
className="zuul-table"
> >
<Table.Header/> <TableHeader />
<Table.Body <TableBody />
rows={projects} </Table>
rowKey="name"
/>
</Table.PfProvider>
</PageSection> </PageSection>
) )
} }