diff --git a/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/RunsSearchResultItemLayout.js b/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/RunsSearchResultItemLayout.js index fc1f976..f55c783 100644 --- a/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/RunsSearchResultItemLayout.js +++ b/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/RunsSearchResultItemLayout.js @@ -10,11 +10,12 @@ import { NotificationContext } from "@js/invenio_administration"; import { i18next } from "@translations/invenio_app_rdm/i18next"; import PropTypes from "prop-types"; import React, { Component } from "react"; -import { UserListItemCompact, toRelativeTime } from "react-invenio-forms"; +import { UserListItemCompact } from "react-invenio-forms"; import { withState } from "react-searchkit"; import { Table } from "semantic-ui-react"; import { StatusFormatter } from "./StatusFormatter"; import { StopButton } from "./StopButton"; +import { diffTimestamps } from "./utils/diffTimestamps"; class SearchResultItemComponent extends Component { constructor(props) { @@ -60,7 +61,19 @@ class SearchResultItemComponent extends Component { > {result.started_at === null ? `${i18next.t("Waiting")}...` - : toRelativeTime(result.started_at, i18next.language)} + : [ + result.finished_at === null + ? `${diffTimestamps( + new Date().toISOString(), + result.started_at, + i18next.language + )}...` + : diffTimestamps( + result.finished_at, + result.started_at, + i18next.language + ), + ]} )} - {status === "RUNNING" || status === "QUEUED" ? ( + {status === "RUNNING" ? ( { diff --git a/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/utils/diffTimestamps.js b/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/utils/diffTimestamps.js new file mode 100644 index 0000000..6a061ac --- /dev/null +++ b/invenio_jobs/assets/semantic-ui/js/invenio_jobs/administration/utils/diffTimestamps.js @@ -0,0 +1,59 @@ +// This file is part of React-Invenio-Forms +// Copyright (C) 2024 CERN. +// +// React-Invenio-Forms is free software; you can redistribute it and/or modify it +// under the terms of the MIT License; see LICENSE file for more details. + +import { DateTime } from "luxon"; + +/** + * Create duration string for two given timestamps + * + * @param firstTimestamp string ISO timestamp + * @param secondTimestamp string ISO timestamp + * @returns {string} string representation of duration, i.e. 3 days + */ +export const diffTimestamps = ( + firstTimestamp, + secondTimestamp, + language = "en" +) => { + const first = DateTime.fromISO(firstTimestamp); + const second = DateTime.fromISO(secondTimestamp); + const duration = first.diff(second).reconfigure({ locale: language }); + // If we used a newer version of luxon we could just do this: + // return duration.toHuman(); + + // instead return the largest unit and value (ignore everything smaller) + const rescale = duration.shiftTo( + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds" + ); // in new luxon this is just duration.rescale() + const units = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + ]; + + for (const unit of units) { + if (rescale[unit] && rescale[unit] > 0) { + if (rescale[unit] === 1) { + return rescale[unit] + " " + unit.slice(0, -1); // remove s + } else { + return rescale[unit] + " " + unit; + } + } + } + return "-"; // in case all components are zero +};