// Copyright 2020 BMW Group // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateSecondaryActions, Spinner, Title, } from '@patternfly/react-core' import { BuildIcon, CodeBranchIcon, CodeIcon, CubeIcon, OutlinedCalendarAltIcon, OutlinedClockIcon, PollIcon, StreamIcon, } from '@patternfly/react-icons' import { Table, TableHeader, TableBody, TableVariant, truncate, breakWord, cellWidth, } from '@patternfly/react-table' import 'moment-duration-format' import * as moment from 'moment' import { BuildResult, BuildResultWithIcon } from './Misc' import { buildExternalTableLink, IconProperty } from '../../Misc' function BuildTable({ builds, fetching, onClearFilters, tenant, timezone, history, }) { const columns = [ { title: } value="Job" />, dataLabel: 'Job', cellTransforms: [breakWord], }, { title: } value="Project" />, dataLabel: 'Project', cellTransforms: [breakWord], }, { title: } value="Branch" />, dataLabel: 'Branch', cellTransforms: [breakWord], }, { title: } value="Pipeline" />, dataLabel: 'Pipeline', }, { title: } value="Change" />, dataLabel: 'Change', transforms: [cellWidth(10)], cellTransforms: [truncate], }, { title: } value="Duration" />, dataLabel: 'Duration', }, { title: ( } value="Start time" /> ), dataLabel: 'Start time', }, { title: } value="Result" />, dataLabel: 'Result', }, ] function createBuildRow(build) { const changeOrRefLink = buildExternalTableLink(build) return { // Pass the build's uuid as row id, so we can use it later on in the // action handler to build the link to the build result page for each row. id: build.uuid, cells: [ { // To allow passing anything else than simple string values to a table // cell, we must use the title attribute. title: ( <> {build.job_name} {!build.voting && ' (non-voting)'} ), }, { title: build.project, }, { title: build.branch ? build.branch : build.ref, }, { title: build.pipeline, }, { title: changeOrRefLink && changeOrRefLink, }, { title: moment .duration(build.duration, 'seconds') .format('h [hr] m [min] s [sec]'), }, { title: moment .utc(build.start_time) .tz(timezone) .format('YYYY-MM-DD HH:mm:ss'), }, { title: ( ), }, ], } } function createFetchingRow() { const rows = [ { heightAuto: true, cells: [ { props: { colSpan: 8 }, title: (
), }, ], }, ] return rows } let rows = [] // For the fetching row we don't need any actions, so we keep them empty by // default. let actions = [] if (fetching) { rows = createFetchingRow() // The dataLabel property is used to show the column header in a list-like // format for smaller viewports. When we are fetching, we don't want the // fetching row to be prepended by a "Job" column header. The other column // headers are not relevant here since we only have a single cell in the // fetcihng row. columns[0].dataLabel = '' } else { rows = builds.map((build) => createBuildRow(build)) // This list of actions will be applied to each row in the table. For // row-specific actions we must evaluate the individual row data provided to // the onClick handler. actions = [ { title: 'Show build result', onClick: (event, rowId, rowData) => // The row's id contains the build's uuid, so we can use this to build // the correct link. history.push(`${tenant.linkPrefix}/build/${rowData.id}`), }, ] } return ( <>
{/* Show an empty state in case we don't have any builds but are also not fetching */} {!fetching && builds.length === 0 && ( No builds found No builds match this filter criteria. Remove some filters or clear all to show results. )} ) } BuildTable.propTypes = { builds: PropTypes.array.isRequired, fetching: PropTypes.bool.isRequired, onClearFilters: PropTypes.func.isRequired, tenant: PropTypes.object.isRequired, timezone: PropTypes.string.isRequired, history: PropTypes.object.isRequired, } export default connect((state) => ({ tenant: state.tenant, timezone: state.timezone, }))(BuildTable)