Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI feat: Update UX for OAuth app configuration #253

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions ui/admin/app/components/oauth-apps/ConfigureOAuthApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { SettingsIcon } from "lucide-react";
import { toast } from "sonner";
import { mutate } from "swr";

import { OAuthAppParams } from "~/lib/model/oauthApps";
import { OAuthProvider } from "~/lib/model/oauthApps/oauth-helpers";
import { OauthAppService } from "~/lib/service/api/oauthAppService";

import { Button } from "~/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import { ScrollArea } from "~/components/ui/scroll-area";
import {
useOAuthAppInfo,
useOAuthAppList,
} from "~/hooks/oauthApps/useOAuthApps";
import { useAsync } from "~/hooks/useAsync";
import { useDisclosure } from "~/hooks/useDisclosure";

import { OAuthAppForm } from "./OAuthAppForm";
import { OAuthAppTypeIcon } from "./OAuthAppTypeIcon";

export function ConfigureOAuthApp({ type }: { type: OAuthProvider }) {
const spec = useOAuthAppInfo(type);
const { customApp } = spec;
const isEdit = !!customApp;

const modal = useDisclosure();
const successModal = useDisclosure();

const createApp = useAsync(async (data: OAuthAppParams) => {
await OauthAppService.createOauthApp({
type,
refName: type,
...data,
});

await mutate(useOAuthAppList.key());

modal.onClose();
successModal.onOpen();
toast.success(`${spec.displayName} OAuth configuration created`);
});

const updateApp = useAsync(async (data: OAuthAppParams) => {
if (!customApp) throw new Error("Custom app not found");

await OauthAppService.updateOauthApp(customApp.id, {
type: customApp.type,
refName: customApp.refName,
...data,
});

await mutate(useOAuthAppList.key());

modal.onClose();
successModal.onOpen();
toast.success(`${spec.displayName} OAuth configuration updated`);
});

return (
<>
<Dialog open={modal.isOpen} onOpenChange={modal.onOpenChange}>
<DialogTrigger asChild>
<Button className="w-full">
<SettingsIcon className="w-4 h-4 mr-2" />
{isEdit
? "Replace Configuration"
: `Configure ${spec.displayName} OAuth App`}
</Button>
</DialogTrigger>

<DialogContent
classNames={{
overlay: "opacity-0",
}}
aria-describedby="create-oauth-app"
className="px-0"
>
<DialogTitle className="flex items-center gap-2 px-4">
<OAuthAppTypeIcon type={type} />
Configure {spec.displayName} OAuth App
</DialogTitle>

<DialogDescription hidden>
Create a new OAuth app for {spec.displayName}
</DialogDescription>

<ScrollArea className="max-h-[80vh] px-4">
<OAuthAppForm
type={type}
onSubmit={
isEdit ? updateApp.execute : createApp.execute
}
isLoading={
isEdit
? updateApp.isLoading
: createApp.isLoading
}
/>
</ScrollArea>
</DialogContent>
</Dialog>

<Dialog
open={successModal.isOpen}
onOpenChange={successModal.onOpenChange}
>
<DialogContent>
<DialogTitle>
Successfully Configured {spec.displayName} OAuth App
</DialogTitle>

<DialogDescription>
Otto will now use your custom {spec.displayName} OAuth
app to authenticate users.
</DialogDescription>

<DialogFooter>
<DialogClose asChild>
<Button className="w-full">Close</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}
80 changes: 0 additions & 80 deletions ui/admin/app/components/oauth-apps/CreateOauthApp.tsx

This file was deleted.

26 changes: 16 additions & 10 deletions ui/admin/app/components/oauth-apps/DeleteOAuthApp.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TrashIcon } from "lucide-react";
import { toast } from "sonner";
import { mutate } from "swr";

import { OAuthProvider } from "~/lib/model/oauthApps/oauth-helpers";
import { OauthAppService } from "~/lib/service/api/oauthAppService";

import { ConfirmationDialog } from "~/components/composed/ConfirmationDialog";
Expand All @@ -13,34 +13,41 @@ import {
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { useOAuthAppList } from "~/hooks/oauthApps/useOAuthApps";
import {
useOAuthAppInfo,
useOAuthAppList,
} from "~/hooks/oauthApps/useOAuthApps";
import { useAsync } from "~/hooks/useAsync";

export function DeleteOAuthApp({
id,
disableTooltip,
type,
}: {
id: string;
disableTooltip?: boolean;
type: OAuthProvider;
}) {
const spec = useOAuthAppInfo(type);

const deleteOAuthApp = useAsync(async () => {
await OauthAppService.deleteOauthApp(id);
await mutate(useOAuthAppList.key());

toast.success("OAuth app deleted");
toast.success(`${spec.displayName} OAuth configuration deleted`);
});

return (
<div className="flex gap-2">
<TooltipProvider>
<Tooltip open={getIsOpen()}>
<ConfirmationDialog
title={`Delete OAuth App`}
description="Are you sure you want to delete this OAuth app?"
title={`Reset ${spec.displayName} OAuth to use Acorn Gateway`}
description={`By clicking \`Reset\`, you will delete your custom ${spec.displayName} OAuth configuration and reset to use Acorn Gateway.`}
onConfirm={deleteOAuthApp.execute}
confirmProps={{
variant: "destructive",
children: "Delete",
children: "Reset",
}}
>
<TooltipTrigger asChild>
Expand All @@ -51,10 +58,9 @@ export function DeleteOAuthApp({
>
{deleteOAuthApp.isLoading ? (
<LoadingSpinner className="w-4 h-4 mr-2" />
) : (
<TrashIcon className="w-4 h-4 mr-2" />
)}
Delete OAuth App
) : null}
Reset {spec.displayName} OAuth to use Acorn
Gateway
</Button>
</TooltipTrigger>
</ConfirmationDialog>
Expand Down
75 changes: 0 additions & 75 deletions ui/admin/app/components/oauth-apps/EditOAuthApp.tsx

This file was deleted.

Loading