Skip to content

Commit

Permalink
Split runActionInstance and runActionInstanceServerAction
Browse files Browse the repository at this point in the history
  • Loading branch information
3mcd committed May 21, 2024
1 parent 232adea commit 1c845ff
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 149 deletions.
Empty file added core/actions/_lib/actions.ts
Empty file.
57 changes: 18 additions & 39 deletions core/actions/_lib/runActionInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,21 @@ import type { StagesId } from "~/kysely/types/public/Stages";
import { db } from "~/kysely/database";
import Action from "~/kysely/types/public/Action";
import ActionRunStatus from "~/kysely/types/public/ActionRunStatus";
import { getLoginData } from "~/lib/auth/loginData";
import { UsersId } from "~/kysely/types/public/Users";
import { getPub } from "~/lib/server";
import { defineServerAction } from "~/lib/server/defineServerAction";
import { ClientException, ClientExceptionOptions } from "~/lib/serverActions";
import { getActionByName } from "../api";
import { ActionSuccess } from "../types";
import { getActionRunByName } from "./getRuns";
import { validatePubValues } from "./validateFields";

type ActionInstanceRunResult = ClientException | ClientExceptionOptions | ActionSuccess;
export type ActionInstanceRunResult = ClientException | ClientExceptionOptions | ActionSuccess;

type ActionInstanceArgs = {
export type RunActionInstanceArgs = {
pubId: PubsId;
actionInstanceId: ActionInstancesId;
args?: Record<string, unknown>;
};
actionInstanceArgs?: Record<string, unknown>;
} & ({ event: Event } | { userId: UsersId });

const _runActionInstance = async (
actionInstance: {
Expand Down Expand Up @@ -111,15 +110,12 @@ const _runActionInstance = async (
}
};

const runAndRecordActionInstance = async (
{ pubId, actionInstanceId, args = {} }: ActionInstanceArgs,
event?: Event
) => {
const pubPromise = getPub(pubId);
export async function runActionInstance(args: RunActionInstanceArgs) {
const pubPromise = getPub(args.pubId);

const actionInstancePromise = db
.selectFrom("action_instances")
.where("action_instances.id", "=", actionInstanceId)
.where("action_instances.id", "=", args.actionInstanceId)
.select((eb) => [
"id",
eb.fn.coalesce("config", sql`'{}'`).as("config"),
Expand Down Expand Up @@ -150,40 +146,25 @@ const runAndRecordActionInstance = async (
};
}

if (!event) {
// If the action was not run by a rule, we record the initiating member.
const loginData = await getLoginData();
const member = loginData?.memberships.find(
(m) => m.communityId === pubResult.value.communityId
);
}

const result = await _runActionInstance(actionInstanceResult.value, pubResult.value, args);

await db
.insertInto("action_runs")
.values({
action_instance_id: actionInstanceId,
pub_id: pubId,
action_instance_id: args.actionInstanceId,
pub_id: args.pubId,
user_id: "userId" in args ? args.userId : null,
status: "error" in result ? ActionRunStatus.failure : ActionRunStatus.success,
config: actionInstanceResult.value.config,
params: args,
event,
event: "userId" in args ? undefined : args.event,
})
.execute();

revalidateTag(`action_runs_${pubResult.value.communityId}`);

return result;
};

export const runActionInstance = defineServerAction(async function runActionInstance({
pubId,
actionInstanceId,
args = {},
}: ActionInstanceArgs) {
return runAndRecordActionInstance({ pubId, actionInstanceId, args });
});
}

export const runInstancesForEvent = async (pubId: PubsId, stageId: StagesId, event: Event) => {
const instances = await db
Expand All @@ -199,13 +180,11 @@ export const runInstancesForEvent = async (pubId: PubsId, stageId: StagesId, eve
return {
actionInstanceId: instance.action_instance_id,
actionInstanceName: instance.name,
result: await runAndRecordActionInstance(
{
pubId,
actionInstanceId: instance.action_instance_id,
},
event
),
result: await runActionInstance({
pubId,
actionInstanceId: instance.action_instance_id,
event,
}),
};
})
);
Expand Down
24 changes: 24 additions & 0 deletions core/actions/_lib/runActionInstanceServerAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UsersId } from "~/kysely/types/public/Users";
import { getLoginData } from "~/lib/auth/loginData";
import {
ActionInstanceRunResult,
RunActionInstanceArgs,
runActionInstance as runActionInstanceInner,
} from "./runActionInstance";

