Progress displaying endpoints and editing them
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
} from "~/models/indexEndpoint.server";
|
||||
import { Project } from "~/models/project.server";
|
||||
import { User } from "~/models/user.server";
|
||||
import { RuntimeEnvironmentType } from "../../../../packages/database/src";
|
||||
|
||||
export type Client = {
|
||||
slug: string;
|
||||
@@ -18,6 +19,11 @@ export type Client = {
|
||||
export type ClientEndpoint =
|
||||
| {
|
||||
state: "unconfigured";
|
||||
environment: {
|
||||
id: string;
|
||||
apiKey: string;
|
||||
type: RuntimeEnvironmentType;
|
||||
};
|
||||
}
|
||||
| {
|
||||
state: "configured";
|
||||
@@ -30,6 +36,11 @@ export type ClientEndpoint =
|
||||
updatedAt: Date;
|
||||
stats: IndexEndpointStats;
|
||||
};
|
||||
environment: {
|
||||
id: string;
|
||||
apiKey: string;
|
||||
type: RuntimeEnvironmentType;
|
||||
};
|
||||
};
|
||||
|
||||
export class EnvironmentsPresenter {
|
||||
@@ -98,8 +109,6 @@ export class EnvironmentsPresenter {
|
||||
return true;
|
||||
});
|
||||
|
||||
console.log("filtered", JSON.stringify(filtered));
|
||||
|
||||
//build up list of clients for display, with endpoints by type
|
||||
const clients: Client[] = [];
|
||||
for (const environment of filtered) {
|
||||
@@ -109,9 +118,9 @@ export class EnvironmentsPresenter {
|
||||
client = {
|
||||
slug: endpoint.slug,
|
||||
endpoints: {
|
||||
DEVELOPMENT: { state: "unconfigured" },
|
||||
STAGING: { state: "unconfigured" },
|
||||
PRODUCTION: { state: "unconfigured" },
|
||||
DEVELOPMENT: { state: "unconfigured", environment },
|
||||
STAGING: { state: "unconfigured", environment },
|
||||
PRODUCTION: { state: "unconfigured", environment },
|
||||
},
|
||||
};
|
||||
clients.push(client);
|
||||
@@ -137,6 +146,7 @@ export class EnvironmentsPresenter {
|
||||
stats: parseEndpointIndexStats(latestIndex.stats),
|
||||
}
|
||||
: undefined,
|
||||
environment,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
+94
-3
@@ -1,12 +1,27 @@
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { Header1 } from "~/components/primitives/Headers";
|
||||
import { Header1, Header2 } from "~/components/primitives/Headers";
|
||||
import {
|
||||
Sheet,
|
||||
SheetBody,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
} from "~/components/primitives/Sheet";
|
||||
import { ClientEndpoint } from "~/presenters/EnvironmentsPresenter.server";
|
||||
import { RuntimeEnvironmentType } from "../../../../../packages/database/src";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
import { InputGroup } from "~/components/primitives/InputGroup";
|
||||
import { Input } from "~/components/primitives/Input";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Label } from "~/components/primitives/Label";
|
||||
import { Hint } from "~/components/primitives/Hint";
|
||||
import { InlineCode } from "~/components/code/InlineCode";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { Callout } from "~/components/primitives/Callout";
|
||||
import { formatDateTime } from "~/utils";
|
||||
import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { bodySchema } from "../resources.environments.$environmentParam.endpoint";
|
||||
import { FormError } from "~/components/primitives/FormError";
|
||||
|
||||
type ConfigureEndpointSheetProps = {
|
||||
slug: string;
|
||||
@@ -18,9 +33,21 @@ type ConfigureEndpointSheetProps = {
|
||||
export function ConfigureEndpointSheet({
|
||||
slug,
|
||||
endpoint,
|
||||
type,
|
||||
onClose,
|
||||
}: ConfigureEndpointSheetProps) {
|
||||
const setEndpointUrlFetcher = useFetcher();
|
||||
|
||||
const [form, { url, clientSlug }] = useForm({
|
||||
id: "endpoint-url",
|
||||
lastSubmission: setEndpointUrlFetcher.data,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: bodySchema });
|
||||
},
|
||||
});
|
||||
const loadingEndpointUrl = setEndpointUrlFetcher.state !== "idle";
|
||||
|
||||
console.log("endpoint", endpoint);
|
||||
|
||||
return (
|
||||
<Sheet
|
||||
open={true}
|
||||
@@ -33,9 +60,73 @@ export function ConfigureEndpointSheet({
|
||||
<SheetContent>
|
||||
<SheetHeader>
|
||||
<Header1>
|
||||
<EnvironmentLabel environment={{ type }} />
|
||||
<div className="flex items-center gap-2">
|
||||
<EnvironmentLabel
|
||||
environment={{ type: endpoint.environment.type }}
|
||||
/>
|
||||
<Header1>Configure endpoint</Header1>
|
||||
</div>
|
||||
</Header1>
|
||||
</SheetHeader>
|
||||
<SheetBody>
|
||||
<setEndpointUrlFetcher.Form
|
||||
method="post"
|
||||
action={`/resources/environments/${endpoint.environment.id}/endpoint`}
|
||||
{...form.props}
|
||||
>
|
||||
<InputGroup className="max-w-none">
|
||||
<Label>Endpoint URL</Label>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
{...conform.input(clientSlug, { type: "hidden" })}
|
||||
value={slug}
|
||||
/>
|
||||
<Input
|
||||
className="rounded-r-none"
|
||||
{...conform.input(url, { type: "url" })}
|
||||
defaultValue={"url" in endpoint ? endpoint.url : ""}
|
||||
placeholder="Path to your Trigger API route"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary/medium"
|
||||
className="rounded-l-none"
|
||||
disabled={loadingEndpointUrl}
|
||||
LeadingIcon={loadingEndpointUrl ? "spinner-white" : undefined}
|
||||
>
|
||||
{loadingEndpointUrl ? "Saving" : "Save"}
|
||||
</Button>
|
||||
</div>
|
||||
<FormError id={url.errorId}>{url.error}</FormError>
|
||||
<FormError id={form.errorId}>{form.error}</FormError>
|
||||
<Hint>
|
||||
This is the URL of your Trigger API route, Typically this would
|
||||
be:{" "}
|
||||
<InlineCode variant="extra-small">
|
||||
https://yourdomain.com/api/trigger
|
||||
</InlineCode>
|
||||
.
|
||||
</Hint>
|
||||
</InputGroup>
|
||||
</setEndpointUrlFetcher.Form>
|
||||
|
||||
{endpoint.state === "configured" && (
|
||||
<div className="mt-4 flex flex-col">
|
||||
<div>
|
||||
<Header2>Status</Header2>
|
||||
<Paragraph>
|
||||
We connect to your endpoint and refresh your Jobs.
|
||||
</Paragraph>
|
||||
<Callout variant="success">
|
||||
Endpoint configured. Last refreshed:{" "}
|
||||
{endpoint.latestIndex
|
||||
? formatDateTime(endpoint.latestIndex.updatedAt)
|
||||
: "–"}
|
||||
</Callout>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</SheetBody>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
|
||||
+3
-11
@@ -1,4 +1,5 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { useMemo, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { ClipboardField } from "~/components/ClipboardField";
|
||||
import {
|
||||
@@ -6,6 +7,7 @@ import {
|
||||
environmentTitle,
|
||||
} from "~/components/environments/EnvironmentLabel";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { ButtonContent } from "~/components/primitives/Buttons";
|
||||
import { Header1, Header2 } from "~/components/primitives/Headers";
|
||||
import {
|
||||
PageDescription,
|
||||
@@ -23,25 +25,15 @@ import {
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
} from "~/components/primitives/Table";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import {
|
||||
ClientEndpoint,
|
||||
EnvironmentsPresenter,
|
||||
} from "~/presenters/EnvironmentsPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { formatDateTime } from "~/utils";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { ProjectParamSchema } from "~/utils/pathBuilder";
|
||||
import { RuntimeEnvironmentType } from "../../../../../packages/database/src";
|
||||
import { formatDateTime } from "~/utils";
|
||||
import { Button, ButtonContent } from "~/components/primitives/Buttons";
|
||||
import { useMemo, useState } from "react";
|
||||
import { s } from "vitest/dist/index-6e18a03a";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
} from "~/components/primitives/Sheet";
|
||||
import { select } from "@conform-to/react/helpers";
|
||||
import { ConfigureEndpointSheet } from "./ConfigureEndpointSheet";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { ActionArgs, json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
import { CreateEndpointService } from "~/services/endpoints/createEndpoint.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
environmentParam: z.string(),
|
||||
});
|
||||
|
||||
export const bodySchema = z.object({
|
||||
clientSlug: z.string(),
|
||||
url: z.string().url("Must be a valid URL"),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const { environmentParam } = ParamsSchema.parse(params);
|
||||
|
||||
const formData = await request.formData();
|
||||
const object = Object.fromEntries(formData.entries());
|
||||
console.log("object", object);
|
||||
|
||||
const submission = parse(formData, { schema: bodySchema });
|
||||
|
||||
console.log(submission);
|
||||
|
||||
if (!submission.value || submission.intent !== "submit") {
|
||||
return json(submission);
|
||||
}
|
||||
|
||||
try {
|
||||
const environment = await prisma.runtimeEnvironment.findUnique({
|
||||
include: {
|
||||
organization: true,
|
||||
project: true,
|
||||
},
|
||||
where: {
|
||||
id: environmentParam,
|
||||
},
|
||||
});
|
||||
|
||||
if (!environment) {
|
||||
throw new Error("Environment not found");
|
||||
}
|
||||
|
||||
const service = new CreateEndpointService();
|
||||
const result = await service.call({
|
||||
id: submission.value.clientSlug,
|
||||
url: submission.value.url,
|
||||
environment,
|
||||
});
|
||||
return json(result);
|
||||
} catch (e) {
|
||||
return json(e, { status: 400 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user