From 6506c2bf0465d9c0d5ba9ee30c72e718069b1335 Mon Sep 17 00:00:00 2001 From: Jordan Phillips Date: Sun, 12 May 2024 11:11:39 +1000 Subject: [PATCH] refactor: use separate encode chip components --- app/src/app/(dashboard)/encode/[id]/page.tsx | 12 +- .../encode/chips/EncodeDuration.tsx | 47 ++++++ .../interfaces/encode/chips/EncodePercent.tsx | 51 +++++++ .../interfaces/encode/chips/EncodeSpeed.tsx | 62 ++++++++ .../interfaces/encode/chips/EncodeStatus.tsx | 76 ++++++++++ .../interfaces/encode/dialog/EncodeDialog.tsx | 19 +-- .../dialog/panels/EncodeScriptPanel.tsx | 16 +- app/src/components/interfaces/encode/index.ts | 5 + .../encode/widgets/EncodeCommandWidget.tsx | 2 +- .../encode/widgets/EncodeOperationWidget.tsx | 74 ++++----- .../tables/encoded/EncodedTable.tsx | 7 +- .../tables/encoding/EncodingTable.tsx | 37 +---- .../ui/encode-badges/EncodeBadges.tsx | 140 ------------------ .../ui/encode-badges/EncodeStatusBadge.tsx | 50 ------- app/src/components/ui/index.ts | 2 +- 15 files changed, 305 insertions(+), 295 deletions(-) create mode 100644 app/src/components/interfaces/encode/chips/EncodeDuration.tsx create mode 100644 app/src/components/interfaces/encode/chips/EncodePercent.tsx create mode 100644 app/src/components/interfaces/encode/chips/EncodeSpeed.tsx create mode 100644 app/src/components/interfaces/encode/chips/EncodeStatus.tsx delete mode 100644 app/src/components/ui/encode-badges/EncodeBadges.tsx delete mode 100644 app/src/components/ui/encode-badges/EncodeStatusBadge.tsx diff --git a/app/src/app/(dashboard)/encode/[id]/page.tsx b/app/src/app/(dashboard)/encode/[id]/page.tsx index 9b4921ac..46196102 100644 --- a/app/src/app/(dashboard)/encode/[id]/page.tsx +++ b/app/src/app/(dashboard)/encode/[id]/page.tsx @@ -53,12 +53,6 @@ const EncodePage: React.FC = ({ params }) => {
- - - - - - {query.encode.failure_reason && ( @@ -71,6 +65,12 @@ const EncodePage: React.FC = ({ params }) => { )} + + + + + + Size diff --git a/app/src/components/interfaces/encode/chips/EncodeDuration.tsx b/app/src/components/interfaces/encode/chips/EncodeDuration.tsx new file mode 100644 index 00000000..475a6c05 --- /dev/null +++ b/app/src/components/interfaces/encode/chips/EncodeDuration.tsx @@ -0,0 +1,47 @@ +import type { EncodeDurationFragment$key } from '@/__generated__/EncodeDurationFragment.graphql' + +import { Chip } from '@giantnodes/react' +import dayjs from 'dayjs' +import React from 'react' +import { graphql, useFragment } from 'react-relay' + +const FRAGMENT = graphql` + fragment EncodeDurationFragment on Encode { + status + failed_at + cancelled_at + completed_at + created_at + } +` + +type EncodeDurationChipProps = { + $key: EncodeDurationFragment$key +} + +const EncodeDuration: React.FC = ({ $key }) => { + const data = useFragment(FRAGMENT, $key) + + const date = React.useMemo(() => { + switch (data.status) { + case 'COMPLETED': + return data.completed_at + case 'CANCELLED': + return data.cancelled_at + + case 'FAILED': + return data.failed_at + + default: + return undefined + } + }, [data.cancelled_at, data.completed_at, data.failed_at, data.status]) + + return ( + + {dayjs.duration(dayjs(date).diff(data.created_at)).format('H[h] m[m] s[s]')} + + ) +} + +export default EncodeDuration diff --git a/app/src/components/interfaces/encode/chips/EncodePercent.tsx b/app/src/components/interfaces/encode/chips/EncodePercent.tsx new file mode 100644 index 00000000..ded839a2 --- /dev/null +++ b/app/src/components/interfaces/encode/chips/EncodePercent.tsx @@ -0,0 +1,51 @@ +import type { EncodePercentFragment$key } from '@/__generated__/EncodePercentFragment.graphql' + +import { Chip } from '@giantnodes/react' +import React from 'react' +import { graphql, useFragment, useSubscription } from 'react-relay' + +import { percent } from '@/utilities/numbers' + +const FRAGMENT = graphql` + fragment EncodePercentFragment on Encode { + id + percent + } +` + +const SUBSCRIPTION = graphql` + subscription EncodePercentSubscription($where: EncodeFilterInput) { + encode_progressed(where: $where) { + ...EncodePercentFragment + } + } +` + +type EncodePercentProps = { + $key: EncodePercentFragment$key +} + +const EncodePercent: React.FC = ({ $key }) => { + const data = useFragment(FRAGMENT, $key) + + useSubscription({ + subscription: SUBSCRIPTION, + variables: { + variables: { + where: { + id: { + eq: data.id, + }, + }, + }, + }, + }) + + if (data.percent == null) { + return undefined + } + + return {percent(data.percent)} +} + +export default EncodePercent diff --git a/app/src/components/interfaces/encode/chips/EncodeSpeed.tsx b/app/src/components/interfaces/encode/chips/EncodeSpeed.tsx new file mode 100644 index 00000000..5b1d6d47 --- /dev/null +++ b/app/src/components/interfaces/encode/chips/EncodeSpeed.tsx @@ -0,0 +1,62 @@ +import type { EncodeSpeedFragment$key } from '@/__generated__/EncodeSpeedFragment.graphql' + +import { Chip } from '@giantnodes/react' +import { filesize } from 'filesize' +import React from 'react' +import { graphql, useFragment, useSubscription } from 'react-relay' + +const FRAGMENT = graphql` + fragment EncodeSpeedFragment on Encode { + id + speed { + frames + bitrate + scale + } + } +` + +const SUBSCRIPTION = graphql` + subscription EncodeSpeedSubscription($where: EncodeFilterInput) { + encode_speed_change(where: $where) { + ...EncodeSpeedFragment + } + } +` + +type EncodeSpeedProps = { + $key: EncodeSpeedFragment$key +} + +const EncodeSpeed: React.FC = ({ $key }) => { + const data = useFragment(FRAGMENT, $key) + + useSubscription({ + subscription: SUBSCRIPTION, + variables: { + variables: { + where: { + id: { + eq: data.id, + }, + }, + }, + }, + }) + + if (data.speed == null) { + return undefined + } + + return ( + <> + {data.speed.frames} fps + + {filesize(data.speed.bitrate * 0.125, { bits: true }).toLowerCase()}/s + + {data.speed.scale.toFixed(2)}x + + ) +} + +export default EncodeSpeed diff --git a/app/src/components/interfaces/encode/chips/EncodeStatus.tsx b/app/src/components/interfaces/encode/chips/EncodeStatus.tsx new file mode 100644 index 00000000..c4da260f --- /dev/null +++ b/app/src/components/interfaces/encode/chips/EncodeStatus.tsx @@ -0,0 +1,76 @@ +import type { EncodeStatusFragment$key } from '@/__generated__/EncodeStatusFragment.graphql' +import type { ChipProps } from '@giantnodes/react' + +import { Chip } from '@giantnodes/react' +import dayjs from 'dayjs' +import React from 'react' +import { graphql, useFragment } from 'react-relay' + +const FRAGMENT = graphql` + fragment EncodeStatusFragment on Encode { + status + failed_at + cancelled_at + completed_at + } +` + +type EncodeStatusChipProps = { + $key: EncodeStatusFragment$key +} + +const EncodeStatus: React.FC = ({ $key }) => { + const data = useFragment(FRAGMENT, $key) + + const color = React.useMemo(() => { + switch (data.status) { + case 'SUBMITTED': + return 'info' + + case 'QUEUED': + return 'info' + + case 'ENCODING': + return 'success' + + case 'DEGRADED': + return 'warning' + + case 'COMPLETED': + return 'success' + + case 'CANCELLED': + return 'neutral' + + case 'FAILED': + return 'danger' + + default: + return 'neutral' + } + }, [data.status]) + + const title = React.useMemo(() => { + switch (data.status) { + case 'COMPLETED': + return dayjs(data.completed_at).format('L LT') + + case 'CANCELLED': + return dayjs(data.cancelled_at).format('L LT') + + case 'FAILED': + return dayjs(data.failed_at).format('L LT') + + default: + return undefined + } + }, [data.cancelled_at, data.completed_at, data.failed_at, data.status]) + + return ( + + {data.status.toLowerCase()} + + ) +} + +export default EncodeStatus diff --git a/app/src/components/interfaces/encode/dialog/EncodeDialog.tsx b/app/src/components/interfaces/encode/dialog/EncodeDialog.tsx index fdcdbbc4..f12cb378 100644 --- a/app/src/components/interfaces/encode/dialog/EncodeDialog.tsx +++ b/app/src/components/interfaces/encode/dialog/EncodeDialog.tsx @@ -4,7 +4,7 @@ import type { DialogProps } from '@giantnodes/react' import { Button, Card, Chip, Dialog, Typography } from '@giantnodes/react' import { IconX } from '@tabler/icons-react' import React from 'react' -import { graphql, useFragment, useSubscription } from 'react-relay' +import { graphql, useFragment } from 'react-relay' import EncodeDialogSidebar from '@/components/interfaces/encode/dialog/EncodeDialogSidebar' import EncodeAnalyticsPanel from '@/components/interfaces/encode/dialog/panels/EncodeAnalyticsPanel' @@ -14,7 +14,6 @@ import { EncodeDialogPanel, useEncodeDialog, } from '@/components/interfaces/encode/dialog/use-encode-dialog.hook' -import EncodeStatusBadge from '@/components/ui/encode-badges/EncodeStatusBadge' const FRAGMENT = graphql` fragment EncodeDialogFragment on Encode { @@ -26,20 +25,11 @@ const FRAGMENT = graphql` name } } - ...EncodeStatusBadgeFragment ...EncodeScriptPanelFragment ...EncodeAnalyticsPanelFragment } ` -const OUTPUTTED_SUBSCRIPTION = graphql` - subscription EncodeDialogOutputtedSubscription { - encode_outputted { - output - } - } -` - type EncodeDialogProps = React.PropsWithChildren & { $key: EncodeDialogFragment$key } & DialogProps @@ -48,11 +38,6 @@ const EncodeDialog: React.FC = ({ $key, children, ...rest }) const data = useFragment(FRAGMENT, $key) const context = useEncodeDialog({ panel: EncodeDialogPanel.SCRIPT }) - useSubscription({ - subscription: OUTPUTTED_SUBSCRIPTION, - variables: {}, - }) - const content = React.useCallback(() => { switch (context.panel) { case EncodeDialogPanel.SCRIPT: @@ -82,8 +67,6 @@ const EncodeDialog: React.FC = ({ $key, children, ...rest })
{data.file.path_info.name} - - {data.recipe.name}
diff --git a/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx b/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx index 1a482d9e..8343a5eb 100644 --- a/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx +++ b/app/src/components/interfaces/encode/dialog/panels/EncodeScriptPanel.tsx @@ -1,12 +1,14 @@ import type { EncodeScriptPanelFragment$key } from '@/__generated__/EncodeScriptPanelFragment.graphql' -import { Card, Typography } from '@giantnodes/react' +import { Alert, Card, Typography } from '@giantnodes/react' +import { IconAlertCircleFilled } from '@tabler/icons-react' import { graphql, useFragment } from 'react-relay' import { EncodeCommandWidget, EncodeOperationWidget, EncodeOutputWidget } from '@/components/interfaces/encode' const FRAGMENT = graphql` fragment EncodeScriptPanelFragment on Encode { + failure_reason ...EncodeOperationWidgetFragment ...EncodeCommandWidgetFragment ...EncodeOutputWidgetFragment @@ -22,6 +24,18 @@ const EncodeScriptPanel: React.FC = ({ $key }) => { return ( <> + {data.failure_reason && ( + + + + The encode operation encountered an error + + {data.failure_reason} + + + + )} + diff --git a/app/src/components/interfaces/encode/index.ts b/app/src/components/interfaces/encode/index.ts index 1f92f079..7680869b 100644 --- a/app/src/components/interfaces/encode/index.ts +++ b/app/src/components/interfaces/encode/index.ts @@ -1,3 +1,8 @@ +export { default as EncodeDuration } from '@/components/interfaces/encode/chips/EncodeDuration' +export { default as EncodePercent } from '@/components/interfaces/encode/chips/EncodePercent' +export { default as EncodeSpeed } from '@/components/interfaces/encode/chips/EncodeSpeed' +export { default as EncodeStatus } from '@/components/interfaces/encode/chips/EncodeStatus' + export { default as EncodeDialog } from '@/components/interfaces/encode/dialog/EncodeDialog' export { default as EncodeCommandWidget } from '@/components/interfaces/encode/widgets/EncodeCommandWidget' diff --git a/app/src/components/interfaces/encode/widgets/EncodeCommandWidget.tsx b/app/src/components/interfaces/encode/widgets/EncodeCommandWidget.tsx index f9e78213..887f9853 100644 --- a/app/src/components/interfaces/encode/widgets/EncodeCommandWidget.tsx +++ b/app/src/components/interfaces/encode/widgets/EncodeCommandWidget.tsx @@ -2,7 +2,7 @@ import type { EncodeCommandWidgetFragment$key } from '@/__generated__/EncodeComm import { graphql, useFragment } from 'react-relay' -import CodeBlock from '@/components/ui/code-block/CodeBlock' +import { CodeBlock } from '@/components/ui' const FRAGMENT = graphql` fragment EncodeCommandWidgetFragment on Encode { diff --git a/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx b/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx index dd80f3b8..05166a84 100644 --- a/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx +++ b/app/src/components/interfaces/encode/widgets/EncodeOperationWidget.tsx @@ -2,24 +2,21 @@ import type { EncodeOperationWidgetFragment$key } from '@/__generated__/EncodeOp 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' +import { EncodePercent, EncodeSpeed, EncodeStatus } from '@/components/interfaces/encode' const FRAGMENT = graphql` fragment EncodeOperationWidgetFragment on Encode { - percent + id updated_at machine { name user_name } - speed { - bitrate - frames - scale - } + ...EncodePercentFragment + ...EncodeStatusFragment + ...EncodeSpeedFragment } ` @@ -31,51 +28,56 @@ const EncodeOperationWidget: React.FC = ({ $key }) = const data = useFragment(FRAGMENT, $key) return ( - +
name - value + value - {data.percent != null && ( - - - Progress - - - {percent(data.percent)} - - - )} + + + Status + + + + + + + + + Progress + + + + + Machine - {data.machine?.name} - {data.machine?.user_name} + {data.machine != null && ( + <> + {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 - - - )} + + + Speed + + + + + {data.updated_at != null && ( diff --git a/app/src/components/tables/encoded/EncodedTable.tsx b/app/src/components/tables/encoded/EncodedTable.tsx index 78a24c4e..7dadbc31 100644 --- a/app/src/components/tables/encoded/EncodedTable.tsx +++ b/app/src/components/tables/encoded/EncodedTable.tsx @@ -5,8 +5,6 @@ import { Button, Link, Table } from '@giantnodes/react' import React from 'react' import { graphql, usePaginationFragment } from 'react-relay' -import { EncodeBadges } from '@/components/ui' - const FRAGMENT = graphql` fragment EncodedTableFragment on Query @refetchable(queryName: "EncodedTableRefetchQuery") @@ -26,7 +24,6 @@ const FRAGMENT = graphql` name } } - ...EncodeBadgesFragment } } pageInfo { @@ -62,9 +59,7 @@ const EncodedTable: React.FC = ({ $key }) => { {item.node.file.path_info.name} - - - + Tbd )} diff --git a/app/src/components/tables/encoding/EncodingTable.tsx b/app/src/components/tables/encoding/EncodingTable.tsx index 3b7d6fef..855cdab7 100644 --- a/app/src/components/tables/encoding/EncodingTable.tsx +++ b/app/src/components/tables/encoding/EncodingTable.tsx @@ -8,9 +8,7 @@ import type { EncodingTableRefetchQuery } from '@/__generated__/EncodingTableRef import { Button, Link, Table } from '@giantnodes/react' import { IconProgressX } from '@tabler/icons-react' import React from 'react' -import { graphql, useMutation, usePaginationFragment, useSubscription } from 'react-relay' - -import { EncodeBadges } from '@/components/ui' +import { graphql, useMutation, usePaginationFragment } from 'react-relay' const FRAGMENT = graphql` fragment EncodingTableFragment on Query @@ -31,7 +29,6 @@ const FRAGMENT = graphql` name } } - ...EncodeBadgesFragment } } pageInfo { @@ -59,26 +56,6 @@ const MUTATION = graphql` } ` -const PROGRESSED_SUBSCRIPTION = graphql` - subscription EncodingTableProgressedSubscription { - encode_progressed { - percent - } - } -` - -const SPEED_SUBSCRIPTION = graphql` - subscription EncodingTableSpeedSubscription { - encode_speed_change { - speed { - frames - bitrate - scale - } - } - } -` - type EncodeEntry = NonNullable['edges']>[0]['node'] type EncodingTableProps = { @@ -93,16 +70,6 @@ const EncodingTable: React.FC = ({ $key }) => { const [commit] = useMutation(MUTATION) - useSubscription({ - subscription: PROGRESSED_SUBSCRIPTION, - variables: {}, - }) - - useSubscription({ - subscription: SPEED_SUBSCRIPTION, - variables: {}, - }) - const cancel = React.useCallback( (entry: EncodeEntry) => { commit({ @@ -134,8 +101,6 @@ const EncodingTable: React.FC = ({ $key }) => {
- - diff --git a/app/src/components/ui/encode-badges/EncodeBadges.tsx b/app/src/components/ui/encode-badges/EncodeBadges.tsx deleted file mode 100644 index b7aee9d6..00000000 --- a/app/src/components/ui/encode-badges/EncodeBadges.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import type { EncodeBadgesFragment$key } from '@/__generated__/EncodeBadgesFragment.graphql' -import type { ChipProps } from '@giantnodes/react' - -import { Chip } from '@giantnodes/react' -import { IconArrowRight, IconTrendingDown, IconTrendingUp } from '@tabler/icons-react' -import dayjs from 'dayjs' -import { filesize } from 'filesize' -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 -} - -const FRAGMENT = graphql` - fragment EncodeBadgesFragment on Encode { - status - percent - started_at - failure_reason - failed_at - cancelled_at - completed_at - created_at - speed { - frames - bitrate - scale - } - snapshots { - size - probed_at - } - ...EncodeStatusBadgeFragment - } -` - -const EncodeBadges: React.FC = ({ $key, size }) => { - const data = useFragment(FRAGMENT, $key) - - 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) - - const icon = () => { - switch (true) { - case increase > 0: - return - - case increase < 0: - return - - case increase === 0: - default: - return - } - } - - const color = () => { - switch (true) { - case increase > 0: - return 'danger' - - case increase < 0: - return 'success' - - case increase === 0: - default: - return 'info' - } - } - - return ( - - {icon()} - - {percent(increase)} - - ) - }, [data.snapshots, size]) - - return ( -
- - - {data.status !== 'COMPLETED' && data.status !== 'CANCELLED' && data.status !== 'FAILED' && ( - <> - {data.speed != null && ( - <> - - {data.speed.frames} fps - - - - {filesize(data.speed.bitrate * 0.125, { bits: true }).toLowerCase()}/s - - - - {data.speed.scale.toFixed(2)}x - - - )} - - {data.percent != null && ( - - {percent(data.percent)} - - )} - - )} - - {data.status === 'COMPLETED' && ( - <> - - {dayjs.duration(dayjs(data.completed_at).diff(data.created_at)).format('H[h] m[m] s[s]')} - - - {SizeChip()} - - )} - - {data.status === 'CANCELLED' && ( - - {dayjs.duration(dayjs(data.cancelled_at).diff(data.created_at)).format('H[h] m[m] s[s]')} - - )} - - {data.status === 'FAILED' && ( - - {dayjs.duration(dayjs(data.failed_at).diff(data.created_at)).format('H[h] m[m] s[s]')} - - )} -
- ) -} - -export default EncodeBadges diff --git a/app/src/components/ui/encode-badges/EncodeStatusBadge.tsx b/app/src/components/ui/encode-badges/EncodeStatusBadge.tsx deleted file mode 100644 index f5c2636d..00000000 --- a/app/src/components/ui/encode-badges/EncodeStatusBadge.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import type { EncodeStatus, EncodeStatusBadgeFragment$key } from '@/__generated__/EncodeStatusBadgeFragment.graphql' - -import { Chip } from '@giantnodes/react' -import { graphql, useFragment } from 'react-relay' - -type EncodeStatusBadgeProps = { - $key: EncodeStatusBadgeFragment$key -} - -const FRAGMENT = graphql` - fragment EncodeStatusBadgeFragment on Encode { - status - } -` - -const EncodeStatusBadge: React.FC = ({ $key }) => { - const data = useFragment(FRAGMENT, $key) - - const color = (status: EncodeStatus) => { - switch (status) { - case 'SUBMITTED': - return 'info' - - case 'QUEUED': - return 'info' - - case 'ENCODING': - return 'success' - - case 'DEGRADED': - return 'warning' - - case 'COMPLETED': - return 'success' - - case 'CANCELLED': - return 'neutral' - - case 'FAILED': - return 'danger' - - default: - return 'neutral' - } - } - - return {data.status.toLowerCase()} -} - -export default EncodeStatusBadge diff --git a/app/src/components/ui/index.ts b/app/src/components/ui/index.ts index 8626f0ed..cb91940b 100644 --- a/app/src/components/ui/index.ts +++ b/app/src/components/ui/index.ts @@ -1 +1 @@ -export { default as EncodeBadges } from '@/components/ui/encode-badges/EncodeBadges' +export { default as CodeBlock } from '@/components/ui/code-block/CodeBlock'