diff --git a/src/rendering/react/components/CronJob/CronJobDetails.tsx b/src/rendering/react/components/CronJob/CronJobDetails.tsx index f6cc2a7f9..0a6b30517 100644 --- a/src/rendering/react/components/CronJob/CronJobDetails.tsx +++ b/src/rendering/react/components/CronJob/CronJobDetails.tsx @@ -1,4 +1,4 @@ -import { FC } from "react"; +import { FC, ReactNode } from "react"; import type { MittwaldAPIV2 } from "@mittwald/api-client"; import { SingleResult } from "../SingleResult.js"; import { Value } from "../Value.js"; @@ -9,12 +9,21 @@ import { useProject } from "../../../../lib/resources/project/hooks.js"; import { useAppInstallation } from "../../../../lib/resources/app/hooks.js"; import { FormattedDate } from "../FormattedDate.js"; type CronjobCronjob = MittwaldAPIV2.Components.Schemas.CronjobCronjob; -type CronjobCronjobUrl = MittwaldAPIV2.Components.Schemas.CronjobCronjobUrl; -type CronjobCronjobCommand = - MittwaldAPIV2.Components.Schemas.CronjobCronjobCommand; +type CronjobServiceTargetResponse = + MittwaldAPIV2.Components.Schemas.CronjobServiceTargetResponse; type CronJobComponent = FC<{ cronjob: CronjobCronjob }>; +// A cron job either targets an app installation or a container (a service +// running in a stack). Container cron jobs carry a service target instead of +// an app id, so we must not try to resolve them as app installations. +const getServiceTarget = ( + cronjob: CronjobCronjob, +): CronjobServiceTargetResponse | undefined => { + const { target } = cronjob; + return target && "stackId" in target ? target : undefined; +}; + const CronJobNextExecution: CronJobComponent = ({ cronjob }) => { if (!cronjob.nextExecutionTime) { return ; @@ -27,47 +36,65 @@ const CronJobNextExecution: CronJobComponent = ({ cronjob }) => { ); }; -const CronJobExecutionTargetURL: FC<{ dest: CronjobCronjobUrl }> = ({ - dest, +const CronJobAppTarget: FC<{ appInstallationId: string }> = ({ + appInstallationId, }) => { - return ( - {dest.url}, - }} - /> - ); + const app = useAppInstallation(appInstallationId); + return ; }; -const CronJobExecutionTargetCommand: FC<{ command: CronjobCronjobCommand }> = ({ - command, -}) => { - return ( - {command.interpreter}, - Script: {command.path}, - Parameters: command.parameters ? ( - {command.parameters} - ) : ( - - ), - }} +// Rows describing where and how the cron job is executed. For container cron +// jobs this is the stack/container running the command; for app cron jobs it +// is the app installation together with the invoked URL or command. +const buildExecutionTargetRows = ( + cronjob: CronjobCronjob, + serviceTarget: CronjobServiceTargetResponse | undefined, +): Record => { + if (serviceTarget) { + return { + Stack: {serviceTarget.stackId}, + Container: {serviceTarget.serviceShortId}, + Command: {serviceTarget.command}, + }; + } + + const app = ( + ); + + const { destination } = cronjob; + if (destination && "url" in destination) { + return { + App: app, + URL: {destination.url}, + }; + } + if (destination) { + return { + App: app, + Interpreter: {destination.interpreter}, + Script: {destination.path}, + Parameters: destination.parameters ? ( + {destination.parameters} + ) : ( + + ), + }; + } + + return { App: app }; }; export const CronJobDetails: CronJobComponent = ({ cronjob }) => { const project = cronjob.projectId ? useProject(cronjob.projectId) : null; - const app = useAppInstallation(cronjob.appId); + const serviceTarget = getServiceTarget(cronjob); - const rows = { + const rows: Record = { "Cron Job ID": , "Created At": , Project: project ? : , - App: , Schedule: ( {cronjob.interval} (next execution:{" "} @@ -77,37 +104,20 @@ export const CronJobDetails: CronJobComponent = ({ cronjob }) => { Timezone: {cronjob.timeZone || "UTC"}, }; - const sections = [ - - CRON JOB DETAILS: {cronjob.description} - - } - rows={rows} - />, - ]; - - if (cronjob.destination && "url" in cronjob.destination) { - sections.push( - , - ); - } else if (cronjob.destination) { - sections.push( - , - ); - } - return ( - {sections} + + CRON JOB DETAILS: {cronjob.description} + + } + rows={rows} + /> + ); };