export const runActionInstanceServerAction = async function runActionInstance(
args: Omit<RunActionInstanceArgs, "userId" | "event">
): Promise<ActionInstanceRunResult> {
const user = await getLoginData();

if (!user) {
return {
error: "Not logged in",
};
}

return runActionInstanceInner({
...args,
userId: user.id as UsersId,
});
};
1 change: 1 addition & 0 deletions core/actions/api/server.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { runActionInstance, runInstancesForEvent } from "../_lib/runActionInstance";
export { runActionInstanceServerAction } from "../_lib/runActionInstanceServerAction";
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ import { ActionRun, getActionRunsTableColumns } from "./getActionRunsTableColumn

export const ActionRunsTable = ({ actionRuns }: { actionRuns: ActionRun[] }) => {
const actionRunsColumns = getActionRunsTableColumns();
return <DataTable columns={actionRunsColumns} data={actionRuns} searchBy="id" />;
return (
<DataTable columns={actionRunsColumns} data={actionRuns} searchBy="actionInstance.name" />
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import type { ColumnDef } from "@tanstack/react-table";

import { Event } from "@prisma/client";

import { Badge } from "ui/badge";
import { DataTableColumnHeader } from "ui/data-table";

Expand All @@ -10,44 +12,69 @@ import { PubTitle } from "~/app/components/PubTitle";
export type ActionRun = {
id: string;
createdAt: Date;
actionInstance: { name: string; action: string };
stage: { id: string; name: string };
actionInstance: { name: string; action: string } | null;
stage: { id: string; name: string } | null;
pub: {
id: string;
values: { field: { slug: string }; value: unknown }[] | Record<string, unknown>;
createdAt: Date;
};
};
} | null;
} & (
| {
event: Event;
user: null;
}
| {
event: null;
user: {
id: string;
firstName: string | null;
lastName: string | null;
};
}
);

