diff options
-rw-r--r-- | web/package.json | 2 | ||||
-rw-r--r-- | web/src/containers/build/Buildset.jsx | 4 | ||||
-rw-r--r-- | web/src/containers/build/Console.jsx | 16 | ||||
-rw-r--r-- | web/src/containers/build/Summary.jsx | 7 | ||||
-rw-r--r-- | web/src/containers/status/ChangePanel.jsx | 77 | ||||
-rw-r--r-- | web/src/index.css | 9 | ||||
-rw-r--r-- | web/src/pages/Builds.jsx | 9 | ||||
-rw-r--r-- | web/yarn.lock | 5 |
8 files changed, 67 insertions, 62 deletions
diff --git a/web/package.json b/web/package.json index 4b11ac432..b811c7a24 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ "js-yaml": "^3.13.0", "lodash": "^4.17.10", "moment": "^2.22.2", + "moment-duration-format": "2.3.2", "patternfly-react": "^2.13.1", "prop-types": "^15.6.2", "react": "^16.4.2", @@ -36,6 +37,7 @@ "yarn": "^1.16.0" }, "scripts": { + "start:opendev": "REACT_APP_ZUUL_API='https://zuul.opendev.org/api/' react-scripts start", "start:openstack": "REACT_APP_ZUUL_API='https://zuul.openstack.org/api/' react-scripts start", "start:multi": "REACT_APP_ZUUL_API='https://softwarefactory-project.io/zuul/api/' react-scripts start", "start": "react-scripts start", diff --git a/web/src/containers/build/Buildset.jsx b/web/src/containers/build/Buildset.jsx index 803022a21..89f246c83 100644 --- a/web/src/containers/build/Buildset.jsx +++ b/web/src/containers/build/Buildset.jsx @@ -18,6 +18,7 @@ import { connect } from 'react-redux' import { Link } from 'react-router-dom' import { Panel } from 'react-bootstrap' import * as moment from 'moment' +import 'moment-duration-format' class Buildset extends React.Component { @@ -61,7 +62,8 @@ class Buildset extends React.Component { if (column === 'job') { row.push(build.job_name) } else if (column === 'duration') { - row.push(moment.duration(build.duration, 'seconds').humanize()) + row.push(moment.duration(build.duration, 'seconds') + .format('h [hr] m [min] s [sec]')) } else if (column === 'voting') { row.push(build.voting ? 'true' : 'false') } else if (column === 'result') { diff --git a/web/src/containers/build/Console.jsx b/web/src/containers/build/Console.jsx index 01b308bfe..d8810170e 100644 --- a/web/src/containers/build/Console.jsx +++ b/web/src/containers/build/Console.jsx @@ -12,6 +12,8 @@ // License for the specific language governing permissions and limitations // under the License. +import * as moment from 'moment' +import 'moment-duration-format' import * as React from 'react' import PropTypes from 'prop-types' import ReactJson from 'react-json-view' @@ -206,6 +208,20 @@ class HostTask extends React.Component { </ListView.InfoItem> ) + let duration = moment.duration( + moment(task.task.duration.end).diff(task.task.duration.start) + ).format({ + template: 'h [hr] m [min] s [sec]', + largest: 2, + minValue: 1, + }) + + ai.push( + <ListView.InfoItem key="task-duration"> + <span className="task-duration">{duration}</span> + </ListView.InfoItem> + ) + const expand = errorIds.has(task.task.id) let name = task.task.name diff --git a/web/src/containers/build/Summary.jsx b/web/src/containers/build/Summary.jsx index 90eea6af7..ef47b9ef9 100644 --- a/web/src/containers/build/Summary.jsx +++ b/web/src/containers/build/Summary.jsx @@ -20,6 +20,9 @@ import { Link } from 'react-router-dom' import ArtifactList from './Artifact' import BuildOutput from './BuildOutput' +import * as moment from 'moment' +import 'moment-duration-format' + class Summary extends React.Component { static propTypes = { @@ -66,6 +69,10 @@ class Summary extends React.Component { value = 'false' } } + if (column === 'duration') { + value = moment.duration(value, 'seconds') + .format('h [hr] m [min] s [sec]') + } if (value && (column === 'log_url' || column === 'ref_url')) { value = <a href={value}>{value}</a> } diff --git a/web/src/containers/status/ChangePanel.jsx b/web/src/containers/status/ChangePanel.jsx index def966e99..6600e6e8e 100644 --- a/web/src/containers/status/ChangePanel.jsx +++ b/web/src/containers/status/ChangePanel.jsx @@ -16,11 +16,8 @@ import * as React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Link } from 'react-router-dom' - -const SECOND = 1000 -const MINUTE = SECOND * 60 -const HOUR = MINUTE * 60 -const DAY = HOUR * 24 +import * as moment from 'moment' +import 'moment-duration-format' class ChangePanel extends React.Component { @@ -52,37 +49,13 @@ class ChangePanel extends React.Component { this.setState({ expanded: !expanded }) } - time (ms, words) { - if (typeof (words) === 'undefined') { - words = false - } - let seconds = (+ms) / 1000 - let minutes = Math.floor(seconds / 60) - let hours = Math.floor(minutes / 60) - seconds = Math.floor(seconds % 60) - minutes = Math.floor(minutes % 60) - let r = '' - if (words) { - if (hours) { - r += hours - r += ' hr ' - } - r += minutes + ' min' - } else { - if (hours < 10) { - r += '0' - } - r += hours + ':' - if (minutes < 10) { - r += '0' - } - r += minutes + ':' - if (seconds < 10) { - r += '0' - } - r += seconds - } - return r + time (ms) { + return moment.duration(ms).format({ + template: 'h [hr] m [min]', + largest: 2, + minValue: 1, + usePlural: false, + }) } enqueueTime (ms) { @@ -91,7 +64,7 @@ class ChangePanel extends React.Component { let now = Date.now() let delta = now - ms let status = 'text-success' - let text = this.time(delta, true) + let text = this.time(delta) if (delta > (4 * hours)) { status = 'text-danger' } else if (delta > (2 * hours)) { @@ -175,7 +148,7 @@ class ChangePanel extends React.Component { if (change.remaining_time === null) { remainingTime = 'unknown' } else { - remainingTime = this.time(change.remaining_time, true) + remainingTime = this.time(change.remaining_time) } return ( <React.Fragment> @@ -204,29 +177,11 @@ class ChangePanel extends React.Component { className = 'progress-bar-striped progress-bar-animated' } if (remaining !== null) { - title = 'Estimated time remaining: ' - if (remaining < MINUTE) { - title = title + 'less than a minute' - } else { - let days = 0 - let hours = 0 - let minutes = 0 - - days = Math.trunc(remaining/DAY) - remaining = Math.trunc(remaining%DAY) - hours = Math.trunc(remaining/HOUR) - remaining = Math.trunc(remaining%HOUR) - minutes = Math.trunc(remaining/MINUTE) - if (days > 0) { - title = title + days + ' days ' - } - if (hours > 0) { - title = title + hours + ' hours ' - } - if (minutes > 0) { - title = title + minutes + ' minutes ' - } - } + title = 'Estimated time remaining: ' + moment.duration(remaining).format({ + template: 'd [days] h [hours] m [minutes] s [seconds]', + largest: 2, + minValue: 30, + }) } return ( diff --git a/web/src/index.css b/web/src/index.css index b638a4600..476a55905 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -9,6 +9,10 @@ a.refresh { text-decoration: none; } +.time { + white-space: nowrap; +} + /* Notification bell color */ .fa-bell { color: orange; @@ -180,6 +184,11 @@ pre.version { padding-top: 1px; padding-bottom: 1px; } +.zuul-console .list-view-pf-additional-info-item { + flex-grow: 1; + flex-shrink: 1; + flex-basis: 0; +} .zuul-console .list-view-pf-expand { padding: 0; diff --git a/web/src/pages/Builds.jsx b/web/src/pages/Builds.jsx index 54c184d41..694608373 100644 --- a/web/src/pages/Builds.jsx +++ b/web/src/pages/Builds.jsx @@ -17,6 +17,8 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Link } from 'react-router-dom' import { Table } from 'patternfly-react' +import * as moment from 'moment' +import 'moment-duration-format' import { fetchBuilds } from '../api' import TableFilters from '../containers/TableFilters' @@ -77,6 +79,11 @@ class BuildsPage extends TableFilters { <a href={rowdata.rowData.ref_url}>{value ? rowdata.rowData.change+','+rowdata.rowData.patchset : rowdata.rowData.newrev ? rowdata.rowData.newrev.substr(0, 7) : rowdata.rowData.branch}</a> </Table.Cell> ) + const durationFormat = (value) => ( + <Table.Cell> + {moment.duration(value, 'seconds').format('h [hr] m [min] s [sec]')} + </Table.Cell> + ) this.columns = [] this.filterTypes = [] const myColumns = [ @@ -101,6 +108,8 @@ class BuildsPage extends TableFilters { formatter = linkChangeFormat } else if (column === 'result') { formatter = linkBuildFormat + } else if (column === 'duration') { + formatter = durationFormat } const label = column.charAt(0).toUpperCase() + column.slice(1) this.columns.push({ diff --git a/web/yarn.lock b/web/yarn.lock index 613645648..f572e43fc 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -6112,6 +6112,11 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@ dependencies: minimist "0.0.8" +moment-duration-format@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/moment-duration-format/-/moment-duration-format-2.3.2.tgz#5fa2b19b941b8d277122ff3f87a12895ec0d6212" + integrity sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ== + moment-timezone@^0.4.0, moment-timezone@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.4.1.tgz#81f598c3ad5e22cdad796b67ecd8d88d0f5baa06" |