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}
+ />
+
);
};