export const getActionRunsTableColumns = () =>
[
{
header: ({ column }) => <DataTableColumnHeader column={column} title="Action" />,
accessorKey: "actionInstance.name",
accessorKey: "actionInstance",
cell: ({ getValue }) => {
const actionInstance = getValue<ActionRun["actionInstance"]>();
return actionInstance ? actionInstance.name : "Unknown";
},
},
{
header: ({ column }) => <DataTableColumnHeader column={column} title="Event" />,
header: ({ column }) => <DataTableColumnHeader column={column} title="Initiator" />,
accessorKey: "event",
cell: ({ getValue }) => {
cell: ({ getValue, row }) => {
const user = row.original.user;
if (user) {
return `${user.firstName} ${user.lastName}`;
}
switch (getValue()) {
case "pubEnteredStage":
return "Entered stage";
return "Rule (Pub entered stage)";
case "pubLeftStage":
return "Left stage";
default:
// TODO: Display user who triggered the action
return "Manual";
return "Rule (Pub exited stage)";
}
},
},
{
header: ({ column }) => <DataTableColumnHeader column={column} title="Stage" />,
accessorKey: "stage.name",
accessorKey: "stage",
cell: ({ getValue }) => {
const stage = getValue<ActionRun["stage"]>();
return stage ? stage.name : "Unknown";
},
},
{
header: ({ column }) => <DataTableColumnHeader column={column} title="Pub" />,
accessorKey: "pub",
cell: ({ getValue }) => <PubTitle pub={getValue<ActionRun["pub"]>()} />,
cell: ({ getValue }) => {
const pub = getValue<ActionRun["pub"]>();
return pub ? <PubTitle pub={pub} /> : "Unknown";
},
},
{
header: ({ column }) => <DataTableColumnHeader column={column} title="Time" />,
Expand All @@ -59,9 +86,9 @@ export const getActionRunsTableColumns = () =>
cell: ({ getValue }) => {
switch (getValue()) {
case "success":
return <Badge color="green">success</Badge>;
return <Badge>success</Badge>;
case "failure":
return <Badge color="red">failure</Badge>;
return <Badge variant="destructive">failure</Badge>;
default:
return <Badge variant="outline">unknown</Badge>;
}
Expand Down
28 changes: 14 additions & 14 deletions core/app/c/[communitySlug]/activity/actions/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getLoginData } from "~/lib/auth/loginData";
import { pubValuesByRef } from "~/lib/server";
import { findCommunityBySlug } from "~/lib/server/community";
import { ActionRunsTable } from "./ActionRunsTable";
import { ActionRun } from "./getActionRunsTableColumns";

export default async function Page({
params: { communitySlug },
Expand Down Expand Up @@ -37,16 +38,18 @@ export default async function Page({
}

const page = parseInt(searchParams.page ?? "1", 10);
const actionRuns = await unstable_cache(
const actionRuns = (await unstable_cache(
() =>
db
.selectFrom("stages")
.where("stages.community_id", "=", community.id)
.innerJoin("action_instances", "stages.id", "action_instances.stage_id")
.innerJoin("action_runs", "action_instances.id", "action_runs.action_instance_id")
.innerJoin("users", "action_runs.user_id", "users.id")
.select((eb) => [
"action_runs.id",
"action_runs.config",
"action_runs.event",
"action_runs.params",
"action_runs.status",
"action_runs.created_at as createdAt",
Expand All @@ -55,34 +58,31 @@ export default async function Page({
.selectFrom("action_instances")
.whereRef("action_instances.id", "=", "action_runs.action_instance_id")
.select(["name", "action"])
)
.$notNull()
.as("actionInstance"),
// Include the action run's stage and pub. $notNull is used to narrow
// the type to exclude null values, which is safe because actions
// must be run in the context of both a pub and stage.
).as("actionInstance"),
jsonObjectFrom(
eb
.selectFrom("stages")
.whereRef("stages.id", "=", "action_instances.stage_id")
.select(["id", "name"])
)
.$notNull()
.as("stage"),
).as("stage"),
jsonObjectFrom(
eb
.selectFrom("pubs")
.whereRef("pubs.id", "=", "action_runs.pub_id")
.select(["id", "created_at as createdAt"])
.select(pubValuesByRef("action_runs.pub_id"))
)
.$notNull()
.as("pub"),
).as("pub"),
jsonObjectFrom(
eb
.selectFrom("users")
.whereRef("users.id", "=", "action_runs.user_id")
.select(["id", "firstName", "lastName"])
).as("user"),
])
.execute(),
[community.id],
{ tags: [`action_runs_${community.id}`] }
)();
)()) as ActionRun[];

logger.info("Action runs", actionRuns);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { toast } from "ui/use-toast";
import type { ActionInstances, ActionInstancesId } from "~/kysely/types/public/ActionInstances";
import type { PubsId } from "~/kysely/types/public/Pubs";
import { getActionByName } from "~/actions/api";
import { runActionInstance } from "~/actions/api/server";
import { runActionInstanceServerAction } from "~/actions/api/server";
import { useServerAction } from "~/lib/serverActions";

export const StagePanelPubsRunActionButton = ({
Expand All @@ -24,7 +24,7 @@ export const StagePanelPubsRunActionButton = ({
actionInstance: ActionInstances;
pub: Pub;
}) => {
const runAction = useServerAction(runActionInstance);
const runAction = useServerAction(runActionInstanceServerAction);

const [isPending, startTransition] = useTransition();

Expand All @@ -41,7 +41,7 @@ export const StagePanelPubsRunActionButton = ({
const result = await runAction({
actionInstanceId: actionInstance.id as ActionInstancesId,
pubId: pub.id as PubsId,
args: values,
actionInstanceArgs: values,
});

if ("success" in result) {
Expand Down Expand Up @@ -80,17 +80,3 @@ export const StagePanelPubsRunActionButton = ({
</Dialog>
);
};

// <Button variant="default" type="button" size="sm">
// {isPending ? (
// <Loader2 size="14" className="animate-spin" />
// ) : result ? (
// "error" in result ? (
// <X size="14" />
// ) : (
// <Check size="14" />
// )
// ) : (
// <Play size="14" />
// )}
// </Button>
Loading

0 comments on commit 1c845ff

Please sign in to comment.