diff --git a/app/src/app/(dashboard)/encode/[id]/page.tsx b/app/src/app/(dashboard)/encode/[id]/page.tsx index f1e712db..0914a533 100644 --- a/app/src/app/(dashboard)/encode/[id]/page.tsx +++ b/app/src/app/(dashboard)/encode/[id]/page.tsx @@ -2,19 +2,27 @@ import type { page_EncodedPage_Query } from '@/__generated__/page_EncodedPage_Query.graphql' -import { Card, Typography } from '@giantnodes/react' +import { Alert, Card, Typography } from '@giantnodes/react' +import { IconAlertCircleFilled } from '@tabler/icons-react' import { notFound } from 'next/navigation' import { graphql, useLazyLoadQuery } from 'react-relay' -import { EncodeCommandWidget, EncodeOutputWidget, EncodeSizeWidget } from '@/components/interfaces/encode' +import { + EncodeCommandWidget, + EncodeOperationWidget, + EncodeOutputWidget, + EncodeSizeWidget, +} from '@/components/interfaces/encode' import { FileSystemBreadcrumb } from '@/components/interfaces/file-system' const QUERY = graphql` query page_EncodedPage_Query($where: EncodeFilterInput) { encode(where: $where) { + failure_reason file { ...FileSystemBreadcrumbFragment } + ...EncodeOperationWidgetFragment ...EncodeCommandWidgetFragment ...EncodeOutputWidgetFragment ...EncodeSizeWidgetFragment @@ -51,6 +59,18 @@ const EncodePage: React.FC = ({ params }) => { + {query.encode.failure_reason && ( + + + + The encode operation encountered an error + + {query.encode.failure_reason} + + + + )} + Size @@ -84,9 +104,7 @@ const EncodePage: React.FC = ({ params }) => {
- - Tbd - +
diff --git a/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx b/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx index e2185db4..1a482d9e 100644 --- a/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx +++ b/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx @@ -3,10 +3,11 @@ import type { EncodeScriptPanelFragment$key } from '@/__generated__/EncodeScript import { Card, Typography } from '@giantnodes/react' import { graphql, useFragment } from 'react-relay' -import { EncodeCommandWidget, EncodeOutputWidget } from '@/components/interfaces/encode' +import { EncodeCommandWidget, EncodeOperationWidget, EncodeOutputWidget } from '@/components/interfaces/encode' const FRAGMENT = graphql` fragment EncodeScriptPanelFragment on Encode { + ...EncodeOperationWidgetFragment ...EncodeCommandWidgetFragment ...EncodeOutputWidgetFragment } @@ -21,6 +22,10 @@ const EncodeScriptPanel: React.FC = ({ $key }) => { return ( <> + + + + Command diff --git a/app/src/components/interfaces/encode/index.ts b/app/src/components/interfaces/encode/index.ts index 115e7f0e..1f92f079 100644 --- a/app/src/components/interfaces/encode/index.ts +++ b/app/src/components/interfaces/encode/index.ts @@ -1,5 +1,6 @@ export { default as EncodeDialog } from '@/components/interfaces/encode/dialog/EncodeDialog' export { default as EncodeCommandWidget } from '@/components/interfaces/encode/widgets/EncodeCommandWidget' +export { default as EncodeOperationWidget } from '@/components/interfaces/encode/widgets/EncodeOperationWidget' export { default as EncodeOutputWidget } from '@/components/interfaces/encode/widgets/EncodeOutputWidget' export { default as EncodeSizeWidget } from '@/components/interfaces/encode/widgets/EncodeSizeWidget' diff --git a/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx b/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx new file mode 100644 index 00000000..dd80f3b8 --- /dev/null +++ b/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx @@ -0,0 +1,99 @@ +import type { EncodeOperationWidgetFragment$key } from '@/__generated__/EncodeOperationWidgetFragment.graphql' + +import { Chip, Table, Typography } from '@giantnodes/react' +import dayjs from 'dayjs' +import { filesize } from 'filesize' +import { graphql, useFragment } from 'react-relay' + +import { percent } from '@/utilities/numbers' + +const FRAGMENT = graphql` + fragment EncodeOperationWidgetFragment on Encode { + percent + updated_at + machine { + name + user_name + } + speed { + bitrate + frames + scale + } + } +` + +type EncodeOperationWidgetProps = { + $key: EncodeOperationWidgetFragment$key +} + +const EncodeOperationWidget: React.FC = ({ $key }) => { + const data = useFragment(FRAGMENT, $key) + + return ( + + + + name + + + value + + + + {data.percent != null && ( + + + Progress + + + {percent(data.percent)} + + + )} + + + + Machine + + + {data.machine?.name} + {data.machine?.user_name} + + + + {data.speed != null && ( + + + Speed + + + {data.speed.frames} fps + + {filesize(data.speed.bitrate * 0.125, { bits: true }).toLowerCase()}/s + + {data.speed.scale.toFixed(2)}x + + + )} + + {data.updated_at != null && ( + + + Heartbeat + + + + + {dayjs(data.updated_at).fromNow()} + + + + + )} + +
+ ) +} + +export default EncodeOperationWidget diff --git a/app/src/components/ui/encode-badges/EncodeBadges.tsx b/app/src/components/ui/encode-badges/EncodeBadges.tsx index 94cb8340..b7aee9d6 100644 --- a/app/src/components/ui/encode-badges/EncodeBadges.tsx +++ b/app/src/components/ui/encode-badges/EncodeBadges.tsx @@ -9,6 +9,7 @@ import React from 'react' import { graphql, useFragment } from 'react-relay' import EncodeStatusBadge from '@/components/ui/encode-badges/EncodeStatusBadge' +import { percent } from '@/utilities/numbers' type EncodeBadgesProps = Omit & { $key: EncodeBadgesFragment$key @@ -40,12 +41,6 @@ const FRAGMENT = graphql` const EncodeBadges: React.FC = ({ $key, size }) => { const data = useFragment(FRAGMENT, $key) - const percent = (value: number): string => - Intl.NumberFormat('en-US', { - style: 'percent', - maximumFractionDigits: 2, - }).format(value) - const SizeChip = React.useCallback(() => { const difference = data.snapshots[data.snapshots.length - 1].size - data.snapshots[0].size const increase = Math.abs(difference / data.snapshots[0].size) diff --git a/app/src/utilities/numbers.ts b/app/src/utilities/numbers.ts new file mode 100644 index 00000000..10407dc6 --- /dev/null +++ b/app/src/utilities/numbers.ts @@ -0,0 +1,5 @@ +export const percent = (value: number): string => + Intl.NumberFormat('en-US', { + style: 'percent', + maximumFractionDigits: 2, + }).format(value)