From 3336619825fc773ee6f6312012000ba662bd832b Mon Sep 17 00:00:00 2001 From: 0x60B2 <60131234+0x60B2@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:08:15 +0100 Subject: [PATCH 1/2] feat: Add ETA for tasks --- ui/v2.5/graphql/subscriptions.graphql | 1 + ui/v2.5/package.json | 1 + .../components/Settings/Tasks/JobTable.tsx | 62 ++++++++++++++----- ui/v2.5/yarn.lock | 5 ++ 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/ui/v2.5/graphql/subscriptions.graphql b/ui/v2.5/graphql/subscriptions.graphql index 4c7ffaebf5f..a5bf4122de0 100644 --- a/ui/v2.5/graphql/subscriptions.graphql +++ b/ui/v2.5/graphql/subscriptions.graphql @@ -8,6 +8,7 @@ subscription JobsSubscribe { description progress error + startTime } } } diff --git a/ui/v2.5/package.json b/ui/v2.5/package.json index 210b750fe0c..cb59056406e 100644 --- a/ui/v2.5/package.json +++ b/ui/v2.5/package.json @@ -50,6 +50,7 @@ "intersection-observer": "^0.12.2", "localforage": "^1.10.0", "lodash-es": "^4.17.21", + "moment": "^2.30.1", "mousetrap": "^1.6.5", "mousetrap-pause": "^1.0.0", "normalize-url": "^4.5.1", diff --git a/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx b/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx index 82ed46c854b..6496dadcbc4 100644 --- a/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx @@ -1,13 +1,3 @@ -import React, { useState, useEffect } from "react"; -import { Button, Card, ProgressBar } from "react-bootstrap"; -import { - mutateStopJob, - useJobQueue, - useJobsSubscribe, -} from "src/core/StashService"; -import * as GQL from "src/core/generated-graphql"; -import { Icon } from "src/components/Shared/Icon"; -import { useIntl } from "react-intl"; import { faBan, faCheck, @@ -17,10 +7,27 @@ import { faHourglassStart, faTimes, } from "@fortawesome/free-solid-svg-icons"; +import moment from "moment"; +import React, { useEffect, useState } from "react"; +import { Button, Card, ProgressBar } from "react-bootstrap"; +import { useIntl } from "react-intl"; +import { Icon } from "src/components/Shared/Icon"; +import { + mutateStopJob, + useJobQueue, + useJobsSubscribe, +} from "src/core/StashService"; +import * as GQL from "src/core/generated-graphql"; type JobFragment = Pick< GQL.Job, - "id" | "status" | "subTasks" | "description" | "progress" | "error" + | "id" + | "status" + | "subTasks" + | "description" + | "progress" + | "error" + | "startTime" >; interface IJob { @@ -124,6 +131,25 @@ const Task: React.FC = ({ job }) => { } } + function maybeRenderETA() { + if ( + job.status === GQL.JobStatus.Running && + job.startTime !== null && + job.startTime !== undefined && + job.progress !== null && + job.progress !== undefined && + job.progress > 0 + ) { + const now = new Date(); + const start = new Date(job.startTime); + const now_ms = now.valueOf(); + const start_ms = start.valueOf(); + const estimated_length = (now_ms - start_ms) / job.progress; + const est_len_str = moment.duration(estimated_length).humanize(); + return ETA: {est_len_str}; + } + } + function maybeRenderSubTasks() { if ( job.status === GQL.JobStatus.Running || @@ -159,9 +185,17 @@ const Task: React.FC = ({ job }) => {
-
- {getStatusIcon()} - {job.description} +
+
+ {getStatusIcon()} + {job.description} +
+ {maybeRenderETA()}
{maybeRenderProgress()}
{maybeRenderSubTasks()} diff --git a/ui/v2.5/yarn.lock b/ui/v2.5/yarn.lock index aa27a347444..b11ee8116c7 100644 --- a/ui/v2.5/yarn.lock +++ b/ui/v2.5/yarn.lock @@ -5818,6 +5818,11 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + moment@~2.29.1: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" From 2df05e31b9c22328bb34c419f37dd32a3b86fd65 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:58:27 +1100 Subject: [PATCH 2/2] Cleanup and i8n --- ui/v2.5/src/App.tsx | 3 +++ .../components/Settings/Tasks/JobTable.tsx | 25 +++++++++---------- ui/v2.5/src/components/Settings/styles.scss | 5 ++++ ui/v2.5/src/locales/en-GB.json | 1 + 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ui/v2.5/src/App.tsx b/ui/v2.5/src/App.tsx index 658ca301122..e8e32cced4b 100644 --- a/ui/v2.5/src/App.tsx +++ b/ui/v2.5/src/App.tsx @@ -48,6 +48,8 @@ import "./pluginApi"; import { ConnectionMonitor } from "./ConnectionMonitor"; import { PatchFunction } from "./patch"; +import moment from "moment/min/moment-with-locales"; + const Performers = lazyComponent( () => import("./components/Performers/Performers") ); @@ -158,6 +160,7 @@ export const App: React.FC = () => { }); setMessages(newMessages); + moment.locale([language, defaultLocale]); }; setLocale(); diff --git a/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx b/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx index 6496dadcbc4..a6b740d585a 100644 --- a/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/JobTable.tsx @@ -7,10 +7,10 @@ import { faHourglassStart, faTimes, } from "@fortawesome/free-solid-svg-icons"; -import moment from "moment"; +import moment from "moment/min/moment-with-locales"; import React, { useEffect, useState } from "react"; import { Button, Card, ProgressBar } from "react-bootstrap"; -import { useIntl } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import { Icon } from "src/components/Shared/Icon"; import { mutateStopJob, @@ -142,11 +142,15 @@ const Task: React.FC = ({ job }) => { ) { const now = new Date(); const start = new Date(job.startTime); - const now_ms = now.valueOf(); - const start_ms = start.valueOf(); - const estimated_length = (now_ms - start_ms) / job.progress; - const est_len_str = moment.duration(estimated_length).humanize(); - return ETA: {est_len_str}; + const nowMS = now.valueOf(); + const startMS = start.valueOf(); + const estimatedLength = (nowMS - startMS) / job.progress; + const estLenStr = moment.duration(estimatedLength).humanize(); + return ( + + : {estLenStr} + + ); } } @@ -185,12 +189,7 @@ const Task: React.FC = ({ job }) => {
-
+
{getStatusIcon()} {job.description} diff --git a/ui/v2.5/src/components/Settings/styles.scss b/ui/v2.5/src/components/Settings/styles.scss index 8861a8122cc..db5c054e8b4 100644 --- a/ui/v2.5/src/components/Settings/styles.scss +++ b/ui/v2.5/src/components/Settings/styles.scss @@ -293,6 +293,11 @@ width: 100%; } + .job-description { + display: flex; + justify-content: space-between; + } + .stop:not(:disabled), .stopping .fa-icon, .cancelled .fa-icon { diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index f22ba1de574..99e14b6373c 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -1054,6 +1054,7 @@ "loading_type": "Error loading {type}", "something_went_wrong": "Something went wrong." }, + "eta": "ETA", "ethnicity": "Ethnicity", "existing_value": "existing value", "eye_color": "Eye Colour",